Stop Sale & Allotment
Manage room availability with the stop sale calendar — set Free Sale, Open Sale, Stop Sale, On Request, and Blocked states per room per day.
Overview
The stop sale module manages availability status for individual room types by date. Each room type in a property can have one of five states per day:
| Code | Name | Color | Meaning |
|---|---|---|---|
0 |
Free Sale | Green | Room is freely available, no restrictions |
1 |
Open Sale | Blue | Room is open for reservations |
2 |
Stop Sale | Red | Room is closed — no new reservations |
3 |
On Request | Yellow | Available on request/approval only |
4 |
Blocked | Grey | Internally blocked, not available |
Data Models
Stopsale — links a user and property to a stop sale configuration:
Stopsale
├── user → FK(User)
├── property → FK(Property)
└── date_update → DateTimeField(auto_now)
Event — one record per room and date combination:
Event
├── room → FK(Room, related_name='events')
├── date → DateField
├── color → PositiveSmallIntegerField (0–4, see table above)
└── Meta: unique_together = ['room', 'date']
Source — named stop sale sources for categorization:
Source
├── user → FK(User)
└── name → CharField(50)
API Endpoints
Rooms list (calendar view):
/api/stop-sale/{hotel_id}/
🔐 Auth required
Get rooms with their events for a hotel.
/api/stop-sale/save/
🔐 Auth required
Save rooms configuration.
Events (individual day operations):
/api/stop-sale/event/create/
🔐 Auth required
Create an event (set a day's status).
/api/stop-sale/event/{pk}/update/
🔐 Auth required
Update an existing event.
/api/stop-sale/event/{pk}/delete/
🔐 Auth required
Delete an event (resets to no state).
Export & Distribution:
/api/stop-sale/pdf/{hotel_id}/
🔐 Auth required
Download the stop sale calendar as a PDF.
/api/stop-sale/pdf/{hotel_id}/send-mail/{mailing_list_id}/
🔐 Auth required
Email the calendar PDF to a mailing list.
Partner API (token-based, no auth required):
/api/stop-sale/StopSale-Export/{token}/
Export stop sale data for a partner token (legacy).
/api/v1/stop-sale/{token}/
Modern stop sale export (JSON). Preferred for new integrations.
Creating Stop Sale Events
Send a
POST
request to create a single event for a room on a given date. The
color
field is the integer code from the status table above.
POST /api/stop-sale/event/create/
{
"room": 42,
"date": "2026-06-15",
"color": 2
}
A successful request returns
201 Created
with the event object. To set a range of dates, send multiple event creation requests — one per date.
Unique constraint
The
Event
model enforces
unique_together = ['room', 'date']
. Use the
PUT /api/stop-sale/event/{pk}/update/
endpoint to change the status of an existing event rather than creating a duplicate.
Calendar View
The
GET /api/stop-sale/{hotel_id}/
endpoint returns all rooms for a hotel together with their event data. The response structure is:
{
"rooms": [
{
"id": 1,
"name": "Standard Room",
"events": [
{"date": "2026-06-15", "color": 2},
{"date": "2026-06-16", "color": 2}
]
}
]
}
Allotment
The allotment concept in Ananas GDS represents the negotiated stop sale deadline defined in a partner contract. The
ss_deadline
field in a
Contract
object specifies how many days in advance a stop sale must be applied. The
to_special_allotment
field controls whether allotment is:
- S (Special stop-sale allotment) — Room-specific allotment. Different room types can carry independent stop sale deadlines.
- G (General accommodations stop-sale) — Property-wide allotment. A single deadline applies to the entire property.
See the Partners & Contracts documentation for the full contract model including allotment fields.
Propagation to Tour Operators
Stop sale events are propagated to tour operators in two ways:
-
API pull
— TOs call
GET /api/v1/stop-sale/{token}/to fetch current events on demand. This is the preferred integration method for automated systems. -
PDF export
— The calendar PDF can be generated and emailed to mailing list contacts via the
POST /api/stop-sale/pdf/{hotel_id}/send-mail/{mailing_list_id}/endpoint.
Token-based partner access
The
/api/v1/stop-sale/{token}/
endpoint does not require an Authorization header. The API token embedded in the URL path identifies the partner and controls which property data is returned.
Sub-User Access
Sub-users require the
stop_sales
permission flag on their
UserPermission
object to access stop sale endpoints. Managers always have access.
if not user.is_manager():
perms = UserPermission.objects.filter(user=user).first()
if not perms or not perms.stop_sales:
return Response({'message': 'Not permitted.'}, status=403)