CASH-152: massive commit to implement pricing by day on schedule page
This commit is contained in:
parent
2bd4d42f57
commit
5412156766
15 changed files with 327 additions and 98 deletions
|
|
@ -3,6 +3,8 @@ const partNumberStrings = {
|
|||
MOBILE_STATIC_RECAL_FEE: "RECAL MOBILE",
|
||||
MOBILE_DUAL_RECAL_FEE: "RECAL MOBILEDUAL",
|
||||
DONATION: "DONATION",
|
||||
// Fees
|
||||
RECYCLE_FEE: "RECYCLE FEE",
|
||||
};
|
||||
|
||||
export { partNumberStrings };
|
||||
|
|
|
|||
|
|
@ -8,9 +8,17 @@ const PREMIUM_TIME_SLOT_ID_FLAG = "-PREMIUM";
|
|||
|
||||
const PREMIUM_FEE_PART_TYPE = "EARLY BIRD";
|
||||
|
||||
const PRICING_BY_DAY_UPCHARGE_FEE_PART_TYPE = "DISC CASHSAVE20";
|
||||
|
||||
const RouteCodeFlags = {
|
||||
ALL_DAY_DROP_OFF: "ALL DAY DROP OFF",
|
||||
OVERNIGHT_DROP_OFF: "OVERNIGHT DROP OFF",
|
||||
};
|
||||
|
||||
export { AppointmentTypeStrings, PREMIUM_TIME_SLOT_ID_FLAG, PREMIUM_FEE_PART_TYPE, RouteCodeFlags };
|
||||
export {
|
||||
AppointmentTypeStrings,
|
||||
PREMIUM_TIME_SLOT_ID_FLAG,
|
||||
PREMIUM_FEE_PART_TYPE,
|
||||
PRICING_BY_DAY_UPCHARGE_FEE_PART_TYPE,
|
||||
RouteCodeFlags,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ const storeActions = {
|
|||
GET_PART_FROM_CAPABILITY_QUESTION_ANSWER: "getPartFromCapabilityQuestionAnswer",
|
||||
GET_MOLDING_QUESTIONS: "getMoldingQuestions",
|
||||
GET_MOBILE_FEE_PART: "getMobileFeePart",
|
||||
GET_PRICING_BY_DAY_UPCHARGE_PART: "getPricingByDayUpchargePart",
|
||||
GET_SERVICE_PACKAGE_DISCOUNT_PART: "getServicePackageDiscountPart",
|
||||
GET_SERVICEABILITY_DETAILS: "getServiceabilityDetails",
|
||||
GET_SHOP_TIME_SLOTS: "getShopTimeSlots",
|
||||
|
|
|
|||
|
|
@ -23,4 +23,6 @@ const MONTHS_OF_YEAR = [
|
|||
|
||||
const DAYS_OF_WEEK = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
|
||||
|
||||
export { TIMINGFUNC_MAP, BUFFER_OFFSET, MONTHS_OF_YEAR, DAYS_OF_WEEK };
|
||||
const PREMIUM_DAY_INDEXES = [1, 5, 6]; // assign Monday, Friday, Saturday to be premium days
|
||||
|
||||
export { TIMINGFUNC_MAP, BUFFER_OFFSET, MONTHS_OF_YEAR, DAYS_OF_WEEK, PREMIUM_DAY_INDEXES };
|
||||
|
|
|
|||
|
|
@ -66,15 +66,15 @@
|
|||
type="radio"
|
||||
name="day-of-month"
|
||||
v-model="selectedDate"
|
||||
@click="fireDateSelectedEvent"
|
||||
@keypress.enter="fireDateSelectedEvent"
|
||||
@click="fireDateSelectedEvent($event, date)"
|
||||
@keypress.enter="fireDateSelectedEvent($event, date)"
|
||||
:value="date.inputValue"
|
||||
:id="`${month.monthLabel}-${date.dateNum.toString()}`" />
|
||||
<label :for="`${month.monthLabel}-${date.dateNum.toString()}`">
|
||||
<span>{{ date.dateNum.toString() }}</span>
|
||||
|
||||
<span v-if="showPricingByDay">$000</span>
|
||||
|
||||
<span v-if="showPricingByDay && date.isSelectable">
|
||||
{{ date.priceString }}
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -106,6 +106,7 @@ import {
|
|||
TIMINGFUNC_MAP,
|
||||
BUFFER_OFFSET,
|
||||
MONTHS_OF_YEAR,
|
||||
PREMIUM_DAY_INDEXES,
|
||||
} from "@/digital-components/date-picker/mixins/constants";
|
||||
import {
|
||||
selectableDaysOptions,
|
||||
|
|
@ -160,6 +161,8 @@ export default {
|
|||
default: "",
|
||||
},
|
||||
showPricingByDay: Boolean,
|
||||
baseDayPrice: Number,
|
||||
pricingByDayUpcharge: Number,
|
||||
},
|
||||
setup(props) {
|
||||
const uuid = uuidv4();
|
||||
|
|
@ -224,17 +227,12 @@ export default {
|
|||
initializeComponent(initialData) {
|
||||
this.setCalendarData(initialData);
|
||||
},
|
||||
fireDateSelectedEvent(event) {
|
||||
fireDateSelectedEvent(event, date) {
|
||||
// Ignore if arrow key selected radioButton
|
||||
if (event.screenX === 0 && event.screenY === 0) {
|
||||
return;
|
||||
}
|
||||
this.$emit("date-clicked");
|
||||
},
|
||||
fireDateSelectedEvent2(date) {
|
||||
console.log("date: ", date);
|
||||
this.selectedDate = date;
|
||||
this.$emit("date-clicked");
|
||||
this.$emit("date-clicked", date);
|
||||
},
|
||||
getWeekStartDate(dateString) {
|
||||
const date = convertDateStringToDate(dateString);
|
||||
|
|
@ -433,6 +431,8 @@ export default {
|
|||
hideSomeDaysForInitialView: hideSomeDaysForInitialView,
|
||||
hideSecondMonth: hideSecondMonth,
|
||||
preSelectedDate: config.preSelectedDate,
|
||||
baseDayPrice: config.baseDayPrice,
|
||||
pricingByDayUpcharge: config.pricingByDayUpcharge,
|
||||
};
|
||||
return initialData;
|
||||
});
|
||||
|
|
@ -457,6 +457,8 @@ export default {
|
|||
initialViewEndDate: config.initialViewEndDate,
|
||||
hideSecondMonth: hideSecondMonth,
|
||||
preSelectedDate: config.preSelectedDate,
|
||||
baseDayPrice: config.baseDayPrice,
|
||||
pricingByDayUpcharge: config.pricingByDayUpcharge,
|
||||
};
|
||||
if (direction === "future") {
|
||||
// first 0, then 1
|
||||
|
|
@ -590,6 +592,17 @@ export default {
|
|||
("0" + monthNum).slice(-2) +
|
||||
"-" +
|
||||
("0" + i).slice(-2);
|
||||
const dayIndex = convertDateStringToDate(dateString).getDay();
|
||||
const isSelectable =
|
||||
this.selectableDatesData.findIndex((date) => date.date === dateString) > -1
|
||||
? true
|
||||
: false;
|
||||
|
||||
const isPricingByDayUpchargeDay = PREMIUM_DAY_INDEXES.includes(dayIndex);
|
||||
let displayPrice = isPricingByDayUpchargeDay
|
||||
? options.baseDayPrice + options.pricingByDayUpcharge
|
||||
: options.baseDayPrice;
|
||||
const priceString = "$" + displayPrice;
|
||||
|
||||
if (offset === 0 && i === this.todayDateNum) {
|
||||
dayClasses += " current-day";
|
||||
|
|
@ -600,7 +613,7 @@ export default {
|
|||
if (offset === 0 && i > this.todayDateNum && calendarViewDirection === "past") {
|
||||
dayClasses += " unavailable-day";
|
||||
}
|
||||
if (convertDateStringToDate(dateString).getDay() === 0) {
|
||||
if (dayIndex === 0) {
|
||||
dayClasses += " sunday";
|
||||
}
|
||||
if (
|
||||
|
|
@ -615,10 +628,9 @@ export default {
|
|||
dateNum: i,
|
||||
dayClasses: dayClasses,
|
||||
inputValue: dateString,
|
||||
isSelectable:
|
||||
this.selectableDatesData.findIndex((date) => date.date === dateString) > -1
|
||||
? true
|
||||
: false,
|
||||
priceString: priceString,
|
||||
isSelectable: isSelectable,
|
||||
isPricingByDayUpchargeDay: isPricingByDayUpchargeDay,
|
||||
};
|
||||
dates.push(dateObject);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import store from "@/store";
|
||||
import { storeActions } from "@/constants/store-actions";
|
||||
import baseMixin from "@/mixins/base-mixin.js";
|
||||
|
||||
export function getDisplayAmountDue(lineItemsObject, includeTax = true) {
|
||||
|
|
@ -58,3 +59,33 @@ export function getSalesTax(lineItemsObject) {
|
|||
// this is amountDue minus subTotal
|
||||
return (((getAmountDue(lineItemsObject) - getSubTotal(lineItemsObject)) * 100) / 100).toFixed(2);
|
||||
}
|
||||
|
||||
export async function getPriceUpchargeByDayPart(pageNameToLog) {
|
||||
// Get the Pricing By Day Part
|
||||
const basePriceByDayPart = await baseMixin.methods.dispatchStoreActionWithLogging(
|
||||
storeActions.GET_PRICING_BY_DAY_UPCHARGE_PART,
|
||||
null,
|
||||
pageNameToLog,
|
||||
false
|
||||
);
|
||||
|
||||
if (
|
||||
basePriceByDayPart?.data === null ||
|
||||
basePriceByDayPart?.data === undefined ||
|
||||
basePriceByDayPart?.data === ""
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get the Pricing By Day Base Part price
|
||||
const pricingResults = await baseMixin.methods.dispatchStoreActionWithLogging(
|
||||
storeActions.PRICE_ORDER_ITEMS_AND_SAVE_SERVER_DATA,
|
||||
{
|
||||
availableLineItems: [basePriceByDayPart?.data],
|
||||
},
|
||||
pageNameToLog,
|
||||
false
|
||||
);
|
||||
|
||||
return pricingResults[0];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import {
|
|||
getAmountDue,
|
||||
getSubTotal,
|
||||
getSalesTax,
|
||||
} from "@/helpers/cart-and-payment-helper.js";
|
||||
} from "@/helpers/pricing-helper.js";
|
||||
|
||||
const lineItems = {
|
||||
glassParts: [],
|
||||
|
|
@ -33,7 +33,7 @@ const lineItems = {
|
|||
promos: [],
|
||||
};
|
||||
|
||||
describe("cart-and-payment-helper", () => {
|
||||
describe("pricing-helper", () => {
|
||||
describe("getDisplayAmountDue", () => {
|
||||
it("should return the correct display amount due", () => {
|
||||
const result = getDisplayAmountDue(lineItems);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,12 @@
|
|||
import { partTypeStrings } from "@/constants/part-type-strings";
|
||||
import { damageLocationsSelected as glassLocations } from "@/constants/damage-locations-selected";
|
||||
import { packageNames } from "@/constants/package-names";
|
||||
import baseMixin from "@/mixins/base-mixin.js";
|
||||
import { getItemsWithoutRecalParts } from "@/helpers/recal-helper";
|
||||
import {
|
||||
getPromosThatMatchLineItemsOnOrder,
|
||||
removeVapsPromosFromPromoArray,
|
||||
} from "@/helpers/promotions-helper";
|
||||
|
||||
export function containsLineItemWithPartType(typeToFind, itemsToSearch) {
|
||||
const partTypeMatches = findLineItemsWithPartType(typeToFind, itemsToSearch);
|
||||
|
|
@ -248,6 +254,90 @@ export function getDiscountedPackageName(discountPackage) {
|
|||
return package_names[discountPackage] || null;
|
||||
}
|
||||
|
||||
// export function getDiscountedPackagePriceString2(packageName, servicePackageDiscount) {
|
||||
// const formattedPriceFloat = parseFloat(
|
||||
// this.getPackagePrice(packageName, {
|
||||
// discountedPrice: true,
|
||||
// servicePackageDiscount,
|
||||
// })
|
||||
// ).toFixed(2);
|
||||
|
||||
// return "$" + formattedPriceFloat;
|
||||
// }
|
||||
|
||||
// export function getPackagePrice(
|
||||
// packageName,
|
||||
// { discountedPrice = false, servicePackageDiscount = false }
|
||||
// ) {
|
||||
// let lineItemsToPrice = [...this.shallowLineItems];
|
||||
|
||||
// if (this.isRecalibrationOnOrder && this.shouldHideRecalibration) {
|
||||
// lineItemsToPrice = getItemsWithoutRecalParts(lineItemsToPrice);
|
||||
// }
|
||||
|
||||
// //remove service package discount part
|
||||
// if (this.isServicePackageDiscountOnOrder) {
|
||||
// lineItemsToPrice = lineItemsToPrice.filter((item) => {
|
||||
// return item.partType != this.servicePackageDiscountParts[0].partType;
|
||||
// });
|
||||
// }
|
||||
|
||||
// if (discountedPrice) {
|
||||
// lineItemsToPrice.push(...removeVapsPromosFromPromoArray(this.activePromos));
|
||||
// }
|
||||
|
||||
// if (servicePackageDiscount) {
|
||||
// lineItemsToPrice.push(...this.servicePackageDiscountParts);
|
||||
// }
|
||||
// let priceFloat = baseMixin.methods.getTierOnePackagePrice(
|
||||
// baseMixin.methods.filterOutFees(lineItemsToPrice)
|
||||
// );
|
||||
|
||||
// priceFloat += this.getVapsPrice(packageName, discountedPrice);
|
||||
|
||||
// // console.log("SPHelper getPackagePrice()... priceFloat: ", priceFloat)
|
||||
// // console.log(" ")
|
||||
|
||||
// return priceFloat;
|
||||
// }
|
||||
|
||||
// export function getVapsPrice(packageName, applyPromoDiscounts = false) {
|
||||
// const vapsItems = this.getVapsLineItemsForSelectedPackage(packageName);
|
||||
// let price = 0;
|
||||
|
||||
// vapsItems.forEach((item) => {
|
||||
// price += baseMixin.methods.getTotalLineItemPrice(item);
|
||||
// });
|
||||
|
||||
// if (applyPromoDiscounts && this.activePromos) {
|
||||
// const relevantPromos = getPromosThatMatchLineItemsOnOrder(this.lineItems.promos, vapsItems);
|
||||
// relevantPromos.forEach((promo) => {
|
||||
// price += baseMixin.methods.getTotalLineItemPrice(promo);
|
||||
// });
|
||||
// }
|
||||
|
||||
// return price;
|
||||
// }
|
||||
|
||||
// export function getVapsLineItemsForSelectedPackage(packageName) {
|
||||
// const packageContentTypes = getPackageContents(
|
||||
// this.glassToReplace,
|
||||
// this.shallowLineItems,
|
||||
// this.isRepair,
|
||||
// packageName
|
||||
// );
|
||||
|
||||
// let vapsLineItemsForSelectedPackage = [];
|
||||
|
||||
// packageContentTypes.forEach((vapType) => {
|
||||
// vapsLineItemsForSelectedPackage.push(
|
||||
// ...findLineItemsWithPartType(vapType, this.shallowLineItems)
|
||||
// );
|
||||
// });
|
||||
|
||||
// return vapsLineItemsForSelectedPackage;
|
||||
// }
|
||||
|
||||
function maxTier(tierA, tierB) {
|
||||
if (tierA === packageNames.TIER_THREE || tierB === packageNames.TIER_THREE) {
|
||||
return packageNames.TIER_THREE;
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ jest.mock("@/helpers/heritage-integration/order-helper.js", () => ({
|
|||
submitWorkOrder: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock("@/helpers/cart-and-payment-helper.js", () => ({
|
||||
jest.mock("@/helpers/pricing-helper.js", () => ({
|
||||
getAmountDue: jest.fn(),
|
||||
}));
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import store from "@/store";
|
|||
import { storeActions } from "@/constants/store-actions";
|
||||
import { paymentMethods } from "@/constants/payment-method-constants";
|
||||
|
||||
jest.mock("@/helpers/cart-and-payment-helper.js", () => ({
|
||||
jest.mock("@/helpers/pricing-helper.js", () => ({
|
||||
getAmountDue: jest.fn(),
|
||||
getDisplayAmountDue: jest.fn(),
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -266,6 +266,7 @@ export default {
|
|||
false
|
||||
);
|
||||
|
||||
// This will remove any servicePackageDiscount item from lineItems.supportingItems
|
||||
baseMixin.methods.dispatchStoreAction(
|
||||
storeActions.SAVE_SUPPORTING_ITEMS,
|
||||
resultMap.supportingItems,
|
||||
|
|
|
|||
|
|
@ -130,6 +130,10 @@ jest.mock("@/mixins/base-mixin.js", () => ({
|
|||
]);
|
||||
}
|
||||
}),
|
||||
filterOutCertainPartTypesOrNumbers: jest.fn(),
|
||||
hasSubmittedOrder: jest.fn(),
|
||||
getTotalPriceOfAllLineItemsAndChildParts: jest.fn(),
|
||||
getTotalLineItemPrice: jest.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
|
|
|
|||
|
|
@ -19,18 +19,20 @@
|
|||
</template>
|
||||
<locationAlerts cmsWidgetPrefix="LocationAlert-" ref="locationAlerts" />
|
||||
<datePickerForPricingByDay
|
||||
v-if="isPricingByDayExperiment"
|
||||
v-show="isPricingByDayExperiment"
|
||||
customComponentId="dateQuestion"
|
||||
selectableDatesSetting="custom"
|
||||
ref="datePicker"
|
||||
ref="datePickerForPricingByDay"
|
||||
v-model="selectedDate"
|
||||
class="text-link-small"
|
||||
:customSelectableDatesCallback="getAvailableDatesMethod"
|
||||
validationRules="date-required"
|
||||
:baseDayPrice="baseDayPrice"
|
||||
:pricingByDayUpcharge="pricingByDayUpcharge"
|
||||
:showPricingByDay="showPricingByDay"
|
||||
@date-clicked="openInshopTimeSlotsModal" />
|
||||
@date-clicked="handleDateClicked" />
|
||||
<datePicker
|
||||
v-else
|
||||
v-show="!isPricingByDayExperiment"
|
||||
customComponentId="dateQuestion"
|
||||
selectableDatesSetting="custom"
|
||||
ref="datePicker"
|
||||
|
|
@ -104,13 +106,17 @@ import {
|
|||
convertDateStringToDate,
|
||||
sumDateString,
|
||||
} from "@/layouts/schedule/helpers/schedule-helper";
|
||||
import { AppointmentTypeStrings, PREMIUM_FEE_PART_TYPE } from "@/constants/schedule-constants";
|
||||
import {
|
||||
AppointmentTypeStrings,
|
||||
PREMIUM_FEE_PART_TYPE,
|
||||
PRICING_BY_DAY_UPCHARGE_FEE_PART_TYPE,
|
||||
} from "@/constants/schedule-constants";
|
||||
import { errorMessages } from "@/constants/error-messages";
|
||||
import { required } from "@/helpers/validation-rules";
|
||||
import store from "@/store";
|
||||
import experimentMixin from "@/mixins/experiment-mixin.js";
|
||||
import { experimentSettings } from "@/constants/experiments";
|
||||
import { getDisplayAmountDue } from "@/helpers/pricing-helper.js";
|
||||
import { getAmountDue, getPriceUpchargeByDayPart } from "@/helpers/pricing-helper.js";
|
||||
import { getItemsWithoutRecalParts } from "@/helpers/recal-helper";
|
||||
import { partNumberStrings } from "@/constants/part-number-strings";
|
||||
import { deepClone } from "@/helpers/object-helper";
|
||||
|
|
@ -228,32 +234,102 @@ export default {
|
|||
mobilePremiumAppointmentFee: null,
|
||||
waitListRequested: null,
|
||||
displayWaitList: null,
|
||||
pricingByDayUpchargeLineItem: null,
|
||||
includePricingByDaySurcharge: null,
|
||||
isPricingByDayExperiment: null,
|
||||
baseDayPrice: null,
|
||||
pricingByDayUpcharge: null,
|
||||
showPricingByDay: null,
|
||||
};
|
||||
},
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
// Call APIs
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
|
||||
// Get data needed for Pricing By Day
|
||||
const lineItems = deepClone(await store.getters.order.lineItems);
|
||||
const isRecalibrationOnOrder = await store.getters.isRecalibrationOnOrder;
|
||||
const shouldHideRecalibration =
|
||||
experimentMixin.methods
|
||||
.getSettingValue(experimentSettings.RECAL_PRICE_REMOVE)
|
||||
?.toLowerCase() === "true" && isRecalibrationOnOrder;
|
||||
const glassParts =
|
||||
isRecalibrationOnOrder && shouldHideRecalibration
|
||||
? getItemsWithoutRecalParts(lineItems.glassParts)
|
||||
: (lineItems.glassParts ?? []);
|
||||
const supportingItemsWithoutFees = baseMixin.methods.filterOutCertainPartTypesOrNumbers(
|
||||
lineItems.supportingItems,
|
||||
{ partNumbersToRemove: [partNumberStrings.RECYCLE_FEE] }
|
||||
);
|
||||
const lineItemsToBePriced = {
|
||||
glassParts: glassParts,
|
||||
supportingItems: supportingItemsWithoutFees,
|
||||
vaps: lineItems.vaps ?? [],
|
||||
promos: lineItems.promos ?? [],
|
||||
};
|
||||
const isPricingByDayExperiment =
|
||||
(await experimentMixin.methods
|
||||
.getSettingValue(experimentSettings.PRICING_BY_DAY)
|
||||
?.toLowerCase()) === "true";
|
||||
const priceString = await getAmountDue(lineItemsToBePriced, false); // pass the IncludeTax param as false
|
||||
const priceStringIntegerRoundedDown = priceString?.split(".")[0]; // same method used as getDisplayPrice() in service-package-radio used on /quote
|
||||
const baseDayPrice = parseInt(priceStringIntegerRoundedDown);
|
||||
const showPricingByDay = !store.getters.payment.isInsurance && isPricingByDayExperiment;
|
||||
const pricingByDayUpchargeLineItem = await getPriceUpchargeByDayPart();
|
||||
const pricingByDayUpcharge = await baseMixin.methods.getTotalLineItemPrice(
|
||||
pricingByDayUpchargeLineItem,
|
||||
false
|
||||
);
|
||||
|
||||
// Check to see if includePricingByDaySurcharge should already be set (based on order lineItems)
|
||||
let includePricingByDaySurcharge = false;
|
||||
if (supportingItemsWithoutFees) {
|
||||
const pricingByDayUpchargeFeeIndex = supportingItemsWithoutFees.findIndex(
|
||||
(item) => item.partType == PRICING_BY_DAY_UPCHARGE_FEE_PART_TYPE
|
||||
);
|
||||
if (pricingByDayUpchargeFeeIndex > -1) {
|
||||
includePricingByDaySurcharge = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Load page with date already selected?
|
||||
let preSelectedDate = await store.getters.order.schedule.date;
|
||||
if (!preSelectedDate || preSelectedDate.startTime === null) {
|
||||
preSelectedDate = null;
|
||||
}
|
||||
|
||||
const datePickerInitialDataPromise = await datePicker.methods.loadInitialData({
|
||||
// setup config options for date-picker
|
||||
selectableDatesSetting: "custom",
|
||||
initialViewRowsToShow: 5,
|
||||
customSelectableDatesCallback: getAvailableDates,
|
||||
preSelectedDate: preSelectedDate,
|
||||
});
|
||||
// TODO - ONCE A DATEPICKER VERSION IS FINALIZED,
|
||||
// MAKE SURE THE ABOVE METHOD loadInitialData POINTS TO THE RIGHT FILE
|
||||
// Set up promises
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
|
||||
|
||||
const alertReasonsPromise = locationAlerts.methods.loadInitialData(
|
||||
store.getters.order.serviceLocation.zipCodeCtu,
|
||||
store.getters.order.serviceLocation.provider?.address?.zipCodeCtu
|
||||
);
|
||||
|
||||
// While Pricing By Day Experiment is ongoing, there are two different datePickers, but only one will load
|
||||
let datePickerInitialDataPromise;
|
||||
if (isPricingByDayExperiment) {
|
||||
datePickerInitialDataPromise = await datePickerForPricingByDay.methods.loadInitialData({
|
||||
// setup config options for date-picker
|
||||
selectableDatesSetting: "custom",
|
||||
initialViewRowsToShow: 5,
|
||||
customSelectableDatesCallback: getAvailableDates,
|
||||
preSelectedDate: preSelectedDate,
|
||||
baseDayPrice: baseDayPrice,
|
||||
pricingByDayUpcharge: pricingByDayUpcharge,
|
||||
});
|
||||
} else {
|
||||
datePickerInitialDataPromise = await datePicker.methods.loadInitialData({
|
||||
// setup config options for date-picker
|
||||
selectableDatesSetting: "custom",
|
||||
initialViewRowsToShow: 5,
|
||||
customSelectableDatesCallback: getAvailableDates,
|
||||
preSelectedDate: preSelectedDate,
|
||||
});
|
||||
}
|
||||
|
||||
const premiumFeePromise = baseMixin.methods.dispatchStoreActionWithLogging(
|
||||
storeActions.GET_MOBILE_PREMIUM_FEE,
|
||||
null,
|
||||
"schedule"
|
||||
);
|
||||
|
||||
const premiumFeeWithPricePromise = premiumFeePromise.then((result) => {
|
||||
if (result.data) {
|
||||
return baseMixin.methods.dispatchStoreActionWithLogging(
|
||||
|
|
@ -269,11 +345,6 @@ export default {
|
|||
}
|
||||
});
|
||||
|
||||
const alertReasonsPromise = locationAlerts.methods.loadInitialData(
|
||||
store.getters.order.serviceLocation.zipCodeCtu,
|
||||
store.getters.order.serviceLocation.provider?.address?.zipCodeCtu
|
||||
);
|
||||
|
||||
// Settle promises and get results
|
||||
const promiseResultMap = [
|
||||
{
|
||||
|
|
@ -300,6 +371,7 @@ export default {
|
|||
next((vm) => {
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
vm.$refs.datePicker.initializeComponent(resultMap.datePickerInitialData);
|
||||
vm.$refs.datePickerForPricingByDay.initializeComponent(resultMap.datePickerInitialData);
|
||||
vm.$refs.locationAlerts.initializeComponent(resultMap.alertReasons);
|
||||
vm.selectableDatesData = resultMap.datePickerInitialData.initialShopTimeSlotsResponse;
|
||||
vm.mobilePremiumAppointmentFee = resultMap.premiumFeeWithPrice
|
||||
|
|
@ -307,6 +379,12 @@ export default {
|
|||
: null;
|
||||
vm.updateFooterButtonText(vm.selectedTimeSlotInfo);
|
||||
vm.setDisplayWaitList();
|
||||
vm.pricingByDayUpchargeLineItem = pricingByDayUpchargeLineItem;
|
||||
vm.includePricingByDaySurcharge = includePricingByDaySurcharge;
|
||||
vm.isPricingByDayExperiment = isPricingByDayExperiment;
|
||||
vm.baseDayPrice = baseDayPrice;
|
||||
vm.pricingByDayUpcharge = pricingByDayUpcharge;
|
||||
vm.showPricingByDay = showPricingByDay;
|
||||
});
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -329,45 +407,6 @@ export default {
|
|||
(selectableDate) => selectableDate.date === this.selectedDate
|
||||
);
|
||||
},
|
||||
isPricingByDayExperiment() {
|
||||
return (
|
||||
experimentMixin.methods
|
||||
.getSettingValue(experimentSettings.PRICING_BY_DAY)
|
||||
?.toLowerCase() === "true"
|
||||
);
|
||||
},
|
||||
showPricingByDay() {
|
||||
return !this.$store.getters.payment.isInsurance && this.isPricingByDayExperiment;
|
||||
},
|
||||
lineItemsToBePriced() {
|
||||
const lineItems = deepClone(store.getters.order.lineItems);
|
||||
|
||||
const glassParts = (this.isRecalibrationOnOrder && this.shouldHideRecalibration) ?
|
||||
getItemsWithoutRecalParts(lineItems.glassParts) :
|
||||
lineItems.glassParts ?? [];
|
||||
|
||||
const supportingItemsWithoutFees = baseMixin.methods.filterOutCertainPartTypesOrNumbers(lineItems.supportingItems, {partNumbersToRemove: [partNumberStrings.RECYCLE_FEE]});
|
||||
|
||||
return {
|
||||
glassParts: glassParts,
|
||||
supportingItems: supportingItemsWithoutFees,
|
||||
vaps: lineItems.vaps ?? [],
|
||||
promos: lineItems.promos ?? [],
|
||||
};
|
||||
},
|
||||
lowestPrice() {
|
||||
return getDisplayAmountDue(this.lineItemsToBePriced, false); // passing false here so IncludeTax is false
|
||||
},
|
||||
isRecalibrationOnOrder() {
|
||||
return store.getters.isRecalibrationOnOrder;
|
||||
},
|
||||
shouldHideRecalibration() {
|
||||
return (
|
||||
experimentMixin.methods
|
||||
.getSettingValue(experimentSettings.RECAL_PRICE_REMOVE)
|
||||
?.toLowerCase() === "true" && this.isRecalibrationOnOrder
|
||||
);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
splitCopyOnCMSPlaceHolder,
|
||||
|
|
@ -414,6 +453,7 @@ export default {
|
|||
this.appointmentType,
|
||||
this.$store.getters.order.serviceLocation.provider.providerNumber
|
||||
);
|
||||
|
||||
// ADD API CALL RESULTS TO EXISTING DATE DATA
|
||||
this.selectableDatesData.days = this.selectableDatesData.days.concat(
|
||||
newShopTimeSlots.days
|
||||
|
|
@ -590,6 +630,28 @@ export default {
|
|||
updateSupportingItems() {
|
||||
const supportingItems = this.getSupportingItems();
|
||||
|
||||
// if we have a pricing by day upcharge, then save/update supporting items with it
|
||||
const pricingByDayUpchargeFeeIndex = supportingItems?.findIndex(
|
||||
(item) => item.partType == PRICING_BY_DAY_UPCHARGE_FEE_PART_TYPE
|
||||
);
|
||||
|
||||
if (this.includePricingByDaySurcharge) {
|
||||
if (pricingByDayUpchargeFeeIndex > -1) {
|
||||
supportingItems[pricingByDayUpchargeFeeIndex].laborAmount =
|
||||
this.pricingByDayUpchargeLineItem.laborAmount;
|
||||
supportingItems[pricingByDayUpchargeFeeIndex].sellingPrice =
|
||||
this.pricingByDayUpchargeLineItem.sellingPrice;
|
||||
supportingItems[pricingByDayUpchargeFeeIndex].kitPrice =
|
||||
this.pricingByDayUpchargeLineItem.kitPrice;
|
||||
} else {
|
||||
supportingItems.push(this.pricingByDayUpchargeLineItem);
|
||||
}
|
||||
} else {
|
||||
if (pricingByDayUpchargeFeeIndex >= 0) {
|
||||
supportingItems.splice(pricingByDayUpchargeFeeIndex, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// if we have a premium fee(early bird), then save/update supporting items
|
||||
if (
|
||||
this.appointmentType === AppointmentTypeStrings.MOBILE &&
|
||||
|
|
@ -599,7 +661,7 @@ export default {
|
|||
(item) => item.partType == PREMIUM_FEE_PART_TYPE
|
||||
);
|
||||
|
||||
if (premiumFeeIndex >= 0) {
|
||||
if (premiumFeeIndex > -1) {
|
||||
supportingItems[premiumFeeIndex].laborAmount =
|
||||
this.mobilePremiumAppointmentFee.laborAmount;
|
||||
supportingItems[premiumFeeIndex].sellingPrice =
|
||||
|
|
@ -609,12 +671,6 @@ export default {
|
|||
} else {
|
||||
supportingItems.push(this.mobilePremiumAppointmentFee);
|
||||
}
|
||||
|
||||
this.dispatchStoreAction(
|
||||
this.storeActions.SAVE_SUPPORTING_ITEMS_SUPPRESSING_STATE_RESETTING,
|
||||
supportingItems,
|
||||
false
|
||||
);
|
||||
} else {
|
||||
if (!supportingItems) {
|
||||
return;
|
||||
|
|
@ -627,17 +683,28 @@ export default {
|
|||
|
||||
if (removePremiumFeeIndex >= 0) {
|
||||
supportingItems.splice(removePremiumFeeIndex, 1);
|
||||
this.dispatchStoreAction(
|
||||
this.storeActions.SAVE_SUPPORTING_ITEMS_SUPPRESSING_STATE_RESETTING,
|
||||
supportingItems,
|
||||
false
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
this.dispatchStoreAction(
|
||||
this.storeActions.SAVE_SUPPORTING_ITEMS_SUPPRESSING_STATE_RESETTING,
|
||||
supportingItems,
|
||||
false
|
||||
);
|
||||
},
|
||||
handleWaitListRequested(value) {
|
||||
this.waitListRequested = value;
|
||||
},
|
||||
handleDateClicked(date) {
|
||||
// do something to mark this as upcharge day or not...
|
||||
if (date.isPricingByDayUpchargeDay) {
|
||||
this.includePricingByDaySurcharge = true;
|
||||
} else {
|
||||
this.includePricingByDaySurcharge = false;
|
||||
}
|
||||
|
||||
this.openInshopTimeSlotsModal();
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
selectedDate(newValue, oldValue) {
|
||||
|
|
|
|||
|
|
@ -144,7 +144,6 @@ describe("baseMixin.js", () => {
|
|||
|
||||
expect(mixIn.methods.dispatchStoreActionWithLogging).toBeCalled();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function getMixInInstance({ isDispatchSuccess = true }) {
|
||||
|
|
|
|||
|
|
@ -1749,6 +1749,18 @@ export const actions = {
|
|||
pageNameToLog: pageNameToLog,
|
||||
});
|
||||
},
|
||||
async getPricingByDayUpchargePart(context, { pageNameToLog }) {
|
||||
return await globalMethods
|
||||
.callHttpClient({
|
||||
method: endpoints.GetPricingByDayUpchargePart.method,
|
||||
endpoint: endpoints.GetPricingByDayUpchargePart.url,
|
||||
logApiCall: true,
|
||||
pageNameToLog: pageNameToLog,
|
||||
})
|
||||
.then((response) => {
|
||||
return response;
|
||||
});
|
||||
},
|
||||
getServicePackageDiscountPart(context, { pageNameToLog }) {
|
||||
const damage = context.getters.damage;
|
||||
const damageType = damage.isRepair ? "Repair" : "Replace";
|
||||
|
|
|
|||
Loading…
Reference in a new issue