День добрый всем.
У меня вот какой вопрос возник.
Имеется Drupal 9/10 (экспериментирую на 10й но на 9й думаю там все тоже самое будет).
Я пытаюсь создать магазин. Разобрался как задать НДС (20%) для товара, как создать доставку (фиксированную). Экспериментировал со скидками.
Все эти действия требуются чтобы настроить эквайринг. Подразумевается также работа с ОФД.
Создал товар стоимостью 22.22р, применил ему НДС, в настройке - НДС включен в стоимость товара. После чего попробовал создать заказ.
Вот что получается. Стоимость товара 22.22. За 5 ед. товара сумма - 111.1р (сюда должен быть включен НДС 20%). Он показывает стоимость в checkout за одну позицию товара 18.52р. Но мне в дальнейшем для платежной системы необходимо передавать полную стоимость товара (включая все скидки и налоги). Стоимость товара, которую я могу получить из заказа - 18.52р. Расчетный НДС для позиции товара - 3,7р. Здесь пока все правильно - 18.52р + 3.7р = 22.22 р.
Теперь же я смотрю на цифру, которую считает commerce за всю позицию товара и вижу там НДС - 18.52р.
Все круто, но на 5 эта цифра не делится. То есть он считает НДС не по стоимости за 1 ед товара (как он пересчитывал стоимость 1й позиции товара) а считает сейчас НДС по всей позиции в целом.
Таким образом, если прибавить стоимость товара и НДС получится 111,12р. Лишние 2 копейки, которые портят жизнь.
Я размотал как именно формируется "новая" стоимость товара (которая идет в заказ) и как формируется НДС и можно ли как-то встроиться. У меня сложилось впечатление что нет - нельзя.
Подскажите, пожалуйста, как вы решаете подобную проблему или в какую сторону посмотреть чтобы постараться решить эту проблему? Похоже, все идет к тому, что придется писать свой метод расчета цен для товаров, делать бы мне этого крайне не хотелось бы.
Комментарии
Если смотреть по коду вот тут:
https://git.drupalcode.org/project/commerce/-/blob/8.x-2.x/modules/tax/s...
то там используется именно unitPrice, то есть цена одной единицы. Можно попробовать поставить там брейкпоинт и посмотреть, что именно попадает $order_item и откуда берётся такое значение.
Хотя вот ещё здесь:
https://git.drupalcode.org/project/commerce/-/blob/8.x-2.x/modules/tax/s...
$tax_amount сначала высчитывается из юнит прайса в 133 строке, а потом пересчитывается заново в 145 для тотал прайса. Выглядит странно.
Вот это не оно случайно? https://www.drupal.org/project/commerce/issues/3044185
Я мельком глянул этот issue, сложилось впечатление, что у них там решение заточено на точности округления, но это неправильный подход. Если работаешь с копейками (центами), то округлять нужно именно до копеек, а не тысячных или десятитысячных. Просто нужно высчитать НДС для одной единицы, округлить, а потом умножать на количество. А самая распространённая ошибка - это когда сначала умножают, а потом округляют.
Ну это причина возникновения\пропадания копеек, это понятно. Это я тоже раскопал. Вопрос то в другом. Мне показалось странным что сначала рассчитывается некая "исходная" стоимость без налога, сохраняется а затем делается "обратный пересчет" но не по исходному алгоритму, когда в качестве исходных данных для расчета берется стоимость 1 ед товара, а по другому алгоритму, когда в качестве исходных данных для расчета берется стоимость всей позиции этого товара. Из-за этого и получается такая проблема - погрешности округлений. Можно ведь было также рассчитать налог для 1 ед. товара и умножить полученную цифру на кол-во товара для получения общей суммы налога которая была бы кратна кол-ву товара и прекрасно бы выделялась для определения стоимости 1 ед товара (для эквайринга), вот я сейчас думаю как мне поступить...
В order_item попадает именно рассчитанная стоимость с учетом НДС (с округлением по всем правилам) с нормальной точностью (до 2го знака) для 1 ед. товара. НДС = 3.7 руб. А вот в моем случае (как на скриншоте) делается обратный пересчет. Суммарно НДС 18.52 р, что составляет 3,704 р. для 1 ед. товара. Нехорошо.
Можно сделать свой tax-плагин с правильным расчётом.
Можно, конечно, но не хотелось бы. Тем более придется копать параллельно еще кучу материала.
Я просто хотел узнать как другие люди справляются с подобной проблемой, есть ли какое-то "стандартное" решение? Я ведь наверняка не первый.