Developing product rental functionality on 1C-Bitrix

Our company is engaged in the development, support and maintenance of Bitrix and Bitrix24 solutions of any complexity. From simple one-page sites to complex online stores, CRM systems with 1C and telephony integration. The experience of developers is confirmed by certificates from the vendor.
Our competencies:
Development stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1189
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    813
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Development based on Bitrix, Bitrix24, 1C for the company Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    747
  • image_crm_dolbimby_434_0.webp
    Website development on CRM Bitrix24 for DOLBIMBY
    657
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    976

Development of Rental Functionality in 1C-Bitrix

The standard sale module in Bitrix is designed for sales: item → cart → payment → delivery. Rental is a different model: an item has time slots, price depends on duration, the same SKU can be "sold" to multiple customers on different dates, and after return is available again. Out-of-the-box Bitrix can't do this — development is needed on top of existing catalog and order architecture.

Data Architecture: What to Store and Where

Main complexity — availability model. For sales, a "balance" field in b_catalog_store_product is enough. For rental you need a booking calendar: specific dates when a unit is occupied.

Option 1 — highload-block of bookings. Create HL-block RentalBooking with fields:

  • UF_PRODUCT_ID — binding to SKU (element of infobux trading offers)
  • UF_UNIT_ID — identifier of specific unit (if one item has 5 units, each tracked separately)
  • UF_DATE_FROM, UF_DATE_TO — booking period
  • UF_ORDER_ID — connection to order b_sale_order
  • UF_STATUS — confirmed / awaiting payment / returned

Option 2 — separate table via module. For high-load projects (equipment rental, tens of thousands of bookings) HL-block becomes slow due to EAV storage. Create your own table:

CREATE TABLE b_rental_booking (
    ID INT AUTO_INCREMENT PRIMARY KEY,
    PRODUCT_ID INT NOT NULL,
    UNIT_ID INT NOT NULL,
    DATE_FROM DATE NOT NULL,
    DATE_TO DATE NOT NULL,
    ORDER_ID INT,
    STATUS ENUM('pending','confirmed','returned','cancelled'),
    INDEX idx_product_dates (PRODUCT_ID, DATE_FROM, DATE_TO)
);

Index on (PRODUCT_ID, DATE_FROM, DATE_TO) is mandatory because date intersection check is the main query of the system.

Availability Check and Blocking

Main engineering challenge — race condition. Two clients simultaneously book one unit on same dates. Standard CIBlockElement::GetList doesn't protect against this.

Solution — SELECT ... FOR UPDATE on booking creation. Wrapped in transaction:

  1. BEGIN
  2. SELECT * FROM b_rental_booking WHERE PRODUCT_ID = ? AND UNIT_ID = ? AND STATUS IN ('pending','confirmed') AND DATE_FROM < ? AND DATE_TO > ? FOR UPDATE
  3. If no rows found — INSERT new booking
  4. COMMIT

In Bitrix this is implemented via $DB->StartTransaction() / $DB->Commit(). D7 ORM (Bitrix\Main\ORM) supports transactions via Application::getConnection()->startTransaction().

Pricing

Rental implies price per unit of time: day, hour, week. Standard price type in b_catalog_group stores fixed value. For rental you need recalculation logic.

Infobux properties for pricing:

  • PRICE_PER_DAY — base rate per day
  • MIN_RENTAL_DAYS — minimum duration
  • DISCOUNT_WEEK — discount for 7+ days rental (percent)
  • DISCOUNT_MONTH — discount for 30+ days

Price calculation executed by custom handler of event OnSaleBasketItemRefreshData. On basket recalculation Bitrix calls this handler, and we inject price based on rental dates stored in basket item properties (BasketPropertyCollection).

Calendar on Frontend

Date selection component on product page. Minimal implementation:

  • AJAX request to custom controller (ajax.php of module or REST-endpoint)
  • Controller returns array of occupied dates for specific item
  • On frontend — datepicker with blocked dates (flatpickr, react-datepicker or similar)
  • On date range selection — repeat AJAX for price calculation and availability check

Occupied dates cached in b_cache_tag with tag by item ID. Invalidation — on booking creation, cancellation or completion.

Booking Lifecycle

Stage Bitrix Event Action
Add to cart OnSaleBasketItemAdd Create preliminary booking (status=pending), TTL 30 minutes
Order payment OnSalePayOrder Confirm booking (status=confirmed)
Order cancellation OnSaleCancelOrder Release dates (status=cancelled)
Item return Custom handler status=returned, unit available again
TTL expiration Agent CAgent Delete pending-bookings older than 30 minutes

Agent for cleanup of stuck bookings is critical. Without it, abandoned carts will block items forever. Agent registration via CAgent::AddAgent() with 300-second interval.

Integration with sale Module

Cart properties (BasketPropertyCollection) store rental dates:

  • RENTAL_DATE_FROM
  • RENTAL_DATE_TO
  • RENTAL_UNIT_ID

These properties added on $basket->addItem() call and used on price calculation, print document formation and display in personal account.

For display in admin order override template sale.admin.order.edit — add columns with rental dates to order composition table.

Implementation Timeframes

Project Scale Work Volume Timeframe
Simple rental (10–50 items, daily rental) HL-block + event handlers + datepicker 1 week
Medium (100+ items, hourly rental, per-unit accounting) Own table + transactions + agents + account integration 1.5–2 weeks
Complex (multi-warehouse, deposits, late penalties) Full module with admin, API and notification system 2–3 weeks

Key limitation of out-of-the-box Bitrix — no temporal dimension in product balance. Everything else (cart, payment, notifications) works as-is if you correctly implement booking layer on top of standard mechanisms.