Свойства заказа - чтение, запись и фильтрация по значению
Читаем и пишем свойства заказа, выбираем заказы по значению и убираем поля, которых быть не должно.
Решение
Читаем все свойства заказа с их кодами:
$order = Bitrix\Sale\Order::load($orderId); // коллекция свойств живёт у заказа// у нового заказа коллекция собирается по типу плательщика, а не из базыforeach ($order->getPropertyCollection() as $property) { printf("%-4d %-22s %-14s %s\n", $property->getPropertyId(), $property->getField('CODE'), $property->getField('TYPE'), (string)$property->getValue());}Коллекция собирается по типу плательщика заказа. У физлица и у организации это разные наборы, поэтому обходить её надо целиком, а не брать поля по номеру.
Пишем значение и сохраняем:
$props = $order->getPropertyCollection();$props->getPhone()->setValue('+7 900 123-45-67');$props->getItemByOrderPropertyId(15)->setValue('Москва, Тверская, 1');$order->save();Методы getPhone, getUserEmail и getPayerName возвращают не любое свойство с
похожим названием, а то, у которого в настройках стоит признак назначения.
Остальные берут по идентификатору.
Выбираем заказы по значению свойства:
$rows = Bitrix\Sale\Internals\OrderPropsValueTable::getList([ 'select' => ['ORDER_ID', 'VALUE'], 'filter' => ['=ORDER_PROPS_ID' => 15, '%VALUE' => 'Тверская'], 'limit' => 50,]);foreach ($rows as $row) { echo "{$row['ORDER_ID']}: {$row['VALUE']}\n";}Значения свойств лежат в отдельной таблице, поэтому фильтр по ним - это условие
по ORDER_PROPS_ID, а не по имени поля заказа. Свойство типа «дата» хранится
строкой, и сравнение по диапазону на нём не работает.
Убираем лишнее поле из формы заказа:
CSaleOrderProps::Update($propertyId, ['ACTIVE' => 'N']); // скрыть, но сохранить значенияСвойство отключают, а не удаляют: удаление уносит значения по всем прежним заказам. Скрытое свойство остаётся в истории и продолжает читаться кодом.
Считаем, у скольких заказов свойство заполнено:
$filled = Bitrix\Sale\Internals\OrderPropsValueTable::getCount([ '=ORDER_PROPS_ID' => $propertyId, '!=VALUE' => '',]);echo "заполнено у {$filled} заказов\n";Перед отключением свойства этот счётчик показывает, что именно уйдёт из формы. Ноль означает, что поле спрашивали зря, и его можно убирать без сожалений.
Смотрим, каким типам плательщиков свойство привязано:
$links = CSaleOrderProps::GetList([], ['ID' => $propertyId], false, false, ['ID', 'CODE', 'PERSON_TYPE_ID', 'ACTIVE', 'REQUIRED']);while ($row = $links->Fetch()) { printf("%-18s тип плательщика %d, обязательное=%s\n", $row['CODE'], $row['PERSON_TYPE_ID'], $row['REQUIRED']);}Одно свойство принадлежит одному типу плательщика. Одинаковый вопрос в двух формах - это две записи справочника, и правят их по отдельности. Забытая вторая запись и даёт классическую жалобу «у юрлиц поле осталось».
Порядок свойств в форме задаётся сортировкой, а группировка - разделами формы заказа. И то и другое настраивается у свойства, а не в шаблоне компонента: шаблон только рисует то, что пришло в результате.
Типичные проблемы
Свойства заполнены, а в заказе пусто.
Значения записаны до создания отгрузки и платежа. Эти операции пересобирают коллекцию свойств, поэтому её заполняют последней, перед самым сохранением.
Код работает на физлице и падает на организации.
Свойство берётся по жёстко заданному идентификатору. У другого типа плательщика тот же вопрос покупателю - это другое свойство с другим номером.
В админке при добавлении товара появляются лишние свойства.
Свойства привязаны ко всем типам плательщиков сразу. Ненужные отвязывают от конкретного типа, а не удаляют из справочника.
Фильтр по свойству типа «дата» ничего не находит.
Значение хранится строкой в формате сайта. Диапазон по нему не работает: либо сравнивают строки целиком, либо заводят отдельное свойство под нужный формат.
Частые вопросы
Как получить свойство заказа, не загружая весь заказ?
Прямой выборкой из OrderPropsValueTable по идентификатору заказа и свойства. Это дешевле полной загрузки, но объект заказа при этом не создаётся, и менять значение так нельзя.
Можно ли завести своё свойство только для одного сайта?
Да, свойства привязываются к типу плательщика, а типы плательщиков - к сайту. На мультисайте это штатный способ развести формы заказа.
Почему свойство не приходит в 1С?
В выгрузку попадают свойства с признаком обмена и заполненным внешним кодом. Свойство без кода на сайте живёт, а в файле обмена его нет.
Как сделать свойство обязательным только на одном шаге оформления?
Штатной настройки для этого нет: обязательность задаётся у свойства целиком. Условную проверку делают своим кодом на событии проверки заказа.
Смежное
-
Заказы - оглавление подтемы
-
Источник заказа: метки в адресе, хранение, отчёт - типовое служебное свойство заказа
-
Своё поле в оформлении заказа: свойство, группа, свой тип - как завести новое свойство заказа
-
Местоположения: импорт, свойство заказа, доставки и индекс - свойство особого типа и его справочник
-
Настройка магазина по шагам: что за чем включать - порядок настройки всего магазина
-
Статусы заказов - смена статуса и события
-
Свои номера документов и заявок: шаблон, счётчики, уникальность - номера для своих документов по заказу
-
Каталог и продажи - заказ и его коллекции
-
Обмен заказами с 1С - какие свойства уезжают в учётную систему
-
Не работает оформление заказа - почему форма оформления показывает пустую корзину
-
Заказ из кода: чтение, поиск по номеру, изменение состава - чтение свойств из объекта заказа
-
Состав заказа и контрагенты при обмене: позиции, покупатели, дубли - как свойства становятся реквизитами контрагента
-
Заказ для юрлица: тип плательщика, реквизиты, счёт - реквизиты организации в свойствах заказа
-
Профиль покупателя - откуда свойства заказа берут значения при повторном оформлении