Настройка автоматической обработки возвратов 1С-Битрикс

Наша компания занимается разработкой, поддержкой и обслуживанием решений на Битрикс и Битрикс24 любой сложности. От простых одностраничных сайтов до сложных интернет магазинов, CRM систем с интеграцией 1С и телефонии. Опыт разработчиков подтвержден сертификатами от вендора.
Предлагаемые услуги
Показано 1 из 1 услугВсе 1626 услуг
Настройка автоматической обработки возвратов 1С-Битрикс
Простая
~1 рабочий день
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1173
  • 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С Предприятие для компании МИРСАНБЕЛ
    745
  • image_crm_dolbimby_434_0.webp
    Разработка сайта на CRM Битрикс24 для компании DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Разработка на базе Битрикс24 для компании ТЕХНОТОРГКОМПЛЕКС
    976

Настройка автоматической обработки возвратов 1С-Битрикс

Автоматизация возвратов нужна там, где объём выше 20–30 заявок в день и менеджер тратит существенное время на рутинные операции: проверить оплату заказа, создать возврат в 1С, провести возврат денег, отправить письмо покупателю. Каждое из этих действий можно запустить автоматически при смене статуса заявки — через обработчики событий модуля sale и агенты Битрикс.

Событийная модель возвратов

Модуль sale генерирует события при работе с возвратами. Ключевые точки для автоматизации:

  • OnSaleOrderReturnSaved — создание или обновление заявки
  • OnSaleOrderReturnStatusChange — смена статуса
  • OnSalePaymentCollectionReturnAdd — добавление возврата платежа

Регистрируем обработчики в /local/php_interface/init.php:

$eventManager = \Bitrix\Main\EventManager::getInstance();

$eventManager->addEventHandler('sale', 'OnSaleOrderReturnSaved',
    [\Local\Returns\AutoProcessor::class, 'onReturnSaved']);

$eventManager->addEventHandler('sale', 'OnSaleOrderReturnStatusChange',
    [\Local\Returns\AutoProcessor::class, 'onStatusChange']);

Автоматические действия при создании заявки

namespace Local\Returns;

class AutoProcessor
{
    public static function onReturnSaved(\Bitrix\Main\Event $event): void
    {
        $return = $event->getParameter('ENTITY');
        if (!$return instanceof \Bitrix\Sale\OrderReturn) return;

        // Только при создании (не при обновлении)
        if (!$event->getParameter('IS_NEW')) return;

        $returnId = $return->getId();

        // 1. Назначаем ответственного по ротации
        self::assignResponsible($returnId);

        // 2. Отправляем подтверждение покупателю
        Notifications::sendToCustomer($returnId, 'RETURN_CREATED');

        // 3. Уведомляем менеджера
        Notifications::sendToManager($returnId, 'NEW_RETURN');

        // 4. Если сумма возврата небольшая — автоодобряем
        self::tryAutoApprove($return);
    }

    public static function onStatusChange(\Bitrix\Main\Event $event): void
    {
        $returnId  = $event->getParameter('RETURN_ID');
        $newStatus = $event->getParameter('NEW_STATUS_ID');
        $oldStatus = $event->getParameter('OLD_STATUS_ID');

        $handler = new self();
        $handler->handleStatusTransition($returnId, $oldStatus, $newStatus);
    }

    private function handleStatusTransition(int $returnId, string $from, string $to): void
    {
        match ($to) {
            'APPROVED' => $this->onApproved($returnId),
            'RECEIVED' => $this->onReceived($returnId),
            'REJECTED' => $this->onRejected($returnId),
            'REFUND'   => $this->onRefunded($returnId),
            default    => null,
        };
    }
}

Автоодобрение мелких возвратов

Возвраты до определённой суммы (конфигурируемый порог) не требуют ручной проверки:

private static function tryAutoApprove(\Bitrix\Sale\OrderReturn $return): void
{
    $autoApproveLimit = (float)\Bitrix\Main\Config\Option::get(
        'local.returns', 'auto_approve_limit', 500
    );

    $returnAmount = (float)$return->getField('REFUND_AMOUNT');

    if ($returnAmount <= 0 || $returnAmount > $autoApproveLimit) {
        return;
    }

    // Проверяем: покупатель без истории спорных возвратов
    $userId = $return->getOrder()->getUserId();
    if (self::hasDisputeHistory($userId)) {
        return;
    }

    // Автоматически меняем статус на APPROVED
    $return->setField('STATUS_ID', 'APPROVED');
    $return->setField('MANAGER_COMMENT', 'Автоодобрено: сумма до ' . $autoApproveLimit . ' руб.');
    $result = $return->save();

    if ($result->isSuccess()) {
        \CEventLog::Add([
            'SEVERITY'      => 'INFO',
            'AUDIT_TYPE_ID' => 'RETURN_AUTO_APPROVED',
            'MODULE_ID'     => 'local.returns',
            'DESCRIPTION'   => "Return #{$return->getId()} auto-approved, amount: {$returnAmount}",
        ]);
    }
}

private static function hasDisputeHistory(int $userId): bool
{
    // Считаем отклонённые возвраты за последние 6 месяцев
    $dateFrom = new \Bitrix\Main\Type\Date();
    $dateFrom->add('-180 days');

    $result = \Bitrix\Sale\OrderReturnTable::getList([
        'filter' => [
            '=ORDER.USER_ID' => $userId,
            'STATUS_ID'      => 'REJECTED',
            '>=DATE_INSERT'  => $dateFrom,
        ],
        'select' => ['ID'],
    ]);

    return (bool)$result->fetch();
}

Автоматический возврат денег при одобрении

При переходе в статус «Одобрен» — автоматически инициируем возврат через API платёжной системы:

private function onApproved(int $returnId): void
{
    $return = \Bitrix\Sale\OrderReturn::loadById($returnId);
    if (!$return) return;

    $order    = $return->getOrder();
    $payments = $order->getPaymentCollection();

    foreach ($payments as $payment) {
        if (!$payment->isPaid()) continue;

        $psHandler = \Bitrix\Sale\PaySystem\Manager::getObjectById(
            $payment->getPaymentSystemId()
        );

        if (!$psHandler) continue;

        $supportsRefund = method_exists($psHandler, 'refund');
        if (!$supportsRefund) {
            // Платёжная система не поддерживает автовозврат — ставим в очередь для ручной обработки
            $this->flagForManualRefund($returnId, 'PS does not support auto refund');
            continue;
        }

        $refundAmount = (float)$return->getField('REFUND_AMOUNT');
        $result       = $psHandler->refund($payment, $refundAmount);

        if ($result->isSuccess()) {
            $return->setField('STATUS_ID', 'REFUND');
            $return->setField('REFUND_DATE', new \Bitrix\Main\Type\DateTime());
            $return->save();

            Notifications::sendToCustomer($returnId, 'RETURN_REFUNDED');
        } else {
            $this->flagForManualRefund($returnId, implode('; ', $result->getErrorMessages()));
        }
    }
}

Автоматическая проверка получения товара через трекинг

Если покупатель отправляет товар назад по трекинг-номеру, можно автоматически отслеживать доставку:

class TrackingWatcher
{
    // Агент, запускаемый каждые 2 часа
    public static function checkPendingReturns(): string
    {
        $returns = \Bitrix\Sale\OrderReturnTable::getList([
            'filter' => [
                'STATUS_ID'  => 'APPROVED',
                'UF_TRACKING' => ['!=', '', false], // заявки с трекинг-номером
            ],
            'select' => ['ID', 'UF_TRACKING', 'UF_CARRIER'],
        ]);

        $checker = new \Local\Delivery\TrackingChecker();

        while ($row = $returns->fetch()) {
            $status = $checker->getStatus($row['UF_TRACKING'], $row['UF_CARRIER'] ?? 'pochta');

            if ($status === 'delivered') {
                $return = \Bitrix\Sale\OrderReturn::loadById($row['ID']);
                $return->setField('STATUS_ID', 'RECEIVED');
                $return->save();
            }
        }

        return 'checkPendingReturns();'; // перезапуск агента
    }
}

Эскалация просроченных заявок

Агент для контроля SLA по возвратам:

class SlaWatcher
{
    private const SLA_HOURS = [
        'WAIT'   => 24,  // рассмотреть в течение 24 часов
        'REVIEW' => 48,  // принять решение в течение 48 часов
    ];

    public static function checkOverdue(): string
    {
        foreach (self::SLA_HOURS as $statusId => $maxHours) {
            $deadline = new \Bitrix\Main\Type\DateTime();
            $deadline->add('-' . $maxHours . ' hours');

            $overdueReturns = \Bitrix\Sale\OrderReturnTable::getList([
                'filter' => [
                    'STATUS_ID'    => $statusId,
                    '<=DATE_STATUS' => $deadline,
                ],
                'select' => ['ID', 'RESPONSIBLE_ID', 'ORDER_ID'],
            ]);

            while ($row = $overdueReturns->fetch()) {
                Notifications::escalate($row['ID'], $row['RESPONSIBLE_ID'], $statusId, $maxHours);
            }
        }

        return 'checkOverdue();';
    }
}

Состав работ

  • Обработчики событий: OnSaleOrderReturnSaved, OnSaleOrderReturnStatusChange
  • Логика автоодобрения по сумме и истории покупателя
  • Автовозврат денег через API платёжных систем (ЮKassa, Тинькофф и др.)
  • Агент трекинга входящих посылок (Почта России, СДЭК, Boxberry)
  • Агент SLA-мониторинга с эскалацией просроченных заявок
  • Email-автоматика: шаблоны под каждый статус

Сроки: базовая автоматизация (уведомления + автовозврат денег) — 2–3 недели. Полный стек со SLA-мониторингом и трекингом — 4–6 недель.