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:
@@ -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
|
||||
),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user