Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,29 @@ nothing about the business rules.** That keeps the availability logic — the pa
brief actually grades — testable in isolation and the data source swappable without
touching either.

## Data model

The catalogue is 40 **Properties**, each owning one or more **Rooms** — a single nested
aggregate that mirrors the source dataset (no normalization or joins; the Property *is*
the unit of storage and retrieval):

- **Property** — `id`, `name`, `description`, `star_rating`, `overall_rating`,
`review_count`, nested `address` / `contact` / `policies`, `amenities[]`, and `rooms[]`.
- **Room** — `room_id`, `type`, bedding & occupancy (`bed_type`, `bed_count`,
`max_occupancy`, `square_footage`), `price_per_night`, `room_amenities[]`, and
`available_dates[]` — the discrete open **Nights** that are the source of truth for
availability.
- **Derived, never stored** — `price_from` (a Property's cheapest Room rate) for search
and list display, plus `nights` / `total_price` on the rooms endpoint. Computing these
keeps one authoritative number per fact instead of a denormalized copy that can drift.

The Zod schemas in [`src/domain/hotel.ts`](src/domain/hotel.ts) are the single source of
truth for these shapes: they **validate the seed at load time** (a malformed dataset fails
fast and legibly) *and* their inferred types are the domain models the rest of the code
programs against — so the model, the wire format, and the OpenAPI docs cannot drift apart.
The wire format stays `snake_case` end-to-end to match the dataset. The domain vocabulary
(Property, Room, Stay window, Night, `price_from`, …) is fixed in [`CONTEXT.md`](CONTEXT.md).

## Testing strategy

`npm test` runs the suite across two complementary styles:
Expand Down
Loading