Как получить в php список статусов заказов и отгрузок в 1С-Битрикс?

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

Сам список статусов (заказа/отгрузки) можно увидеть в админке 1С-Битрикс в разделе Магазин=>Настройки=>Статусы.

Страница статусов в админке 1с-Битрикс
Страница статусов в админке 1с-Битрикс

Эта страница расположена по адресу /bitrix/admin/sale_status.php попробуем открыть этот файл и видим там:

require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/sale/admin/status.php");

Идем по указанному пути ... и находим внутри файла код формирования данной страницы. Немного посмотрев обнаруживаем интересные строки напоминающие формирование запроса к БД:

$query = \Bitrix\Sale\Internals\StatusTable::query();
$query->setSelect([
	'ID', 'SORT', 'TYPE', 'NOTIFY', 'LID' => 'STATUS_LANG.LID',
	'COLOR' ,'NAME' => 'STATUS_LANG.NAME', 'DESCRIPTION' => 'STATUS_LANG.DESCRIPTION'
]);
$query->where(
	\Bitrix\Main\ORM\Query\Query::filter()
		->logic('OR')
		->where('STATUS_LANG.LID', '=', LANGUAGE_ID)
		->where('STATUS_LANG.LID', NULL)
);

Как оказалось \Bitrix\Sale\Internals это пространство имен с классами для работы с таблицами БД модуля интернет-магазин, а вышеприведенный код использует функционал ORM 1С-Битрикс. Классы из \Bitrix\Sale\Internals подгружаются в файле /bitrix/modules/sale/autoload.php. наследуются от \Main\Entity\DataManager.

Это сообщение на странице документации. Не рекомендуется, но целый модуль построен на этом :)
Это сообщение на странице документации. Не рекомендуется, но целый модуль построен на этом :)

Быстренько читаем что там по вышеприведенным ссылкам и пробуем разобраться в коде.

Сначала нужно получить объект запроса:

$query = \Bitrix\Sale\Internals\StatusTable::query();

Теперь нужно указать что будем выбирать из таблицы (таблица выборки уже указана в самом классе):

$query->setSelect([
	'ID', 'SORT', 'TYPE', 'NAME' => 'STATUS_LANG.NAME'
]);

В моей задаче требовалось выбрать все статусы относящиеся к доставке, поэтому доавляем условие TYPE='D':

$query->where(
	\Bitrix\Main\ORM\Query\Query::filter()
		->logic("AND")
		->where('TYPE', '=', "D")
);

Хотелось бы поставить фильтр по языку STATUS_LANG.LID=LANGUAGE_ID, чтобы показывать для каждого языка поддерживаемого сайтом определенный статус (и те строки для которых язык не определен STATUS_LANG.LID = NULL):

$query->where(
	\Bitrix\Main\ORM\Query\Query::filter()
		->logic('OR')
		->where('STATUS_LANG.LID', '=', LANGUAGE_ID)
		->where('STATUS_LANG.LID', NULL)
);

Устанавливаем сортировку по полю SORT в прямом порядке:

$query->setOrder(["SORT" => "ASC"]);

На этом этапе можно посмотреть как будет выглядеть наш запрос к БД таким образом $query->getQuery();, получим что-то подобное:

SELECT 
	`sale_internals_status`.`ID` AS `ID`,
	`sale_internals_status`.`SORT` AS `SORT`,
	`sale_internals_status`.`TYPE` AS `TYPE`,
	`sale_internals_status_status_lang`.`NAME` AS `NAME`
FROM `b_sale_status` `sale_internals_status` 
LEFT JOIN `b_sale_status_lang` `sale_internals_status_status_lang` ON `sale_internals_status`.`ID` = `sale_internals_status_status_lang`.`STATUS_ID`
WHERE `sale_internals_status`.`TYPE` = 'D' AND (`sale_internals_status_status_lang`.`LID` = 'ru' OR `sale_internals_status_status_lang`.`LID` IS NULL)
ORDER BY `SORT` ASC

Казалось бы несколько строк кода php, а сгенерирован SQL с JOIN. Все потому что ORM и внутри уже настроены связи между объектами.

Теперь выполняем запрос и распределяем данные запроса по ассоциативному массиву:

$aRes = $query->exec()->fetchAll();
foreach($aRes as $value)
	$a[$value["ID"]] = $value["NAME"];

В итоге получим что-то подобное:

Array
(
  [DN] => Ожидает обработки
  [DA] => Комплектация заказа
  [DG] => Ожидаем приход товара
  [DT] => Ожидаем забора транспортной компанией
  [DS] => Передан в службу доставки
  [DF] => Отгружен
)