AstroBaaS

Inventory & suppliers

Room Inventory by Date/Occupancy (Hotels)

Paid pluginsize Lplanned, not built

Indicative price, not an offer: €64/mo; calendar view, occupancy blocking, overbooking prevention

Generated from docs/plan/paid/room-inventory-by-date-occupancy/PLAN.md in the AstroBaaS repository. Nothing described below is implemented — it is the written plan for it.

A paid inventory module for hospitality merchants (hotels, resorts, short-term rentals) managing rooms as date-based inventory. Replaces flat SKU inventory with calendar-aware blocking, occupancy queries by date range, and overbooking prevention. Essential for any room-rental business where inventory is not a single qty but a time-bound availability matrix.

The problem

I have 50 rooms; each can be booked on different dates. Standard inventory counts stock as one number; I need to know if Room 201 is available June 1–5, and prevent double-booking. Existing product inventory cannot express ‘Room 201 is blocked June 2 for maintenance’ or ‘booked June 1–3’.

What it does

  • Room entity linked to product (room as product variant or separate inventory type)
  • Date-range occupancy: booked_from, booked_to, reason (guest_order_id, maintenance, block_out)
  • Calendar view: 12-month grid showing all rooms, color-coded by status (available, booked, blocked)
  • Availability query: GET /api/rooms/availability/:checkInDate/:checkOutDate returns available room list
  • Block creation: staff can manually block dates for maintenance, overbooking hold, or special event
  • Occupancy validation on order checkout: reject if any night in requested range is booked
  • Partial-night support: 2-night minimum, same-day checkout rules, timezone-aware date boundaries
  • Overbooking detection: warn if blocking X nights would exceed room count for any night
  • Occupancy report: GET /api/rooms/:roomId/occupancy-history returns all bookings/blocks for audit
  • Admin calendar editor: drag-to-block, click-to-unblock, bulk block by reason (e.g., ‘all rooms June 1 for inspection’)

What it deliberately does NOT do

Each boundary carries its reason. A boundary without a reason gets crossed by the next person who reads this.

  • Full PMS (property management system) — no guest check-in/check-out process, no housekeeping workflow, no maintenance work orders
  • Guest management or profiles — this is inventory only; guest data lives in orders/customers
  • Revenue management or dynamic pricing — no rate optimization; pricing stays in product config
  • Inter-property transfers or multi-location reconciliation — each shop is independent; no corporate rollup

Data model

New tables: room_inventory (id, product_id, room_number, room_name, capacity, created_at), room_occupancy (id, room_id, booked_from_date, booked_to_date, reason, related_order_id, created_by, created_at), room_blocks (id, room_id, blocked_from_date, blocked_to_date, block_reason, block_type enum(guest_order, maintenance, event, hold), created_at). Inventory table extended with room_id and optional date_range_from/date_range_to if storing non-room inventory.

API

  • GET /api/rooms
  • POST /api/rooms
  • GET /api/rooms/:id/occupancy-calendar/:year/:month
  • GET /api/rooms/availability/:checkInDate/:checkOutDate
  • POST /api/rooms/:id/occupancy
  • GET /api/rooms/:id/occupancy-history
  • POST /api/rooms/:id/block
  • DELETE /api/rooms/:id/occupancy/:occupancyId
  • POST /api/rooms/bulk-block

Every route added here must also appear in src/pages/openapi.json.ts — a test fails the build if it does not.

Admin

Calendar view with 12-month grid, drag-to-block UI, color legend (booked=blue, blocked=red, available=green), room detail sidebar showing upcoming bookings, bulk-block dialog for maintenance windows, occupancy history with edit/delete controls.

The seam — why this is paid

Core owns the date-aware inventory interface and occupancy query logic. Paid owns calendar conflict resolution, overbooking prevention algorithms, occupancy audit trails, and multi-night validation rules.

Support commitment: calendar conflict resolution, double-booking prevention, occupancy audits

Dependencies

  • product module (room as product)
  • order module (links occupancy to order_id)
  • date/calendar handling (timezone support)

Acceptance checks

Each of these must be able to fail. Before claiming this is done, break the code deliberately and watch each one go red.

  • POST occupancy with overlapping dates on same room is rejected
  • GET availability/:checkIn/:checkOut returns only rooms with zero occupancy across all nights
  • Calendar shows booked and blocked dates in correct color
  • Bulk-block successfully blocks one date across multiple rooms
  • Occupancy history includes deleted occupancy with deletion timestamp and user
  • Same-day checkout does not block next day (date boundary timezone-aware)

Risks

Date boundary errors (UTC vs local time breaks multi-day logic); concurrent booking of same room race condition; bulk-block rolls back on error for one room (partial commit); occupancy query timeout on 10,000+ room/date combinations; guest cancellation does not auto-free room.

Commercial context

Suggested price€64/mo; calendar view, occupancy blocking, overbooking prevention
Rival anchorOpera/Fosse PMS: €500-1000/mo; custom: €5000+

The anchor is what the nearest equivalent charges on Shopify or Magento today. It is context for a pricing decision, not the decision.


Generated from the commerce plan. See docs/COMMERCE-PLAN.md for the full catalogue and ../../AI-GUIDE.md for how to work on this repository.