Разработка кастомной логики смены статусов заказа 1С-Битрикс

Наша компания занимается разработкой, поддержкой и обслуживанием решений на Битрикс и Битрикс24 любой сложности. От простых одностраничных сайтов до сложных интернет магазинов, CRM систем с интеграцией 1С и телефонии. Опыт разработчиков подтвержден сертификатами от вендора.
Предлагаемые услуги
Показано 1 из 1 услугВсе 1626 услуг
Разработка кастомной логики смены статусов заказа 1С-Битрикс
Средняя
~1-2 недели
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1177
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Разработка на базе Битрикс, Битрикс24, 1С для компании Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Разработка на базе 1С Предприятие для компании МИРСАНБЕЛ
    747
  • image_crm_dolbimby_434_0.webp
    Разработка сайта на CRM Битрикс24 для компании DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Разработка на базе Битрикс24 для компании ТЕХНОТОРГКОМПЛЕКС
    976

Разработка кастомной логики смены статусов заказа 1С-Битрикс

Стандартный механизм статусов Битрикс позволяет менеджеру вручную переводить заказ в любой статус с нужными правами доступа. Но реальный процесс обработки заказа сложнее: перевод в «доставляется» должен быть возможен только из «собирается», переход в «отменён» — только если заказ не оплачен, возврат из «завершён» — только для администратора. Всё это — кастомная логика переходов, которая не реализуется через стандартные настройки.

Валидация переходов: событийная модель

Битрикс предоставляет событие OnSaleOrderBeforeStatusChange — обработчик может заблокировать переход и вернуть ошибку:

// /local/php_interface/init.php
\Bitrix\Main\EventManager::getInstance()->addEventHandler(
    'sale',
    'OnSaleOrderBeforeStatusChange',
    ['\App\Order\StatusValidator', 'validate']
);
// /local/lib/Order/StatusValidator.php
namespace App\Order;

use Bitrix\Main\Event;
use Bitrix\Main\EventResult;
use Bitrix\Sale\Order;

class StatusValidator
{
    // Матрица допустимых переходов
    private static array $allowedTransitions = [
        'N' => ['P', 'A'],           // Новый → Принят или Отменён
        'P' => ['W', 'ASSEMBLY', 'A'], // Принят → Ожидает оплаты, Сборка, Отменён
        'W' => ['P', 'ASSEMBLY', 'A'], // Ожидает оплаты → Принят, Сборка, Отменён
        'ASSEMBLY' => ['D', 'A'],     // Сборка → Доставляется, Отменён
        'D' => ['F'],                 // Доставляется → Завершён
        'F' => [],                    // Завершён — финальный
        'A' => [],                    // Отменён — финальный
    ];

    public static function validate(Event $event): EventResult
    {
        /** @var Order $order */
        $order = $event->getParameter('ENTITY');
        $newStatus = $event->getParameter('VALUE');
        $currentStatus = $order->getField('STATUS_ID');

        $allowed = self::$allowedTransitions[$currentStatus] ?? [];

        if (!in_array($newStatus, $allowed, true)) {
            return new EventResult(
                EventResult::ERROR,
                [
                    'message' => sprintf(
                        'Переход из статуса "%s" в "%s" запрещён',
                        $currentStatus,
                        $newStatus
                    ),
                ],
                'sale'
            );
        }

        // Дополнительная бизнес-проверка: нельзя отменить оплаченный заказ
        if ($newStatus === 'A' && $order->isPaid()) {
            return new EventResult(
                EventResult::ERROR,
                ['message' => 'Нельзя отменить оплаченный заказ. Оформите возврат.'],
                'sale'
            );
        }

        return new EventResult(EventResult::SUCCESS);
    }
}

Дополнительная валидация по ролям

Администратор может делать то, что недоступно менеджеру:

public static function validate(Event $event): EventResult
{
    global $USER;

    $order = $event->getParameter('ENTITY');
    $newStatus = $event->getParameter('VALUE');
    $currentStatus = $order->getField('STATUS_ID');

    // Возврат из финального статуса — только администратор
    if ($currentStatus === 'F' && !$USER->IsAdmin()) {
        return new EventResult(
            EventResult::ERROR,
            ['message' => 'Изменение завершённого заказа доступно только администратору'],
            'sale'
        );
    }

    // ... остальные проверки
}

Реакция на переход: постобработка

После успешного перехода — событие OnSaleOrderStatusChange:

\Bitrix\Main\EventManager::getInstance()->addEventHandler(
    'sale',
    'OnSaleOrderStatusChange',
    function(Event $event) {
        $order = $event->getParameter('ENTITY');
        $newStatus = $event->getParameter('VALUE');
        $oldStatus = $event->getParameter('OLD_VALUE');

        switch ($newStatus) {
            case 'ASSEMBLY':
                // Создать задачу на складе
                WarehouseIntegration::createPickingTask($order);
                break;

            case 'D':
                // Передать в службу доставки
                DeliveryService::registerShipment($order);
                // Отправить покупателю трек-номер
                Notifications::sendTrackingNumber($order);
                break;

            case 'F':
                // Начислить бонусные баллы
                LoyaltyProgram::creditPoints($order);
                // Запросить отзыв через 3 дня
                ReviewRequest::schedule($order->getUserId(), 3);
                break;

            case 'A':
                // Вернуть резерв на складе
                if ($oldStatus !== 'N') {
                    StockManager::releaseReservation($order);
                }
                // Инициировать возврат оплаты если нужно
                if ($order->isPaid()) {
                    RefundManager::initiate($order);
                }
                break;
        }
    }
);

Программная смена статуса

При изменении статуса из кода — не через setField напрямую, а через корректный метод:

$order = \Bitrix\Sale\Order::load($orderId);

// Правильный способ — с триггером всех событий
$result = $order->setField('STATUS_ID', 'D');

if ($result->isSuccess()) {
    $saveResult = $order->save();
    if (!$saveResult->isSuccess()) {
        // Обработка ошибок сохранения
        $errors = $saveResult->getErrorMessages();
    }
} else {
    // Событие OnSaleOrderBeforeStatusChange вернуло ошибку
    $errors = $result->getErrorMessages();
}

Журнал переходов

Все смены статусов логируются в b_sale_order_change автоматически. Для кастомного аудита — собственная таблица с историей переходов и причинами:

// При каждой смене статуса
\App\Order\StatusLog::record([
    'order_id'   => $order->getId(),
    'from_status' => $oldStatus,
    'to_status'   => $newStatus,
    'user_id'     => $GLOBALS['USER']->GetID(),
    'comment'     => $comment,
    'timestamp'   => new \Bitrix\Main\Type\DateTime(),
]);

Интерфейс смены статуса с комментарием

Стандартный интерфейс не предоставляет поле комментария при смене статуса. Это решается кастомным AJAX-обработчиком на странице детали заказа в админке:

// /local/ajax/change_order_status.php
$orderId = (int)$_POST['order_id'];
$newStatus = htmlspecialchars($_POST['status']);
$comment = htmlspecialchars($_POST['comment']);

$order = \Bitrix\Sale\Order::load($orderId);
// Сохраняем комментарий в сессии/глобале для обработчика события
$_SESSION['order_status_comment'][$orderId] = $comment;

$order->setField('STATUS_ID', $newStatus);
$result = $order->save();

Сроки выполнения

Матрица переходов с валидацией + обработчики реакций на 3–5 статусов — 1–2 рабочих дня. Полноценная система с журналом, интерфейсом комментариев, интеграцией со складом и службой доставки — 3–5 рабочих дней.