Merge pull request #827 from Safelite/feature/CSR-504
CSR-504 | Implement Quote page service calls
This commit is contained in:
commit
5e963ab491
6 changed files with 119 additions and 65 deletions
|
|
@ -62,6 +62,18 @@ const endpoints = {
|
||||||
url: "/parts/api/v1/parts/parts",
|
url: "/parts/api/v1/parts/parts",
|
||||||
method: "POST",
|
method: "POST",
|
||||||
},
|
},
|
||||||
|
GetWipers: {
|
||||||
|
url: "/parts/api/v1/parts/wipers",
|
||||||
|
method: "GET",
|
||||||
|
},
|
||||||
|
GetRainDefense: {
|
||||||
|
url: "/parts/api/v1/parts/rain-defense",
|
||||||
|
method: "GET",
|
||||||
|
},
|
||||||
|
GetSupportingItems: {
|
||||||
|
url: "/parts/api/v1/parts/supporting-items",
|
||||||
|
method: "POST",
|
||||||
|
},
|
||||||
GetCapabilityQuestions: {
|
GetCapabilityQuestions: {
|
||||||
url: "/parts/api/v1/parts/capability-questions",
|
url: "/parts/api/v1/parts/capability-questions",
|
||||||
method: "GET",
|
method: "GET",
|
||||||
|
|
@ -82,6 +94,10 @@ const endpoints = {
|
||||||
url: "/location/api/v1/location/zip",
|
url: "/location/api/v1/location/zip",
|
||||||
method: "GET",
|
method: "GET",
|
||||||
},
|
},
|
||||||
|
PriceOrderItems: {
|
||||||
|
url: "/price/api/v1/price/order-items",
|
||||||
|
method: "POST",
|
||||||
|
},
|
||||||
LogExperimentExposureIfAssigned: {
|
LogExperimentExposureIfAssigned: {
|
||||||
url: "/experiments/api/v1/experiments/log-exposure",
|
url: "/experiments/api/v1/experiments/log-exposure",
|
||||||
method: "POST",
|
method: "POST",
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,9 @@ const storeActions = {
|
||||||
LOOKUP_VIN_BY_ADDRESS: "lookupVinByAddress",
|
LOOKUP_VIN_BY_ADDRESS: "lookupVinByAddress",
|
||||||
GET_PARTS_OR_QUESTIONS: "getPartsOrQuestions",
|
GET_PARTS_OR_QUESTIONS: "getPartsOrQuestions",
|
||||||
GET_PARTS: "getParts",
|
GET_PARTS: "getParts",
|
||||||
|
GET_WIPERS: "getWipers",
|
||||||
|
GET_RAIN_DEFENSE: "getRainDefense",
|
||||||
|
GET_SUPPORTING_ITEMS: "getSupportingItems",
|
||||||
GET_CAPABILITY_QUESTIONS: "getCapabilityQuestions",
|
GET_CAPABILITY_QUESTIONS: "getCapabilityQuestions",
|
||||||
GET_PART_FROM_CAPABILITY_QUESTION_ANSWER: "getPartFromCapabilityQuestionAnswer",
|
GET_PART_FROM_CAPABILITY_QUESTION_ANSWER: "getPartFromCapabilityQuestionAnswer",
|
||||||
GET_MOLDING_QUESTIONS: "getMoldingQuestions",
|
GET_MOLDING_QUESTIONS: "getMoldingQuestions",
|
||||||
|
|
@ -27,6 +30,7 @@ const storeActions = {
|
||||||
LOAD_SESSION: "loadSession",
|
LOAD_SESSION: "loadSession",
|
||||||
UPDATE_STORE_WITH_SAVE_SESSION_RESPONSE: "updateStoreWithSaveSessionResponse",
|
UPDATE_STORE_WITH_SAVE_SESSION_RESPONSE: "updateStoreWithSaveSessionResponse",
|
||||||
VALIDATE_ZIP: "validateZip",
|
VALIDATE_ZIP: "validateZip",
|
||||||
|
PRICE_ORDER_ITEMS: "priceOrderItems",
|
||||||
LOG_EXPERIMENT_EXPOSURE: "logExperimentExposure",
|
LOG_EXPERIMENT_EXPOSURE: "logExperimentExposure",
|
||||||
LOG_PAGE_VIEW: "logPageView",
|
LOG_PAGE_VIEW: "logPageView",
|
||||||
LOG_CUSTOM_EVENT: "logCustomEvent",
|
LOG_CUSTOM_EVENT: "logCustomEvent",
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,9 @@ import textBlock from "@/common-components/text-block/text-block";
|
||||||
import modal from "@/common-components/modal/modal";
|
import modal from "@/common-components/modal/modal";
|
||||||
import baseMixin from "@/mixins/base-mixin.js";
|
import baseMixin from "@/mixins/base-mixin.js";
|
||||||
import vehicleQuestionsMixin from "../../mixins/vehicle-questions-mixin";
|
import vehicleQuestionsMixin from "../../mixins/vehicle-questions-mixin";
|
||||||
|
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||||
|
import { storeActions } from "@/constants/store-actions";
|
||||||
|
import store from "@/store";
|
||||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||||
import { Form } from "vee-validate";
|
import { Form } from "vee-validate";
|
||||||
|
|
||||||
|
|
@ -66,70 +68,48 @@ export default {
|
||||||
async beforeRouteEnter(to, from, next) {
|
async beforeRouteEnter(to, from, next) {
|
||||||
// Call APIs
|
// Call APIs
|
||||||
const cmsContent = await fetchCmsContentForPage(to.query.fmgPage);
|
const cmsContent = await fetchCmsContentForPage(to.query.fmgPage);
|
||||||
|
const wipersPromise = baseMixin.methods.dispatchStoreAction(storeActions.GET_WIPERS);
|
||||||
|
const rainDefensePromise = baseMixin.methods.dispatchStoreAction(
|
||||||
|
storeActions.GET_RAIN_DEFENSE
|
||||||
|
);
|
||||||
|
const supportingItemsPromise = baseMixin.methods.dispatchStoreAction(
|
||||||
|
storeActions.GET_SUPPORTING_ITEMS
|
||||||
|
);
|
||||||
|
|
||||||
// TODOS - modify as needed, just a rough sketch to place initializations
|
const promiseResultMap = [
|
||||||
|
{
|
||||||
|
resultKey: "wipers",
|
||||||
|
promise: wipersPromise,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
resultKey: "rainDefense",
|
||||||
|
promise: rainDefensePromise,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
resultKey: "supportingItems",
|
||||||
|
promise: supportingItemsPromise,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
// get supporting availableLineItems
|
const resultMap = await settleAllPromises(promiseResultMap);
|
||||||
|
const glassParts = [...store.getters.order.lineItems.glassParts];
|
||||||
|
const availableLineItems = [
|
||||||
|
resultMap.rainDefense,
|
||||||
|
...resultMap.supportingItems,
|
||||||
|
...resultMap.wipers,
|
||||||
|
...glassParts,
|
||||||
|
];
|
||||||
|
|
||||||
// get wiper and rain defense availableLineItems
|
const pricingResults = await baseMixin.methods.dispatchStoreAction(
|
||||||
|
storeActions.PRICE_ORDER_ITEMS,
|
||||||
// Settle promises and get results
|
availableLineItems,
|
||||||
|
false
|
||||||
// get price of supporting, rain defense & wipers, and parts
|
);
|
||||||
|
|
||||||
// Settle pricing promise and get results
|
|
||||||
|
|
||||||
// Call the "next" function to complete the transition to this page.
|
// Call the "next" function to complete the transition to this page.
|
||||||
next((vm) => {
|
next((vm) => {
|
||||||
vm.setCmsContent(cmsContent);
|
vm.setCmsContent(cmsContent);
|
||||||
vm.availableLineItems = [
|
vm.availableLineItems = pricingResults;
|
||||||
{
|
|
||||||
partNumber: "001",
|
|
||||||
Description: "Windshield with Recal",
|
|
||||||
partType: "Windshield",
|
|
||||||
Quantity: "1",
|
|
||||||
BasePartNumber: "001",
|
|
||||||
Color: "Green",
|
|
||||||
CanSafeliteRecalibrate: true,
|
|
||||||
price: 350.22,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
partNumber: "SBB16",
|
|
||||||
description: "SAFELITE BEAM BLADE 16",
|
|
||||||
partType: "FRONT WIPER",
|
|
||||||
price: 32.64,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
partNumber: "A DISPOSAL FEE",
|
|
||||||
partType: "DISPOSAL FEE",
|
|
||||||
price: 15.0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
partNumber: "SBB26",
|
|
||||||
description: "SAFELITE BEAM BLADE 26",
|
|
||||||
partType: "FRONT WIPER",
|
|
||||||
price: 53.04,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
partNumber: "SBBR12A",
|
|
||||||
description: "SAFELITE REAR BLADE 12A",
|
|
||||||
partType: "REAR WIPER",
|
|
||||||
price: 24.48,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
partNumber: "RAIN DEFENSE",
|
|
||||||
description: null,
|
|
||||||
partType: "RAIN DEFENSE",
|
|
||||||
price: 35.5,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
partNumber: "RECAL STATIC",
|
|
||||||
Description: "Recalibration",
|
|
||||||
partType: "recalibration",
|
|
||||||
Quantity: "1",
|
|
||||||
price: 150.0,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
vm.isInsuranceSelected = vm.getDefaultIsInsuranceSelectedValue();
|
vm.isInsuranceSelected = vm.getDefaultIsInsuranceSelectedValue();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,8 @@ export default {
|
||||||
partNumber: singlePart.partNumber,
|
partNumber: singlePart.partNumber,
|
||||||
description: singlePart.description,
|
description: singlePart.description,
|
||||||
color: singlePart.color,
|
color: singlePart.color,
|
||||||
|
partType: singlePart.partType,
|
||||||
|
canSafeliteRecalibrate: singlePart.canSafeliteRecalibrate,
|
||||||
requiresRecalibration: singlePart.requiresRecalibration,
|
requiresRecalibration: singlePart.requiresRecalibration,
|
||||||
requiresCapabilityQuestions: singlePart.requiresCapabilityQuestions,
|
requiresCapabilityQuestions: singlePart.requiresCapabilityQuestions,
|
||||||
recalibrationType: singlePart.recalibrationType,
|
recalibrationType: singlePart.recalibrationType,
|
||||||
|
|
|
||||||
|
|
@ -342,7 +342,7 @@ export const mutations = {
|
||||||
state.order.damage.isRepair = sessionInformation.order.damage.isRepair;
|
state.order.damage.isRepair = sessionInformation.order.damage.isRepair;
|
||||||
state.order.damage.numberOfChips = sessionInformation.order.damage.numberOfChips;
|
state.order.damage.numberOfChips = sessionInformation.order.damage.numberOfChips;
|
||||||
|
|
||||||
state.order.lineItems.glassParts = sessionInformation.order.lineItems.parts;
|
state.order.lineItems.glassParts = sessionInformation.order.lineItems.glassParts;
|
||||||
state.order.accountNumber = sessionInformation.order.accountNumber;
|
state.order.accountNumber = sessionInformation.order.accountNumber;
|
||||||
state.order.providerNumber = sessionInformation.order.providerNumber;
|
state.order.providerNumber = sessionInformation.order.providerNumber;
|
||||||
(state.order.serviceLocation.address =
|
(state.order.serviceLocation.address =
|
||||||
|
|
@ -871,6 +871,49 @@ export const actions = {
|
||||||
return response;
|
return response;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getWipers(context) {
|
||||||
|
const carId = context.getters.vehicle.carId;
|
||||||
|
const serviceZipCode = context.getters.order.serviceLocation.zipCode;
|
||||||
|
return globalMethods
|
||||||
|
.callHttpClient({
|
||||||
|
method: endpoints.GetWipers.method,
|
||||||
|
endpoint: `${endpoints.GetWipers.url}/${carId}/${serviceZipCode}`,
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
// The wiper service sometimes returns 500s on legitimate carId/zipCode combination - return empty array instead of breaking flow
|
||||||
|
return [];
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
getRainDefense(context) {
|
||||||
|
return globalMethods.callHttpClient({
|
||||||
|
method: endpoints.GetRainDefense.method,
|
||||||
|
endpoint: endpoints.GetRainDefense.url,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
getSupportingItems(context) {
|
||||||
|
const glassPartsArray = context.getters.lineItems.glassParts;
|
||||||
|
if (!glassPartsArray) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
const carId = context.getters.vehicle.carId;
|
||||||
|
const isRepair = context.getters.damage.isRepair;
|
||||||
|
const numberOfChips = context.getters.damage.numberOfChips;
|
||||||
|
const accountNumber = "82791"; //context.getters.order.accountNumber.toString();
|
||||||
|
return globalMethods.callHttpClient({
|
||||||
|
method: endpoints.GetSupportingItems.method,
|
||||||
|
endpoint: endpoints.GetSupportingItems.url,
|
||||||
|
payload: {
|
||||||
|
carId: carId,
|
||||||
|
serviceType: isRepair ? "Repair" : "Replace",
|
||||||
|
//accountNumber: accountNumber,
|
||||||
|
parts: glassPartsArray,
|
||||||
|
numberOfRepairChips: isRepair ? numberOfChips : 0,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
getCapabilityQuestions(context, { carId, partNumber }) {
|
getCapabilityQuestions(context, { carId, partNumber }) {
|
||||||
return globalMethods.callHttpClient({
|
return globalMethods.callHttpClient({
|
||||||
method: endpoints.GetCapabilityQuestions.method,
|
method: endpoints.GetCapabilityQuestions.method,
|
||||||
|
|
@ -984,7 +1027,7 @@ export const actions = {
|
||||||
})
|
})
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
// Flatten location and name properties
|
// Flatten location and name properties
|
||||||
response.data.damage?.glassToReplace?.map((glass) => {
|
response.data.order.damage?.glassToReplace?.map((glass) => {
|
||||||
glass.glassLocation = glass.location;
|
glass.glassLocation = glass.location;
|
||||||
glass.glassName = glass.name;
|
glass.glassName = glass.name;
|
||||||
delete glass.location;
|
delete glass.location;
|
||||||
|
|
@ -1311,6 +1354,14 @@ export const actions = {
|
||||||
capabilityQuestionAnswers
|
capabilityQuestionAnswers
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
// Price order actions
|
||||||
|
// PLACEHOLDER, WILL CHANGE WHEN PRICING END POINT IS IMPLEMENTED
|
||||||
|
priceOrderItems(context, availableLineItems) {
|
||||||
|
availableLineItems.forEach((lineItem) => {
|
||||||
|
lineItem["price"] = parseFloat((Math.random() * 100).toFixed(2));
|
||||||
|
});
|
||||||
|
return availableLineItems;
|
||||||
|
},
|
||||||
// Misc order actions
|
// Misc order actions
|
||||||
saveServiceLocation(context, serviceLocationInfo) {
|
saveServiceLocation(context, serviceLocationInfo) {
|
||||||
context.commit(storeMutations.UPDATE_SERVICE_LOCATION, serviceLocationInfo);
|
context.commit(storeMutations.UPDATE_SERVICE_LOCATION, serviceLocationInfo);
|
||||||
|
|
@ -1394,7 +1445,7 @@ function sortArrayOfObjectsByPropertyValue(arrayOfObjects, propertyName) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function convertGlassPieceNamingForApi(glassArray) {
|
function convertGlassPieceNamingForApi(glassArray) {
|
||||||
if (!glassArray) return [];
|
if (!glassArray || glassArray.length === 0) return [];
|
||||||
|
|
||||||
// check if array already converted. (likely when a session has been saved previously and then reloaded)
|
// check if array already converted. (likely when a session has been saved previously and then reloaded)
|
||||||
if (glassArray[0].location !== undefined) {
|
if (glassArray[0].location !== undefined) {
|
||||||
|
|
|
||||||
|
|
@ -662,7 +662,7 @@ describe("Actions", () => {
|
||||||
const context = state;
|
const context = state;
|
||||||
|
|
||||||
globalMethods.callHttpClient.mockImplementation(() => {
|
globalMethods.callHttpClient.mockImplementation(() => {
|
||||||
return Promise.resolve({ data: { referralNumber: 123 } });
|
return Promise.resolve({ data: { referralNumber: 123, order: {} } });
|
||||||
});
|
});
|
||||||
|
|
||||||
const commit = jest.fn();
|
const commit = jest.fn();
|
||||||
|
|
@ -675,9 +675,10 @@ describe("Actions", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
expect(response.data).toEqual({ referralNumber: 123 });
|
expect(response.data).toEqual({ referralNumber: 123, order: {} });
|
||||||
expect(commit).toBeCalledWith(storeMutations.UPDATE_STATE_WITH_ORDER_INFORMATION, {
|
expect(commit).toBeCalledWith(storeMutations.UPDATE_STATE_WITH_ORDER_INFORMATION, {
|
||||||
referralNumber: 123,
|
referralNumber: 123,
|
||||||
|
order: {},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -686,7 +687,7 @@ describe("Actions", () => {
|
||||||
const context = state;
|
const context = state;
|
||||||
|
|
||||||
globalMethods.callHttpClient.mockImplementation(() => {
|
globalMethods.callHttpClient.mockImplementation(() => {
|
||||||
return Promise.resolve({ data: { eon: "123" } });
|
return Promise.resolve({ data: { eon: "123", order: {} } });
|
||||||
});
|
});
|
||||||
|
|
||||||
context.commit = jest.fn();
|
context.commit = jest.fn();
|
||||||
|
|
@ -709,7 +710,7 @@ describe("Actions", () => {
|
||||||
const context = state;
|
const context = state;
|
||||||
|
|
||||||
globalMethods.callHttpClient.mockImplementation(() => {
|
globalMethods.callHttpClient.mockImplementation(() => {
|
||||||
return Promise.resolve({ data: { eon: "123" } });
|
return Promise.resolve({ data: { eon: "123", order: {} } });
|
||||||
});
|
});
|
||||||
|
|
||||||
context.commit = jest.fn();
|
context.commit = jest.fn();
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue