Skip to main content
The inventory module (@voyant-travel/inventory) is where an operator authors and manages the inventory it actually runs. It owns Product structure and versioning, product-internal components (options, units, itinerary days, day services, media, translations, taxonomy), the owned-inventory publication lifecycle, and the availability primitives that decide whether a Product is buyable for a given date and party. It is the authoring half of the operated story; the catalog plane is the discovery half, and inventory projects its Products into that plane. Inventory is optional. A retail or OTA deployment can install catalog and bookings to resell sourced inventory without ever installing the inventory authoring routes, schema, or staff UI. Where it is installed, it is the canonical, module-owned truth for Operated Inventory: it does not own catalog search, overlays, provenance, or snapshots (those stay in catalog), and it does not own quote-time commercial decisions, checkout, bookings, or finance documents.

Key concepts

Product
sellable offering
A sellable travel offering with a booking mode (date, date-time, open, stay, transfer, itinerary), a capacity mode, and visibility. Canonical module-owned truth. See Product.
Product Option
variant
A configurable variant of a Product, such as “English Guided” or “Private Group”, composed of Option Units. See Product Option.
Option Unit
pricing dimension
A pricing or age dimension within an Option, such as “Adult”, “Child 3 to 11”, or “Group 1 to 4”. See Option Unit.
Product Version
immutable snapshot
An immutable snapshot of a Product’s structure at a point in time, produced by explicit operator-triggered snapshots rather than auto-bumped per edit.
Availability Rule
recurrence
A recurring capacity definition (RFC 5545 recurrence) that generates concrete Slots. This is the “every Tuesday and Thursday at 09:00 from April to October” definition, not a single occurrence. See Availability Rule.
Slot
dated inventory unit
A concrete dated inventory unit (date or date-time) with remaining capacity. Generated from an Availability Rule. Slot-level pax is the gross capacity. A Slot has both a capacity and a status; capacity is always a number, never a status. See Slot.
Closeout
block
An explicit block on a date or date range: a holiday, maintenance window, or a sold-out override. Avoid “blackout” or “exception”. See Closeout.
Allotment
reserved block
A block of inventory reserved for a specific Channel. The channel sells against its allotment; release rules govern when unsold allotment returns to general capacity. See Allotment.
Capacity
quantity
The numeric upper bound on a Slot, Allotment, or Vehicle. Always a quantity, never a status. See Capacity.
Allocation resource
per-slot bookable unit
A typed, individually-bookable unit that breaks a Slot’s gross pax capacity into named inventory: double rooms, single rooms, vehicle seats. An operator describes the resource mix once per Product Option as a template (kind, capacity, label pattern, default count), and slot publish materializes the concrete resources. A booking that fits inside the slot’s remaining pax but oversells a specific resource is rejected.

What it owns

  • Product structure and versioning: the products, product_options, option_units, and pax-pricing-tier tables, plus itinerary days, day services, media, translations, and product taxonomy.
  • The owned-inventory publication lifecycle: publish state, publication timestamps, and the triggers that project owned Products into the catalog plane.
  • Availability: Availability Rules and the slot generation that turns them into concrete dated Slots, Closeouts, and the slot-level pax capacity bucket.
  • Allocation resources: the canonical resource-mix templates per Product Option (product_option_resource_templates) and the materialized per-slot allocation_resources. Slot publish auto-materializes resources from template defaults idempotently; an admin can override, add, or re-seed a resource kind.
  • The catalog policy for owned products: inventory writes its own field-policy file (the catalog-policy subpath) so its Products govern correctly inside the plane.
  • Operated authoring: product graph compose and duplicate flows live under the inventory authoring owner path and keep the /v1/admin/products mount.
It does not own catalog projection or search, overlays, provenance, or snapshots (catalog), nor bookings, finance, or external counterparty identity. Cross-module references use plain id columns and template-layer defineLink tables, not hard foreign keys into other modules.

Working with it

Operators author Products and their structure, then publish. The publication step is what makes a Product visible in the catalog plane.
import { productsService } from "@voyant-travel/inventory";

// Author a Product with an option and two pricing units.
const product = await productsService.create(ctx, {
  name: "Aswan Felucca Day Trip",
  bookingMode: "date-time",
  capacityMode: "shared",
  options: [
    {
      name: "Group Departure",
      units: [
        { label: "Adult", pricingCategory: "adult" },
        { label: "Child 3 to 11", pricingCategory: "child" },
      ],
    },
  ],
});
Availability is defined as a recurring rule, then generated into Slots. Slot generation also materializes the option’s allocation resources from their templates.
// Define the recurrence, then generate concrete dated Slots from it.
await availability.createRule(ctx, {
  optionId: option.id,
  recurrence: "FREQ=WEEKLY;BYDAY=TU,TH",
  startTime: "09:00",
  capacity: 24,
  effectiveFrom: "2026-04-01",
  effectiveTo: "2026-10-31",
});

await availability.generateAvailabilitySlots(ctx, { optionId: option.id });

// A holiday block: a Closeout removes specific dates from the generated grid.
await availability.createCloseout(ctx, {
  optionId: option.id,
  from: "2026-08-15",
  to: "2026-08-15",
  reason: "national_holiday",
});
A resource template declares the bookable unit mix once; publish does the rest. The storefront departure response then carries a resourceManifest with per-kind capacity, assigned, and available counts.
// Catalog-level template: 20 double rooms per slot, auto-materialized at publish.
await resources.upsertTemplate(ctx, {
  optionId: option.id,
  kind: "room_dbl",
  capacity: 2,
  namePattern: "DBL {sequence}",
  defaultCount: 20,
});
Both gates run at reservation time. The slot-level pax check (adjustSlotCapacity) and the per-resource capacity check both have to pass for a booking to confirm. A request that fits the slot but oversells a specific resource is rejected with resource_capacity_exhausted, citing the offending resource. A default_count of null disables auto-materialization, so vehicle-seat layouts (which need pax-aware parent/child hierarchy) are seeded through the admin route instead.
  • catalog consumes inventory’s projection. Inventory publishes owned Products into the plane and writes its own field policy; catalog owns search, overlays, provenance, and snapshots.
  • commerce prices what inventory authors. An operated price-availability adapter reports Product pricing and slot availability into the commercial decision.
  • bookings holds Allocations against inventory’s Slots and resources. Booking confirm and cancel adjust slot capacity and per-resource assignment; the per-resource capacity guard there matches the one used during authoring assignment.
  • distribution sells inventory’s Slots to Channels through Allotments, and pushes availability changes outbound when a slot’s remaining pax moves.
  • operations owns the day-to-day execution (dispatches, resource holds) that sits behind a confirmed booking.

React package

The @voyant-travel/inventory-react family provides the authoring and detail UI: @voyant-travel/inventory-react/admin for the staff authoring surface, @voyant-travel/inventory-react/components/product-detail and other components for rendering, plus hooks and i18n. Retail-spine React packages must not hard-depend on it; operated authoring UI is an explicit optional peer edge.

Next steps

Catalog

How operated Products and sourced inventory share one discovery plane.

Commerce

Pricing, sellability, and the commercial decision over your inventory.

Distribution

Allotments, channels, and pushing availability to resellers.

Glossary

Availability Rule, Slot, Allotment, Capacity, and the rest of the vocabulary.