PHP
#bitrix#sale#order#php#d7#status#save

D7: Изменить статус заказа и сохранить

Изменение статуса заказа через setField() и сохранение через save() с обработкой результата и ошибок.

Как использовать

  1. Подключите модуль sale, загрузите заказ через Order::load($orderId), установите статус setField('STATUS_ID', $newStatusId) и вызовите save().
  2. Проверяйте результат через isSuccess() и getErrorMessages(); проверьте существование статуса через CSaleStatus::GetByID().
  3. Используйте в обработчиках платежей, агентах или админ-действиях после проверки оплаты/доставки.

В 1С-Битрикс заказы в D7 меняют через объект Order: без вызова save() изменения в БД не попадают. При автоматизации (оплата, доставка, интеграции) нужно единообразно ставить новый статус, обрабатывать ошибки и не полагаться на то, что статус «сам сохранится». Проблема возникает в обработчиках платежей, агентах и админке: вызвали setField('STATUS_ID', 'P'), но забыли save() или не проверили результат — статус в интерфейсе не меняется или скрипт падает без понятной ошибки. Симптомы: заказ остаётся в старом статусе после оплаты, либо в логах пустая ошибка. Ниже — функция с проверкой существования статуса, вызовом save() и возвратом результата с прежним/новым статусом и текстом ошибки; плюс как проверить изменение в БД.

Решение

Изменение статуса заказа через D7 API с сохранением и обработкой результата. Используйте в обработчиках платежей, агентах, админ-панели для автоматического изменения статусов заказов.

use Bitrix\Main\Loader;
use Bitrix\Sale\Order;
use Bitrix\Main\Error;

/**
 * Изменить статус заказа
 * @param int $orderId ID заказа
 * @param string $newStatusId Новый статус (например, 'F', 'P', 'N')
 * @return array ['success' => bool, 'error' => string]
 */
function changeOrderStatus($orderId, $newStatusId) {
    if (!Loader::includeModule('sale')) {
        return ['success' => false, 'error' => 'Модуль sale не подключен'];
    }
    
    // Проверяем существование статуса
    $status = \CSaleStatus::GetByID($newStatusId);
    if (!$status) {
        return ['success' => false, 'error' => 'Статус не найден'];
    }
    
    $order = Order::load($orderId);
    if (!$order) {
        return ['success' => false, 'error' => 'Заказ не найден'];
    }
    
    // Получаем текущий статус
    $currentStatus = $order->getField('STATUS_ID');
    
    // Устанавливаем новый статус
    $result = $order->setField('STATUS_ID', $newStatusId);
    
    if (!$result->isSuccess()) {
        $errors = $result->getErrorMessages();
        return ['success' => false, 'error' => implode(', ', $errors)];
    }
    
    // Сохраняем заказ
    $saveResult = $order->save();
    
    if (!$saveResult->isSuccess()) {
        $errors = $saveResult->getErrorMessages();
        return ['success' => false, 'error' => implode(', ', $errors)];
    }
    
    return [
        'success' => true,
        'error' => '',
        'old_status' => $currentStatus,
        'new_status' => $newStatusId
    ];
}

Пример использования:

// В обработчике платежа или агенте
$result = changeOrderStatus(12345, 'P'); // P - оплачен

if ($result['success']) {
    echo 'Статус изменён с ' . $result['old_status'] . ' на ' . $result['new_status'];
} else {
    echo 'Ошибка: ' . $result['error'];
}

// Изменить на статус "Выполнен"
changeOrderStatus(12345, 'F');

После setField() обязательно вызывайте save() для применения изменений. Метод save() возвращает Result с isSuccess() и getErrorMessages(). Статусы должны существовать в системе (N — новый, P — оплачен, F — выполнен, C — отменён и т.д.). Изменение статуса может вызвать события OnSaleOrderSaved.

Проверка

  1. Проверить, что статус сохранился в БД — после вызова функции загрузите заказ снова и прочитайте поле:
$order = \Bitrix\Sale\Order::load(12345);
echo $order->getField('STATUS_ID'); // ожидаем новый статус, например P
  1. Диагностика списка статусов — убедиться, что используемый код статуса есть в системе:
$status = \CSaleStatus::GetByID('P');
var_dump($status); // массив с ID, NAME и т.д. или false
  1. Проверка в админке — заказ → карточка заказа → поле «Статус». Должен отображаться новый статус после выполнения скрипта (обработчик или агент).

Типичные ошибки

  • Статус в коде не меняется — не вызван save() после setField(). В D7 все изменения применяются только после $order->save().
  • Ошибка «Статус не найден» — передан несуществующий ID статуса. Проверьте коды в настройках продаж (Настройки → Настройки продукта → Статусы заказов) или через CSaleStatus::GetList().
  • Заказ не найден (Order::load возвращает null) — неверный ID заказа или заказ удалён. Проверьте наличие заказа в БД (таблица заказов модуля sale).
  • События при смене статуса — если подписаны обработчики на OnSaleOrderSaved, они выполнятся при save(); учитывайте рекурсию или тяжёлую логику в обработчиках. См. Клонирование заказа со статусом при необходимости копирования заказа.

Где применять

  • Prod / dev: обработчики оплаты (внутренние платёжные системы, webhook от платёжного шлюза), агенты (автосмена статуса по времени), админ-действия, интеграции с 1С/CRM.
  • Локально: вызовите функцию из скрипта в корне сайта с подключённым прологом Bitrix или из тестовой страницы в админке.

Связанные сниппеты: Получение платежей и отгрузок заказа, Сопоставление статуса заказа и режим запроса, PHP 8.5: клонирование заказа со статусом.