diff --git a/src/constants/endpoints.js b/src/constants/endpoints.js index e6ad5cdd..6562047f 100644 --- a/src/constants/endpoints.js +++ b/src/constants/endpoints.js @@ -76,6 +76,10 @@ const endpoints = Object.freeze({ url: `${PRICE_BASE_URL}/order-items-with-insurance-pricing`, method: 'GET' }, + GetITACPriceOrderItems: { + url: `${PRICE_BASE_URL}/order-items-with-itac-pricing`, + method: 'POST' + }, GetProviders: { url: `${LOCATION_BASE_URL}/providers`, method: 'GET' diff --git a/src/helpers/service-location-helper.js b/src/helpers/service-location-helper.js index de557b21..f21cd763 100644 --- a/src/helpers/service-location-helper.js +++ b/src/helpers/service-location-helper.js @@ -28,7 +28,7 @@ export async function getPricedMobileFeePart(serviceZipCode) { // Get the Mobile Fee Part Price const pricingResults = await useMainStore() - .getPriceOrderItems([mobileFeePart.data]); + .getInsurancePriceOrderItems([mobileFeePart.data]); return Promise.resolve(pricingResults[0]); } diff --git a/src/layouts/coverage-statement/coverage-statement.spec.js b/src/layouts/coverage-statement/coverage-statement.spec.js index 82c85297..048c8bd5 100644 --- a/src/layouts/coverage-statement/coverage-statement.spec.js +++ b/src/layouts/coverage-statement/coverage-statement.spec.js @@ -668,32 +668,7 @@ describe('coverageStatement.vue', () => { }); }); }); - describe('ITAC CoverageType', () => { - test('set ITAC coverageType once component is initialized', async () => { - // Arrange - const mainInitialState = { - order: { - insuranceCoverage: { - coverageStatus: coverageStatuses.VERIFIED, - coverageType: coverageType.Deductible - }, - currentDeductible: 666 - } - }; - getPriceOfLineItems.mockReturnValue(333); - const { wrapper } = getMountedComponent(mainInitialState); - - // Act - await wrapper.vm.initializeComponent(); - - // Assert - expect(wrapper.vm.mainStore.updateCoverageType) - .toHaveBeenCalledTimes(1); - - expect(wrapper.vm.mainStore.updateCoverageType) - .toHaveBeenCalledWith(coverageType.ITAC); - }); - + describe('claim registration api call', () => { it('Loaded duplicate with previously registered claim => claim registration is not called', async () => { // Arrange const sellingPrice = getRandomInt(50, 100); @@ -722,7 +697,14 @@ describe('coverageStatement.vue', () => { useMainStore().getWipers = jest.fn().mockImplementation(() => Promise.resolve()); useMainStore().getRainDefense = jest.fn().mockImplementation(() => Promise.resolve()); useMainStore().getSupportingItems = jest.fn().mockImplementation(() => Promise.resolve()); - useMainStore().getPriceOrderItems = jest.fn().mockImplementation(() => Promise.resolve([ + useMainStore().getInsurancePriceOrderItems = jest.fn().mockImplementation(() => Promise.resolve([ + { + sellingPrice, + kitPrice: 0, + laborAmount: 0 + } + ])); + useMainStore().getITACPriceOrderItems = jest.fn().mockImplementation(() => Promise.resolve([ { sellingPrice, kitPrice: 0, @@ -743,15 +725,14 @@ describe('coverageStatement.vue', () => { // Assert expect(wrapper.vm.mainStore.registerClaim).toHaveBeenCalledTimes(0); }); - }); - describe('claim registration api call', () => { it('claim registration not required => method not called', async () => { // Arrange const mockStoreActions = () => { useMainStore().getWipers = jest.fn().mockImplementation(() => Promise.resolve()); useMainStore().getRainDefense = jest.fn().mockImplementation(() => Promise.resolve()); useMainStore().getSupportingItems = jest.fn().mockImplementation(() => Promise.resolve()); - useMainStore().getPriceOrderItems = jest.fn().mockImplementation(() => Promise.resolve()); + useMainStore().getInsurancePriceOrderItems = jest.fn().mockImplementation(() => Promise.resolve()); + useMainStore().getITACPriceOrderItems = jest.fn().mockImplementation(() => Promise.resolve()); }; const { wrapper } = getMountedComponent({ issConfig: { @@ -796,7 +777,8 @@ describe('coverageStatement.vue', () => { useMainStore().getWipers = jest.fn().mockImplementation(() => Promise.resolve()); useMainStore().getRainDefense = jest.fn().mockImplementation(() => Promise.resolve()); useMainStore().getSupportingItems = jest.fn().mockImplementation(() => Promise.resolve()); - useMainStore().getPriceOrderItems = jest.fn().mockImplementation(() => Promise.resolve()); + useMainStore().getInsurancePriceOrderItems = jest.fn().mockImplementation(() => Promise.resolve()); + useMainStore().getITACPriceOrderItems = jest.fn().mockImplementation(() => Promise.resolve()); }; const { wrapper } = getMountedComponent(initialStore, {}, mockStoreActions); const next = (method) => { method(wrapper.vm); }; diff --git a/src/layouts/coverage-statement/coverage-statement.vue b/src/layouts/coverage-statement/coverage-statement.vue index 85231267..465d5b93 100644 --- a/src/layouts/coverage-statement/coverage-statement.vue +++ b/src/layouts/coverage-statement/coverage-statement.vue @@ -124,7 +124,6 @@ import widgetFields from '@/constants/cms-widget-fields.js'; import { formatAmountInDollars } from '@/helpers/text-helper.js'; import showIssLoadingModal from '@/helpers/loading-modal-helper'; import { getPriceOfLineItems } from '@/helpers/price-calculator'; -import coverageType from '@/constants/coverage-type'; import coverageStatuses from '@/constants/coverage-statuses'; const SAFELITE_PROVIDER = 'Safelite'; @@ -146,8 +145,7 @@ export default { async beforeRouteEnter(to, from, next) { // Call APIs const cmsContentPromise = fetchCmsContentForPage(to?.query?.issPage); - const supportingItemsPromise = - await useMainStore().getSupportingItems(); + const supportingItemsPromise = await useMainStore().getSupportingItems(); // Settle promises and get results const promiseResultMap = [ @@ -162,53 +160,23 @@ export default { ]; const resultMap = await settleAllPromises(promiseResultMap); - const clonedGlassParts = useMainStore().lineItems.glassParts - ? JSON.parse(JSON.stringify(useMainStore().lineItems.glassParts)) - : []; - // TODO SSR-1165: Recycle fee needs removed from quote calculation - const availableLineItems = [ - ...(resultMap.supportingItems ?? []), - ...(clonedGlassParts ?? []) - ]; - let hasBailedOut = false; - let pricingResults = []; const { vehicle, isPolicyLookupSuccessful, isITAC, isDeductible } = useMainStore(); if (isPolicyLookupSuccessful && vehicle.policyVehicleId >= 0) { if (isITAC || isDeductible) { await useMainStore().getFinalDeductible(); } - - pricingResults = await useMainStore() - .getPriceOrderItems(availableLineItems) - .catch((err) => { - useMainStore().setBailout(bailoutMessage.pricingResponseError( - availableLineItems.map((li) => li.partNumber), - { - code: err.code, - message: err.message, - data: err.data - } - )); - hasBailedOut = true; - next(`/?issPage=${issPageValues.BAILOUT_PAGE}`); - }); } - if (!hasBailedOut) { - // Call the "next" function to complete the transition to this page. - next(async (vm) => { - showIssLoadingModal(true); - vm.setCmsContent(resultMap.cmsContent); - vm.setSupportingItems(resultMap.supportingItems); - // eslint-disable-next-line no-param-reassign - vm.setBaseServiceLineItems(pricingResults); - await vm.initializeComponent(); - if (!vm.unverified) { - useMainStore().disableKeyFields(); - } - }); - } + next(async (vm) => { + showIssLoadingModal(true); + vm.setCmsContent(resultMap.cmsContent); + vm.setSupportingItems(resultMap.supportingItems); + await vm.initializeComponent(); + if (!vm.unverified) { + useMainStore().disableKeyFields(); + } + }); }, setup() { const mainStore = useMainStore(); @@ -372,12 +340,30 @@ export default { this.mainStore.updateCoverageStatus(coverageStatuses.VERIFIED); } - // TODO this should be determined based on the result of the ITAC price call - // TODO it seems that ITAC now requires claim registration calls. If this call fails - if (this.mainStore.isVerified - && this.mainStore.isDeductible - && this.deductibleValue > this.totalServicePrice) { - this.mainStore.updateCoverageType(coverageType.ITAC); + if (this.mainStore.isVerified) { + const clonedGlassParts = useMainStore().lineItems.glassParts + ? JSON.parse(JSON.stringify(useMainStore().lineItems.glassParts)) + : []; + const availableLineItems = [ + ...(this.supportingItems ?? []), + ...(clonedGlassParts ?? []) + ]; + + const pricingResults = await useMainStore() + .getITACPriceOrderItems(availableLineItems) + .catch((err) => { + useMainStore().setBailout(bailoutMessage.pricingResponseError( + availableLineItems.map((li) => li.partNumber), + { + code: err.code, + message: err.message, + data: err.data + } + )); + this.navigateWithScenario(navigationScenarios.PRICING_LOOKUP_ERROR); + }); + + this.setBaseServiceLineItems(pricingResults); } showIssLoadingModal(false); diff --git a/src/layouts/payment-method/payment-method.vue b/src/layouts/payment-method/payment-method.vue index 7dee7636..8d41f1d2 100644 --- a/src/layouts/payment-method/payment-method.vue +++ b/src/layouts/payment-method/payment-method.vue @@ -141,7 +141,7 @@ export default { let hasBailedOut = false; const pricedVaps = await useMainStore() - .getPriceOrderItems(unpricedVaps) + .getInsurancePriceOrderItems(unpricedVaps) .catch((err) => { useMainStore().setBailout(bailoutMessage.pricingResponseError( unpricedVaps.map((li) => li.partNumber), diff --git a/src/layouts/schedule-page/schedule-page.vue b/src/layouts/schedule-page/schedule-page.vue index 3a429532..d62ba77a 100644 --- a/src/layouts/schedule-page/schedule-page.vue +++ b/src/layouts/schedule-page/schedule-page.vue @@ -261,7 +261,7 @@ export default { const premiumFeeWithPricePromise = premiumFeePromise.then((result) => { if (result.data) { - return useMainStore().getPriceOrderItems(result.data); + return useMainStore().getInsurancePriceOrderItems(result.data); } return result.data; }); diff --git a/src/layouts/service-packages/service-packages.vue b/src/layouts/service-packages/service-packages.vue index 98c83864..9c1d2985 100644 --- a/src/layouts/service-packages/service-packages.vue +++ b/src/layouts/service-packages/service-packages.vue @@ -129,7 +129,7 @@ export default { let hasBailedOut = false; const pricingResults = await store - .getPriceOrderItems(availableLineItems) + .getInsurancePriceOrderItems(availableLineItems) .catch((err) => { useMainStore().setBailout(bailoutMessage.pricingResponseError( availableLineItems.map((li) => li.partNumber), diff --git a/src/router/router-constants/navigation-scenarios.js b/src/router/router-constants/navigation-scenarios.js index 8bc295df..4d6cde2a 100644 --- a/src/router/router-constants/navigation-scenarios.js +++ b/src/router/router-constants/navigation-scenarios.js @@ -67,6 +67,7 @@ const navigationScenarios = Object.freeze({ // Coverage Statement CLICKED_BACK_WITH_REPAIR: 'CLICKED_BACK_WITH_REPAIR', CLICKED_FORWARD_WITH_INVALID_STATE: 'CLICKED_FORWARD_WITH_INVALID_STATE', + PRICING_LOOKUP_ERROR: 'PRICING_LOOKUP_ERROR', // TPA Search CLICKED_DO_NOT_SEE_MY_SHOP_LINK: 'CLICKED_DO_NOT_SEE_MY_SHOP_LINK', diff --git a/src/router/router-constants/routing-table.js b/src/router/router-constants/routing-table.js index 6a66676d..640c7d20 100644 --- a/src/router/router-constants/routing-table.js +++ b/src/router/router-constants/routing-table.js @@ -535,6 +535,10 @@ const routingTable = () => [ { scenario: navigationScenarios.CLICKED_FORWARD_WITH_INVALID_STATE, destinationIssPageValue: issPageValues.BAILOUT_PAGE + }, + { + scenario: navigationScenarios.PRICING_LOOKUP_ERROR, + destinationIssPageValue: issPageValues.BAILOUT_PAGE } ] }, diff --git a/src/store/index.js b/src/store/index.js index 4e859a18..17ef3231 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -1036,7 +1036,7 @@ export const useMainStore = defineStore({ }); }, - async getPriceOrderItems(availableLineItems) { + async getInsurancePriceOrderItems(availableLineItems) { const zipCodeToUse = this.order.serviceLocation.zipCode; if (!this.order.serviceLocation.zipCodeCtu) { const zipInfo = await this.validateZip({ zip: zipCodeToUse }); @@ -1081,6 +1081,84 @@ export const useMainStore = defineStore({ return availableLineItems; }, + async getITACPriceOrderItems(availableLineItems) { + const zipCodeToUse = this.order.serviceLocation.zipCode; + if (!this.order.serviceLocation.zipCodeCtu) { + const zipInfo = await this.validateZip({ zip: zipCodeToUse }); + this.order.serviceLocation.zipCodeCtu = zipInfo.zipCodeCtu; + } + + const { policy, vehicle, contactInfo, serviceLocation, insuranceCoverage } = this.order; + + const response = await globalMethods + .callHttpClient({ + method: endpoints.GetITACPriceOrderItems.method, + endpoint: endpoints.GetITACPriceOrderItems.url, + payload: { + Eon: this.order.eon, + ReferralNumber: this.order.referralNumber, + ReferralSequenceNumber: this.order.referralSequenceNumber, + ReferralDate: `${this.order.referralDate}Z`, + lineItems: availableLineItems, + ServerData: this.order.lineItems.serverData, + ServiceZipCode: zipCodeToUse, + Customer: { + PhoneNumber: contactInfo.servicePhone, + State: policy.damageState, + ZipCode: policy.policyZipCode + }, + Provider: { + ProviderNumber: serviceLocation.zipCodeCtu, + ProviderCtuNumber: serviceLocation.zipCodeCtu + }, + Vehicle: { + CarId: vehicle.carId, + Year: vehicle.year, + Make: vehicle.make, + Model: vehicle.model + }, + Insurance: { + AccountNumber: this.order.parentAccountNumber, + Deductible: this.order.currentDeductible ?? 0, + LineOfBusiness: 'PERSONAL', + PolicyNumber: policy.policyNumber, + CoverageStatus: insuranceCoverage.coverageStatus, + IsNoComp: this.isNoComp + } + } + }).catch((error) => { + console.error(error); + throw error; + }); + + const { lineItems, serverData, isItac, primaryBillToNumber } = response.data; + + if (serverData) { + this.order.lineItems.serverData = serverData; + } + + if (isItac) { + // if the ITAC Pricing API call returns isItac = true then we should switch to ITAC coverage type + this.updateCoverageType(coverageType.ITAC); + } else if (this.isITAC) { + // If the ITAC pricing API call returns isItac = false, and we are currently ITAC in the store then we should switch to deductible coverage type + this.updateCoverageType(coverageType.Deductible); + } + + if (primaryBillToNumber && primaryBillToNumber.length !== 0) { + this.issConfig.billToAccountNumber = primaryBillToNumber; + } else { + await this.getBillToInfo(); + } + + if (lineItems) { + const retAvailableLineItems = addPricesToLineItems(availableLineItems, lineItems); + return retAvailableLineItems; + } + + return availableLineItems; + }, + getMobileFeePart() { const damageType = this.damage.isRepair ? 'Repair' : 'Replace'; @@ -1670,7 +1748,7 @@ export const useMainStore = defineStore({ ) ]; - await this.getPriceOrderItems(lineItemsToTax); + await this.getInsurancePriceOrderItems(lineItemsToTax); await this.getTaxOrderItems(lineItemsToTax); }, @@ -2295,7 +2373,7 @@ export const useMainStore = defineStore({ providerNumber: order.serviceLocation.zipCodeCtu.toString(), typeOfClaim: 'GLASS ONLY', lineOfBusiness: 'PERSONAL', - isItac: false + isItac: this.isITAC }); const response = await globalMethods.callHttpClient({