Differentiate arrived vs arriving-today in Rooms Accessible View
A confirmed booking for today that hasn't checked in yet is accessible — staff can get in before the guest arrives. Previously it was lumped with in-room guests and greyed out. Backend: classifyBookingStatus() splits NewBook 'staying' bookings by status string (normalised). Statuses containing 'arriv', 'inhouse' or 'checkedin' → occupied; everything else → arriving. /api/occupancy now returns both occupied_site_ids and arriving_site_ids. Frontend: - Occupied rooms: greyed out + 'Occupied' badge (guest physically in room) - Arriving today: normal display + amber 'Arrival today' badge (access now, prioritise before guest checks in) - Chip label shows 'Rooms (X free • Y arriving • Z occupied)' breakdown Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
3fc23eaecc
commit
25d6323aa4
4 changed files with 61 additions and 15 deletions
|
|
@ -25,16 +25,31 @@ function stripCosts(task) {
|
|||
return rest
|
||||
}
|
||||
|
||||
async function fetchOccupiedSiteIds() {
|
||||
// Returns guests physically in the room right now vs those booked to arrive today.
|
||||
// NewBook status strings vary by account; we normalise and check for 'arriv' / 'inhouse'
|
||||
// / 'checkedin' to identify in-room guests. Everything else in the 'staying' list is
|
||||
// treated as "arriving today" — confirmed but not yet checked in.
|
||||
function classifyBookingStatus(rawStatus) {
|
||||
const s = String(rawStatus ?? '').toLowerCase().replace(/[\s_\-]/g, '')
|
||||
if (s.includes('arriv') || s.includes('inhouse') || s.includes('checkedin')) return 'occupied'
|
||||
return 'arriving'
|
||||
}
|
||||
|
||||
async function fetchRoomOccupancy() {
|
||||
const today = new Date().toISOString().slice(0, 10)
|
||||
const bookings = await fetchBookings(today, today)
|
||||
const occupied = new Set()
|
||||
const arriving = new Set()
|
||||
for (const b of bookings) {
|
||||
// NewBook returns booking_site_id on some account configurations, site_id on others
|
||||
const siteId = b.booking_site_id ?? b.site_id
|
||||
if (siteId != null) occupied.add(String(siteId))
|
||||
if (siteId == null) continue
|
||||
const id = String(siteId)
|
||||
if (classifyBookingStatus(b.booking_status) === 'occupied') occupied.add(id)
|
||||
else arriving.add(id)
|
||||
}
|
||||
return occupied
|
||||
// A site that is both (e.g. multi-booking day) should be treated as occupied
|
||||
for (const id of occupied) arriving.delete(id)
|
||||
return { occupied, arriving }
|
||||
}
|
||||
|
||||
export async function taskRoutes(app) {
|
||||
|
|
@ -266,11 +281,16 @@ export async function taskRoutes(app) {
|
|||
return { ok: true, added_to_template: addedToTemplate }
|
||||
})
|
||||
|
||||
// GET /api/occupancy — today's in-house NewBook site ids (for the unoccupied filter UI)
|
||||
// GET /api/occupancy — room state from NewBook for the Rooms Accessible View
|
||||
// Returns two lists: occupied (guest in room) and arriving (booked today, not yet checked in)
|
||||
app.get('/api/occupancy', { preHandler: requireCap('view') }, async (req, reply) => {
|
||||
try {
|
||||
const occupied = await fetchOccupiedSiteIds()
|
||||
return { date: new Date().toISOString().slice(0, 10), occupied_site_ids: [...occupied] }
|
||||
const { occupied, arriving } = await fetchRoomOccupancy()
|
||||
return {
|
||||
date: new Date().toISOString().slice(0, 10),
|
||||
occupied_site_ids: [...occupied],
|
||||
arriving_site_ids: [...arriving],
|
||||
}
|
||||
} catch (err) {
|
||||
return reply.status(502).send({ error: `NewBook error: ${err.message}` })
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue