Merge pull request #603 from Safelite/feature/CSR-700

CSR-706 | Updating SaveOrder
This commit is contained in:
scottkiener 2022-07-13 10:33:17 -04:00 committed by GitHub
commit bca6efff7d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 133 additions and 38 deletions

View file

@ -23,7 +23,7 @@ const storeActions = {
GET_PARTS: "getParts", GET_PARTS: "getParts",
SAVE_ORDER: "saveOrder", SAVE_ORDER: "saveOrder",
LOAD_ORDER: "loadOrder", LOAD_ORDER: "loadOrder",
SET_REFERRAL_INFORMATION: "setReferralInformation", UPDATE_STORE_WITH_SAVE_ORDER_RESPONSE: "updateStoreWithSaveOrderResponse",
VALIDATE_ZIP: "validateZip", VALIDATE_ZIP: "validateZip",
LOG_EXPERIMENT_EXPOSURE: "logExperimentExposure", LOG_EXPERIMENT_EXPOSURE: "logExperimentExposure",
LOG_PAGE_VIEW: "logPageView", LOG_PAGE_VIEW: "logPageView",

View file

@ -39,6 +39,8 @@ const storeMutations = {
UPDATE_REFERRAL_DATE: "updateReferralDate", UPDATE_REFERRAL_DATE: "updateReferralDate",
UPDATE_REFERRAL_CORRELATION_ID: "updateReferralCorrelationId", UPDATE_REFERRAL_CORRELATION_ID: "updateReferralCorrelationId",
UPDATE_PARENT_ACCT_NUMBER: "updateParentAcctNumber", UPDATE_PARENT_ACCT_NUMBER: "updateParentAcctNumber",
UPDATE_SAVE_QUOTE_ID: "updateSaveQuoteId",
UPDATE_CRM_CUSTOMER_ID: "updateCrmCustomerId",
// EVENT BUS MUTATIONS // EVENT BUS MUTATIONS
ADD_EVENT_TO_BUS: "addEventToBus", ADD_EVENT_TO_BUS: "addEventToBus",
@ -54,6 +56,8 @@ const storeMutations = {
// OTHER MUTATIONS // OTHER MUTATIONS
UPDATE_PAGE_DATA: "updatePageData", UPDATE_PAGE_DATA: "updatePageData",
UPDATE_STATE_WITH_ORDER_INFORMATION: "updateStateWithOrderInformation", UPDATE_STATE_WITH_ORDER_INFORMATION: "updateStateWithOrderInformation",
UPDATE_SAVE_ORDER_PROMISE: "updateSaveOrderPromise",
UPDATE_LAST_PAGE_VISITED: "updateLastPageVisited",
}; };
export { storeMutations }; export { storeMutations };

View file

@ -308,8 +308,11 @@ describe("navigateToHeritageFunnel", () => {
const mockReferralNumber = "2"; const mockReferralNumber = "2";
const mockCorrelationId = "55"; const mockCorrelationId = "55";
const mockReferralDate = "2022"; const mockReferralDate = "2022";
const mockAccountNumber = "167132";
const mockSaveQuoteId = "xxx-xxx-xxx";
const mockCrmCustomerId = "xxx-xxx-xxx"
const mockOrderInfo = getMockOrderInfo(mockReferralNumber, mockCorrelationId, mockReferralDate); const mockOrderInfo = getMockOrderInfo(mockReferralNumber, mockCorrelationId, mockReferralDate, mockAccountNumber, mockSaveQuoteId, mockCrmCustomerId);
const mockData = { const mockData = {
actionList: [{ actionList: [{
@ -340,8 +343,11 @@ describe("navigateToHeritageFunnel", () => {
const mockReferralNumber = "2"; const mockReferralNumber = "2";
const mockCorrelationId = "55"; const mockCorrelationId = "55";
const mockReferralDate = "2022"; const mockReferralDate = "2022";
const mockAccountNumber = "167132";
const mockSaveQuoteId = "xxx-xxx-xxx";
const mockCrmCustomerId = "xxx-xxx-xxx"
const mockOrderInfo = getMockOrderInfo(mockReferralNumber, mockCorrelationId, mockReferralDate); const mockOrderInfo = getMockOrderInfo(mockReferralNumber, mockCorrelationId, mockReferralDate, mockAccountNumber, mockSaveQuoteId, mockCrmCustomerId);
const mockData = { const mockData = {
actionList: [{ actionList: [{

View file

@ -1,6 +1,8 @@
import { storeActions } from "@/constants/store-actions.js"; import { storeActions } from "@/constants/store-actions.js";
import { getFunnelCookie, updateOrCreateFunnelCookie, deleteFunnelCookie } from "@/helpers/heritage-integration/cookie-helper.js"; import { getFunnelCookie, updateOrCreateFunnelCookie, deleteFunnelCookie } from "@/helpers/heritage-integration/cookie-helper.js";
import baseMixin from "@/mixins/base-mixin"; import baseMixin from "@/mixins/base-mixin";
import store from "@/store";
import { storeMutations } from "@/constants/store-mutations";
/* /*
Will call API and hydrate state with data from API if present. If there is no order present Will call API and hydrate state with data from API if present. If there is no order present
@ -34,18 +36,20 @@ export async function loadOrderIfPresent() {
update the cookie. update the cookie.
*/ */
export async function saveOrder() { export async function saveOrder() {
const savedOrderInfo = await baseMixin.methods.dispatchStoreAction(storeActions.SAVE_ORDER); var saveOrderPromise;
if (store.getters.applicationUser.saveOrderPromise) {
// Save the referral information back from the store. // queue newest request after current saveOrderPromise resolves
await baseMixin.methods.dispatchStoreAction(storeActions.SET_REFERRAL_INFORMATION, { saveOrderPromise = store.getters.applicationUser.saveOrderPromise.then(() => {
referralNumber: savedOrderInfo.data.referralNumber.toString(), // get a new saveOrderPromise
referralCorrelationId: savedOrderInfo.data.referralCorrelationId, return saveOrderHelper();
referralDate: savedOrderInfo.data.referralDate, });
accountNumber: savedOrderInfo.data.accountNumber.toString() } else {
}, false); // create an initial saveOrderPromise
saveOrderPromise = saveOrderHelper();
// Update the cookie with the referral information when saved. }
updateOrCreateFunnelCookie(); store.commit(storeMutations.UPDATE_SAVE_ORDER_PROMISE, saveOrderPromise);
// await here to allow for a caller to await and make the function synchronous
await saveOrderPromise;
} }
@ -65,4 +69,23 @@ async function loadOrder(referralNumber, referralDate, referralCorrelationId, ac
}, false); }, false);
return response; return response;
}
/*
Encapsulates asynchronous Save Order logic inside a promise to allow for Save Order queuing
*/
async function saveOrderHelper() {
const savedOrderInfo = await baseMixin.methods.dispatchStoreAction(storeActions.SAVE_ORDER);
// Update the store with information received from the saveOrder response
await baseMixin.methods.dispatchStoreAction(storeActions.UPDATE_STORE_WITH_SAVE_ORDER_RESPONSE, {
referralNumber: savedOrderInfo.data.referralNumber.toString(),
referralCorrelationId: savedOrderInfo.data.referralCorrelationId,
referralDate: savedOrderInfo.data.referralDate,
accountNumber: savedOrderInfo.data.accountNumber.toString(),
saveQuoteId: savedOrderInfo.data.saveQuoteId,
crmCustomerId: savedOrderInfo.data.crmCustomerId.toString(),
}, false);
// Update the cookie with the referral information when saved.
updateOrCreateFunnelCookie();
} }

View file

@ -111,9 +111,11 @@ describe("saveOrder", () => {
const mockReferralNumber = "2"; const mockReferralNumber = "2";
const mockCorrelationId = "55"; const mockCorrelationId = "55";
const mockReferralDate = "2022"; const mockReferralDate = "2022";
const mockAccountNumber = "5"; const mockAccountNumber = "167132";
const mockSaveQuoteId = "xxx-xxx-xxx";
const mockCrmCustomerId = "xxx-xxx-xxx"
const mockOrderInfo = getMockOrderInfo(mockReferralNumber, mockCorrelationId, mockReferralDate, mockAccountNumber); const mockOrderInfo = getMockOrderInfo(mockReferralNumber, mockCorrelationId, mockReferralDate, mockAccountNumber, mockSaveQuoteId, mockCrmCustomerId);
const mockData = { const mockData = {
actionList: [ actionList: [
@ -122,7 +124,7 @@ describe("saveOrder", () => {
data: mockOrderInfo, data: mockOrderInfo,
}, },
{ {
actionName: storeActions.SET_REFERRAL_INFORMATION actionName: storeActions.UPDATE_STORE_WITH_SAVE_ORDER_RESPONSE
} }
] ]
} }
@ -134,21 +136,26 @@ describe("saveOrder", () => {
// Assert // Assert
expect(mocks.baseMixin.methods.dispatchStoreAction).toHaveBeenCalledWith(storeActions.SAVE_ORDER); expect(mocks.baseMixin.methods.dispatchStoreAction).toHaveBeenCalledWith(storeActions.SAVE_ORDER);
expect(mocks.baseMixin.methods.dispatchStoreAction).toHaveBeenCalledWith(storeActions.SET_REFERRAL_INFORMATION, { expect(mocks.baseMixin.methods.dispatchStoreAction).toHaveBeenCalledWith(storeActions.UPDATE_STORE_WITH_SAVE_ORDER_RESPONSE, {
referralNumber: mockReferralNumber, referralNumber: mockReferralNumber,
referralDate: mockReferralDate, referralDate: mockReferralDate,
referralCorrelationId: mockCorrelationId, referralCorrelationId: mockCorrelationId,
accountNumber: mockAccountNumber accountNumber: mockAccountNumber,
saveQuoteId: mockSaveQuoteId,
crmCustomerId: mockCrmCustomerId,
}, false); }, false);
}); });
test("saveOrder => should update DidHeritageFunnelUpdateLast cookie value to false", async () => { test("saveOrder => should update DidHeritageFunnelUpdateLast cookie value to false", async () => {
// Arrange // Arrange
const testReferralNumber = 1566818; const mockReferralNumber = 1566818;
const testReferralDate = "2022-03-15T10:56:24.597"; const mockReferralDate = "2022-03-15T10:56:24.597";
const testReferralCorrelationId = "404d2b04-f86e-45c3-b373-127b6217b060"; const mockReferralCorrelationId = "404d2b04-f86e-45c3-b373-127b6217b060";
const mockAccountNumber = "167132";
const mockSaveQuoteId = "xxx-xxx-xxx";
const mockCrmCustomerId = "xxx-xxx-xxx"
const mockOrderInfo = getMockOrderInfo(testReferralNumber, testReferralCorrelationId, testReferralDate); const mockOrderInfo = getMockOrderInfo(mockReferralNumber, mockReferralCorrelationId, mockReferralDate, mockAccountNumber, mockSaveQuoteId, mockCrmCustomerId);
const mockData = { const mockData = {
actionList: [{ actionList: [{
@ -161,9 +168,9 @@ describe("saveOrder", () => {
setupMocksForJsFiles(mockData); setupMocksForJsFiles(mockData);
const testCookieValue = { const testCookieValue = {
ReferralNumber: testReferralNumber, ReferralNumber: mockReferralNumber,
ReferralDate: testReferralDate, ReferralDate: mockReferralDate,
ReferralCorrelationId: testReferralCorrelationId, ReferralCorrelationId: mockReferralCorrelationId,
ShouldResetState: false, ShouldResetState: false,
DidHeritageFunnelUpdateLast: true DidHeritageFunnelUpdateLast: true
} }

View file

@ -90,12 +90,14 @@ export function removeAllTestCookies() {
}); });
} }
export function getMockOrderInfo(mockReferralNumber, mockCorrelationId, mockReferralDate, accountNumber = "0") { export function getMockOrderInfo(mockReferralNumber, mockCorrelationId, mockReferralDate, accountNumber = "0", saveQuoteId, crmCustomerId) {
return { return {
referralNumber: mockReferralNumber, referralNumber: mockReferralNumber,
referralCorrelationId: mockCorrelationId, referralCorrelationId: mockCorrelationId,
referralDate: mockReferralDate, referralDate: mockReferralDate,
accountNumber: accountNumber accountNumber: accountNumber,
saveQuoteId: saveQuoteId,
crmCustomerId: crmCustomerId,
} }
} }

View file

@ -1,6 +1,7 @@
// Supporting files // Supporting files
import { createWebHistory, createRouter } from "vue-router"; import { createWebHistory, createRouter } from "vue-router";
import { storeActions } from "@/constants/store-actions"; import { storeActions } from "@/constants/store-actions";
import { storeMutations } from "../constants/store-mutations";
import { lazyLoadComponent } from "@/router/dynamic-routing/component-loader.js"; import { lazyLoadComponent } from "@/router/dynamic-routing/component-loader.js";
import { routingTable } from "@/router/router-constants/routing-table.js"; import { routingTable } from "@/router/router-constants/routing-table.js";
import { globalEvents, globalEventTypes } from "@/constants/events"; import { globalEvents, globalEventTypes } from "@/constants/events";
@ -113,7 +114,9 @@ const router = createRouter({
//---------------------------------------------------------- Router Functions ---------------------------------------------------------- //---------------------------------------------------------- Router Functions ----------------------------------------------------------
router.afterEach(async (to, from) => { router.afterEach((to, from) => {
// Update lastPageVisited in the store
store.commit(storeMutations.UPDATE_LAST_PAGE_VISITED, to.name);
// Push page view to GA // Push page view to GA
analyticsMixin.methods.pushPageViewToGA(to.query[queryStrings.FMG_PAGE]); analyticsMixin.methods.pushPageViewToGA(to.query[queryStrings.FMG_PAGE]);
@ -152,9 +155,9 @@ async function navigate(scenario, currentRoute, optionalQuery = {}, optionalPara
// Append page data to the store for the NEXT page, if any. It will be an empty object if none is provided. // Append page data to the store for the NEXT page, if any. It will be an empty object if none is provided.
baseMixin.methods.savePageDataToStore(destinationFmgPageValue, optionalPageData); baseMixin.methods.savePageDataToStore(destinationFmgPageValue, optionalPageData);
// if cookie and referralNumber/Date exists // if cookie and referralNumber/Date exists OR an emailAddress has been saved
if (getFunnelCookie()?.ReferralNumber && getFunnelCookie()?.ReferralDate) { if ((getFunnelCookie()?.ReferralNumber && getFunnelCookie()?.ReferralDate) || store.getters.order.customer?.emailAddress) {
await saveOrder(); saveOrder();
} }
router.push({ router.push({

View file

@ -64,7 +64,11 @@ const getDefaultState = () => {
applicationUser: { applicationUser: {
eventBus: [], eventBus: [],
pageData: {}, pageData: {},
savedSessionTimeout: getDateForSavedSessionTimeout() savedSessionTimeout: getDateForSavedSessionTimeout(),
saveOrderPromise: null,
saveQuoteId: null,
crmCustomerId: null,
lastPageVisited: null,
}, },
} }
}; };
@ -200,6 +204,19 @@ export const mutations = {
state.order.serviceLocation.zipCode = serviceLocationInfo.zipCode; state.order.serviceLocation.zipCode = serviceLocationInfo.zipCode;
}, },
// applicationUser MUTATIONS
updateSaveOrderPromise(state, saveOrderPromise){
state.applicationUser.saveOrderPromise = saveOrderPromise;
},
updateSaveQuoteId(state, saveQuoteId) {
state.applicationUser.saveQuoteId = saveQuoteId;
},
updateCrmCustomerId(state, crmCustomerId) {
state.applicationUser.crmCustomerId = crmCustomerId;
},
updateLastPageVisited(state, lastPageVisited) {
state.applicationUser.lastPageVisited = lastPageVisited
},
// EVENT BUS MUTATIONS // EVENT BUS MUTATIONS
addEventToBus(state, event) { addEventToBus(state, event) {
state.applicationUser.eventBus.push(event); state.applicationUser.eventBus.push(event);
@ -476,6 +493,17 @@ export const actions = {
} }
}); });
}, },
// Misc Actions
updateStoreWithSaveOrderResponse(context, { referralNumber, referralDate, referralCorrelationId, accountNumber, saveQuoteId, crmCustomerId }) {
context.commit(storeMutations.UPDATE_REFERRAL_NUMBER, referralNumber);
context.commit(storeMutations.UPDATE_REFERRAL_DATE, referralDate);
context.commit(storeMutations.UPDATE_REFERRAL_CORRELATION_ID, referralCorrelationId);
context.commit(storeMutations.UPDATE_PARENT_ACCT_NUMBER, accountNumber);
context.commit(storeMutations.UPDATE_SAVE_QUOTE_ID, saveQuoteId);
context.commit(storeMutations.UPDATE_CRM_CUSTOMER_ID, crmCustomerId);
},
logPageView(context, { userId, sessionKey, pageName, sessionId, action, event, shouldUseSessionId }) { logPageView(context, { userId, sessionKey, pageName, sessionId, action, event, shouldUseSessionId }) {
var payload = { var payload = {
userId: userId, userId: userId,
@ -612,6 +640,7 @@ export const actions = {
const vehicle = context.getters.vehicle; const vehicle = context.getters.vehicle;
const damage = context.getters.damage; const damage = context.getters.damage;
const order = context.state.order; const order = context.state.order;
const applicationUser = context.getters.applicationUser;
return globalMethods.callHttpClient({ return globalMethods.callHttpClient({
method: endpoints.SaveOrder.method, method: endpoints.SaveOrder.method,
@ -650,7 +679,12 @@ export const actions = {
}, },
referralNumber: order.referralNumber?.toString(), // TODO It'd be nice to save these as strings in the first place referralNumber: order.referralNumber?.toString(), // TODO It'd be nice to save these as strings in the first place
referralDate: order.referralDate, referralDate: order.referralDate,
accountNumber: order.accountNumber?.toString() accountNumber: order.accountNumber?.toString(),
existingPromoCode: null,
lastPage: applicationUser.lastPageVisited,
crmCustomerId: applicationUser.crmCustomerId,
saveQuoteId: applicationUser.saveQuoteId,
}, },
}); });
}, },

View file

@ -571,12 +571,17 @@ describe("Actions", () => {
registration: {} registration: {}
}, },
damage: {}, damage: {},
applicationUser: {
lastPageVisited: "test-page",
crmCustomerId: "xxx-xxx-xxx",
saveQuoteId: "xxx-xxx-xxx"
}
}; };
context.state = { context.state = {
order: { order: {
serviceLocation: {}, serviceLocation: {},
customer: {} customer: {}
} },
}; };
globalMethods.callHttpClient.mockImplementation(() => { globalMethods.callHttpClient.mockImplementation(() => {
@ -611,7 +616,7 @@ describe("Actions", () => {
expect(commit).toBeCalledWith(storeMutations.UPDATE_STATE_WITH_ORDER_INFORMATION, { "referralNumber": 123 }); expect(commit).toBeCalledWith(storeMutations.UPDATE_STATE_WITH_ORDER_INFORMATION, { "referralNumber": 123 });
}); });
it("setReferralInformation, should call commit three times", () => { it("updateStoreWithSaveOrderResponse, should call commit six times", () => {
// Arrange // Arrange
const context = state; const context = state;
const commit = jest.fn(); const commit = jest.fn();
@ -619,12 +624,23 @@ describe("Actions", () => {
context.commit = commit; context.commit = commit;
// Act // Act
actions.setReferralInformation(context, { referralNumber: "123", referralDate: new Date().toUTCString(), referralCorrelationId: "xxx-xxx-xxx" }); actions.updateStoreWithSaveOrderResponse(context,
{
referralNumber: "123",
referralDate: new Date().toUTCString(),
referralCorrelationId: "xxx-xxx-xxx",
accountNumber: "167132",
saveQuoteId: "xxx-xxx-xxx",
crmCustomerId: "xxx-xxx-xxx",
});
// Assert // Assert
expect(commit).toBeCalledWith(storeMutations.UPDATE_REFERRAL_NUMBER, "123"); expect(commit).toBeCalledWith(storeMutations.UPDATE_REFERRAL_NUMBER, "123");
expect(commit).toBeCalledWith(storeMutations.UPDATE_REFERRAL_DATE, new Date().toUTCString()); expect(commit).toBeCalledWith(storeMutations.UPDATE_REFERRAL_DATE, new Date().toUTCString());
expect(commit).toBeCalledWith(storeMutations.UPDATE_REFERRAL_CORRELATION_ID, "xxx-xxx-xxx"); expect(commit).toBeCalledWith(storeMutations.UPDATE_REFERRAL_CORRELATION_ID, "xxx-xxx-xxx");
expect(commit).toBeCalledWith(storeMutations.UPDATE_PARENT_ACCT_NUMBER, "167132");
expect(commit).toBeCalledWith(storeMutations.UPDATE_SAVE_QUOTE_ID, "xxx-xxx-xxx");
expect(commit).toBeCalledWith(storeMutations.UPDATE_CRM_CUSTOMER_ID, "xxx-xxx-xxx");
}); });
it("logPageView action, should return nothing", async () => { it("logPageView action, should return nothing", async () => {