Untitled
unknown
plain_text
a year ago
41 kB
12
Indexable
"use node"
import { PMSPlatformEnum, AvailabilityCalendar } from "../../types"
import { fetchCalendarForListingIdInRange as fetchHostawayCalendarForListingIdInRange } from "../integrations/hostaway"
import { fetchCalendarForListingIdInRange as fetchGuestyCalendarForListingIdInRange } from "../integrations/guesty"
import { getAvailabilityForPropertyWithDates as fetchCalryCalendarForListingIdInRange } from "../integrations/calry"
import { action, internalAction } from "../../_generated/server"
import { Doc, Id } from "../../_generated/dataModel"
import _, { get } from "lodash"
import { logSlackError } from "./slackLogger"
import { getIntegrationFunctions } from "../integrationFlow"
import { UpsellType } from "../../upsells/types"
import { internal } from "../../_generated/api"
import { fetchCalendarWithAvailability } from "../pmsData"
import { api } from "../../_generated/api"
import { fetchAvailabilityForPropertyIdInRange as fetchLodgifyCalendarForListingIdInRange } from "../integrations/lodgify"
import { decrypt } from "./crypto"
import moment from "moment"
export const getAvailabilityResponseWithStartEnd = async ({
listing,
reservation,
pmsIntegration,
startDate,
endDate,
}: {
listing: Doc<"listings">
pmsIntegration?: Doc<"integrations"> | null
reservation: Doc<"reservations">
startDate: string
endDate: string
}): Promise<{
response: string
possible: boolean
calendar: AvailabilityCalendar
}> => {
const pmsPlatform = listing?.pmsPlatform
if (!pmsIntegration) {
throw new Error(
`No integration found for ${pmsPlatform}. Please connect to ${pmsPlatform} first.`
)
}
let passedStartDate = startDate
let passedEndDate = endDate
// if there isn't a start date,
// if there is an end date, set start date to 10 days before end date
// else set start date to 1 month before today
if (!startDate)
passedStartDate = endDate
? changeDateWithDayDelta(endDate, -10)
: getDateWithMonthDelta(-1)
// if there isn't an end date, set end date to 10 days after start date
if (!endDate)
passedEndDate = changeDateWithDayDelta(startDate, 10)
let calendar: any[] = []
// if call is gonna be invalid, swap dates
if (new Date(passedStartDate) > new Date(passedEndDate)) {
const temp = passedStartDate
passedStartDate = passedEndDate
passedEndDate = temp
}
// check if passed dates are YYYY-MM-DD
if (!passedStartDate.match(/^\d{4}-\d{2}-\d{2}$/)) {
passedStartDate = moment(passedStartDate).format("YYYY-MM-DD")
}
if (!passedEndDate.match(/^\d{4}-\d{2}-\d{2}$/)) {
passedEndDate = moment(passedEndDate).format("YYYY-MM-DD")
}
try {
calendar = await fetchCalendarWithAvailability(
pmsIntegration,
listing.listingId as number,
passedStartDate,
passedEndDate
)
// const maxDate = new Date(Math.max(...dates.map(date => date.getTime())));
if (startDate && endDate) {
return checkAvailabilityWithStartEnd(
reservation,
startDate,
endDate,
calendar,
reservation.status?.includes("inquiry") || true
)
}
if (startDate && !endDate) {
const reservationStart = new Date(reservation.arrivalDate)
if (
new Date(startDate).getTime() ===
reservationStart.getTime()
) {
return {
response: `The requested date of ${startDate} is available.`,
possible: true,
calendar,
}
}
return checkAvailabilityWithStartEnd(
reservation,
startDate,
reservation.arrivalDate,
calendar,
reservation.status?.includes("inquiry") || true
)
}
if (!startDate && endDate) {
const reservationEnd = new Date(reservation.departureDate)
if (
new Date(endDate).getTime() ===
reservationEnd.getTime()
) {
return {
response: `The requested date of ${endDate} is available.`,
possible: true,
calendar,
}
}
return checkAvailabilityWithStartEnd(
reservation,
reservation.departureDate,
endDate,
calendar,
reservation.status?.includes("inquiry") || true
)
}
return {
response: "",
possible: false,
calendar,
}
} catch (e: any) {
console.log(e)
await logSlackError(
e.message,
"getAvailabilityResponseWithStartEnd"
)
return {
response: "",
possible: false,
calendar,
}
}
}
export const getAvailabilityResponseWithSingleDate = async ({
listing,
pmsIntegration,
date,
request,
}: {
listing: Doc<"listings">
pmsIntegration?: Doc<"integrations"> | null
date: string
request: string
}): Promise<{
response: string
possible: boolean
calendar: AvailabilityCalendar
}> => {
const pmsPlatform = listing?.pmsPlatform
if (!pmsIntegration) {
throw new Error(
`No integration found for ${pmsPlatform}. Please connect to ${pmsPlatform} first.`
)
}
let calendar: any[] = []
let formattedStartDate = getCurrentDateString()
formattedStartDate = changeDateWithDayDelta(
formattedStartDate,
-2
)
let formattedEndDate = changeDateWithDayDelta(date, 1)
if (!formattedStartDate.match(/^\d{4}-\d{2}-\d{2}$/)) {
formattedStartDate = moment(formattedStartDate).format(
"YYYY-MM-DD"
)
}
if (!formattedEndDate.match(/^\d{4}-\d{2}-\d{2}$/)) {
formattedEndDate =
moment(formattedEndDate).format("YYYY-MM-DD")
}
try {
calendar = await fetchCalendarWithAvailability(
pmsIntegration,
listing.listingId as number,
formattedStartDate,
formattedEndDate
)
// Check dates
if (!date) {
return {
response: `No requested date.`,
possible: false,
calendar,
}
}
return checkSingleDateAvailability(date, calendar, request)
} catch (e: any) {
console.log(e)
await logSlackError(
e.message,
"getAvailabilityResponseWithStartEnd"
)
return {
response: "",
possible: false,
calendar,
}
}
}
export const changeDateWithMonthDelta = (
dateString: string,
delta: number
): string => {
const date = new Date(dateString)
date.setMonth(date.getMonth() + delta)
const formatted =
date.getFullYear() +
"-" +
(date.getMonth() + 1) +
"-" +
date.getDate()
return formatDateString(formatted)
}
export const changeDateWithDayDelta = (
dateString: string,
delta: number
): string => {
const date = new Date(dateString)
date.setDate(date.getDate() + delta)
const formatted =
date.getFullYear() +
"-" +
(date.getMonth() + 1) +
"-" +
date.getDate()
return formatDateString(formatted)
}
export const getDateWithMonthDelta = (delta: number): string => {
const date = new Date()
date.setMonth(date.getMonth() + delta)
const formatted =
date.getFullYear() +
"-" +
(date.getMonth() + 1) +
"-" +
date.getDate()
return formatDateString(formatted)
}
export const getCurrentDateString = () => {
const today = new Date()
const date =
today.getFullYear() +
"-" +
(today.getMonth() + 1) +
"-" +
today.getDate()
return formatDateString(date)
}
function formatDateString(dateString: string): string {
let parts = dateString.split("-")
// Ensure the year, month, and day parts exist
if (parts.length !== 3) {
throw new Error("Invalid date format")
}
let [year, month, day] = parts
// Pad month and day with leading zero if necessary
month = month.length === 1 ? `0${month}` : month
day = day.length === 1 ? `0${day}` : day
return `${year}-${month}-${day}`
}
export type UpsellItem = {
reservationId: string | number
newStartDate: string
newEndDate: string
priceWithoutDiscount: number
currency: string
}
export const getBookedNights = async ({
listingId,
reservationId,
startDate,
endDate,
pmsIntegration,
}: {
listingId: number | string
reservationId: string | number
startDate: string
endDate: string
pmsIntegration: Doc<"integrations">
}): Promise<any[] | null> => {
let calendar = []
try {
calendar = await getCalendarWithReservationDetails({
listingId,
reservationId,
pmsIntegration,
pmsPlatform:
pmsIntegration.pmsPlatform as PMSPlatformEnum,
startDate,
endDate,
})
const bookedNights = calendar
.filter((item) => !item.isAvailable)
.map((item) => item.date)
return bookedNights
} catch (e: any) {
console.log(e)
await logSlackError(e.message, "getBookedNights")
return null
}
}
async function getCalendarWithReservationDetails({
listingId,
reservationId,
pmsIntegration,
pmsPlatform,
startDate,
endDate,
}: {
listingId: number | string
reservationId: string | number
pmsIntegration: Doc<"integrations">
pmsPlatform: PMSPlatformEnum
startDate: string
endDate: string
}): Promise<any[]> {
let calendar = []
// if dates are more than a month in the past, ignroe
const oneMonthLookback =
new Date().getTime() - 30 * 24 * 60 * 60 * 1000
if (new Date(startDate).getTime() < oneMonthLookback) {
return []
}
try {
switch (pmsPlatform) {
case PMSPlatformEnum.HOSTAWAY:
calendar =
await fetchHostawayCalendarForListingIdInRange(
pmsIntegration.accessToken!,
listingId as number,
startDate,
endDate
)
calendar = calendar.map((item) => {
const { reservations } = item
if (reservations.length > 0) {
return {
...item,
reservation: reservations[0],
}
} else {
return {
...item,
reservation: null,
}
}
})
break
case PMSPlatformEnum.HOSTFULLY:
const hostfullyEncryptedAccessToken =
pmsIntegration?.accessToken
if (!hostfullyEncryptedAccessToken) {
throw new Error("accessToken not provided")
}
calendar = (
await fetchCalryCalendarForListingIdInRange(
decrypt(hostfullyEncryptedAccessToken),
listingId as string,
startDate,
endDate
)
).data
calendar = calendar.dateWiseAvailability.map(
(item: any) => {
const available =
item.status == "AVAILABLE" ? 1 : 0
const reservationIds =
item.reservationIds &&
item.reservationIds.length > 0
? item.reservationIds
: []
return {
date: item.date,
isAvailable: available ? 1 : 0,
reservationIds: reservationIds,
}
}
)
break
case PMSPlatformEnum.GUESTY:
calendar =
await fetchGuestyCalendarForListingIdInRange(
pmsIntegration.accessToken,
listingId as string,
startDate,
endDate
)
calendar = calendar.map((item) => {
const isAvailable = _.isNumber(item.allotment)
? item.allotment > 0
: item.status === "available"
const { reservation } = item
if (reservation) {
return {
...item,
reservation: {
...reservation,
id: reservation?._id,
arrivalDate:
reservation?.checkInDateLocalized,
departureDate:
reservation?.checkOutDateLocalized,
currency: item.currency,
},
isAvailable: isAvailable ? 1 : 0,
}
} else {
return {
...item,
reservation: null,
isAvailable: isAvailable ? 1 : 0,
}
}
})
break
case PMSPlatformEnum.LODGIFY:
const encryptedAccessToken =
pmsIntegration?.accessToken
if (!encryptedAccessToken) {
throw new Error("accessToken not provided")
}
const accessToken = decrypt(encryptedAccessToken)
calendar =
await fetchLodgifyCalendarForListingIdInRange(
accessToken,
listingId as string,
startDate,
endDate
)
if (calendar.length === 0) {
return []
}
calendar = calendar[0].periods
calendar = calendar.flatMap((item: any) => {
const isAvailable = item.available
const startDate = moment(item.start)
const endDate = moment(item.end)
const { bookings } = item
const getDateRange = (
start: moment.Moment,
end: moment.Moment
): string[] => {
let dateArray: string[] = []
for (let i = 0; i < 1000; i++) {
// Large number to ensure coverage
let currentDate = moment(start).add(
i,
"day"
)
if (currentDate.isAfter(end)) break
dateArray.push(
currentDate.format("YYYY-MM-DD")
)
}
return dateArray
}
const dateList = getDateRange(startDate, endDate)
const reservation = bookings ? bookings[0] : null
return dateList.map((date) => ({
date,
reservation: reservation
? {
...reservation,
id: reservation.id,
arrivalDate:
startDate.format("YYYY-MM-DD"),
departureDate:
endDate.format("YYYY-MM-DD"),
}
: null,
isAvailable: isAvailable ? 1 : 0,
}))
})
break
default:
break
}
return calendar
} catch (e: any) {
console.log(e)
await logSlackError(
e.message,
"getCalendarWithReservationDetails listingId:" +
listingId +
" pmsPlatform" +
pmsPlatform
)
return []
}
}
export const searchCalendarForGapNight = async ({
listingId,
reservationId,
pmsIntegration,
checkInDate,
checkOutDate,
config,
}: {
listingId: number | string
reservationId: string | number
pmsIntegration: Doc<"integrations">
checkInDate: string
checkOutDate: string
config: Doc<"upsellConfig">
}): Promise<UpsellItem[]> => {
const pmsPlatform = pmsIntegration.pmsPlatform as PMSPlatformEnum
if (!pmsIntegration) {
throw new Error(
`No integration found for ${pmsPlatform}. Please connect to ${pmsPlatform} first.`
)
}
const { gapSize, daysBefore } = config
console.log("input checkin", checkInDate)
console.log("input checkout", checkOutDate)
let calendar: any[] = []
const todaysDate = getCurrentDateString()
let formattedStartDate = changeDateWithDayDelta(checkInDate, -5) // get checkindate - daysbefore - 2
let formattedEndDate = changeDateWithDayDelta(checkOutDate, 5) // get checkoutdate + 5
const todayMs = new Date(todaysDate).getTime()
calendar = await getCalendarWithReservationDetails({
listingId,
reservationId,
pmsIntegration,
pmsPlatform,
startDate: formattedStartDate,
endDate: formattedEndDate,
})
console.log("formattedStartDate", formattedStartDate)
console.log("formattedEndDate", formattedEndDate)
let upsellItems: UpsellItem[] = []
console.log(
"calendar",
calendar.map((item: any) => ({
date: item.date,
available: item.isAvailable,
}))
)
// search for gap nights and add upsell items to gap nights
for (let i = 0; i < calendar.length; i++) {
if (!calendar[i]) continue
const { date } = calendar[i]
// if the gap size is 1 and the current day is available and the next day is not available
if (
gapSize === 1 &&
i < calendar.length - 1 && // for ioobe
(!calendar[i - 1] || calendar[i - 1].isAvailable === 0) &&
calendar[i].isAvailable === 1 && // if current day is available
calendar[i + 1].isAvailable === 0 && // if next day is not available
todayMs <= new Date(date).getTime() // if current day is not today
) {
const isPreStay =
config.type === UpsellType.PreStayGapNight
// get the reservation from the previous day
if (!isPreStay && i > 0) {
const { reservation, reservationIds } =
calendar[i - 1]
if (!reservation) {
if (
reservationIds &&
reservationIds.length > 0 &&
reservationIds.includes(reservationId)
) {
const upsellItem: UpsellItem = {
reservationId,
newStartDate: checkInDate,
newEndDate: changeDateWithDayDelta(
date,
1
), // for checkout, add one day
priceWithoutDiscount: calendar[i].price,
currency: "",
}
upsellItems.push(upsellItem)
}
continue
}
const { arrivalDate } = reservation
const upsellItem: UpsellItem = {
reservationId: reservation.id,
newStartDate: arrivalDate,
newEndDate: changeDateWithDayDelta(date, 1), // for checkout, add one day
priceWithoutDiscount: calendar[i].price,
currency: reservation.currency,
}
upsellItems.push(upsellItem)
}
// get the reservation from the next day
if (isPreStay && i < calendar.length - 1) {
const { reservation, reservationIds } =
calendar[i + 1]
if (!reservation) {
if (
reservationIds &&
reservationIds.length > 0 &&
reservationIds.includes(reservationId)
) {
const upsellItem: UpsellItem = {
reservationId,
newStartDate: checkInDate,
newEndDate: changeDateWithDayDelta(
date,
1
), // for checkout, add one day
priceWithoutDiscount: calendar[i].price,
currency: "",
}
upsellItems.push(upsellItem)
}
continue
}
const { departureDate } = reservation
const upsellItem: UpsellItem = {
reservationId: reservation.id,
newStartDate: date,
newEndDate: departureDate,
priceWithoutDiscount: calendar[i].price,
currency: reservation.currency,
}
upsellItems.push(upsellItem)
}
}
// gap size 2
if (
gapSize === 2 &&
i < calendar.length - 2 && // for ioobe
(!calendar[i - 1] || calendar[i - 1].isAvailable === 0) &&
calendar[i].isAvailable === 1 && // if current day is available
calendar[i + 1].isAvailable === 1 && // if next day is available
calendar[i + 2].isAvailable === 0 && // if next next day is not available
todayMs <= new Date(date).getTime() // if current day is not today
) {
const isPreStay =
config.type === UpsellType.PreStayGapNight
// get the reservation from the previous day
if (!isPreStay && i > 0) {
const { reservation, reservationIds } =
calendar[i - 1]
if (!reservation) {
if (
reservationIds &&
reservationIds.length > 0 &&
reservationIds.includes(reservationId)
) {
const upsellItem: UpsellItem = {
reservationId,
newStartDate: checkInDate,
newEndDate: changeDateWithDayDelta(
date,
1
), // for checkout, add one day
priceWithoutDiscount: calendar[i].price,
currency: "",
}
upsellItems.push(upsellItem)
}
continue
}
const { arrivalDate } = reservation
const upsellItem: UpsellItem = {
reservationId: reservation.id,
newStartDate: arrivalDate,
newEndDate: changeDateWithDayDelta(
calendar[i + 1].date,
1
), // for checkout, add one day
priceWithoutDiscount:
calendar[i].price + calendar[i + 1].price,
currency: reservation.currency,
}
upsellItems.push(upsellItem)
}
// get the reservation from the next reservation (in 2 days because of gap size 2)
if (isPreStay && i < calendar.length - 2) {
const { reservation, reservationIds } =
calendar[i + 2]
if (!reservation) {
if (
reservationIds &&
reservationIds.length > 0 &&
reservationIds.includes(reservationId)
) {
const upsellItem: UpsellItem = {
reservationId,
newStartDate: checkInDate,
newEndDate: changeDateWithDayDelta(
date,
1
), // for checkout, add one day
priceWithoutDiscount: calendar[i].price,
currency: "",
}
upsellItems.push(upsellItem)
}
continue
}
const { departureDate } = reservation
const upsellItem: UpsellItem = {
reservationId: reservation.id,
newStartDate: date,
newEndDate: departureDate,
priceWithoutDiscount:
calendar[i].price + calendar[i + 1].price,
currency: reservation.currency,
}
upsellItems.push(upsellItem)
}
}
if (
gapSize === 3 &&
i < calendar.length - 3 && // for ioobe
(!calendar[i - 1] || calendar[i - 1].isAvailable === 0) &&
calendar[i].isAvailable === 1 && // if current day is available
calendar[i + 1].isAvailable === 1 && // if next day is available
calendar[i + 2].isAvailable === 1 && // if next day is available
calendar[i + 3].isAvailable === 0 && // if next next day is not available
todayMs <= new Date(date).getTime() // if current day is not today
) {
const isPreStay =
config.type === UpsellType.PreStayGapNight
// get the reservation from the previous day
if (!isPreStay && i > 0) {
const { reservation, reservationIds } =
calendar[i - 1]
if (!reservation) {
if (
reservationIds &&
reservationIds.length > 0 &&
reservationIds.includes(reservationId)
) {
const upsellItem: UpsellItem = {
reservationId,
newStartDate: checkInDate,
newEndDate: changeDateWithDayDelta(
date,
1
), // for checkout, add one day
priceWithoutDiscount: calendar[i].price,
currency: "",
}
upsellItems.push(upsellItem)
}
continue
}
const { arrivalDate } = reservation
const upsellItem: UpsellItem = {
reservationId: reservation.id,
newStartDate: arrivalDate,
newEndDate: changeDateWithDayDelta(
calendar[i + 2].date,
1
), // for checkout, add one day
priceWithoutDiscount:
calendar[i].price +
calendar[i + 1].price +
calendar[i + 2].price,
currency: reservation.currency,
}
upsellItems.push(upsellItem)
}
// get the reservation from the next reservation (in 3 days because of gap size 2)
if (isPreStay && i < calendar.length - 3) {
const { reservation, reservationIds } =
calendar[i + 3]
if (!reservation) {
if (
reservationIds &&
reservationIds.length > 0 &&
reservationIds.includes(reservationId)
) {
const upsellItem: UpsellItem = {
reservationId,
newStartDate: checkInDate,
newEndDate: changeDateWithDayDelta(
date,
1
), // for checkout, add one day
priceWithoutDiscount: calendar[i].price,
currency: "",
}
upsellItems.push(upsellItem)
}
continue
}
const { departureDate } = reservation
const upsellItem: UpsellItem = {
reservationId: reservation.id,
newStartDate: date,
newEndDate: departureDate,
priceWithoutDiscount:
calendar[i].price +
calendar[i + 1].price +
calendar[i + 2].price,
currency: reservation.currency,
}
upsellItems.push(upsellItem)
}
}
if (
gapSize === 4 &&
i < calendar.length - 4 && // for ioobe
(!calendar[i - 1] || calendar[i - 1].isAvailable === 0) &&
calendar[i].isAvailable === 1 && // if current day is available
calendar[i + 1].isAvailable === 1 && // if next day is available
calendar[i + 2].isAvailable === 1 && // if next day is available
calendar[i + 3].isAvailable === 1 && // if next day is available
calendar[i + 4].isAvailable === 0 && // if next next day is not available
todayMs <= new Date(date).getTime() // if current day is not today
) {
const isPreStay =
config.type === UpsellType.PreStayGapNight
// get the reservation from the previous day
if (!isPreStay && i > 0) {
const { reservation, reservationIds } =
calendar[i - 1]
if (!reservation) {
if (
reservationIds &&
reservationIds.length > 0 &&
reservationIds.includes(reservationId)
) {
const upsellItem: UpsellItem = {
reservationId,
newStartDate: checkInDate,
newEndDate: changeDateWithDayDelta(
date,
1
), // for checkout, add one day
priceWithoutDiscount: calendar[i].price,
currency: "",
}
upsellItems.push(upsellItem)
}
continue
}
const { arrivalDate } = reservation
const upsellItem: UpsellItem = {
reservationId: reservation.id,
newStartDate: arrivalDate,
newEndDate: changeDateWithDayDelta(
calendar[i + 3].date,
1
), // for checkout, add one day
priceWithoutDiscount:
calendar[i].price +
calendar[i + 1].price +
calendar[i + 2].price +
calendar[i + 2].price,
currency: reservation.currency,
}
upsellItems.push(upsellItem)
}
// get the reservation from the next reservation (in 3 days because of gap size 2)
if (isPreStay && i < calendar.length - 4) {
const { reservation, reservationIds } =
calendar[i + 4]
if (!reservation) {
if (
reservationIds &&
reservationIds.length > 0 &&
reservationIds.includes(reservationId)
) {
const upsellItem: UpsellItem = {
reservationId,
newStartDate: checkInDate,
newEndDate: changeDateWithDayDelta(
date,
1
), // for checkout, add one day
priceWithoutDiscount: calendar[i].price,
currency: "",
}
upsellItems.push(upsellItem)
}
continue
}
const { departureDate } = reservation
const upsellItem: UpsellItem = {
reservationId: reservation.id,
newStartDate: date,
newEndDate: departureDate,
priceWithoutDiscount:
calendar[i].price +
calendar[i + 1].price +
calendar[i + 2].price +
calendar[i + 3].price,
currency: reservation.currency,
}
upsellItems.push(upsellItem)
}
}
}
return upsellItems
}
function isGapSized(
calendar: any[],
i: number,
gapSize: number
): boolean {
// Check if there's enough room in the calendar to avoid IndexOutOfBounds
if (i >= calendar.length - gapSize) {
return false
}
// Check if the current day is available
if (calendar[i].isAvailable !== 1) {
return false
}
// Check if the subsequent days up to gapSize are available, and the day after the gap is not
for (let gap = 1; gap <= gapSize; gap++) {
// If it's the last day of the gap, check if it's not available
if (gap === gapSize) {
if (calendar[i + gap].isAvailable !== 0) {
return false
}
} else {
// For days within the gap, check if they are available
if (calendar[i + gap].isAvailable !== 1) {
return false
}
}
}
// If all conditions are met
return true
}
function checkAvailabilityWithStartEnd(
reservation: { arrivalDate: string; departureDate: string },
startDate: string,
endDate: string,
calendar: AvailabilityCalendar,
isInquiry: boolean
): {
response: string
possible: boolean
calendar: AvailabilityCalendar
} {
const reservationStart = new Date(reservation.arrivalDate)
const reservationEnd = new Date(reservation.departureDate)
const requestedStart = new Date(startDate)
const requestedEnd = new Date(endDate)
let intervalsToCheck: [Date, Date][] = []
if (isInquiry) {
intervalsToCheck.push([reservationStart, reservationEnd])
} else {
if (
reservationStart.getTime() === requestedStart.getTime() &&
reservationEnd.getTime() === requestedEnd.getTime()
) {
return {
response: `The requested dates of ${startDate} to ${endDate} are available. The request from the guest is possible.`,
possible: true,
calendar,
}
}
// Define intervals to check based on conditions
if (reservationStart.getTime() === requestedStart.getTime()) {
intervalsToCheck.push([reservationEnd, requestedEnd])
} else if (
reservationEnd.getTime() === requestedEnd.getTime()
) {
intervalsToCheck.push([requestedStart, reservationStart])
} else if (requestedStart < reservationStart) {
if (requestedEnd < reservationStart) {
intervalsToCheck.push([requestedStart, requestedEnd])
} else {
intervalsToCheck.push([
requestedStart,
reservationStart,
])
if (requestedEnd >= reservationEnd) {
intervalsToCheck.push([
reservationEnd,
requestedEnd,
])
}
}
} else {
if (requestedEnd < reservationEnd) {
return {
response: `The requested dates of ${startDate} to ${endDate} are available. The request from the guest is possible.`,
possible: true,
calendar,
}
} else {
intervalsToCheck.push([reservationEnd, requestedEnd])
}
}
}
// Check intervals
const isUnavailable = intervalsToCheck.some(([start, end]) =>
calendar.some(
(item) =>
new Date(item.date) >= start &&
new Date(item.date) < end &&
item.isAvailable === 0
)
)
if (isUnavailable) {
console.log(
`The requested dates of ${startDate} to ${endDate} are not available. The request from the guest is not possible.`
)
return {
response: `The requested dates of ${startDate} to ${endDate} are not available. The request from the guest is not possible.`,
possible: false,
calendar,
}
}
return {
response: `The requested dates of ${startDate} to ${endDate} are available. The request from the guest is possible.`,
possible: true,
calendar,
}
}
function checkSingleDateAvailability(
date: string | null,
calendar: AvailabilityCalendar,
request?: string
): {
response: string
possible: boolean
calendar: AvailabilityCalendar
} {
if (!date)
return {
response: "No date provided.",
possible: true,
calendar,
}
console.log("date to check", date)
console.log("calendar", calendar)
const isAvailable = calendar.some(
(item) =>
moment(item.date).isSame(moment(date), "day") &&
item.isAvailable === 1
)
console.log("isAvailable", isAvailable)
let processedDate = date
if (request === "Early Check-in") {
processedDate = changeDateWithDayDelta(date, 1)
}
if (isAvailable) {
console.log(
`The requested date of ${processedDate} is available.`
)
return {
response: request
? `The requested date of ${processedDate} is available for ${request}. The request from the guest is possible.`
: `The requested dates for ${processedDate} is available. The request from the guest is possible.`,
possible: true,
calendar,
}
}
console.log(
`The requested date of ${processedDate} is not available.`
)
return {
response: request
? `The guest request for ${request} on ${processedDate} is not available. So the request cannot be fulfilled.`
: `The requested date of ${processedDate} is not available.t The request from the guest is not possible.`,
possible: false,
calendar,
}
}
Editor is loading...
Leave a Comment