diff --git a/src/helpers/line-items-helper.js b/src/helpers/line-items-helper.js index 9ad4bca3..e5c02530 100644 --- a/src/helpers/line-items-helper.js +++ b/src/helpers/line-items-helper.js @@ -6,3 +6,14 @@ export function getLineItemsFlattened(lineItems) { export function findLineItemIndex(lineItems, partNumber, startIndex = 0) { return lineItems.findIndex((li, index) => index >= startIndex && li.partNumber === partNumber); } + +// replaces partNumber, which is initially NAGS format, with the safelite part number +export function mapSafelitePartNumberToPartNumber(lineItems) { + return lineItems?.map(({ safelitePartNumber, childParts, ...rest }) => ({ + ...rest, + partNumber: safelitePartNumber, + childParts: childParts?.map((part) => ({ + partNumber: part.safelitePartNumber + })) ?? [] + })) ?? []; +} diff --git a/src/helpers/line-items-helper.spec.js b/src/helpers/line-items-helper.spec.js index af8337a7..6b756cdf 100644 --- a/src/helpers/line-items-helper.spec.js +++ b/src/helpers/line-items-helper.spec.js @@ -1,6 +1,94 @@ -import { getLineItemsFlattened } from '@/helpers/line-items-helper'; +import { getLineItemsFlattened, mapSafelitePartNumberToPartNumber } from '@/helpers/line-items-helper'; describe('getLineItemsFlattened', () => { + describe('mapSafelitePartNumberToPartNumber', () => { + test.each([null, undefined, []])('returns empty list when %p passed', (lineItems) => { + // Arrange + const expected = []; + + // Act + const result = mapSafelitePartNumberToPartNumber(lineItems); + + // Assert + expect(result).toMatchObject(expected); + }); + test('assigns partNumber to null when safelitePartNumber DNE', () => { + // Arrange + const lineItems = [ + { + apple: 'a', + partNumber: 111 + } + ]; + const expected = [ + { + apple: 'a', + partNumber: undefined, + childParts: [] + } + ]; + + // Act + const result = mapSafelitePartNumberToPartNumber(lineItems); + + // Assert + expect(result).toMatchObject(expected); + }); + test('assigns partNumber as expected when multiple line items passed', () => { + // Arrange + const lineItems = [ + { + apple: 'a', + banana: 'b', + partNumber: 111, + safelitePartNumber: 222, + childParts: [ + { + partNumber: 333, + safelitePartNumber: 444 + }, + { + partNumber: 555, + safelitePartNumber: 666 + } + ] + }, + { + apple: 'apple', + banana: 'banana', + partNumber: 123, + safelitePartNumber: 321 + } + ]; + const expected = [ + { + apple: 'a', + banana: 'b', + partNumber: 222, + childParts: [ + { + partNumber: 444 + }, + { + partNumber: 666 + } + ] + }, + { + apple: 'apple', + banana: 'banana', + partNumber: 321, + childParts: [] + } + ]; + + // Act + const result = mapSafelitePartNumberToPartNumber(lineItems); + + // Assert + expect(result).toMatchObject(expected); + }); + }); describe('getLineItemsFlattened', () => { it('Returns empty array when null is passed', () => { // Arrange diff --git a/src/iss-components/cart-dropdown/cart-dropdown.vue b/src/iss-components/cart-dropdown/cart-dropdown.vue index ebb083fa..34788563 100644 --- a/src/iss-components/cart-dropdown/cart-dropdown.vue +++ b/src/iss-components/cart-dropdown/cart-dropdown.vue @@ -178,7 +178,7 @@ import { import { getPriceOfLineItems, getTaxOfLineItems } from '@/helpers/price-calculator'; const VERIFYING_COVERAGE = 'Verifying coverage'; -const RECYCLING_MODAL_REF_NAME = "RecycleModal"; +const RECYCLING_MODAL_REF_NAME = 'RecycleModal'; export default { name: 'cart-dropdown', diff --git a/src/mixins/vehicle-questions-mixin.js b/src/mixins/vehicle-questions-mixin.js index 76964e08..c5f59540 100644 --- a/src/mixins/vehicle-questions-mixin.js +++ b/src/mixins/vehicle-questions-mixin.js @@ -23,9 +23,10 @@ export default { glassParts.forEach((glass) => { if (Array.isArray(glass.parts) && glass.parts.length === 1) { const singlePart = glass.parts[0]; - if (singlePart){ + if (singlePart) { reducedGlassParts.push({ partNumber: singlePart.partNumber, + safelitePartNumber: singlePart.safelitePartNumber, description: singlePart.description, color: singlePart.color, partType: singlePart.partType, @@ -119,10 +120,10 @@ export default { }); // remove any disabled dependent answers - const answerQuestionNums = new Set(alreadyAnsweredQuestions[alreadyAnsweredQuestions.length-1].answeredQuestions.map(q => q.questionNum)); - glass.questions.forEach(q => { - if(!answerQuestionNums.has(q.questionSequence)) { - delete q.answerSelected + const answerQuestionNums = new Set(alreadyAnsweredQuestions[alreadyAnsweredQuestions.length - 1].answeredQuestions.map((q) => q.questionNum)); + glass.questions.forEach((q) => { + if (!answerQuestionNums.has(q.questionSequence)) { + delete q.answerSelected; } }); diff --git a/src/store/index.js b/src/store/index.js index 7f26d157..c165d552 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -24,7 +24,7 @@ import partTypeStrings from '@/constants/part-type-strings'; import bailoutMessage from '@/constants/bailoutMessage'; import bailoutCode from '@/constants/bailoutCode'; import partNumberStrings from '@/constants/part-number-strings'; -import { findLineItemIndex, getLineItemsFlattened } from '@/helpers/line-items-helper'; +import { findLineItemIndex, getLineItemsFlattened, mapSafelitePartNumberToPartNumber } from '@/helpers/line-items-helper'; import { buildQueryStringParameterFromArrayOfComplexObjects, getLineItemQueryString, getTaxLineItemQueryString } from '@/helpers/querystring-helper'; import coverageType from '@/constants/coverage-type'; import { getExperimentSettingValue, getFeatureTogglesQueryString } from '@/helpers/experiment-helper'; @@ -1076,9 +1076,10 @@ export const useMainStore = defineStore({ return availableLineItems; }, + // NOTE: The endpoint requires that safelite part numbers be used!! async getITACPriceOrderItems(availableLineItems) { const { policy, vehicle, contactInfo, serviceLocation, insuranceCoverage } = this.order; - + const lineItemsUsingSafelitePartNumber = mapSafelitePartNumberToPartNumber(availableLineItems); const response = await globalMethods .callHttpClient({ method: endpoints.GetITACPriceOrderItems.method, @@ -1088,7 +1089,7 @@ export const useMainStore = defineStore({ ReferralNumber: this.order.referralNumber, ReferralSequenceNumber: this.order.referralSequenceNumber, ReferralDate: `${this.order.referralDate}Z`, - lineItems: getLineItemsFlattened(availableLineItems), + lineItems: getLineItemsFlattened(lineItemsUsingSafelitePartNumber), ServerData: this.order.lineItems.serverData, ServiceZipCode: serviceLocation.zipCode, Customer: { @@ -1141,7 +1142,7 @@ export const useMainStore = defineStore({ } if (lineItems) { - const retAvailableLineItems = addPricesToLineItems(availableLineItems, lineItems); + const retAvailableLineItems = addPricesToLineItems(availableLineItems, lineItems, false); return retAvailableLineItems; } @@ -2767,20 +2768,24 @@ function convertGlassPieceNamingFromApi(glassArray) { return glassArray; } -function addPricesToLineItems(lineItems, pricingLineItems) { +// Note this is used for both the insurance and the itac endpoints, so it needs to deal with safelite or nags part numbers +function addPricesToLineItems(lineItems, pricingLineItems, pricedPartNumberIsNags = true) { const partOffset = {}; + const partNumberPropertyToCompare = pricedPartNumberIsNags ? 'partNumber' : 'safelitePartNumber'; + lineItems.forEach((lineItem) => { if (lineItem.childParts) { addPricesToLineItems(lineItem.childParts, pricingLineItems); } + const partNumberToCompare = lineItem[partNumberPropertyToCompare]; - const pricedIndex = findLineItemIndex(pricingLineItems, lineItem.partNumber, partOffset[lineItem.partNumber] ?? 0); + const pricedIndex = findLineItemIndex(pricingLineItems, partNumberToCompare, partOffset[partNumberToCompare] ?? 0); if (pricedIndex !== -1) { const pricedLineItem = pricingLineItems[pricedIndex]; lineItem.laborAmount = pricedLineItem.laborAmount; lineItem.sellingPrice = pricedLineItem.sellingPrice; lineItem.kitPrice = pricedLineItem.kitPrice; - partOffset[lineItem.partNumber] = pricedIndex + 1; + partOffset[partNumberToCompare] = pricedIndex + 1; } }); return lineItems;