Перейти к содержимому

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

Настраиваем двусторонний обмен заказами с 1С и разбираемся, почему заказы дублируются, а статусы не возвращаются.

Решение

Включаем обмен заказами и протоколирование:

COption::SetOptionString('sale', 'secure_1c_exchange', 'N'); // без шифрования пакета
COption::SetOptionString('sale', 'log_level_1c', '3'); // лог выключен по умолчанию
COption::SetOptionString('sale', '1C_SALE_EXPORT_PAYED', 'Y'); // выгружать оплаченные
// уровень протоколирования выше нуля пишет каждый шаг сеанса обмена

Лог заказов пишется в /upload/1c_exchange/ и по умолчанию выключен. Без него разбирать сбой нечем: окно 1С показывает только итог сеанса.

Сопоставляем статусы сайта со статусами 1С:

$statuses = CSaleStatus::GetList([], [], false, false, ['ID', 'NAME', 'XML_ID']);
while ($status = $statuses->Fetch()) {
printf("%-4s %-24s xml_id=%s\n", $status['ID'], $status['NAME'], $status['XML_ID']);
}

Статус с пустым внешним кодом заведён на сайте руками, и возврат из 1С в него не попадёт. Заказ при этом обменяется успешно, а статус останется прежним.

Это одна из самых обидных поломок обмена заказами: ошибки нет нигде, лог чистый, а менеджер видит в админке вчерашний статус. Проверять сопоставление стоит сразу после первого успешного сеанса, а не когда накопится сотня расхождений.

Смотрим, какие заказы уже выгружены:

$orders = Bitrix\Sale\Internals\OrderTable::getList([
'select' => ['ID', 'ACCOUNT_NUMBER', 'STATUS_ID', 'UPDATED_1C', 'VERSION_1C'],
'filter' => ['=UPDATED_1C' => 'Y'],
'limit' => 20,
]);
foreach ($orders as $order) {
print_r($order);
}

Поле UPDATED_1C помечает заказы, побывавшие в обмене, VERSION_1C хранит версию от 1С. По ним отличают «ещё не выгружался» от «выгружался, но не обновился».

Ищем дубли по составу и номеру:

SELECT ACCOUNT_NUMBER, COUNT(*) AS cnt, GROUP_CONCAT(ID) AS ids
FROM b_sale_order
GROUP BY ACCOUNT_NUMBER
HAVING cnt > 1;

Сопоставление идёт по номеру заказа, а не по внутреннему идентификатору. Смена нумерации на живом магазине - самая частая причина, по которой 1С перестаёт узнавать прежние заказы и заводит их заново.

Снимаем отметку выгрузки, чтобы отдать заказ в 1С заново:

Bitrix\Sale\Internals\OrderTable::update($orderId, [
'UPDATED_1C' => 'N', // следующий сеанс заберёт заказ как новый
'VERSION_1C' => '', // версия от 1С сбрасывается вместе с отметкой
]);

Так возвращают в обмен заказы, созданные до его включения. Делать это лучше пачками по сотне: годовая история за один сеанс укладывает обмен в таймаут.

Отсюда правило: нумерацию заказов выбирают до запуска обмена и больше не трогают. Префикс, счётчик, формат номера - всё это часть договорённости с учётной системой, а не оформление письма покупателю. Менять формат на работающем обмене означает разорвать связь по всем прежним заказам разом.

Типичные проблемы

При каждом обмене заказы задваиваются.

Номер заказа изменился после создания: включили свою нумерацию или префикс. Сопоставление идёт по ACCOUNT_NUMBER, и 1С не находит прежний заказ.

Статус из 1С не применяется к заказу.

У статуса на сайте пустой внешний код. Возврат статуса сопоставляется по XML_ID, названия при этом не используются вовсе.

Заказ уехал, а позиции в 1С неопознанные.

Внешние коды товаров разошлись. Заказ сам по себе выгрузится, но подбор номенклатуры в 1С не сработает, и строки придётся сопоставлять руками.

В логе пусто, хотя обмен идёт.

Протоколирование обмена заказами выключено по умолчанию и включается отдельно от лога каталога, настройкой модуля продаж.

Выгружаются не все заказы.

В настройках ограничен список типов плательщиков или выгружаются только оплаченные. Заказы других типов обмен просто не берёт.

Частые вопросы

Как обмениваться заказами на мультисайте?

Каждый сайт выгружается отдельным узлом обмена со своим адресом и своим пользователем. Разделить потоки внутри одного узла нечем: обмен работает в контексте одного сайта.

Можно ли выгрузить в 1С заказы, созданные до включения обмена?

Да, у них снимают отметку UPDATED_1C, и следующий сеанс заберёт их как новые. Делать это лучше пачками: разовая выгрузка годовой истории укладывает сеанс в таймаут.

Что происходит с заказом, если его правят и на сайте, и в 1С?

Побеждает 1С: при возврате она перезаписывает поля заказа целиком. Поля, которые ведёт сайт, защищают обработчиком на событиях сохранения заказа, по тому же принципу, что и свойства товара.

Как выгрузить офлайн-заказы из 1С на сайт?

Тем же обменом: 1С шлёт их как обычные заказы, а сайт создаёт недостающие. Покупателя при этом сопоставляют по электронной почте, поэтому у офлайн-клиентов её надо заполнять.

Смежное

Первоисточник