fix: add bookingCode to product

This commit is contained in:
Simon Emanuelsson
2025-03-31 13:52:53 +02:00
parent b48053b8b4
commit 9d584887ad
4 changed files with 159 additions and 227 deletions

View File

@@ -49,7 +49,6 @@ import type {
PriceChangeData, PriceChangeData,
} from "@/types/components/hotelReservation/enterDetails/payment" } from "@/types/components/hotelReservation/enterDetails/payment"
import { RoomPackageCodeEnum } from "@/types/components/hotelReservation/selectRate/roomFilter" import { RoomPackageCodeEnum } from "@/types/components/hotelReservation/selectRate/roomFilter"
import { RateTypeEnum } from "@/types/enums/rateType"
const maxRetries = 15 const maxRetries = 15
const retryInterval = 2000 const retryInterval = 2000
@@ -287,103 +286,72 @@ export default function PaymentClient({
hotelId, hotelId,
language: lang, language: lang,
payment, payment,
rooms: rooms.map(({ room }, idx) => { rooms: rooms.map(({ room }, idx) => ({
let bookingCode = undefined adults: room.adults,
if (room.roomRate.rateDefinition) { bookingCode: room.roomRate.bookingCode,
switch (room.roomRate.rateDefinition.rateType) { childrenAges: room.childrenInRoom?.map((child) => ({
case RateTypeEnum.Regular: age: child.age,
// do nothing, regular is not bookable with bookingCode bedType: bedTypeMap[parseInt(child.bed.toString())],
break })),
case RateTypeEnum.PublicPromotion: guest: {
// PublicPromotion WITH CODE becomeMember: room.guest.join,
// only way to figure it out since API use the same countryCode: room.guest.countryCode,
// label for both yet only one should have bookingCoke email: room.guest.email,
if ( firstName: room.guest.firstName,
booking.bookingCode === room.roomRate.rateDefinition.rateCode lastName: room.guest.lastName,
) { membershipNumber: room.guest.membershipNo,
bookingCode = booking.bookingCode phoneNumber: room.guest.phoneNumber,
} // Only allowed for room one
break ...(idx === 0 && {
case RateTypeEnum.Arb: dateOfBirth:
case RateTypeEnum.Company: "dateOfBirth" in room.guest && room.guest.dateOfBirth
case RateTypeEnum.CorporateCheque: ? room.guest.dateOfBirth
case RateTypeEnum.Promotion:
case RateTypeEnum.Redemption:
case RateTypeEnum.TravelAgent:
case RateTypeEnum.Voucher:
default:
bookingCode = booking.bookingCode
break
}
}
return {
adults: room.adults,
bookingCode,
childrenAges: room.childrenInRoom?.map((child) => ({
age: child.age,
bedType: bedTypeMap[parseInt(child.bed.toString())],
})),
guest: {
becomeMember: room.guest.join,
countryCode: room.guest.countryCode,
email: room.guest.email,
firstName: room.guest.firstName,
lastName: room.guest.lastName,
membershipNumber: room.guest.membershipNo,
phoneNumber: room.guest.phoneNumber,
// Only allowed for room one
...(idx === 0 && {
dateOfBirth:
"dateOfBirth" in room.guest && room.guest.dateOfBirth
? room.guest.dateOfBirth
: undefined,
postalCode:
"zipCode" in room.guest && room.guest.zipCode
? room.guest.zipCode
: undefined,
}),
},
packages: {
accessibility:
room.roomFeatures?.some(
(feature) =>
feature.code === RoomPackageCodeEnum.ACCESSIBILITY_ROOM
) ?? false,
allergyFriendly:
room.roomFeatures?.some(
(feature) => feature.code === RoomPackageCodeEnum.ALLERGY_ROOM
) ?? false,
breakfast: !!(room.breakfast && room.breakfast.code),
petFriendly:
room.roomFeatures?.some(
(feature) => feature.code === RoomPackageCodeEnum.PET_ROOM
) ?? false,
},
rateCode:
(room.guest.join || room.guest.membershipNo) &&
booking.rooms[idx].counterRateCode
? booking.rooms[idx].counterRateCode
: booking.rooms[idx].rateCode,
roomPrice: {
memberPrice:
"member" in room.roomRate
? room.roomRate.member?.localPrice.pricePerStay
: undefined, : undefined,
publicPrice: postalCode:
"public" in room.roomRate "zipCode" in room.guest && room.guest.zipCode
? room.roomRate.public?.localPrice.pricePerStay ? room.guest.zipCode
: undefined, : undefined,
}, }),
roomTypeCode: room.bedType!.roomTypeCode, // A selection has been made in order to get to this step. },
smsConfirmationRequested: data.smsConfirmation, packages: {
specialRequest: { accessibility:
comment: room.specialRequest.comment room.roomFeatures?.some(
? room.specialRequest.comment (feature) =>
feature.code === RoomPackageCodeEnum.ACCESSIBILITY_ROOM
) ?? false,
allergyFriendly:
room.roomFeatures?.some(
(feature) => feature.code === RoomPackageCodeEnum.ALLERGY_ROOM
) ?? false,
breakfast: !!(room.breakfast && room.breakfast.code),
petFriendly:
room.roomFeatures?.some(
(feature) => feature.code === RoomPackageCodeEnum.PET_ROOM
) ?? false,
},
rateCode:
(room.guest.join || room.guest.membershipNo) &&
booking.rooms[idx].counterRateCode
? booking.rooms[idx].counterRateCode
: booking.rooms[idx].rateCode,
roomPrice: {
memberPrice:
"member" in room.roomRate
? room.roomRate.member?.localPrice.pricePerStay
: undefined, : undefined,
}, publicPrice:
} "public" in room.roomRate
}), ? room.roomRate.public?.localPrice.pricePerStay
: undefined,
},
roomTypeCode: room.bedType!.roomTypeCode, // A selection has been made in order to get to this step.
smsConfirmationRequested: data.smsConfirmation,
specialRequest: {
comment: room.specialRequest.comment
? room.specialRequest.comment
: undefined,
},
})),
}) })
}, },
[ [

View File

@@ -267,6 +267,11 @@ export const roomsAvailabilitySchema = z
return null return null
} }
if (attributes.bookingCode) {
product.bookingCode = attributes.bookingCode
} else {
product.bookingCode = undefined
}
product.breakfastIncluded = rateDefinition.breakfastIncluded product.breakfastIncluded = rateDefinition.breakfastIncluded
product.rate = rate product.rate = rate
product.rateDefinition = rateDefinition product.rateDefinition = rateDefinition

View File

@@ -8,63 +8,51 @@ import {
voucherProduct, voucherProduct,
} from "./product" } from "./product"
import { import { AvailabilityEnum } from "@/types/components/hotelReservation/selectHotel/selectHotel"
AvailabilityEnum, import { RoomPackageCodeEnum } from "@/types/components/hotelReservation/selectRate/roomFilter"
} from "@/types/components/hotelReservation/selectHotel/selectHotel"
import {
RoomPackageCodeEnum,
} from "@/types/components/hotelReservation/selectRate/roomFilter"
export const roomConfigurationSchema = z export const roomConfigurationSchema = z.object({
.object({ breakfastIncludedInAllRatesMember: z.boolean().default(false),
breakfastIncludedInAllRatesMember: z.boolean().default(false), breakfastIncludedInAllRates: z.boolean().default(false),
breakfastIncludedInAllRates: z.boolean().default(false), features: z
features: z .array(
.array( z.object({
z.object({ inventory: z.number(),
inventory: z.number(), code: z.enum([
code: z.enum([ RoomPackageCodeEnum.PET_ROOM,
RoomPackageCodeEnum.PET_ROOM, RoomPackageCodeEnum.ALLERGY_ROOM,
RoomPackageCodeEnum.ALLERGY_ROOM, RoomPackageCodeEnum.ACCESSIBILITY_ROOM,
RoomPackageCodeEnum.ACCESSIBILITY_ROOM, ]),
]), })
}) )
) .default([]),
.default([]), products: z.array(productSchema).default([]),
products: z.array(productSchema).default([]), roomsLeft: z.number(),
roomsLeft: z.number(), roomType: z.string(),
roomType: z.string(), roomTypeCode: z.string(),
roomTypeCode: z.string(), status: z
status: z .nativeEnum(AvailabilityEnum)
.nativeEnum(AvailabilityEnum) .nullish()
.nullish() .default(AvailabilityEnum.NotAvailable),
.default(AvailabilityEnum.NotAvailable),
// Red // Red
campaign: z campaign: z
.array(priceProduct) .array(priceProduct)
.nullish() .optional()
.transform(val => val ? val.filter(Boolean) : []), .transform((val) => (val ? val.filter(Boolean) : [])),
// Blue // Blue
code: z code: z
.array( .array(z.union([corporateChequeProduct, priceProduct, voucherProduct]))
z .optional()
.union([ .transform((val) => (val ? val.filter(Boolean) : [])),
corporateChequeProduct, // Beige
priceProduct, regular: z
voucherProduct, .array(priceProduct)
]) .optional()
) .transform((val) => (val ? val.filter(Boolean) : [])),
.nullish() // Burgundy
.transform(val => val ? val.filter(Boolean) : []), redemptions: z
// Beige .array(redemptionProduct)
regular: z .optional()
.array(priceProduct) .transform((val) => (val ? val.filter(Boolean) : [])),
.nullish() })
.transform(val => val ? val.filter(Boolean) : []),
// Burgundy
redemptions: z
.array(redemptionProduct)
.nullish()
.transform(val => val ? val.filter(Boolean) : []),
})

View File

@@ -9,6 +9,11 @@ import {
import { rateDefinitionSchema } from "./rateDefinition" import { rateDefinitionSchema } from "./rateDefinition"
const baseProductSchema = z.object({ const baseProductSchema = z.object({
// transform empty string to undefined
bookingCode: z
.string()
.optional()
.transform((val) => val),
// Is breakfast included on product // Is breakfast included on product
breakfastIncluded: z.boolean().default(false), breakfastIncluded: z.boolean().default(false),
// Used to set the rate that we use to chose titles etc. // Used to set the rate that we use to chose titles etc.
@@ -35,13 +40,14 @@ const baseProductSchema = z.object({
function mapBaseProduct(baseProduct: typeof baseProductSchema._type) { function mapBaseProduct(baseProduct: typeof baseProductSchema._type) {
return { return {
bookingCode: baseProduct.bookingCode,
breakfastIncluded: baseProduct.breakfastIncluded, breakfastIncluded: baseProduct.breakfastIncluded,
rate: baseProduct.rate, rate: baseProduct.rate,
rateDefinition: baseProduct.rateDefinition, rateDefinition: baseProduct.rateDefinition,
} }
} }
const rawCorporateChequeProduct = z export const corporateChequeProduct = z
.object({ .object({
productType: z productType: z
.object({ .object({
@@ -52,21 +58,12 @@ const rawCorporateChequeProduct = z
})), })),
}) })
.merge(baseProductSchema) .merge(baseProductSchema)
.transform((data) => ({
function transformCorporateCheque(
data: z.output<typeof rawCorporateChequeProduct>
) {
return {
...data.productType, ...data.productType,
...mapBaseProduct(data), ...mapBaseProduct(data),
} }))
}
export const corporateChequeProduct = rawCorporateChequeProduct.transform( export const priceProduct = z
transformCorporateCheque
)
const rawPriceProduct = z
.object({ .object({
productType: z.object({ productType: z.object({
member: productTypePriceSchema.nullish().default(null), member: productTypePriceSchema.nullish().default(null),
@@ -74,63 +71,58 @@ const rawPriceProduct = z
}), }),
}) })
.merge(baseProductSchema) .merge(baseProductSchema)
.transform((data) => ({
function transformPriceProduct(data: z.output<typeof rawPriceProduct>) {
return {
...data.productType, ...data.productType,
...mapBaseProduct(data), ...mapBaseProduct(data),
} }))
}
export const priceProduct = rawPriceProduct.transform(transformPriceProduct)
export const redemptionProduct = z export const redemptionProduct = z
.object({ .object({
redemption: productTypePointsSchema, redemption: productTypePointsSchema,
}) })
.merge(baseProductSchema) .merge(baseProductSchema)
.transform((data) => ({
redemption: data.redemption,
...mapBaseProduct(data),
}))
const rawRedemptionsProduct = z.object({ export const redemptionsProduct = z
type: z.literal("REDEMPTION").optional().default("REDEMPTION"), .object({
productType: z.object({ productType: z.object({
redemptions: z redemptions: z
.array(productTypePointsSchema.merge(baseProductSchema)) .array(productTypePointsSchema.merge(baseProductSchema))
.transform((data) => .transform((data) =>
data.map( data.map(
({ breakfastIncluded, rate, rateDefinition, ...redemption }) => ({ ({
breakfastIncluded, bookingCode,
rate, breakfastIncluded,
rateDefinition, rate,
redemption, rateDefinition,
}) ...redemption
) }) => ({
), bookingCode,
}), breakfastIncluded,
}) rate,
rateDefinition,
export const redemptionsProduct = rawRedemptionsProduct.transform( redemption,
(data) => data.productType.redemptions })
) )
),
const rawVoucherProduct = z }),
})
.transform((data) => data.productType.redemptions)
export const voucherProduct = z
.object({ .object({
type: z.literal("VOUCHER").optional().default("VOUCHER"),
productType: z.object({ productType: z.object({
voucher: productTypeVoucherSchema, voucher: productTypeVoucherSchema,
}), }),
}) })
.merge(baseProductSchema) .merge(baseProductSchema)
.transform((data) => ({
function transformVoucherProduct(data: z.output<typeof rawVoucherProduct>) {
return {
...data.productType, ...data.productType,
...mapBaseProduct(data), ...mapBaseProduct(data),
} }))
}
export const voucherProduct = rawVoucherProduct.transform(
transformVoucherProduct
)
export const productSchema = z.union([ export const productSchema = z.union([
corporateChequeProduct, corporateChequeProduct,
@@ -138,24 +130,3 @@ export const productSchema = z.union([
voucherProduct, voucherProduct,
priceProduct, priceProduct,
]) ])
// export const productSchema = z.discriminatedUnion(
// "type",
// [
// rawCorporateChequeProduct,
// rawPriceProduct,
// rawRedemptionsProduct,
// rawVoucherProduct,
// ]
// )
// .transform(data => {
// switch (data.type) {
// case "CORPORATECHEQUE":
// return transformCorporateCheque(data)
// case "PRICEPRODUCT":
// return transformPriceProduct(data)
// case "REDEMPTION":
// return data.productType.redemptions
// case "VOUCHER":
// return transformVoucherProduct(data)
// }
// })