crm.quote.productrows.set
Установить товарные позиции предложения
Описание
Метод crm.quote.productrows.set создает или обновляет товарные позиции коммерческого предложения.
Чтобы изменить только одну позицию, используйте методы crm.item.productrow.*.
Параметры
id
integer
обязательный
Идентификатор коммерческого предложения.
Идентификатор можно получить с помощью методов crm.quote.list или crm.quote.add
rows
object[]
необязательный
Массив товарных позиций.
Формат элемента массива:
{
"field_1": "value_1",
"field_2": "value_2",
"...": "..."
}
где:
- field_n — название поля товарной позиции
- value_n — значение поля
Список основных полей описан ниже
Список доступных полей у товарных позиций
PRODUCT_ID
integer
необязательный
Идентификатор товара в каталоге.
Список товаров можно получить методом catalog.product.list.
Если PRODUCT_ID = 0, позиция создается как «произвольная»
PRODUCT_NAME
string
необязательный
Наименование товарной позиции
PRODUCT_DESCRIPTION
string
необязательный
Описание товарной позиции
PRICE
double
необязательный
Итоговая стоимость товара за единицу
QUANTITY
double
необязательный
Количество единиц товара
DISCOUNT_TYPE_ID
integer
необязательный
Тип скидки:
- 1 — абсолютная
- 2 — процентная
DISCOUNT_RATE
double
необязательный
Значение скидки в процентах
DISCOUNT_SUM
double
необязательный
Абсолютное значение скидки
TAX_RATE
double
необязательный
Ставка налога в процентах
TAX_INCLUDED
char
необязательный
Включен ли налог в стоимость:
- Y — да
- N — нет
MEASURE_CODE
catalog_measure.code
необязательный
Код единицы измерения
MEASURE_NAME
string
необязательный
Текстовое представление единицы измерения
SORT
integer
необязательный
Сортировка
Примеры запроса
curl -X POST \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{"id":1,"rows":[{"PRODUCT_ID":459,"PRICE":3000,"QUANTITY":1,"DISCOUNT_TYPE_ID":2,"DISCOUNT_RATE":0,"TAX_RATE":0,"TAX_INCLUDED":"Y","MEASURE_CODE":796,"MEASURE_NAME":"шт","SORT":10},{"PRODUCT_NAME":"Услуга сопровождения","PRICE":1500,"QUANTITY":2,"DISCOUNT_TYPE_ID":2,"DISCOUNT_RATE":0,"TAX_RATE":0,"TAX_INCLUDED":"Y","MEASURE_CODE":796,"MEASURE_NAME":"шт","SORT":20}]}' \
https://**put_your_bitrix24_address**/rest/**put_your_user_id_here**/**put_your_webhook_here**/crm.quote.productrows.set
curl -X POST \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{"id":1,"rows":[{"PRODUCT_ID":459,"PRICE":3000,"QUANTITY":1,"DISCOUNT_TYPE_ID":2,"DISCOUNT_RATE":0,"TAX_RATE":0,"TAX_INCLUDED":"Y","MEASURE_CODE":796,"MEASURE_NAME":"шт","SORT":10},{"PRODUCT_NAME":"Услуга сопровождения","PRICE":1500,"QUANTITY":2,"DISCOUNT_TYPE_ID":2,"DISCOUNT_RATE":0,"TAX_RATE":0,"TAX_INCLUDED":"Y","MEASURE_CODE":796,"MEASURE_NAME":"шт","SORT":20}],"auth":"**put_access_token_here**"}' \
https://**put_your_bitrix24_address**/rest/crm.quote.productrows.set
// This snippet is an ES module: top-level await requires type="module" or a bundler.
// $b24 is an already-initialized SDK instance (see the SDK "Get started" guide).
import { Text } from '@bitrix24/b24jssdk'
import type { B24Frame } from '@bitrix24/b24jssdk'
declare const $b24: B24Frame
try {
const response = await $b24.actions.v2.call.make<boolean>({
method: 'crm.quote.productrows.set',
params: {
id: 1,
rows: [
{
PRODUCT_ID: 459,
PRICE: 3000,
QUANTITY: 1,
DISCOUNT_TYPE_ID: 2,
DISCOUNT_RATE: 0,
TAX_RATE: 0,
TAX_INCLUDED: 'Y',
MEASURE_CODE: 796,
MEASURE_NAME: 'pcs',
SORT: 10,
},
{
PRODUCT_NAME: 'Support service',
PRICE: 1500,
QUANTITY: 2,
DISCOUNT_TYPE_ID: 2,
DISCOUNT_RATE: 0,
TAX_RATE: 0,
TAX_INCLUDED: 'Y',
MEASURE_CODE: 796,
MEASURE_NAME: 'pcs',
SORT: 20,
},
],
},
requestId: Text.getUuidRfc4122()
})
// The payload is available only on a successful response
if (!response.isSuccess) {
console.error(response.getErrorMessages().join('; '))
} else {
const result = response.getData()!.result
console.info('Product rows saved:', result)
}
} catch (error) {
// Thrown on transport or SDK failures (AjaxError, SdkError, etc.)
console.error(error)
}
<!-- Load the SDK (UMD build); it is exposed as the global B24Js -->
<script src="https://unpkg.com/@bitrix24/b24jssdk@1/dist/umd/index.min.js"></script>
<script>
async function setQuoteProductRows() {
try {
// Initialize the SDK inside a Bitrix24 frame
const $b24 = await B24Js.initializeB24Frame()
const response = await $b24.actions.v2.call.make({
method: 'crm.quote.productrows.set',
params: {
id: 1,
rows: [
{
PRODUCT_ID: 459,
PRICE: 3000,
QUANTITY: 1,
DISCOUNT_TYPE_ID: 2,
DISCOUNT_RATE: 0,
TAX_RATE: 0,
TAX_INCLUDED: 'Y',
MEASURE_CODE: 796,
MEASURE_NAME: 'pcs',
SORT: 10,
},
{
PRODUCT_NAME: 'Support service',
PRICE: 1500,
QUANTITY: 2,
DISCOUNT_TYPE_ID: 2,
DISCOUNT_RATE: 0,
TAX_RATE: 0,
TAX_INCLUDED: 'Y',
MEASURE_CODE: 796,
MEASURE_NAME: 'pcs',
SORT: 20,
},
],
},
requestId: B24Js.Text.getUuidRfc4122()
})
// The payload is available only on a successful response
if (!response.isSuccess) {
console.error(response.getErrorMessages().join('; '))
return
}
const result = response.getData().result
console.info('Product rows saved:', result)
} catch (error) {
// Thrown on transport or SDK failures (AjaxError, SdkError, etc.)
console.error(error)
}
}
document.addEventListener('DOMContentLoaded', setQuoteProductRows)
</script>
try {
$response = $b24Service
->core
->call(
'crm.quote.productrows.set',
[
'id' => 1,
'rows' => [
[
'PRODUCT_ID' => 459,
'PRICE' => 3000,
'QUANTITY' => 1,
'DISCOUNT_TYPE_ID' => 2,
'DISCOUNT_RATE' => 0,
'TAX_RATE' => 0,
'TAX_INCLUDED' => 'Y',
'MEASURE_CODE' => 796,
'MEASURE_NAME' => 'шт',
'SORT' => 10,
],
[
'PRODUCT_NAME' => 'Услуга сопровождения',
'PRICE' => 1500,
'QUANTITY' => 2,
'DISCOUNT_TYPE_ID' => 2,
'DISCOUNT_RATE' => 0,
'TAX_RATE' => 0,
'TAX_INCLUDED' => 'Y',
'MEASURE_CODE' => 796,
'MEASURE_NAME' => 'шт',
'SORT' => 20,
],
],
]
);
$result = $response
->getResponseData()
->getResult();
echo 'Updated: ' . ($result ? 'true' : 'false');
} catch (Throwable $e) {
error_log($e->getMessage());
echo 'Error setting quote product rows: ' . $e->getMessage();
}
BX24.callMethod(
'crm.quote.productrows.set',
{
id: 1,
rows: [
{
PRODUCT_ID: 459,
PRICE: 3000,
QUANTITY: 1,
DISCOUNT_TYPE_ID: 2,
DISCOUNT_RATE: 0,
TAX_RATE: 0,
TAX_INCLUDED: 'Y',
MEASURE_CODE: 796,
MEASURE_NAME: 'шт',
SORT: 10,
},
{
PRODUCT_NAME: 'Услуга сопровождения',
PRICE: 1500,
QUANTITY: 2,
DISCOUNT_TYPE_ID: 2,
DISCOUNT_RATE: 0,
TAX_RATE: 0,
TAX_INCLUDED: 'Y',
MEASURE_CODE: 796,
MEASURE_NAME: 'шт',
SORT: 20,
},
],
},
(result) => {
result.error()
? console.error(result.error())
: console.info(result.data())
;
},
);
require_once('crest.php');
$result = CRest::call(
'crm.quote.productrows.set',
[
'id' => 1,
'rows' => [
[
'PRODUCT_ID' => 459,
'PRICE' => 3000,
'QUANTITY' => 1,
'DISCOUNT_TYPE_ID' => 2,
'DISCOUNT_RATE' => 0,
'TAX_RATE' => 0,
'TAX_INCLUDED' => 'Y',
'MEASURE_CODE' => 796,
'MEASURE_NAME' => 'шт',
'SORT' => 10,
],
[
'PRODUCT_NAME' => 'Услуга сопровождения',
'PRICE' => 1500,
'QUANTITY' => 2,
'DISCOUNT_TYPE_ID' => 2,
'DISCOUNT_RATE' => 0,
'TAX_RATE' => 0,
'TAX_INCLUDED' => 'Y',
'MEASURE_CODE' => 796,
'MEASURE_NAME' => 'шт',
'SORT' => 20,
],
],
]
);
echo '<PRE>';
print_r($result);
echo '</PRE>';
// client и ctx уже созданы — см. раздел «SDK для Go»
res, err := client.Core().Call(ctx, "crm.quote.productrows.set", b24.Params{
"id": 1,
"rows": []b24.Params{
{
"PRODUCT_ID": 459,
"PRICE": 3000,
"QUANTITY": 1,
"DISCOUNT_TYPE_ID": 2,
"DISCOUNT_RATE": 0,
"TAX_RATE": 0,
"TAX_INCLUDED": "Y",
"MEASURE_CODE": 796,
"MEASURE_NAME": "шт",
"SORT": 10,
},
{
"PRODUCT_NAME": "Услуга сопровождения",
"PRICE": 1500,
"QUANTITY": 2,
"DISCOUNT_TYPE_ID": 2,
"DISCOUNT_RATE": 0,
"TAX_RATE": 0,
"TAX_INCLUDED": "Y",
"MEASURE_CODE": 796,
"MEASURE_NAME": "шт",
"SORT": 20,
},
},
})
if err != nil {
return fmt.Errorf("crm.quote.productrows.set: %w", err)
}
var ok bool
if err := json.Unmarshal(res.Result, &ok); err != nil {
return fmt.Errorf("разбор ответа: %w", err)
}
fmt.Println("выполнено:", ok)
Ответ
HTTP-статус: 200
{
"result": true,
"time": {
"start": 1773416018,
"finish": 1773416018.877651,
"duration": 0.8776509761810303,
"processing": 0,
"date_start": "2026-03-13T18:33:38+03:00",
"date_finish": "2026-03-13T18:33:38+03:00",
"operating_reset_at": 1773416618,
"operating": 0.5666530132293701
}
}
Возвращаемые данные
result
boolean
Корневой элемент ответа. Содержит:
- true — товарные позиции успешно сохранены
- false — товарные позиции не сохранены
time
time
Информация о времени выполнения запроса
Обработка ошибок
HTTP-статус: 400
{
"error": "",
"error_description": "Not found."
}
| Код | Описание | Значение |
|---|---|---|
| — | The parameter id is invalid or not defined. |
В параметр id не передано значение или передано невалидное значение |
| — | The parameter rows must be array. |
В параметр rows передан не массив |
| — | Access denied. |
У пользователя нет прав на изменение коммерческого предложения |
| — | Not found. |
Коммерческое предложение с переданным id не найдено |
| — | Текст ошибки проверки прав каталога | Ошибка проверки прав на товары каталога и/или ограничения каталога для переданных позиций |

