Home Modules Tour Operators
Module

Tour Operators

How tour operators access partner hotel data, configure property mappings, and apply override facts for their own catalogue.

Overview

Tour operators (TOs) consume hotel data from their accommodation partners. The TO module provides:

  1. A view of all properties from connected partners
  2. Hotel and room mapping — mapping Ananas property and room names to the TO's internal codes
  3. Override facts — modifying specific fact fields for the TO's catalogue without changing the source data from the hotel
  4. API access for automated data consumption

Before any data is accessible, an accepted contract (status=A) must exist between the TO and the accommodation provider. See the Partners & Contracts module for contract setup.

Accessing Partner Data

TOs access partner data through two mechanisms:

Method How it works Best for
Dashboard Visual review of partner properties via the Ananas GDS web app Manual review, one-off checks
API Programmatic access via API tokens issued by the accommodation provider Automated catalogue ingestion, integrations

For API access, the accommodation provider issues an API token to the TO. The token is passed as a URL path segment — not as an Authorization header.

Token-based access

The token endpoints (/api/v1/facts/{token}/, /api/v1/photos/{token}/, /api/v1/stop-sale/{token}/) require no Authorization header. The token in the URL path identifies both the partner relationship and the scope of data returned.

Hotel Mapping (HotelMapping)

A HotelMapping record lets a TO assign their own internal codes to a partner hotel. This is essential for automated ingestion where the TO's back-office system uses its own identifiers.

text
HotelMapping
├── user           → FK(User)       — the TO user
├── hotel          → FK(Property)   — the partner's property
├── override_code  → CharField(20)  — TO's internal hotel code
├── local_id       → CharField(50)  — TO's local identifier
├── external_id    → CharField(50)  — external system ID (GDS, OTA, PMS)
├── supplying_name → CharField(50)  — name used in the TO's system
├── event_free     → CharField(20)  — code for Free Sale events
├── event_open     → CharField(20)  — code for Open Sale events
├── event_stop     → CharField(20)  — code for Stop Sale events
├── event_request  → CharField(20)  — code for On Request events
└── event_block    → CharField(20)  — code for Blocked events

The event_* fields translate Ananas event codes (0–4) into the TO's own stop sale codes for their internal systems. For example, if the TO's PMS uses CLS to represent a closed room, set event_stop = "CLS".

Ananas Code Ananas Name HotelMapping field
0Free Saleevent_free
1Open Saleevent_open
2Stop Saleevent_stop
3On Requestevent_request
4Blockedevent_block

Room Mapping (RoomMapping)

Each room within a partner hotel can also carry a TO-specific mapping. RoomMapping extends HotelMapping with room-level overrides:

text
RoomMapping
├── room           → FK(Room, nullable)
├── user           → FK(User)          — the TO user
├── hotel          → FK(HotelMapping)
├── override_code  → CharField(20)     — TO's room code
├── name           → CharField(500)    — override display name
├── original_name  → BooleanField      — use the property's original room name?
├── event_free / event_open / event_stop / event_request / event_block
│                  → CharField(20)     — room-level event codes
├── linked         → BooleanField      — is this mapping active?
├── link_date      → DateTimeField
└── unlink_date    → DateTimeField

The get_event_code(event_code) instance method on RoomMapping translates an Ananas integer event code to the TO's own string code. If no room-level code is set, the method falls back to the parent HotelMapping value.

Linked vs. unlinked rooms

A RoomMapping with linked=False is inactive — it will not appear in API exports for that TO. Use link_date and unlink_date to audit when a room was connected or disconnected.

Override Facts (FactsOverride)

Tour operators can override specific fact fields for their own catalogue without modifying the source data from the hotel. Overrides are stored per TO user and property combination. When the TO fetches fact data via the API, override fields are merged on top of the hotel's base fact data.

text
FactsOverride
├── user                        → FK(User)       — the TO
├── property                    → FK(Property)   — the hotel
├── add_operator_logo           → BooleanField   — show TO logo on this property's facts?
├── enable_stopsale_api         → BooleanField   — expose stop sale via API?
├── set_stopsale_closed_request → BooleanField   — treat stop sales as on-request?
├── location_environment        → TextField      — custom location description
├── around_hotel                → TextField      — custom "around the hotel" text
├── beach_characteristics       → TextField
├── beach_information           → TextField
├── distance_to_beach           → DecimalField
├── distance_to_beach_unit      → CharField
├── distance_to_airport         → DecimalField
├── airport_distance_type       → CharField
├── outdoor_characteristics     → TextField
└── outdoor_equipment           → TextField

Only fields explicitly set in a FactsOverride record replace the hotel's values. Fields left blank fall through to the source data. This means a hotel's fact sheet remains canonical — the TO overlay is applied at query time.

TO-Specific API Endpoints

TOs also use the standard partner contract endpoints documented in the Partners module. The following endpoints are additionally available:

Override facts management:

GET /api/partners/override-facts/ 🔐 Auth required

List all override facts records for the authenticated TO.

POST /api/partners/override-facts/create/ 🔐 Auth required

Create or update an override record for a property.

GET /api/partners/override-facts/get/{prop_id}/ 🔐 Auth required

Get the override record for a specific property.

GET /api/partners/partners-properties/ 🔐 Auth required

List all properties visible from the TO's partner connections.

GET /api/partners/check-facts/{prop_id}/ 🔐 Auth required

Check fact access status for a given property under the current contract.

Data consumption (token-based, no auth header required):

GET /api/v1/facts/{token}/

Retrieve the full fact sheet for the property associated with this token. Override facts are merged into the response.

GET /api/v1/photos/{token}/

Retrieve the photo gallery for the property associated with this token.

GET /api/v1/stop-sale/{token}/

Retrieve the stop sale calendar for the property associated with this token. Room event codes are translated using RoomMapping.get_event_code() where a mapping exists.

TO Sub-User Access

TO sub-users use a different set of permission flags from accommodation sub-users. The flags relevant to TO operations are:

Flag Description
edit_products Create and edit hotel and accommodation listings in the TO's catalogue
view_content View partner fact sheets, room info, media, and the stop sale calendar
accounting View invoices issued to this TO

Different permission model

TO sub-users are governed by the same UserPermission model as accommodation sub-users, but the meaningful flags differ. Accommodation-side flags such as stop_sales, facts, and photos apply to the property manager's side; edit_products, view_content, and accounting apply to the TO side.

Property Visibility

The properties a TO can see depend on their active contract connections. Only properties belonging to partners with status=A (Accepted) contracts are returned by any TO-facing endpoint.

For TO sub-users with SubUserRegionAccess records, visibility is further filtered by country or region. A sub-user without any SubUserRegionAccess records sees all properties from accepted partners; one with records sees only the intersection of their region grants and accepted-contract properties.