1C-Bitrix Booking Module Development
Booking is the reservation of a resource for a time interval with conflict prevention. The resource can be anything: a hotel room, a rental car, a meeting room, a tourist tour, a sports facility. The underlying logic is the same — show availability, accept the reservation, and block the slot for others.
Bitrix has no ready-made tool for this. The task is sometimes attempted using online store orders, but b_sale_order is not designed for time intervals — there is no concept of "period", no conflict checking, and no occupancy visualization.
Data Model
The vendor.booking module with key tables:
-
b_vendor_booking_resource— resources: id, name, type, capacity, iblock_element_id (link to an info block element), settings (JSON: minimum period, maximum period, step, prepayment) -
b_vendor_booking_slot— predefined slots (for hourly rental): id, resource_id, date, time_from, time_to, status -
b_vendor_booking_reservation— reservations: id, resource_id, user_id, date_from, date_to, status (pending/confirmed/cancelled/completed), total_price, order_id -
b_vendor_booking_block— manual date blocking: id, resource_id, date_from, date_to, reason
For daily rental the model uses date_from/date_to without slots. For hourly rental — slots with fixed intervals.
Availability Check
The key operation is an atomic check and reservation. Without a transaction, a race condition is inevitable under concurrent requests:
public function reserve(int $resourceId, \DateTime $from, \DateTime $to, int $userId): ReservationResult
{
$connection = \Bitrix\Main\Application::getConnection();
$connection->startTransaction();
try {
// Check for conflicts with row locking
$conflicts = $connection->query("
SELECT id FROM b_vendor_booking_reservation
WHERE resource_id = {$resourceId}
AND status IN ('pending', 'confirmed')
AND NOT (date_to <= '{$from->format('Y-m-d')}' OR date_from >= '{$to->format('Y-m-d')}')
FOR UPDATE
")->fetch();
if ($conflicts) {
$connection->rollbackTransaction();
return ReservationResult::conflict();
}
$reservationId = ReservationTable::add([
'RESOURCE_ID' => $resourceId,
'USER_ID' => $userId,
'DATE_FROM' => $from,
'DATE_TO' => $to,
'STATUS' => 'pending',
])->getId();
$connection->commitTransaction();
return ReservationResult::success($reservationId);
} catch (\Throwable $e) {
$connection->rollbackTransaction();
throw $e;
}
}
Date Selection Widget
On the frontend — an interactive calendar. Implemented via flatpickr or a custom component. Available dates are fetched via AJAX:
GET /bitrix/components/vendor/booking.calendar/ajax.php
?resource_id=12&month=2024-06
→ {"available": ["2024-06-01","2024-06-03",...], "booked": ["2024-06-02","2024-06-05",...]}
Data is cached via \Bitrix\Main\Data\Cache for 5 minutes. When a reservation changes, the cache is invalidated via the tag booking_resource_{id}.
Pricing
The cost is calculated according to the following rules:
- Base rate per period (day/hour) from
b_vendor_booking_resource - Seasonal surcharges (high season, public holidays) from
b_vendor_booking_price_rule - Long-term rental discounts (7+ days — minus 10%)
- Minimum prepayment percentage
$calculator = new PriceCalculator($resource);
$result = $calculator->calculate($dateFrom, $dateTo);
// → ['total' => 15000, 'prepayment' => 3000, 'discount' => 1500, 'nights' => 3]
Payment and Order Link
After a reservation is confirmed, an order is created in b_sale_order for the prepayment amount (or the full amount). The reservation is linked to the order via reservation.order_id. After successful payment the reservation status changes from pending to confirmed.
When a paid order is cancelled — reservation status becomes cancelled and the slot is released.
Administrative Interface
The administrator section includes:
- Resource list with settings
- Visual schedule (timeline view) with reservations by day
- Manual reservation creation form (for telephone inquiries)
- Date blocking for maintenance
- Resource utilisation report
The timeline view is built via a JS library (FullCalendar or dhtmlxScheduler), data provided through the module's REST endpoint.
Notifications
- To the user upon booking creation (confirmation with details)
- To the user upon manager confirmation
- To the administrator upon a new booking
- Reminder N days before the start (via agent)
All notifications via the standard \Bitrix\Main\Mail\Event::send() with event templates in the main module.
Development Timeline
| Stage | Duration |
|---|---|
| Data model, ORM tables | 1 day |
| Availability check logic (transactions) | 2 days |
| Calendar widget, availability AJAX | 2 days |
| Pricing, seasonal rules | 2 days |
| Order and payment integration | 2 days |
| Administrative interface + timeline | 3 days |
| Notifications, reminders | 1 day |
| Concurrent reservation testing | 1 day |
Total: 14 working days. For hotels with multiple room categories and channel manager integration — separate estimate required.







