Time-Based Sales Restriction for Products (Alcohol) in 1C-Bitrix
Russian legislation prohibits the sale of alcohol at night — from 23:00 to 08:00 (Federal Law No. 171-FZ). Regions may impose stricter restrictions. An online store is obligated to block the ability to place an order containing alcoholic products during the restricted hours.
Blocking Points in Bitrix
The restriction must be applied in several places simultaneously — otherwise the customer will either bypass it or see a confusing error at the last step:
- "Buy" button on the product card — hide or disable during restricted hours
-
Adding to cart —
OnSaleBasketItemAddevent handler -
Order checkout — check before saving the order in
OnBeforeSaleOrderSaved
Determining the Time Window
The key question is which time zone to use. Three approaches:
- By server time — simple, but incorrect: the server is in Moscow while the customer may be in Vladivostok
- By the customer's time zone — via IP geolocation (MaxMind GeoIP database or equivalent)
- By delivery time — for courier delivery, the relevant time is in the recipient's city
The most correct approach for an online store with delivery is to determine the time zone by the customer's IP. In Bitrix, the sale.location module or a third-party geolocation database is used for this.
Simple check using Moscow time (UTC+3):
function isAlcoholSaleAllowed(): bool {
$hour = (int)date('H', time() + 3 * 3600); // Moscow time
return ($hour >= 8 && $hour < 23);
}
Marking Alcohol Products
A property UF_IS_ALCOHOL (type "Yes/No") is created in the catalog infoblock. Or section-based: if the "Alcohol" section has the flag UF_TIME_RESTRICTED, all products in it fall under the restriction.
Checking whether a product belongs to a restricted category:
function isTimeRestrictedProduct(int $productId): bool {
$element = CIBlockElement::GetByID($productId)->Fetch();
if ($element['PROPERTY_UF_IS_ALCOHOL_VALUE'] === 'Y') return true;
// Check the section
$section = CIBlockSection::GetByID($element['IBLOCK_SECTION_ID'])->Fetch();
return $section['UF_TIME_RESTRICTED'] === '1';
}
Cart Add Handler
AddEventHandler('sale', 'OnSaleBasketItemAdd', function(&$arFields) {
if (!isTimeRestrictedProduct($arFields['PRODUCT_ID'])) return;
if (!isAlcoholSaleAllowed()) {
$arFields['ERROR_MESSAGE'] =
'Alcohol sales are permitted from 08:00 to 23:00 Moscow time';
return false;
}
});
Visual Block on the Frontend
On the product card and in the catalog, the "Buy" button is replaced with a message about time restrictions. JavaScript checks the client's time — but this is a supplement to the server-side check, not a replacement:
const hour = new Date().getHours();
if (isAlcoholProduct && (hour < 8 || hour >= 23)) {
document.querySelector('.buy-btn').disabled = true;
document.querySelector('.buy-btn').textContent = 'Sales from 08:00 to 23:00';
}
Regional Restrictions
If the store operates in regions with stricter-than-federal restrictions, the time zone and time window are determined dynamically based on IP geolocation. A database of regions with their restrictions is stored in a separate table.
What Is Included in the Setup
- Creating the
UF_IS_ALCOHOLorUF_TIME_RESTRICTEDproperty in the infoblock - Server-side time check accounting for the customer's time zone
-
OnSaleBasketItemAddhandler blocking alcohol products - Pre-save order check in
OnBeforeSaleOrderSaved - Visual "Buy" button block during restricted hours
- If needed — support for regional restrictions

