import { sumPackages } from "@scandic-hotels/booking-flow/utils/SelectRate" import { CurrencyEnum } from "@scandic-hotels/common/constants/currency" import { RateTypeEnum } from "@scandic-hotels/common/constants/rateType" import type { Rate } from "@scandic-hotels/booking-flow/types/components/selectRate/selectRate" import type { Packages } from "@scandic-hotels/trpc/types/packages" import type { Product, RedemptionProduct, } from "@scandic-hotels/trpc/types/roomAvailability" import type { Price } from "@/types/components/hotelReservation/price" export function calculateTotalPrice( selectedRateSummary: Rate[], isUserLoggedIn: boolean ) { return selectedRateSummary.reduce( (total, room, idx) => { if (!("member" in room.product) || !("public" in room.product)) { return total } const roomNr = idx + 1 const isMainRoom = roomNr === 1 let rate if (isUserLoggedIn && isMainRoom && room.product.member) { rate = room.product.member } else if (room.product.public) { rate = room.product.public } if (!rate) { return total } const packagesPrice = room.packages.reduce( (total, pkg) => { total.local = total.local + pkg.localPrice.totalPrice if (pkg.requestedPrice.totalPrice) { total.requested = total.requested + pkg.requestedPrice.totalPrice } return total }, { local: 0, requested: 0 } ) total.local.currency = rate.localPrice.currency total.local.price = total.local.price + rate.localPrice.pricePerStay + packagesPrice.local if (rate.localPrice.regularPricePerStay) { total.local.regularPrice = (total.local.regularPrice || 0) + rate.localPrice.regularPricePerStay + packagesPrice.local } 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 + packagesPrice.requested if (rate.requestedPrice.regularPricePerStay) { total.requested.regularPrice = (total.requested.regularPrice || 0) + rate.requestedPrice.regularPricePerStay + packagesPrice.requested } } return total }, { local: { currency: CurrencyEnum.Unknown, price: 0, regularPrice: undefined, }, requested: undefined, } ) } export function calculateRedemptionTotalPrice( redemption: RedemptionProduct["redemption"], packages: Packages | null ) { const pkgsSum = sumPackages(packages) 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: CurrencyEnum.POINTS, price: redemption.localPrice.pointsPerStay, }, } } export function calculateVoucherPrice(selectedRateSummary: Rate[]) { return selectedRateSummary.reduce( (total, room) => { if (!("voucher" in room.product)) { return total } const rate = room.product.voucher total.local.price = total.local.price + rate.numberOfVouchers const pkgsSum = sumPackages(room.packages) 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, }, requested: undefined, } ) } export function calculateCorporateChequePrice(selectedRateSummary: Rate[]) { return selectedRateSummary.reduce( (total, room) => { if (!("corporateCheque" in room.product)) { return total } const rate = room.product.corporateCheque const pkgsSum = sumPackages(room.packages) 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 } if (rate.requestedPrice.currency) { total.requested.additionalPriceCurrency = rate.requestedPrice.currency } } return total }, { local: { currency: CurrencyEnum.CC, price: 0, }, requested: undefined, } ) } export function getTotalPrice( mainRoomProduct: Rate | null, rateSummary: Array, isUserLoggedIn: boolean ): Price | null { const summaryArray = rateSummary.filter((rate): rate is Rate => rate !== null) if (summaryArray.some((rate) => "corporateCheque" in rate.product)) { return calculateCorporateChequePrice(summaryArray) } if (!mainRoomProduct) { return calculateTotalPrice(summaryArray, isUserLoggedIn) } const { packages, product } = mainRoomProduct // In case of reward night (redemption) or voucher only single room booking is supported by business rules if ("redemption" in product) { return calculateRedemptionTotalPrice(product.redemption, packages) } if ("voucher" in product) { const voucherPrice = calculateVoucherPrice(summaryArray) return voucherPrice } return calculateTotalPrice(summaryArray, isUserLoggedIn) } export function isBookingCodeRate(product: Product | undefined | null) { if (!product) return false if ( "corporateCheque" in product || "redemption" in product || "voucher" in product ) { return true } else { if (product.public) { return product.public.rateType !== RateTypeEnum.Regular } if (product.member) { return product.member.rateType !== RateTypeEnum.Regular } return false } }