The challenge
The agency sold two things that look similar to a customer and behave nothing alike underneath.
Accommodation is continuous inventory. A hotel has room types, each with some number of rooms, available on any date the hotel is open. Availability is a question about a date range, and two bookings for different weeks do not compete.
An organised tour is the opposite. It has a fixed departure date, a finite number of seats, an itinerary, and often a minimum viable group size below which it does not run at all. Every booking competes with every other booking for the same departure.
Building these as two separate systems produces two of everything: two booking flows, two payment paths, two invoicing routes, and a customer who cannot book a tour and a hotel night together. Building them as one requires an inventory model that genuinely accommodates both rather than forcing one to pretend to be the other.
Approach
Inventory is abstracted, not flattened. Both products expose the same question, which is whether a given quantity is available for a given period, while answering it differently underneath. Accommodation resolves against room-type allocation per date. A tour resolves against remaining seats on a departure. The booking flow, the basket and the payment path are shared, and the difference stays where it belongs, in the inventory layer.
Reservations hold before they confirm. A customer part-way through checkout has not paid, but the inventory they are about to buy cannot be sold to someone else in the meantime. Holds carry an expiry so that abandoned checkouts release capacity automatically rather than requiring someone to notice and clear them.
This matters far more for tours than for hotels. A held seat on a departure with twelve places is a meaningful proportion of the product.
Hotel and room management is first-class. The agency maintains hotels, room types, rates and availability directly. Rates vary by season, by room type and by length of stay, and availability can be closed off for specific dates. Giving the agency control over this without developer involvement is what makes the system usable day to day rather than a permanent source of change requests.
Tours carry their own operational data. Departure dates, capacity, itinerary, pricing per person, and the minimum group size that determines whether a departure runs. When a departure fails to reach its minimum, the system needs to identify who is booked on it and what has been paid, because those bookings have to be moved or refunded.
Payment and invoicing are part of the booking, not a separate process. A reservation records what was paid, when, by which method, and what remains outstanding. Deposits followed by balance payments are normal in travel, so a booking is rarely settled in one transaction. The invoice is generated from the reservation, which means it reflects what was actually booked and what has actually been received.
Amendments are expected. Travel bookings change constantly. Dates move, party sizes change, rooms are upgraded. Each amendment adjusts inventory on both sides, recalculates the amount due, and leaves a record of what changed. Treating amendments as a normal path rather than as an exception is what keeps the reservation and the invoice in agreement.
Results
The platform runs online booking, reservation management, hotel and room inventory, organised tours with capacity management, payments and invoicing in a single system, with real-time availability across all of it.
The design decision that carried the most weight was refusing to force the two inventory models into one shape. Keeping the difference contained in a single layer, rather than letting it spread through the booking flow, is what allowed one product to serve both without the compromises that usually show up in the customer experience.