Files
web/packages/booking-flow/lib/components/EnterDetails/Payment/helpers.ts
Anton Gunnarsson 7faa9933a2 Merged in feat/sw-3642-inject-sas-eb-payment (pull request #3243)
feat(SW-3642): Enable SAS EB payments

* Wip add SAS eb payment

* Add validate payment call

* Check booking status payment method to determine validation

* Clean up getPaymentData

* Fix PartnerPoints casing

* Add comment for validatePartnerPayment error handling

* Remove comment


Approved-by: Joakim Jäderberg
2025-12-11 13:23:12 +00:00

213 lines
5.2 KiB
TypeScript

import { PaymentMethodEnum } from "@scandic-hotels/common/constants/paymentMethod"
import { logger } from "@scandic-hotels/common/logger"
import { env } from "../../../../env/client"
import type { Lang } from "@scandic-hotels/common/constants/language"
import type { CreditCard } from "@scandic-hotels/trpc/types/user"
import type { RedemptionType } from "../../../bookingFlowConfig/bookingFlowConfig"
import type { RoomState } from "../../../stores/enter-details/types"
export function isPaymentMethodEnum(value: string): value is PaymentMethodEnum {
return Object.values<string>(PaymentMethodEnum).includes(value)
}
export function hasFlexibleRate({ room }: RoomState): boolean {
return room.isFlexRate
}
export function hasPrepaidRate({ room }: RoomState): boolean {
return !room.isFlexRate
}
export function calculateTotalRoomPrice(
{ room }: RoomState,
initialRoomPrice?: number
) {
let totalPrice = initialRoomPrice ?? room.roomPrice.perStay.local.price
if (room.breakfast) {
totalPrice += Number(room.breakfast.localPrice.totalPrice) * room.adults
}
if (room.roomFeatures) {
room.roomFeatures.forEach((pkg) => {
totalPrice += Number(pkg.localPrice.price)
})
}
let comparisonPrice = totalPrice
const isMember = room.guest.join || room.guest.membershipNo
if (isMember && "member" in room.roomRate) {
const publicPrice = room.roomRate.public?.localPrice.pricePerStay ?? 0
const memberPrice = room.roomRate.member?.localPrice.pricePerStay ?? 0
const diff = publicPrice - memberPrice
comparisonPrice = totalPrice + diff
}
return {
totalPrice,
comparisonPrice,
}
}
export const paymentInfoStorageName = "payment-info-storage"
type PaymentInfoSessionData = {
paymentMethod: string
isSavedCreditCard: boolean
}
export function readPaymentInfoFromSessionStorage():
| PaymentInfoSessionData
| undefined {
try {
const paymentInfoSessionData = sessionStorage.getItem(
paymentInfoStorageName
)
if (!paymentInfoSessionData) return undefined
return JSON.parse(paymentInfoSessionData)
} catch (error) {
logger.error("Error reading from session storage:", error)
return undefined
}
}
export function writePaymentInfoToSessionStorage(
paymentMethod: string,
isSavedCreditCard: boolean
) {
try {
sessionStorage.setItem(
paymentInfoStorageName,
JSON.stringify({
paymentMethod,
isSavedCreditCard,
})
)
} catch (error) {
logger.error("Error writing to session storage:", error)
}
}
export function clearPaymentInfoSessionStorage() {
sessionStorage.removeItem(paymentInfoStorageName)
}
export function mustGuaranteeBooking({
isUserLoggedIn,
booking,
rooms,
}: {
isUserLoggedIn: boolean
booking: { rooms: { counterRateCode?: string }[] }
rooms: {
room: {
memberMustBeGuaranteed?: boolean
mustBeGuaranteed: boolean
guest: {
join: boolean
membershipNo?: string
}
}
}[]
}) {
return rooms.some(({ room }, idx) => {
if (idx === 0 && isUserLoggedIn && room.memberMustBeGuaranteed) {
return true
}
if (
(room.guest.join || room.guest.membershipNo) &&
booking.rooms[idx].counterRateCode
) {
return room.memberMustBeGuaranteed
}
return room.mustBeGuaranteed
})
}
function createPaymentCallbackUrl(lang: Lang) {
return `${env.NEXT_PUBLIC_NODE_ENV === "development" ? `http://localhost:${env.NEXT_PUBLIC_PORT}` : ""}/${lang}/hotelreservation/payment-callback`
}
export function getPaymentData({
guarantee,
bookingMustBeGuaranteed,
hasOnlyFlexRates,
paymentMethod,
isRedemptionBooking,
savedCreditCard,
lang,
}: {
guarantee: boolean
bookingMustBeGuaranteed: boolean
hasOnlyFlexRates: boolean
paymentMethod: PaymentMethodEnum
isRedemptionBooking: boolean
savedCreditCard?: CreditCard
lang: Lang
}) {
const paymentRedirectUrl = createPaymentCallbackUrl(lang)
const redirectUrls = {
success: `${paymentRedirectUrl}/success`,
error: `${paymentRedirectUrl}/error`,
cancel: `${paymentRedirectUrl}/cancel`,
}
if (
isRedemptionBooking &&
paymentMethod === PaymentMethodEnum.PartnerPoints
) {
return {
paymentMethod: paymentMethod,
...redirectUrls,
}
}
const shouldUsePayment =
guarantee || bookingMustBeGuaranteed || !hasOnlyFlexRates
if (!shouldUsePayment) {
return null
}
return {
paymentMethod: paymentMethod,
...redirectUrls,
card: savedCreditCard
? {
alias: savedCreditCard.alias,
expiryDate: savedCreditCard.expirationDate,
cardType: savedCreditCard.cardType,
}
: undefined,
}
}
export const getPaymentMethod = ({
paymentMethod,
hasFlexRates,
isRedemptionBooking,
redemptionType,
}: {
paymentMethod: string | null | undefined
hasFlexRates: boolean
isRedemptionBooking: boolean
redemptionType: RedemptionType
}): PaymentMethodEnum => {
if (isRedemptionBooking && redemptionType === "partner") {
return PaymentMethodEnum.PartnerPoints
}
if (hasFlexRates) {
return PaymentMethodEnum.card
}
return paymentMethod && isPaymentMethodEnum(paymentMethod)
? paymentMethod
: PaymentMethodEnum.card
}