Compare commits
No commits in common. "89ad3811da36b5ce9a85aa8dbc63f6faa414b471" and "916dc5039058a0dccb9a0f2082290f7f9f134433" have entirely different histories.
89ad3811da
...
916dc50390
3 changed files with 10 additions and 86 deletions
|
|
@ -58,14 +58,13 @@ export async function fetchSites() {
|
||||||
return res?.data ?? []
|
return res?.data ?? []
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch bookings whose stay overlaps the date window.
|
// Fetch bookings spanning a date range.
|
||||||
// list_type 'staying' returns bookings where arrival <= period_to AND departure >= period_from,
|
// list_type 'all' includes arrived, confirmed, unconfirmed, departed, blocked.
|
||||||
// so a booking arriving on period_to is included. This matches the original plugin behaviour.
|
|
||||||
export async function fetchBookings(fromDate, toDate) {
|
export async function fetchBookings(fromDate, toDate) {
|
||||||
const res = await callApi('bookings_list', {
|
const res = await callApi('bookings_list', {
|
||||||
period_from: `${fromDate} 00:00:00`,
|
period_from: `${fromDate} 00:00:00`,
|
||||||
period_to: `${toDate} 23:59:59`,
|
period_to: `${toDate} 23:59:59`,
|
||||||
list_type: 'staying',
|
list_type: 'all',
|
||||||
})
|
})
|
||||||
return res?.data ?? []
|
return res?.data ?? []
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,82 +47,6 @@ function filterBookingData(booking, canSeeGuest, canSeeRate, canSeeAllNotes, vis
|
||||||
export async function roomRoutes(app) {
|
export async function roomRoutes(app) {
|
||||||
app.addHook('preHandler', requireAuth)
|
app.addHook('preHandler', requireAuth)
|
||||||
|
|
||||||
// GET /api/rooms/debug-room?room=101&date=YYYY-MM-DD
|
|
||||||
// Returns raw NewBook data for a single room — use to diagnose bracket/booking issues.
|
|
||||||
app.get('/api/rooms/debug-room', async (req, reply) => {
|
|
||||||
if (!hasCap(req, 'settings')) return reply.status(403).send({ error: 'Forbidden' })
|
|
||||||
|
|
||||||
const viewDate = req.query.date || new Date().toISOString().slice(0, 10)
|
|
||||||
const roomName = req.query.room
|
|
||||||
const yesterday = dateOffset(viewDate, -1)
|
|
||||||
const tomorrow = dateOffset(viewDate, +1)
|
|
||||||
|
|
||||||
const [sites, bookings] = await Promise.all([
|
|
||||||
fetchSites(),
|
|
||||||
fetchBookings(yesterday, tomorrow),
|
|
||||||
])
|
|
||||||
|
|
||||||
if (!roomName) {
|
|
||||||
const sample = bookings[0] || {}
|
|
||||||
return {
|
|
||||||
hint: 'Pass ?room=<site_name> to inspect a specific room',
|
|
||||||
view_date: viewDate,
|
|
||||||
total_sites: sites.length,
|
|
||||||
total_bookings: bookings.length,
|
|
||||||
booking_field_names: Object.keys(sample),
|
|
||||||
site_field_names: sites.length ? Object.keys(sites[0]) : [],
|
|
||||||
site_list: sites.map(s => ({ id: s.site_id, name: s.site_name })),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const site = sites.find(s => s.site_name === roomName)
|
|
||||||
if (!site) return { error: `Room "${roomName}" not found`, available: sites.map(s => s.site_name) }
|
|
||||||
|
|
||||||
const siteId = String(site.site_id)
|
|
||||||
const idFields = bookings.length
|
|
||||||
? Object.keys(bookings[0]).filter(k =>
|
|
||||||
k.toLowerCase().includes('site') || k.toLowerCase().includes('room') ||
|
|
||||||
k.toLowerCase().includes('unit') || k.toLowerCase().includes('location')
|
|
||||||
)
|
|
||||||
: []
|
|
||||||
|
|
||||||
const matchFn = b =>
|
|
||||||
idFields.some(f => String(b[f] || '') === siteId) ||
|
|
||||||
String(b.site_id || '') === siteId ||
|
|
||||||
String(b.booking_site_id || '') === siteId ||
|
|
||||||
(b.site_name && b.site_name === roomName)
|
|
||||||
|
|
||||||
const siteBookings = bookings.filter(matchFn)
|
|
||||||
|
|
||||||
const classified = classifyRoom(site, bookings, viewDate, yesterday, tomorrow)
|
|
||||||
|
|
||||||
return {
|
|
||||||
view_date: viewDate, yesterday, tomorrow,
|
|
||||||
site: { id: siteId, name: site.site_name, fields: Object.keys(site) },
|
|
||||||
booking_id_fields: idFields,
|
|
||||||
total_bookings_fetched: bookings.length,
|
|
||||||
matching_bookings: siteBookings.map(b => {
|
|
||||||
const out = {}
|
|
||||||
for (const f of ['booking_id', 'booking_status', 'booking_arrival', 'booking_departure', ...idFields]) {
|
|
||||||
out[f] = b[f]
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
}),
|
|
||||||
classified: {
|
|
||||||
flow_type: classified.flow_type,
|
|
||||||
spans_previous: classified.spans_previous,
|
|
||||||
spans_next: classified.spans_next,
|
|
||||||
previous_status: classified.previous_status,
|
|
||||||
next_status: classified.next_status,
|
|
||||||
booking_id: classified.booking?.booking_id,
|
|
||||||
booking_arrival: classified.booking?.booking_arrival,
|
|
||||||
booking_departure: classified.booking?.booking_departure,
|
|
||||||
next_booking_id: classified.next_booking?.booking_id,
|
|
||||||
next_booking_arrival: classified.next_booking?.booking_arrival,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// GET /api/rooms?date=YYYY-MM-DD
|
// GET /api/rooms?date=YYYY-MM-DD
|
||||||
app.get('/api/rooms', async (req, reply) => {
|
app.get('/api/rooms', async (req, reply) => {
|
||||||
if (!hasCap(req, 'view')) return reply.status(403).send({ error: 'Missing capability: view' })
|
if (!hasCap(req, 'view')) return reply.status(403).send({ error: 'Missing capability: view' })
|
||||||
|
|
@ -150,11 +74,12 @@ export async function roomRoutes(app) {
|
||||||
// Fetch from NewBook in parallel
|
// Fetch from NewBook in parallel
|
||||||
let sites, bookings, tasks
|
let sites, bookings, tasks
|
||||||
try {
|
try {
|
||||||
// list_type 'staying' includes bookings with arrival <= period_to,
|
// Fetch bookings one day beyond tomorrow so tomorrow-arriving bookings appear
|
||||||
// so fetching yesterday→tomorrow captures all adjacent-day brackets.
|
// in nextBooking lookups (some NewBook regions exclude period_to-date arrivals).
|
||||||
|
const dayAfterTomorrow = dateOffset(viewDate, +2)
|
||||||
;[sites, bookings, tasks] = await Promise.all([
|
;[sites, bookings, tasks] = await Promise.all([
|
||||||
fetchSites(),
|
fetchSites(),
|
||||||
fetchBookings(yesterday, tomorrow),
|
fetchBookings(yesterday, dayAfterTomorrow),
|
||||||
fetchTasks(yesterday, tomorrow),
|
fetchTasks(yesterday, tomorrow),
|
||||||
])
|
])
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
@ -178,7 +103,7 @@ export async function roomRoutes(app) {
|
||||||
// Classify each site
|
// Classify each site
|
||||||
const rooms = []
|
const rooms = []
|
||||||
for (const site of sites) {
|
for (const site of sites) {
|
||||||
const catId = String(site.site_category_id ?? site.category_id ?? site.category?.id ?? '')
|
const catId = String(site.site_category_id || '')
|
||||||
const isExcluded = excludedCategories.includes(catId)
|
const isExcluded = excludedCategories.includes(catId)
|
||||||
if (isExcluded && hideExcluded) continue
|
if (isExcluded && hideExcluded) continue
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -104,8 +104,8 @@ function RoomCard({ room, viewDate, config, onClick }: Props) {
|
||||||
}
|
}
|
||||||
if (room.spans_next) {
|
if (room.spans_next) {
|
||||||
dataAttrs['data-spans-next'] = 'true'
|
dataAttrs['data-spans-next'] = 'true'
|
||||||
} else if (room.next_status != null) {
|
} else if (room.next_status) {
|
||||||
dataAttrs['data-next-status'] = room.next_status || 'unknown'
|
dataAttrs['data-next-status'] = room.next_status.toLowerCase()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Task status pill
|
// Task status pill
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue