Как маркировать предупреждения в Bitrix\Sale
Проблема/контекст
В sale не каждая проблемная ситуация должна ронять сохранение заказа. Часто интеграция с доставкой, кассой или внутренней проверкой находит состояние, которое нужно показать оператору, но не превращать в фатальную ошибку. В ядре для этого есть не только поля MARKED и REASON_MARKED, но и отдельный механизм Bitrix\Sale\EntityMarker: он берет warnings из Bitrix\Sale\Result, создает marker-записи, записывает последнюю причину в заказ и помечает оплату или отгрузку как проблемную.
Практически это значит: если вы уже возвращаете Result с предупреждениями, не дублируйте еще один собственный реестр проблем. Используйте штатный контур Sale.
Решение с кодом
Ключевой момент в ядре такой: EntityMarker::addMarker() работает именно с warnings, а не с обычными errors. Поэтому для нефатального кейса нужен Bitrix\Sale\ResultWarning.
<?php
declare(strict_types=1);
use Bitrix\Main\Loader;
use Bitrix\Sale\EntityMarker;
use Bitrix\Sale\Order;
use Bitrix\Sale\Result;
use Bitrix\Sale\ResultWarning;
use Bitrix\Sale\Shipment;
Loader::includeModule('sale');
function markShipmentIntegrationWarning(Order $order, Shipment $shipment): void
{
$result = new Result();
// Нефатальная проблема: заказ сохранять можно, но отгрузку нужно подсветить оператору
$result->addWarning(new ResultWarning(
'Не удалось подтвердить трек-номер во внешней службе доставки',
'SHIPMENT_TRACKING_SYNC_WARNING'
));
EntityMarker::addMarker($order, $shipment, $result);
EntityMarker::saveMarkers($order);
$saveResult = $order->save();
if (!$saveResult->isSuccess())
{
throw new \RuntimeException(implode('; ', $saveResult->getErrorMessages()));
}
}
После этого в заказ попадет REASON_MARKED, у отгрузки выставится MARKED = 'Y', а сам marker сохранится в таблице маркеров. Это важнее простого $shipment->setField('MARKED', 'Y'): в ядре сохраняются код проблемы, тип маркера (AUTO или MANUAL) и статус успешности исправления.

Когда причина уже устранена, снимайте проблему не только с поля, но и с marker-записи. Для этого можно удалить маркеры сущности и пересчитать состояние заказа через refreshMarkers().
<?php
declare(strict_types=1);
use Bitrix\Sale\EntityMarker;
use Bitrix\Sale\Order;
use Bitrix\Sale\Shipment;
function clearShipmentMarkers(Order $order, Shipment $shipment): void
{
// deleteByEntity() работает только для уже сохраненной сущности с ID
EntityMarker::deleteByEntity($shipment);
EntityMarker::refreshMarkers($order);
$saveResult = $order->save();
if (!$saveResult->isSuccess())
{
throw new \RuntimeException(implode('; ', $saveResult->getErrorMessages()));
}
}
Итог
EntityMarker в sale нужен не для декоративного флага, а для нормального жизненного цикла предупреждений. Если проблема не фатальна, но должна остаться в истории и интерфейсе заказа, сохраняйте ее как marker, а после исправления очищайте через API маркеров, а не только через поле MARKED.
Комментарии (0)
Пожалуйста, войдите в аккаунт, чтобы оставить комментарий
Оставить комментарийПока нет ни одного комментария. Будьте первым!
Похожие советы