BookingService
Create, manage, and query room bookings
Overview
BookingService is the primary service for booking lifecycle management. It handles creation with idempotency and atomic conflict checking, state transitions, optimistic concurrency on modifications, delegation, and person/room queries.
import { BookingService } from '@roomkit/nestjs';Methods
create
Create a new booking. Validates the time range, checks idempotency, resolves the priority tier, and creates the booking with an atomic conflict check. Emits BookingRequested on success.
async create(dto: CreateBookingDto): Promise<Booking>| Parameter | Type | Description |
|---|---|---|
dto | CreateBookingDto | Booking creation data |
const booking = await bookingService.create({
roomId: 'room-a1',
personId: 'user-42',
title: 'Project Standup',
startsAt: new Date('2026-03-02T09:00:00'),
endsAt: new Date('2026-03-02T09:30:00'),
priorityName: 'standard',
idempotencyKey: 'standup-2026-03-02',
});Throws InvalidTimeRangeError if endsAt is not after startsAt.
Throws RoomNotFoundError if the room does not exist.
Throws BookingConflictError if the room has an overlapping booking.
confirm
Transition a booking from REQUESTED to CONFIRMED. Emits BookingConfirmed.
async confirm(id: string, triggeredBy: string): Promise<Booking>| Parameter | Type | Description |
|---|---|---|
id | string | Booking ID |
triggeredBy | string | ID of the user or system triggering the transition |
const confirmed = await bookingService.confirm('booking-1', 'admin-5');Throws BookingNotFoundError if the booking does not exist.
Throws InvalidStateTransitionError if the booking is not in REQUESTED state.
checkIn
Transition a booking from CONFIRMED to IN_PROGRESS. Emits BookingStarted.
async checkIn(id: string, triggeredBy: string): Promise<Booking>| Parameter | Type | Description |
|---|---|---|
id | string | Booking ID |
triggeredBy | string | ID of the user or system triggering the transition |
const active = await bookingService.checkIn('booking-1', 'user-42');Throws BookingNotFoundError if the booking does not exist.
Throws InvalidStateTransitionError if the booking is not in CONFIRMED state.
complete
Transition a booking from IN_PROGRESS to COMPLETED. Emits BookingCompleted.
async complete(id: string, triggeredBy: string): Promise<Booking>| Parameter | Type | Description |
|---|---|---|
id | string | Booking ID |
triggeredBy | string | ID of the user or system triggering the transition |
const done = await bookingService.complete('booking-1', 'user-42');Throws BookingNotFoundError if the booking does not exist.
Throws InvalidStateTransitionError if the booking is not in IN_PROGRESS state.
cancel
Cancel a booking from any non-terminal state. Emits BookingCancelled.
async cancel(id: string, triggeredBy: string, reason?: string): Promise<Booking>| Parameter | Type | Description |
|---|---|---|
id | string | Booking ID |
triggeredBy | string | ID of the user or system triggering the cancellation |
reason | string | Optional cancellation reason |
const cancelled = await bookingService.cancel('booking-1', 'admin-5', 'Room maintenance');Throws BookingNotFoundError if the booking does not exist.
Throws InvalidStateTransitionError if the booking is already in a terminal state (COMPLETED or CANCELLED).
modify
Update a booking with optimistic concurrency control. Re-checks conflicts when the time range or room changes. Emits BookingModified.
async modify(id: string, changes: UpdateBookingDto, expectedVersion: number): Promise<Booking>| Parameter | Type | Description |
|---|---|---|
id | string | Booking ID |
changes | UpdateBookingDto | Fields to update |
expectedVersion | number | Expected version for optimistic locking |
const updated = await bookingService.modify(
'booking-1',
{
startsAt: new Date('2026-03-02T10:00:00'),
endsAt: new Date('2026-03-02T10:30:00'),
},
1, // expectedVersion
);Throws BookingNotFoundError if the booking does not exist.
Throws BookingConflictError if the updated time/room has an overlapping booking.
delegate
Update the delegation of a booking to another person. Emits BookingModified.
async delegate(id: string, onBehalfOfId: string, triggeredBy: string): Promise<Booking>| Parameter | Type | Description |
|---|---|---|
id | string | Booking ID |
onBehalfOfId | string | ID of the person the booking is being delegated to |
triggeredBy | string | ID of the user performing the delegation |
const delegated = await bookingService.delegate('booking-1', 'user-99', 'admin-5');Throws BookingNotFoundError if the booking does not exist.
getByPerson
Retrieve bookings for a person within a time range.
async getByPerson(
personId: string,
timeRange: TimeRange,
pagination?: Pagination,
): Promise<PaginatedResult<Booking>>| Parameter | Type | Description |
|---|---|---|
personId | string | Person ID |
timeRange | TimeRange | Start and end dates to filter by |
pagination | Pagination | Optional cursor-based pagination |
const result = await bookingService.getByPerson('user-42', {
startsAt: new Date('2026-03-01'),
endsAt: new Date('2026-03-31'),
});getByRoom
Retrieve bookings for a room within a time range.
async getByRoom(
roomId: string,
timeRange: TimeRange,
pagination?: Pagination,
): Promise<PaginatedResult<Booking>>| Parameter | Type | Description |
|---|---|---|
roomId | string | Room ID |
timeRange | TimeRange | Start and end dates to filter by |
pagination | Pagination | Optional cursor-based pagination |
const result = await bookingService.getByRoom('room-a1', {
startsAt: new Date('2026-03-02'),
endsAt: new Date('2026-03-02T23:59:59'),
});getById
Retrieve a single booking by ID.
async getById(id: string): Promise<Booking | null>| Parameter | Type | Description |
|---|---|---|
id | string | Booking ID |
Returns the booking or null if not found.
const booking = await bookingService.getById('booking-1');