fix: make sure calculations in booking flow are correct

This commit is contained in:
Simon Emanuelsson
2025-04-02 15:49:59 +02:00
committed by Michael Zetterberg
parent 3e0f503314
commit a222ecfc5c
28 changed files with 309 additions and 276 deletions

View File

@@ -430,7 +430,7 @@ export function calcTotalPrice(
? (room.breakfast.localPrice?.price ?? 0)
: 0
const roomFeaturesTotal = room.roomFeatures?.reduce(
const roomFeaturesTotal = (room.roomFeatures || []).reduce(
(total, pkg) => {
if (pkg.requestedPrice.totalPrice) {
total.requestedPrice = add(
@@ -445,45 +445,72 @@ export function calcTotalPrice(
{ local: 0, requestedPrice: 0 }
)
const result: Price = {
requested: roomPrice.perStay.requested
? {
currency: roomPrice.perStay.requested.currency,
price: add(
acc.requested?.price ?? 0,
roomPrice.perStay.requested.price,
breakfastRequestedPrice * room.adults * nights
),
}
: undefined,
local: {
currency: roomPrice.perStay.local.currency,
price: add(
acc.local.price,
roomPrice.perStay.local.price,
breakfastLocalPrice * room.adults * nights,
roomFeaturesTotal?.local ?? 0
),
regularPrice: add(
acc.local.regularPrice,
roomPrice.perStay.local.regularPrice,
breakfastLocalPrice * room.adults * nights,
roomFeaturesTotal?.requestedPrice ?? 0
),
additionalPrice: add(
acc.local.additionalPrice,
roomPrice.perStay.local.additionalPrice,
breakfastLocalPrice * room.adults * nights,
roomFeaturesTotal?.local ?? 0
),
additionalPriceCurrency: roomPrice.perStay.local
.additionalPriceCurrency
? roomPrice.perStay.local.additionalPriceCurrency
: undefined,
},
if (roomPrice.perStay.requested) {
if (!acc.requested) {
acc.requested = {
currency: roomPrice.perStay.requested.currency,
price: 0,
}
}
acc.requested.price = add(
acc.requested.price,
roomPrice.perStay.requested.price,
breakfastRequestedPrice * room.adults * nights
)
// TODO: Come back and verify on CC, PTS, Voucher
if (roomPrice.perStay.requested.additionalPrice) {
acc.requested.additionalPrice = add(
acc.requested.additionalPrice,
roomPrice.perStay.requested.additionalPrice
)
}
if (
roomPrice.perStay.requested.additionalPriceCurrency &&
!acc.requested.additionalPriceCurrency
) {
acc.requested.additionalPriceCurrency =
roomPrice.perStay.requested.additionalPriceCurrency
}
}
return result
const breakfastLocalTotalPrice =
breakfastLocalPrice * room.adults * nights
acc.local.price = add(
acc.local.price,
roomPrice.perStay.local.price,
breakfastLocalTotalPrice,
roomFeaturesTotal.local
)
if (roomPrice.perStay.local.regularPrice) {
acc.local.regularPrice = add(
acc.local.regularPrice,
roomPrice.perStay.local.regularPrice,
breakfastLocalTotalPrice,
roomFeaturesTotal.local
)
}
if (roomPrice.perStay.local.additionalPrice) {
acc.local.additionalPrice = add(
acc.local.additionalPrice,
roomPrice.perStay.local.additionalPrice
)
}
if (
roomPrice.perStay.local.additionalPriceCurrency &&
!acc.local.additionalPriceCurrency
) {
acc.local.additionalPriceCurrency =
roomPrice.perStay.local.additionalPriceCurrency
}
return acc
},
{
requested: undefined,

View File

@@ -168,100 +168,19 @@ export function createDetailsStore(
currentRoom.steps[StepEnum.breakfast].isValid = true
}
const currentTotalPriceRequested = state.totalPrice.requested
let stateTotalRequestedPrice = 0
if (currentTotalPriceRequested) {
stateTotalRequestedPrice =
currentTotalPriceRequested.price ?? 0
}
const stateTotalLocalPrice = state.totalPrice.local.price
const stateTotalLocalRegularPrice =
state.totalPrice.local.regularPrice
const addToTotalPrice =
(currentRoom.room.breakfast === undefined ||
currentRoom.room.breakfast === false) &&
!!breakfast
const subtractFromTotalPrice =
currentRoom.room.breakfast && breakfast === false
currentRoom.room.breakfast = breakfast
const nights = dt(state.booking.toDate).diff(
state.booking.fromDate,
"days"
)
if (addToTotalPrice) {
const breakfastTotalRequestedPrice =
breakfast.requestedPrice.price *
currentRoom.room.adults *
nights
const breakfastTotalPrice =
breakfast.localPrice.price *
currentRoom.room.adults *
nights
state.totalPrice = {
requested: state.totalPrice.requested && {
currency: state.totalPrice.requested.currency,
price:
stateTotalRequestedPrice + breakfastTotalRequestedPrice,
},
local: {
currency: breakfast.localPrice.currency,
price: stateTotalLocalPrice ?? 0 + breakfastTotalPrice,
regularPrice: stateTotalLocalRegularPrice
? stateTotalLocalRegularPrice + breakfastTotalPrice
: undefined,
},
}
}
if (subtractFromTotalPrice) {
let currency = state.totalPrice.local.currency
let currentBreakfastTotalPrice = 0
let currentBreakfastTotalRequestedPrice = 0
if (currentRoom.room.breakfast) {
currentBreakfastTotalPrice =
currentRoom.room.breakfast.localPrice.price *
currentRoom.room.adults *
nights
currentBreakfastTotalRequestedPrice =
currentRoom.room.breakfast.requestedPrice.totalPrice *
currentRoom.room.adults *
nights
currency = currentRoom.room.breakfast.localPrice.currency
}
let requestedPrice =
stateTotalRequestedPrice -
currentBreakfastTotalRequestedPrice
if (requestedPrice < 0) {
requestedPrice = 0
}
let localPrice =
stateTotalLocalPrice - currentBreakfastTotalPrice
if (localPrice < 0) {
localPrice = 0
}
let regularPrice = stateTotalLocalRegularPrice
? stateTotalLocalRegularPrice - currentBreakfastTotalPrice
: undefined
state.totalPrice = {
requested: state.totalPrice.requested && {
currency: state.totalPrice.requested.currency,
price: requestedPrice,
},
local: {
currency,
price: localPrice,
regularPrice,
},
}
}
currentRoom.room.breakfast = breakfast
state.totalPrice = calcTotalPrice(
state.rooms,
currentRoom.room.roomPrice.perStay.local.currency,
isMember,
nights
)
const isAllStepsCompleted = checkRoomProgress(
state.rooms[idx].steps

View File

@@ -5,7 +5,11 @@ import type {
RoomConfiguration,
} from "@/types/trpc/routers/hotel/roomAvailability"
export function findProduct(rateCode: string, product: Product) {
export function findProduct(
rateCode: string,
product: Product,
counterRateCode = ""
) {
if ("corporateCheque" in product) {
return product.corporateCheque.rateCode === rateCode
}
@@ -18,21 +22,35 @@ export function findProduct(rateCode: string, product: Product) {
return product.voucher.rateCode === rateCode
}
if ("public" in product && product.public) {
return product.public.rateCode === rateCode
}
if ("member" in product && product.member) {
return product.member.rateCode === rateCode
const memberExists = "member" in product
const publicExists = "public" in product
const isRegularRate = memberExists && publicExists
if (isRegularRate) {
let isProduct = false
if (product.member) {
isProduct =
product.member.rateCode === rateCode ||
product.member.rateCode === counterRateCode
}
if (product.public) {
isProduct =
product.public.rateCode === rateCode ||
product.public.rateCode === counterRateCode
}
return isProduct
}
return null
}
export function findProductInRoom(rateCode: string, room: RoomConfiguration) {
export function findProductInRoom(
rateCode: string,
room: RoomConfiguration,
counterRateCode = ""
) {
if (room.campaign.length) {
const campaignProduct = room.campaign.find((product) =>
findProduct(rateCode, product)
findProduct(rateCode, product, counterRateCode)
)
if (campaignProduct) {
return campaignProduct
@@ -40,7 +58,7 @@ export function findProductInRoom(rateCode: string, room: RoomConfiguration) {
}
if (room.code.length) {
const codeProduct = room.code.find((product) =>
findProduct(rateCode, product)
findProduct(rateCode, product, counterRateCode)
)
if (codeProduct) {
return codeProduct
@@ -56,7 +74,7 @@ export function findProductInRoom(rateCode: string, room: RoomConfiguration) {
}
if (room.regular.length) {
const regularProduct = room.regular.find((product) =>
findProduct(rateCode, product)
findProduct(rateCode, product, counterRateCode)
)
if (regularProduct) {
return regularProduct
@@ -66,6 +84,7 @@ export function findProductInRoom(rateCode: string, room: RoomConfiguration) {
export function findSelectedRate(
rateCode: string,
counterRateCode: string,
roomTypeCode: string,
rooms: RoomConfiguration[] | AvailabilityError
) {
@@ -76,7 +95,7 @@ export function findSelectedRate(
if (room.roomTypeCode !== roomTypeCode) {
return false
}
return findProductInRoom(rateCode, room)
return findProductInRoom(rateCode, room, counterRateCode)
})
}

View File

@@ -71,6 +71,7 @@ export function createRatesStore({
const roomConfiguration = roomConfigurations?.[idx]
const selectedRoom = findSelectedRate(
room.rateCode,
room.counterRateCode,
room.roomTypeCode,
roomConfiguration
)
@@ -79,7 +80,11 @@ export function createRatesStore({
continue
}
const product = findProductInRoom(room.rateCode, selectedRoom)
const product = findProductInRoom(
room.rateCode,
selectedRoom,
room.counterRateCode
)
if (product) {
rateSummary[idx] = {
features: selectedRoom.features,
@@ -121,13 +126,18 @@ export function createRatesStore({
const selectedRate =
findSelectedRate(
room.rateCode,
room.counterRateCode,
room.roomTypeCode,
roomConfiguration
) ?? null
let product = null
if (selectedRate) {
product = findProductInRoom(room.rateCode, selectedRate)
product = findProductInRoom(
room.rateCode,
selectedRate,
room.counterRateCode
)
}
// Since features are fetched async based on query string, we need to read from query string to apply correct filtering