Перейти к содержимому

Сумма заказа не сходится с корзиной - разбор причин

В корзине одна сумма, а в оформленном заказе другая. Разбираем причины по убыванию частоты, начиная с раскладки самой суммы на части.

С чего начать

Печатаем позиции корзины со всеми ценами:

foreach ($basket as $item) {
printf("%-30s база=%.2f цена=%.2f скидка=%.2f своя=%s\n", $item->getField('NAME'),
$item->getField('BASE_PRICE'), $item->getPrice(),
$item->getField('DISCOUNT_PRICE'), $item->getField('CUSTOM_PRICE'));
}
// разница базовой и итоговой цены показывает, сработала ли скидка на позицию

Раскладка по позициям сразу отделяет проблему скидки от проблемы доставки. Пока непонятно, в какой именно части расходится сумма, разбор идёт вслепую и упирается в общие рассуждения о ценах.

Раскладываем сумму самого заказа:

$order = \Bitrix\Sale\Order::load($orderId);
printf("товары=%.2f доставка=%.2f итог=%.2f оплачено=%.2f\n",
$order->getBasket()->getPrice(), $order->getDeliveryPrice(),
$order->getPrice(), $order->getSumPaid());
// итог заказа - это сумма корзины плюс доставка и наценки, а не цена товаров

Итог заказа почти никогда не равен сумме товаров. В него входят доставка, наценка платёжной системы и налоги, и покупатель сравнивает совсем не те числа, что видит разработчик в корзине.

Смотрим налог в цене позиции:

foreach ($basket as $item) {
printf("%s ставка=%s включён=%s\n", $item->getField('NAME'),
$item->getField('VAT_RATE'), $item->getField('VAT_INCLUDED'));
}
// налог сверху и налог в цене дают разные итоги при одинаковых настройках товара

Проверяем купон и применённые правила:

printf("купоны: %s\n", implode(', ', \Bitrix\Sale\DiscountCouponsManager::get(true)));
printf("скидка заказа=%.2f\n", $order->getField('DISCOUNT_VALUE'));
// купон живёт в сеансе покупателя: до заказа он есть, а в заказе может не оказаться

Сверяем цены под нужным покупателем:

// консольная проверка от имени конкретного пользователя
$USER->Authorize($userId); // группы покупателя определяют его тип цены
printf("тип цены даёт %.2f\n", \CCatalogProduct::GetOptimalPrice($productId, 1)['PRICE']['PRICE']);

Причины

  1. Скидки пересчитываются при оформлении заказа примерно 25% случаев

    ПризнакВ корзине цена со скидкой, а в созданном заказе позиция идёт по базовой цене.

    ПроверкаПечатаем базовую и итоговую цену позиции в корзине и в заказе по очереди.

    Что делатьПроверяем условия правил корзины: тип плательщика, местоположение и сумму, которые меняются при оформлении.

  2. В итог входят доставка и наценка оплаты примерно 20% случаев

    ПризнакИтог заказа больше суммы товаров ровно на стоимость доставки или процент наценки.

    ПроверкаРаскладываем итог заказа на сумму корзины, доставку и наценку платёжной системы.

    Что делатьПоказываем покупателю раскладку суммы, а не одно число: расхождение оказывается мнимым.

  3. Налог считается сверху, а не в цене примерно 15% случаев

    ПризнакИтог отличается ровно на ставку налога, а цены товаров совпадают до копейки.

    ПроверкаСмотрим у позиций ставку налога и признак включения налога в цену товара.

    Что делатьПриводим настройку налога к принятой в проекте: налог либо в цене, либо сверху, но не вперемешку.

  4. Купон применился в корзине, но не в заказе примерно 15% случаев

    ПризнакСкидка по купону видна на витрине и исчезает в оформленном заказе.

    ПроверкаПечатаем список активных купонов сеанса и значение скидки в самом заказе.

    Что делатьПередаём купон при создании заказа и проверяем его срок, лимит применений и условия.

  5. У покупателя другой тип цены примерно 15% случаев

    ПризнакСумма меняется после авторизации или отличается у сотрудника и у покупателя.

    ПроверкаСчитаем оптимальную цену товара от имени конкретного пользователя в консольном скрипте.

    Что делатьПроверяем группы покупателя и права групп на типы цен: цену выбирает группа, а не товар.

  6. Расхождение на копейки из-за округления примерно 10% случаев

    ПризнакИтог отличается от ожидаемого на копейку при большом числе позиций.

    ПроверкаСмотрим настройки округления цен и валюту заказа вместе с числом знаков после запятой.

    Что делатьПриводим правила округления к одному виду и округляем итог, а не каждую позицию отдельно.

Частые вопросы

Почему скидка исчезает в момент оформления?

Условия правила корзины перестают выполняться: меняется тип плательщика, местоположение или состав корзины. Правило пересчитывается при создании заказа, а не переносится из корзины.

Как показать покупателю, из чего сложилась сумма?

Раскладкой в форме оформления: товары, скидка, доставка, наценка и налог отдельными строками. Большинство обращений «сумма не та» после этого исчезает.

Можно ли зафиксировать цену позиции?

Да, признаком своей цены у позиции корзины: тогда пересчёт её не трогает. Пользуются им осторожно, иначе скидки перестают работать вообще.

Почему у менеджера в админке другая сумма?

Он работает от своей учётной записи с другими группами и типами цен. Проверять цены нужно от имени того же покупателя, а не администратора.

Как сверить корзину и заказ разом?

Скриптом, который печатает позиции корзины и позиции заказа рядом с ценами. Разница видна за секунды, а гадать по интерфейсу можно долго.

Смежное

Первоисточник