> ## Documentation Index
> Fetch the complete documentation index at: https://voyant.travel/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Inventory

> The operated-inventory authoring module: product structure, options and units, itinerary, availability rules and slots, closeouts, allotments, capacity, and per-slot allocation resources.

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](/docs/platform/modules/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](/docs/concepts/glossary): 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

<ResponseField name="Product" type="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](/docs/concepts/glossary).
</ResponseField>

<ResponseField name="Product Option" type="variant">
  A configurable variant of a Product, such as "English Guided" or "Private Group", composed of Option Units. See [Product Option](/docs/concepts/glossary).
</ResponseField>

<ResponseField name="Option Unit" type="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](/docs/concepts/glossary).
</ResponseField>

<ResponseField name="Product Version" type="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.
</ResponseField>

<ResponseField name="Availability Rule" type="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](/docs/concepts/glossary).
</ResponseField>

<ResponseField name="Slot" type="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](/docs/concepts/glossary).
</ResponseField>

<ResponseField name="Closeout" type="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](/docs/concepts/glossary).
</ResponseField>

<ResponseField name="Allotment" type="reserved block">
  A block of inventory reserved for a specific [Channel](/docs/concepts/glossary). The channel sells against its allotment; release rules govern when unsold allotment returns to general capacity. See [Allotment](/docs/concepts/glossary).
</ResponseField>

<ResponseField name="Capacity" type="quantity">
  The numeric upper bound on a Slot, Allotment, or Vehicle. Always a quantity, never a status. See [Capacity](/docs/concepts/glossary).
</ResponseField>

<ResponseField name="Allocation resource" type="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.
</ResponseField>

## 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.

```ts theme={null}
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.

```ts theme={null}
// 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.

```ts theme={null}
// 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,
});
```

<Note>
  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.
</Note>

## Links to other modules

* **[catalog](/docs/platform/modules/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](/docs/platform/modules/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](/docs/platform/modules/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

<CardGroup cols={2}>
  <Card title="Catalog" icon="layer-group" href="/docs/platform/modules/catalog">
    How operated Products and sourced inventory share one discovery plane.
  </Card>

  <Card title="Commerce" icon="tag" href="/docs/platform/modules/commerce">
    Pricing, sellability, and the commercial decision over your inventory.
  </Card>

  <Card title="Distribution" icon="share-nodes" href="/docs/platform/modules/distribution">
    Allotments, channels, and pushing availability to resellers.
  </Card>

  <Card title="Glossary" icon="book-open" href="/docs/concepts/glossary">
    Availability Rule, Slot, Allotment, Capacity, and the rest of the vocabulary.
  </Card>
</CardGroup>
