Разработка модуля предзаказа 1С-Битрикс
Предзаказ — это возможность оплатить товар до его появления в продаже: новинку, которая ещё не поступила на склад, или лимитированное издание с закрытой датой старта продаж. В отличие от «уведомить о поступлении», предзаказ предполагает реальный платёж или резервирование средств. Стандартный b_sale_order не поддерживает состояние «товар недоступен, но принят предзаказ» — нет статуса отложенного исполнения, нет дедлайна, нет массовой активации.
Модель данных
Модуль vendor.preorder:
-
b_vendor_preorder_campaign— кампании предзаказа: id, iblock_element_id (товар), sku_id, name, available_from (дата начала продаж), preorder_from, preorder_to, limit_qty (лимит предзаказов), reserved_qty, payment_type (full/deposit), deposit_amount, deposit_percent, status (draft/active/closed/fulfilled) -
b_vendor_preorder_order— предзаказы: id, campaign_id, user_id, order_id (ссылка на b_sale_order), qty, paid_amount, status (pending/paid/confirmed/shipped/cancelled), created_at -
b_vendor_preorder_notify_queue— очередь уведомлений при активации
Кампания предзаказа
Кампания привязана к конкретному товару или SKU. Параметры:
- Тип оплаты: полная предоплата или задаток (фиксированная сумма или процент от цены)
-
Лимит: максимальное количество предзаказов —
limit_qty. При достижении лимита форма закрывается -
Период:
preorder_from/preorder_to— когда принимаются предзаказы -
Дата поставки:
available_from— когда товар реально поступит, отображается покупателю
Создание предзаказа
class PreorderService
{
public function create(int $campaignId, int $userId, int $qty): PreorderResult
{
$campaign = CampaignTable::getById($campaignId)->fetch();
if ($campaign['STATUS'] !== 'active') {
return PreorderResult::error('Кампания неактивна');
}
if ($campaign['LIMIT_QTY'] && ($campaign['RESERVED_QTY'] + $qty) > $campaign['LIMIT_QTY']) {
return PreorderResult::error('Лимит предзаказов исчерпан');
}
// Определяем сумму для оплаты
$productPrice = $this->getProductPrice($campaign['SKU_ID']);
$payAmount = $campaign['PAYMENT_TYPE'] === 'deposit'
? ($campaign['DEPOSIT_AMOUNT'] ?: $productPrice * $campaign['DEPOSIT_PERCENT'] / 100)
: $productPrice * $qty;
// Создаём заказ в sale с кастомным статусом
$order = \Bitrix\Sale\Order::create(SITE_ID, $userId);
$order->setField('STATUS_ID', 'PRE'); // кастомный статус «Предзаказ»
// ...добавляем товар в корзину...
$order->save();
PreorderOrderTable::add([
'CAMPAIGN_ID' => $campaignId,
'USER_ID' => $userId,
'ORDER_ID' => $order->getId(),
'QTY' => $qty,
'PAID_AMOUNT' => $payAmount,
'STATUS' => 'pending',
]);
// Атомарно увеличиваем счётчик резерва
CampaignTable::incrementReserved($campaignId, $qty);
return PreorderResult::success($order->getId());
}
}
Активация предзаказов при поступлении товара
Когда товар поступает на склад, менеджер переводит кампанию в статус fulfilled. Агент массово обрабатывает предзаказы:
public static function activateCampaign(int $campaignId): void
{
$preorders = PreorderOrderTable::getList([
'filter' => ['CAMPAIGN_ID' => $campaignId, 'STATUS' => 'paid'],
'order' => ['CREATED_AT' => 'ASC'], // первым подтверждаем раньше оформленные
])->fetchAll();
foreach ($preorders as $preorder) {
// Меняем статус основного заказа на стандартный «В обработке»
$order = \Bitrix\Sale\Order::load($preorder['ORDER_ID']);
$order->setField('STATUS_ID', 'N');
$order->save();
PreorderOrderTable::update($preorder['ID'], ['STATUS' => 'confirmed']);
// Ставим в очередь уведомление покупателю
NotifyQueueTable::add(['PREORDER_ID' => $preorder['ID']]);
}
}
Отображение на карточке товара
Компонент vendor:preorder.button:
- Если кампания активна: показывает форму предзаказа с ценой, датой поставки, количеством оставшихся мест
- Если лимит исчерпан: «Предзаказ закрыт» с кнопкой подписки на обычное уведомление
- Обратный отсчёт до даты старта продаж (JavaScript)
- Прогресс-бар заполнения лимита: «Зарезервировано 47 из 100»
Административный интерфейс
- Создание и управление кампаниями
- Список предзаказов по кампании с фильтром по статусу оплаты
- Кнопка «Активировать кампанию» — запускает массовое подтверждение
- Экспорт списка предзаказов в CSV для логиста
- Статистика: конверсия в оплату, средний чек предзаказа
Сроки разработки
| Этап | Срок |
|---|---|
| ORM-таблицы, модель кампаний | 1 день |
| Сервис создания предзаказов, атомарный резерв | 2 дня |
| Интеграция с b_sale_order, кастомный статус | 1 день |
| Активация кампании, агент массового подтверждения | 2 дня |
| Виджет карточки товара | 1 день |
| Административный интерфейс | 2 дня |
| Тестирование | 1 день |
Итого: 10 рабочих дней. Для задатка с доплатой при активации — дополнительная интеграция с платёжной системой: +2 дня.







