Merged in feat/SW-1308-booking-codes-track-b (pull request #1607)

Feat/SW-1308 booking codes track b

* feat: SW-1308 Booking codes track b

* feat: SW-1308 Booking codes Track B implementation

* feat: SW-1308 Optimized after rebase


Approved-by: Arvid Norlin
This commit is contained in:
Hrishikesh Vaipurkar
2025-03-24 11:23:11 +00:00
parent 5643bcc62a
commit b0674d07f5
66 changed files with 1612 additions and 285 deletions

View File

@@ -79,6 +79,23 @@ export function subtract(...nums: (number | string | undefined)[]) {
}, 0)
}
export function getCurrency(roomRate: RoomRate) {
const requestedCurrency = <CurrencyEnum>(
(roomRate.publicRate?.requestedPrice?.currency ??
(roomRate.chequeRate && CurrencyEnum.CC))
)
const localCurrency = <CurrencyEnum>(
(roomRate.publicRate?.localPrice.currency ??
(roomRate.voucherRate && CurrencyEnum.Voucher) ??
(roomRate.chequeRate && CurrencyEnum.CC))
)
return {
requestedCurrency,
localCurrency,
}
}
export function getRoomPrice(roomRate: RoomRate, isMember: boolean) {
if (isMember && roomRate.memberRate) {
return {
@@ -132,6 +149,62 @@ export function getRoomPrice(roomRate: RoomRate, isMember: boolean) {
}
}
if (roomRate.chequeRate) {
return {
perNight: {
requested: roomRate.chequeRate.requestedPrice && {
currency: CurrencyEnum.CC,
price: roomRate.chequeRate.requestedPrice.numberOfBonusCheques,
additionalPrice:
roomRate.chequeRate.requestedPrice.additionalPricePerStay,
additionalPriceCurrency: roomRate.chequeRate.requestedPrice.currency,
},
local: {
currency: CurrencyEnum.CC,
price: roomRate.chequeRate.localPrice.numberOfBonusCheques,
additionalPrice:
roomRate.chequeRate.localPrice.additionalPricePerStay,
additionalPriceCurrency: roomRate.chequeRate.localPrice.currency,
},
},
perStay: {
requested: roomRate.chequeRate.requestedPrice && {
currency: CurrencyEnum.CC,
price: roomRate.chequeRate.requestedPrice.numberOfBonusCheques,
additionalPrice:
roomRate.chequeRate.requestedPrice.additionalPricePerStay,
additionalPriceCurrency: roomRate.chequeRate.requestedPrice.currency,
},
local: {
currency: CurrencyEnum.CC,
price: roomRate.chequeRate.localPrice.numberOfBonusCheques,
additionalPrice:
roomRate.chequeRate.localPrice.additionalPricePerStay,
additionalPriceCurrency: roomRate.chequeRate.localPrice.currency,
},
},
}
}
if (roomRate.voucherRate) {
return {
perNight: {
requested: undefined,
local: {
currency: CurrencyEnum.Voucher,
price: roomRate.voucherRate.numberOfVouchers,
},
},
perStay: {
requested: undefined,
local: {
currency: CurrencyEnum.Voucher,
price: roomRate.voucherRate.numberOfVouchers,
},
},
}
}
if (roomRate.redemptionRate) {
return {
// ToDo Handle perNight as undefined
@@ -210,6 +283,87 @@ export function getTotalPrice(roomRates: RoomRate[], isMember: boolean) {
)
}
export const calculateVoucherPrice = (roomRates: RoomRate[]) => {
return roomRates.reduce<Price>(
(total, room) => {
const rate = room.voucherRate
if (!rate) {
return total
}
return <Price>{
local: {
currency: total.local.currency,
price: total.local.price + rate.numberOfVouchers,
},
requested: undefined,
}
},
{
local: {
currency: CurrencyEnum.Voucher,
price: 0,
},
requested: undefined,
}
)
}
export const calculateChequePrice = (roomRates: RoomRate[]) => {
return roomRates.reduce<Price>(
(total, room) => {
const rate = room.chequeRate
if (!rate) {
return total
}
const price = total.local.price + rate.localPrice.numberOfBonusCheques
const additionalPrice =
rate.localPrice.numberOfBonusCheques &&
(total.local.additionalPrice ?? 0) +
(rate.localPrice.additionalPricePerStay ?? 0)
const additionalPriceCurrency = (rate.localPrice.numberOfBonusCheques &&
rate.localPrice.currency)!
const requestedPrice = rate.requestedPrice?.numberOfBonusCheques
? (total.requested?.price ?? 0) +
rate.requestedPrice?.numberOfBonusCheques
: total.requested?.price
const requestedAdditionalPrice =
rate.requestedPrice?.additionalPricePerStay &&
(total.requested?.additionalPrice ??
0 + rate.requestedPrice?.additionalPricePerStay ??
0)
return <Price>{
local: {
currency: CurrencyEnum.CC,
price,
additionalPrice,
additionalPriceCurrency,
},
requested: rate.requestedPrice
? {
currency: CurrencyEnum.CC,
price: requestedPrice,
additionalPrice: requestedAdditionalPrice,
additionalPriceCurrency: rate.requestedPrice?.currency,
}
: undefined,
}
},
{
local: {
currency: CurrencyEnum.CC,
price: 0,
},
requested: undefined,
}
)
}
export function calcTotalPrice(
rooms: RoomState[],
currency: Price["local"]["currency"],
@@ -277,6 +431,12 @@ export function calcTotalPrice(
breakfastLocalPrice * room.adults * nights,
roomFeaturesTotal?.requestedPrice ?? 0
),
additionalPrice: add(
acc.local.additionalPrice,
roomPrice.perStay.local.additionalPrice,
breakfastLocalPrice * room.adults * nights,
roomFeaturesTotal?.local ?? 0
),
},
}

View File

@@ -11,6 +11,8 @@ import { DetailsContext } from "@/contexts/Details"
import {
add,
calcTotalPrice,
calculateChequePrice,
calculateVoucherPrice,
checkRoomProgress,
extractGuestFromUser,
findNextInvalidStep,
@@ -56,11 +58,22 @@ export function createDetailsStore(
const isRedemption =
new URLSearchParams(searchParams).get("searchtype") === REDEMPTION
const isVoucher = initialState.rooms.some((room) => room.roomRate.voucherRate)
const isCorpChq = initialState.rooms.some((room) => room.roomRate.chequeRate)
let initialTotalPrice: Price
if (isRedemption && initialState.rooms[0].roomRate.redemptionRate) {
initialTotalPrice = PointsPriceSchema.parse(
initialState.rooms[0].roomRate.redemptionRate
)
} else if (isVoucher) {
initialTotalPrice = calculateVoucherPrice(
initialState.rooms.map((r) => r.roomRate)
)
} else if (isCorpChq) {
initialTotalPrice = calculateChequePrice(
initialState.rooms.map((r) => r.roomRate)
)
} else {
initialTotalPrice = getTotalPrice(
initialState.rooms.map((r) => r.roomRate),
@@ -270,7 +283,7 @@ export function createDetailsStore(
const currentTotalPriceRequested = state.totalPrice.requested
let stateTotalRequestedPrice = 0
if (currentTotalPriceRequested) {
stateTotalRequestedPrice = currentTotalPriceRequested.price
stateTotalRequestedPrice = currentTotalPriceRequested.price ?? 0
}
const stateTotalLocalPrice = state.totalPrice.local.price
@@ -305,7 +318,7 @@ export function createDetailsStore(
},
local: {
currency: breakfast.localPrice.currency,
price: stateTotalLocalPrice + breakfastTotalPrice,
price: stateTotalLocalPrice ?? 0 + breakfastTotalPrice,
regularPrice: stateTotalLocalRegularPrice
? stateTotalLocalRegularPrice + breakfastTotalPrice
: undefined,

View File

@@ -28,7 +28,9 @@ function findSelectedRate(
room.products.find(
(product) =>
product.public?.rateCode === rateCode ||
product.member?.rateCode === rateCode
product.member?.rateCode === rateCode ||
product.bonusCheque?.rateCode === rateCode ||
product.voucher?.rateCode === rateCode
)
)
}
@@ -94,7 +96,9 @@ export function createRatesStore({
product.member?.rateCode === room.rateCode ||
product.redemptions?.find(
(redemption) => redemption?.rateCode === room.rateCode
)
) ||
product.bonusCheque?.rateCode === room.rateCode ||
product.voucher?.rateCode === room.rateCode
)
)
const redemptionProduct = selectedRoom?.products[0].redemptions?.find(
@@ -103,18 +107,26 @@ export function createRatesStore({
const product = selectedRoom?.products.find(
(p) =>
p.public?.rateCode === room.rateCode ||
p.member?.rateCode === room.rateCode
p.member?.rateCode === room.rateCode ||
p.bonusCheque?.rateCode === room.rateCode ||
p.voucher?.rateCode === room.rateCode
)
if (selectedRoom && product) {
rateSummary[idx] = {
features: selectedRoom.features,
member: product.member,
public: product.public,
redemption: undefined,
rate: product.rate,
roomType: selectedRoom.roomType,
roomTypeCode: selectedRoom.roomTypeCode,
}
if (product.member || product.public) {
rateSummary[idx].member = product.member
rateSummary[idx].public = product.public
} else if (product.bonusCheque) {
rateSummary[idx].bonusCheque = product.bonusCheque
} else if (product.voucher) {
rateSummary[idx].voucher = product.voucher
}
} else if (selectedRoom && redemptionProduct) {
rateSummary[idx] = {
features: selectedRoom.features,
@@ -300,6 +312,90 @@ export function createRatesStore({
selectedRate.roomTypeCode
)
state.searchParams = new ReadonlyURLSearchParams(searchParams)
window.history.pushState(
{},
"",
`${state.pathname}?${searchParams}`
)
})
)
}
},
selectRateVoucher() {
return function (selectedRate) {
return set(
produce((state: RatesState) => {
const voucherRate = selectedRate.product.voucher
if (!voucherRate) {
return
}
state.rooms[0].selectedRate = selectedRate
state.rateSummary[0] = {
features: selectedRate.features,
voucher: selectedRate.product.voucher,
bonusCheque: undefined,
package: state.rooms[0].selectedPackage,
rate: selectedRate.product.rate,
roomType: selectedRate.roomType,
roomTypeCode: selectedRate.roomTypeCode,
}
const searchParams = new URLSearchParams(state.searchParams)
searchParams.set(`room[0].ratecode`, voucherRate.rateCode)
searchParams.set(`room[0].roomtype`, selectedRate.roomTypeCode)
if (state.rateSummary.length === state.booking.rooms.length) {
state.activeRoom = -1
} else {
state.activeRoom = 1
}
state.searchParams = new ReadonlyURLSearchParams(searchParams)
window.history.pushState(
{},
"",
`${state.pathname}?${searchParams}`
)
})
)
}
},
selectRateCheque(idx) {
return function (selectedRate) {
return set(
produce((state: RatesState) => {
const chequeRate = selectedRate.product.bonusCheque
if (!chequeRate) {
return
}
state.rooms[idx].selectedRate = selectedRate
state.rateSummary[idx] = {
features: selectedRate.features,
package: state.rooms[idx].selectedPackage,
rate: selectedRate.product.rate,
voucher: undefined,
bonusCheque: chequeRate,
roomType: selectedRate.roomType,
roomTypeCode: selectedRate.roomTypeCode,
}
const searchParams = new URLSearchParams(state.searchParams)
searchParams.set(`room[${idx}].ratecode`, chequeRate.rateCode)
searchParams.set(
`room[${idx}].roomtype`,
selectedRate.roomTypeCode
)
if (state.rateSummary.length === state.booking.rooms.length) {
state.activeRoom = -1
} else {
state.activeRoom = idx + 1
}
state.searchParams = new ReadonlyURLSearchParams(searchParams)
window.history.pushState(
{},
@@ -332,7 +428,9 @@ export function createRatesStore({
const product = selectedRate?.products.find(
(prd) =>
prd.public?.rateCode === room.rateCode ||
prd.member?.rateCode === room.rateCode
prd.member?.rateCode === room.rateCode ||
prd.bonusCheque?.rateCode === room.rateCode ||
prd.voucher?.rateCode === room.rateCode
)
const selectedPackage = room.packages?.[0]