crm.productrow.set — универсальный метод для установки товарных позиций у любой сущности CRM: сделки, счёта нового поколения, предложения или элемента смарт-процесса. Он заменяет весь набор строк владельца целиком и пришёл на смену узкоспециализированному crm.deal.productrows.set.
Зачем нужен универсальный метод
Раньше товары каждой сущности задавались своим методом: crm.deal.productrows.set, crm.lead.productrows.set и так далее. С появлением смарт-процессов и счетов нового поколения потребовался единый интерфейс, который работает с любым владельцем через указание его типа.
crm.productrow.set— заменить весь набор строк владельца;crm.productrow.get— получить строки владельца;crm.productrow.list— выборка строк по фильтру;crm.productrow.add/delete— операции с отдельной строкой;crm.productrow.fields— описание полей позиции.
set не добавляет строки к существующим, а полностью перезаписывает состав. Чтобы добавить одну позицию к текущим, сначала получите список через get, дополните его и отправьте целиком.Идентификация владельца
Владелец задаётся двумя параметрами: ownerType — символьный код типа сущности, и ownerId — её идентификатор.
| Сущность | ownerType |
|---|---|
| Сделка | D |
| Лид | L |
| Предложение | Q |
| Счёт (новый) | SI |
| Элемент смарт-процесса | T + ID типа, напр. T176 |
Именно поддержка смарт-процессов делает crm.productrow.set предпочтительным: узкие методы вроде deal.productrows не умеют работать с товарами динамических сущностей.
Установка позиций: пример запроса
Зададим две товарные позиции для сделки 340:
POST /rest/1/xxxxxxxx/crm.productrow.set.json
{
"ownerType": "D",
"ownerId": 340,
"productRows": [
{
"productId": 27,
"productName": "Насос центробежный",
"price": 15000,
"quantity": 2,
"taxRate": 20,
"taxIncluded": "Y"
},
{
"productName": "Доставка",
"price": 2000,
"quantity": 1,
"taxRate": 20,
"taxIncluded": "Y"
}
]
}Поле productId ссылается на товар каталога; для произвольной строки его можно опустить, оставив только productName и цену. Полный перечень полей — в crm.productrow.fields.
Поля товарной позиции
Строка описывается набором ценовых и налоговых полей. Самые важные из них:
productId— ID товара каталога;price— цена за единицу с учётом настроек налога;quantity— количество;discountRate/discountSum— скидка в процентах или сумме;taxRate— ставка налога,taxIncluded— включён ли налог в цену (Y/N);measureCode/measureName— единица измерения.
discountSum, поле price трактуется как итоговая цена позиции. Несогласованные price и скидка приводят к неожиданной сумме сделки.Пересчёт суммы сделки
После установки товаров сумма владельца пересчитывается автоматически, если поле суммы не зафиксировано вручную. У сделки за это отвечает флаг IS_MANUAL_OPPORTUNITY.
- Если
IS_MANUAL_OPPORTUNITY= N — суммаOPPORTUNITYбудет рассчитана из товарных строк; - Если = Y — сумма зафиксирована и не изменится при обновлении товаров;
- Чтобы товары «управляли» суммой, при обновлении сделки установите флаг в N.
POST /rest/1/xxxxxxxx/crm.deal.update.json
{ "id": 340, "fields": { "IS_MANUAL_OPPORTUNITY": "N" } }Типичный сценарий интеграции с 1С: сначала установить товары через crm.productrow.set, затем убедиться, что сумма сделки не заморожена вручную.
Стоит понимать разницу между суммой и валютой. Сумма считается в валюте владельца (CURRENCY_ID сделки), поэтому если товар в каталоге хранится в другой валюте, цену нужно передавать уже приведённой к валюте сделки — автоматической конвертации по курсу в момент установки строк не происходит. Отдельно проверяйте налоговую модель портала: поле taxIncluded имеет смысл только когда в настройках CRM включён учёт налога, иначе значение игнорируется. Эти детали особенно важны при выгрузке заказов из внешней учётной системы, где цены и налоги уже рассчитаны и их нельзя искажать.
Практика и подводные камни
| Ситуация | Причина | Решение |
|---|---|---|
| Старые товары не удалились | Ожидали, что set добавит | set перезаписывает — присылайте полный набор |
| Сумма сделки не изменилась | IS_MANUAL_OPPORTUNITY = Y | Сбросить флаг в N |
| Товар каталога не связался | Не передан productId | Указать ID из crm.product.list |
| Ошибка на смарт-процессе | Использован crm.deal.productrows | Только crm.productrow.set с ownerType T+ID |
Для массовой загрузки заказов оборачивайте установку товаров в batch, но помните про лимит на размер запроса: очень длинные спецификации разбивайте на части и используйте отдельную сущность-владельца на каждый заказ.
Ещё одна деталь касается связи товарной строки с каталогом. Если вы указали productId, но затем в каталоге товар был удалён, строка сохранит своё название и цену, однако перестанет корректно учитываться в товарной аналитике. Поэтому при обмене с внешней системой полезно хранить у себя соответствие «внешний артикул → productId каталога» и поддерживать его в актуальном состоянии через crm.product.list. Так вы гарантируете, что позиции сделок всегда ссылаются на действительные товары, а отчёты по продажам остаются достоверными.
Итог
crm.productrow.set — правильный выбор для установки товаров в современных сценариях, потому что работает единообразно со сделками, счетами и смарт-процессами. Помните два правила: метод перезаписывает весь набор строк, а автоматический пересчёт суммы зависит от флага IS_MANUAL_OPPORTUNITY. Согласованность цены, скидки и налога — залог корректной итоговой суммы.
Мы переносим состав заказов из сайта и 1С в сделки и счета Битрикс24 с сохранением цен, скидок и налогов, а также настраиваем пересчёт сумм. Если нужна точная выгрузка товарных позиций в CRM — поможем с интеграцией и обменом данными.
Частые вопросы
Чем crm.productrow.set лучше crm.deal.productrows.set?
Универсальностью: один метод обслуживает сделки, счета, предложения и смарт-процессы через параметр ownerType. Старые методы работают только со своей конкретной сущностью.
Метод добавляет строки или заменяет их?
Заменяет весь набор целиком. Чтобы дополнить состав, сначала получите текущие строки через crm.productrow.get, добавьте новые и отправьте полный список обратно.
Как задать товар для смарт-процесса?
В ownerType укажите T с идентификатором типа смарт-процесса, например T176, а в ownerId — ID элемента. Узкие методы сделок для смарт-процессов не подходят.
Почему сумма сделки не пересчитывается после установки товаров?
Скорее всего у сделки включён флаг IS_MANUAL_OPPORTUNITY равный Y, то есть сумма зафиксирована вручную. Сбросьте флаг в N, чтобы товары определяли сумму.
Обязательно ли указывать productId?
Нет. Для произвольной строки достаточно productName и цены. productId нужен, чтобы связать позицию с товаром каталога и учитывать её в товарной аналитике.
Как правильно задать скидку?
Используйте discountRate для процента или discountSum для суммы. Следите за согласованностью с price, иначе итоговая стоимость позиции окажется неожиданной.
Можно ли грузить большие спецификации?
Да, но учитывайте лимит на размер запроса. Длинные списки товаров разбивайте на части и выполняйте установку через batch по нескольким владельцам.
Поможем с настройкой и поддержкой Для разработчиков
Поможем с настройкой, доработкой и поддержкой Для разработчиков.