В триггерах по аналогии с шаблонами больше не обязательно проверять, что переменная не равна null
. Код order.getStatus().getCode()
больше не генерирует исключение если order.getStatus()
или order
равны null
, и возвращает null
.
Поэтому стоит обратить внимание на код триггеров, где идет обратная проверка (например not in
, !=
и т.п.). Возможно их нужно будет изменить, чтобы они учитывали новое поведение.
Если, например, раньше выражение order.getPaymentStatus().getCode() not in ['paid', 'not-paid']
генерировало исключение, если статус оплаты не указан у заказа, и триггер не выполнялся, то в новой логике левая часть выражения будет возвращать null
, который успешно пройдет указанную проверку.
До обновления на 6.0, стоит по Журналу действий найти срабатывания, которые приводят к ошибке, и поправить соответствующим образом триггеры.
В версии 6.0 была добавлена возможность добавлять несколько оплат в рамках одного заказа. Это влечет изменение в модели данных, т.к. у заказа теперь не оплата, а коллекция оплат со всеми вытекающими.
Прежние прямые методы доступа к данным платежа order.getPaymentType()
, order.getPaymentStatus()
, order.getPaymentDetail()
сохранены для совместимости, но работают только в случае одного платежа в заказе.
Появляется коллекция платежей order.getPayments()
, а также поле order.fullPaidAt
и метод order.getFullPaidAt()
, которые возвращают дату полной оплаты заказа.
Для сохранения совместимости методы объектов, доступных в шаблонах и триггерах, а также методы API v4 и ниже работают по логике «рабочего платежа»:
order.payments
будет создан автоматически
null
, вызов устаревших set*-методов вызовет исключение
Таким образов в случае работы с предоплатой и старыми версиями API, менеджер должен добавлять ее сразу в оплаченном статусе.
1. [Можно скорректировать ДО обновления] В триггерах условие полной оплаченности заказа нужно проверять с помощью order.fullPaidAt
, и реагировать на изменение full_paid_at
.
Т.е. выражения, срабатывающие на факт полной оплаты заказа вида
changeSet.hasChangedField("payment_status") and changeSet.getNewValue("payment_status").getCode() == "paid"
нужно заменять на выражения вида
changeSet.hasChangedField("full_paid_at") and changeSet.getNewValue("full_paid_at")
А выражения проверки, что заказ оплачен, вида
order.getPaymentStatus() && order.getPaymentStatus().getCode() == 'paid'
нужно заменять на выражения вида
order.fullPaidAt
2. [Требуется корректировать ПОСЛЕ обновления] Проверку данных платежа в заказе нужно корректировать с учетом того, что оплаты теперь являются коллекцией
Выражения вида
order.getPaymentType() and
order.getPaymentType().getCode() in [ "cash", "bank-card-courier", "bank-card-office", "axiomus", "posthub" ]
нужно заменять на выражения:
а) если хотя бы одна из оплат в заказе указанного типа:
order.payments | contains( item => item.type.code in [ "cash", "bank-card-courier", "bank-card-office", "axiomus", "posthub" ] )
б) если все оплаты заказа указанного типа:
order.payments | every( item => item.type.code in [ "cash", "bank-card-courier", "bank-card-office", "axiomus", "posthub" ] )
В старых версиях API мы постарались сохранить максимальную совместимость, которая будет выполняться пока вы не начнете добавлять второй и более платеж в заказ. Как только вы решите работать с мультиоплатами в retailCRM, вам предварительно потребуется перейти на API v5.
1. В /api/v5/orders
и /api/v5/orders/get
возвращается коллекция платежей order[payments][]
.
2. Для добавления платежа в заказ появился новый API-метод /api/v5/orders/payments/create
, для редактирования — /api/v5/orders/payments/{id}/edit
, для удаления — /api/v5/orders/payments/{id}/delete
3. В версиях API v4
и ниже структура данных не изменилась, но данные по оплате заказа возвращаются, только если в заказе одна оплата либо оплат несколько, но только одна из них неоплаченная, в противном случае будут приходить пустые поля. Редактирование оплаты также возможно только, пока ее нет или она одна в заказе.
4. В /api/v*/orders/history
истории заказа больше не возвращаются изменения поля order.prepaySum
, так как теперь это только сумматор сумм оплаченных платежей
Начиная с версии 6.0 работа со скидками построена по другому. Ключевое изменение заключается в том, что скидка на заказ теперь учитывается не в общей сумме заказа, а распределяется между товарами и учитывается в сумме каждой отдельной позиции товара в заказе. При этом распределенная скидка заказа не затрагивает скидки на товары, которые можно так же, как и раньше отдельно указывать.
Покажем на примере. Допустим есть следующий заказ:
| Название | Цена | Скидка | Кол-во | Итого |
| | | | | |
| Шорты | 600 руб | 50 руб (на товар) | 2 | 1100 руб |
| | | | | |
| Сланцы | 300 руб | 0 руб (на товар) | 3 | 900 руб |
| | |
| Итого | 2000 руб |
Мы дали скидку на заказ 300 рублей.
В версии системы 5.0 и ниже данная скидка будет учтена в общей стоимости заказа:
| Название | Цена | Скидка | Кол-во | Итого |
| | | | | |
| Шорты | 600 руб | 50 руб (на товар) | 2 | 1100 руб |
| | | | | |
| Сланцы | 300 руб | 0 руб (на товар) | 3 | 900 руб |
| | |
| Скидка на заказ | 300 руб |
| | |
| Итого | 1700 руб |
В версии 6.0 и выше скидка заказа распределится между товарами и будет учтена в их стоимости:
| Название | Цена | Скидка | Кол-во | Итого |
| | | | | |
| Шорты | 600 руб | 50 руб (на товар) | 2 | 980 руб |
| | | 60 руб (на заказ) | | |
| | | | | |
| Сланцы | 300 руб | 0 руб (на товар) | 3 | 720 руб |
| | | 60 руб (на заказ) | | |
| | |
| Итого | 1700 руб |
Стоимость заказа в таком случае рассчитывается так: (600 – 50 – 60) x 2 + (300 – 60) x 3 = 1700
В API v4 поля скидок order[discount]
, order[discountPercent]
, order[items][][discount]
, order[items][][discountPercent]
в заказе остаются без изменений и доступны как на запись, так и на чтение.
На примере заказа выше при создании заказа значения нужно передавать в следующем виде:
order = {
// ...
"discount": 300,
"items": [
{
"offer": { "externalId": "1" },
"initialPrice": 600,
"discount": 50,
"quantity": 2
},
{
"offer": { "externalId": "2" },
"initialPrice": 300,
"quantity": 3
}
],
// ...
}
В API-методах получения заказов состав и значения полей будут аналогичными:
{
// ...
"discount": 300,
"items": [
{
"offer": { "externalId": "1" },
"initialPrice": 600,
"discount": 50,
"quantity": 2
},
{
"offer": { "externalId": "2" },
"initialPrice": 300,
"quantity": 3
}
],
// ...
}
В методах создания и редактирования заказа /api/v5/orders/create
, /api/v5/orders/{externalId}/edit
, /api/v5/orders/upload
можно передавать скидки на заказ и товары в полях order[discountManualAmount]
, order[discountManualPercent]
, order[items][][discountManualAmount]
, order[items][][discountManualPercent]
, при этом скидки на заказ будут распределяться между товарами.
На примере заказа выше при создании заказа значения нужно передавать в следующем виде:
order = {
// ...
"discountManualAmount": 300,
"items": [
{
"offer": { "externalId": "1" },
"initialPrice": 600,
"discountManualAmount": 50,
"quantity": 2
},
{
"offer": { "externalId": "2" },
"initialPrice": 300,
"quantity": 3
}
],
// ...
}
В методах получения заказов /api/v5/orders
, /api/v5/orders/{externalId}
возвращается итоговая расчетная денежная скидка на единицу товара для каждой позиции товара в поле order[items][][discountTotal]
, которая учитывает и скидки на текущий товар, и скидки на заказ, распределенные между товарами.
{
// ...
"items": [
{
"offer": { "externalId": "1" },
"initialPrice": 600,
"discountTotal": 110,
"quantity": 2
},
{
"offer": { "externalId": "2" },
"initialPrice": 300,
"discountTotal": 60,
"quantity": 3
}
],
// ...
}
В объекте OrderProduct поля OrderProduct.discount
и OrderProduct. discountPercent
теперь считаются устаревшими. Нужно использовать поле OrderProduct. discountTotal
, которое возвращает итоговую денежную скидку на единицу товара c учетом всех скидок на товар и заказ. При обращении к полю OrderProduct.discount
будет возвращено значение поля OrderProduct.discountTotal
, при обращении к полю OrderProduct.discountPercent
— будет всегда возвращаться 0.
В некоторых случаях система не может распределить скидку заказ между товарами. Покажем на примере.
Допустим, есть заказ со следующим составом:
| Название | Цена | Скидка | Кол-во | Итого |
| | | | | |
| Шорты | 600 руб | – | 3 | 1800 руб |
| | |
| Итого | 1800 руб |
Мы добавляем скидку на заказ 10 рублей. Системе нужно распределить скидку заказа между всеми единицами товаров, которых в заказе 3 штуки.
По умолчанию при попытке указания такой скидки для заказа системой будет выдано сообщение об ошибке. Что важно, ошибка будет выдаваться, как если вы оформляете такой заказ в системе, так и через API, независимо от версии API.
Если же в системе включена настройка «Корректировать скидку на заказ» в разделе Настройки > Заказы, то система скорректирует скидку на заказ до ближайшего делимого значения (в данном случае изменит скидку на заказ с 10 рублей на 9,99 рублей).
В версии 6.0 добавлена функция округления, которую можно включить в разделе Настройки > Заказы. Округление, если его включить, применяется к позициям товаров в заказе. Та стоимость, что откидывается от суммы товара в результате округления, идет в скидку товара.
В настройках также есть опция округления стоимости товара с учетом стоимости заказа, которая выставлена по умолчанию при включенном округлении. С данной опцией округление стоимости товаров производится таким образом, чтобы результирующая стоимость заказа была максимально близка к стоимости заказа без округления.