fix(BOOK-499): fix total price strikethrough rate * fix(BOOK-499): fix total price strikethrough rate Approved-by: Erik Tiekstra
300 lines
8.6 KiB
TypeScript
300 lines
8.6 KiB
TypeScript
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
|
|
|
import { calculateRegularPrice } from "../../utils/calculateRegularPrice"
|
|
import { sumPackages, sumPackagesRequestedPrice } from "../../utils/SelectRate"
|
|
|
|
import type { RedemptionProduct } from "@scandic-hotels/trpc/types/roomAvailability"
|
|
|
|
import type { Price } from "../../types/price"
|
|
import type { AvailabilityWithRoomInfo, Rate, RoomPackage } from "./types"
|
|
|
|
type SelectedRate = {
|
|
roomConfiguration: AvailabilityWithRoomInfo | null
|
|
rate: Rate | undefined
|
|
}
|
|
|
|
export function getTotalPrice({
|
|
selectedRates,
|
|
isMember,
|
|
addAdditionalCost = true,
|
|
pointsCurrency,
|
|
}: {
|
|
selectedRates: Array<SelectedRate | null>
|
|
isMember: boolean
|
|
addAdditionalCost?: boolean
|
|
pointsCurrency?: CurrencyEnum
|
|
}): Price | null {
|
|
const mainRoom = selectedRates[0]
|
|
const mainRoomRate = mainRoom?.rate
|
|
const summaryArray = selectedRates.filter(
|
|
(x): x is OneLevelNonNullable<SelectedRate> => !!x
|
|
)
|
|
|
|
if (
|
|
summaryArray.some((room) => room.rate && "corporateCheque" in room.rate)
|
|
) {
|
|
return calculateCorporateChequePrice(summaryArray, addAdditionalCost)
|
|
}
|
|
|
|
if (!mainRoomRate) {
|
|
return calculateTotalPrice(summaryArray, isMember, addAdditionalCost)
|
|
}
|
|
|
|
// In case of reward night (redemption) or voucher only single room booking is supported by business rules
|
|
if ("redemption" in mainRoomRate) {
|
|
return calculateRedemptionTotalPrice(
|
|
mainRoomRate.redemption,
|
|
mainRoom.roomConfiguration?.selectedPackages.filter(
|
|
(pkg) => "localPrice" in pkg
|
|
) ?? null,
|
|
addAdditionalCost,
|
|
pointsCurrency
|
|
)
|
|
}
|
|
if ("voucher" in mainRoomRate) {
|
|
const voucherPrice = calculateVoucherPrice(summaryArray, addAdditionalCost)
|
|
return voucherPrice
|
|
}
|
|
|
|
return calculateTotalPrice(summaryArray, isMember, addAdditionalCost)
|
|
}
|
|
|
|
function calculateTotalPrice(
|
|
selectedRateSummary: OneLevelNonNullable<SelectedRate>[],
|
|
isMember: boolean,
|
|
addAdditionalCost: boolean
|
|
) {
|
|
const totalPrice = selectedRateSummary.reduce<Price>(
|
|
(total, room, idx) => {
|
|
if (!room.rate || !("member" in room.rate) || !("public" in room.rate)) {
|
|
return total
|
|
}
|
|
|
|
const roomNr = idx + 1
|
|
const isMainRoom = roomNr === 1
|
|
|
|
const useMemberRate = isMainRoom && isMember && room.rate.member
|
|
const rate = useMemberRate ? room.rate.member : room.rate.public
|
|
const publicRate = room.rate.public
|
|
const memberRate = room.rate.member
|
|
|
|
if (!rate) {
|
|
return total
|
|
}
|
|
|
|
const packagesPrice = addAdditionalCost
|
|
? sumPackages(room.roomConfiguration?.selectedPackages)
|
|
: { price: 0, currency: undefined }
|
|
const packagesRequestedPrice = addAdditionalCost
|
|
? sumPackagesRequestedPrice(room.roomConfiguration?.selectedPackages)
|
|
: { price: 0, currency: undefined }
|
|
|
|
total.local.currency = rate.localPrice.currency
|
|
total.local.price =
|
|
total.local.price + rate.localPrice.pricePerStay + packagesPrice.price
|
|
|
|
if (rate.requestedPrice) {
|
|
if (!total.requested) {
|
|
total.requested = {
|
|
currency: rate.requestedPrice.currency,
|
|
price: 0,
|
|
}
|
|
}
|
|
|
|
if (!total.requested.currency) {
|
|
total.requested.currency = rate.requestedPrice.currency
|
|
}
|
|
|
|
total.requested.price =
|
|
total.requested.price +
|
|
rate.requestedPrice.pricePerStay +
|
|
packagesRequestedPrice.price
|
|
|
|
if (rate.requestedPrice.regularPricePerStay) {
|
|
total.requested.regularPrice =
|
|
(total.requested.regularPrice || 0) +
|
|
rate.requestedPrice.regularPricePerStay +
|
|
packagesRequestedPrice.price
|
|
}
|
|
}
|
|
return calculateRegularPrice({
|
|
total,
|
|
useMemberRate: !!useMemberRate,
|
|
regularMemberPrice: memberRate
|
|
? {
|
|
pricePerStay: memberRate.localPrice.pricePerStay,
|
|
regularPricePerStay: memberRate.localPrice.regularPricePerStay,
|
|
}
|
|
: undefined,
|
|
regularPublicPrice: publicRate
|
|
? {
|
|
pricePerStay: publicRate.localPrice.pricePerStay,
|
|
regularPricePerStay: publicRate.localPrice.regularPricePerStay,
|
|
}
|
|
: undefined,
|
|
|
|
additionalCost: packagesPrice.price,
|
|
})
|
|
},
|
|
{
|
|
local: {
|
|
currency: CurrencyEnum.Unknown,
|
|
price: 0,
|
|
regularPrice: undefined,
|
|
},
|
|
requested: undefined,
|
|
}
|
|
)
|
|
|
|
if (
|
|
totalPrice.local.regularPrice &&
|
|
totalPrice.local.price >= totalPrice.local.regularPrice
|
|
) {
|
|
totalPrice.local.regularPrice = undefined
|
|
}
|
|
|
|
return totalPrice
|
|
}
|
|
|
|
function calculateRedemptionTotalPrice(
|
|
redemption: RedemptionProduct["redemption"],
|
|
packages: RoomPackage[] | null,
|
|
addAdditonalCost: boolean,
|
|
pointsCurrency?: CurrencyEnum
|
|
) {
|
|
const pkgsSum = addAdditonalCost
|
|
? sumPackages(packages)
|
|
: { price: 0, currency: undefined }
|
|
let additionalPrice
|
|
if (redemption.localPrice.additionalPricePerStay) {
|
|
additionalPrice =
|
|
redemption.localPrice.additionalPricePerStay + pkgsSum.price
|
|
} else if (pkgsSum.price) {
|
|
additionalPrice = pkgsSum.price
|
|
}
|
|
|
|
let additionalPriceCurrency
|
|
if (redemption.localPrice.currency) {
|
|
additionalPriceCurrency = redemption.localPrice.currency
|
|
} else if (pkgsSum.currency) {
|
|
additionalPriceCurrency = pkgsSum.currency
|
|
}
|
|
return {
|
|
local: {
|
|
additionalPrice,
|
|
additionalPriceCurrency,
|
|
currency: pointsCurrency ?? CurrencyEnum.POINTS,
|
|
price: redemption.localPrice.pointsPerStay,
|
|
},
|
|
}
|
|
}
|
|
|
|
function calculateVoucherPrice(
|
|
selectedRateSummary: OneLevelNonNullable<SelectedRate>[],
|
|
addAdditionalPrice?: boolean
|
|
) {
|
|
return selectedRateSummary.reduce<Price>(
|
|
(total, room) => {
|
|
if (!("voucher" in room.rate)) {
|
|
return total
|
|
}
|
|
const rate = room.rate.voucher
|
|
|
|
total.local.price = total.local.price + rate.numberOfVouchers
|
|
|
|
const pkgsSum = addAdditionalPrice
|
|
? sumPackages(room.roomConfiguration?.selectedPackages)
|
|
: { price: 0, currency: undefined }
|
|
if (pkgsSum.price && pkgsSum.currency) {
|
|
total.local.additionalPrice =
|
|
(total.local.additionalPrice || 0) + pkgsSum.price
|
|
total.local.additionalPriceCurrency = pkgsSum.currency
|
|
}
|
|
|
|
return total
|
|
},
|
|
{
|
|
local: {
|
|
currency: CurrencyEnum.Voucher,
|
|
price: 0,
|
|
regularPrice: undefined,
|
|
},
|
|
requested: undefined,
|
|
}
|
|
)
|
|
}
|
|
|
|
type OneLevelNonNullable<T> = {
|
|
[K in keyof T]-?: NonNullable<T[K]>
|
|
}
|
|
|
|
function calculateCorporateChequePrice(
|
|
selectedRates: OneLevelNonNullable<SelectedRate>[],
|
|
addAdditionalCost?: boolean
|
|
) {
|
|
return selectedRates.reduce<Price>(
|
|
(total, room) => {
|
|
if (!(room.rate && "corporateCheque" in room.rate)) {
|
|
return total
|
|
}
|
|
|
|
const rate = room.rate.corporateCheque
|
|
const pkgsSum = addAdditionalCost
|
|
? sumPackages(room.roomConfiguration?.selectedPackages)
|
|
: { price: 0, currency: undefined }
|
|
const packagesRequestedPrice = addAdditionalCost
|
|
? sumPackagesRequestedPrice(room.roomConfiguration?.selectedPackages)
|
|
: { price: 0, currency: undefined }
|
|
|
|
total.local.price = total.local.price + rate.localPrice.numberOfCheques
|
|
if (rate.localPrice.additionalPricePerStay) {
|
|
total.local.additionalPrice =
|
|
(total.local.additionalPrice || 0) +
|
|
rate.localPrice.additionalPricePerStay +
|
|
pkgsSum.price
|
|
} else if (pkgsSum.price) {
|
|
total.local.additionalPrice =
|
|
(total.local.additionalPrice || 0) + pkgsSum.price
|
|
}
|
|
if (rate.localPrice.currency) {
|
|
total.local.additionalPriceCurrency = rate.localPrice.currency
|
|
}
|
|
|
|
if (rate.requestedPrice) {
|
|
if (!total.requested) {
|
|
total.requested = {
|
|
currency: CurrencyEnum.CC,
|
|
price: 0,
|
|
}
|
|
}
|
|
|
|
total.requested.price =
|
|
total.requested.price + rate.requestedPrice.numberOfCheques
|
|
|
|
if (rate.requestedPrice.additionalPricePerStay) {
|
|
total.requested.additionalPrice =
|
|
(total.requested.additionalPrice || 0) +
|
|
rate.requestedPrice.additionalPricePerStay +
|
|
packagesRequestedPrice.price
|
|
} else if (packagesRequestedPrice.price) {
|
|
total.local.additionalPrice =
|
|
(total.local.additionalPrice || 0) + packagesRequestedPrice.price
|
|
}
|
|
|
|
if (rate.requestedPrice.currency) {
|
|
total.requested.additionalPriceCurrency = rate.requestedPrice.currency
|
|
}
|
|
}
|
|
|
|
return total
|
|
},
|
|
{
|
|
local: {
|
|
currency: CurrencyEnum.CC,
|
|
price: 0,
|
|
},
|
|
requested: undefined,
|
|
}
|
|
)
|
|
}
|