Настройка автоматической обработки возвратов 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 недель.







