Расчет налога с помощью MoneyStack Overflow

Я использую moneyphp / деньги класс для хранения денежных величин. Однако при расчете причитающегося налога у меня возникает проблема, когда рассчитанный налог является десятичным, а библиотека ищет целочисленное значение.

Пример:

$invoiceTotal = new Money("155" new Currency("USD")); //$1.55
$taxRate= 0.065;
$invoiceTotalWithTax = $invoiceTotal->multiply($taxRate);
echo $invoiceTotalWithTax; //0.10 whereas actual value is 1.55*0.065 = 0.10075
$formatter = new DecimalMoneyFormatter();
$formatter->format($invoiceTotalWithTax); //will return $0.10

Из вышеприведенного примера теряется некоторое значение дробного процента. По отдельности это не много, однако, если мы обработаем несколько тысяч счетов за налоговый период, общая сумма собранных налогов в конечном итоге превысит 1 цент.

  • Есть ли способ справиться с этими ситуациями с помощью пакета Money?
  • Если нет, то есть ли другой пакет, который может справиться с этим?

0

Решение

Бесстыдная вилка: я не знаю, есть ли способ сделать это с moneyphp/money пакет, но вот как вы можете справиться с этой ситуацией с кирпич / деньги пакет (отказ от ответственности: я его создал).

Выбор, который вы выберете, будет зависеть от того, чего вы пытаетесь достичь.

Вариант 1: использовать деньги со шкалой по умолчанию, округлить вверх или вниз

Используйте этот метод, если вам нужен результат в масштабе по умолчанию для валюты (2 десятичных знака для USD) и знать, какое округление применить:

use Brick\Money\Money;
use Brick\Math\RoundingMode;

$invoiceTotal = Money::ofMinor('155', 'USD'); // USD 1.55
// or
$invoiceTotal = Money::of('1.55', 'USD');

$taxRate = '0.065'; // prefer strings over floats!

$totalWithTax = $invoiceTotal->multipliedBy($taxRate, RoundingMode::DOWN); // USD 0.10
$totalWithTax = $invoiceTotal->multipliedBy($taxRate, RoundingMode::UP); // USD 0.11

У вас есть еще много режимы округления выбирать из. Если вы не предоставляете режим округления, а результат не помещается в 2 десятичных знака, вы получите исключение.

Вариант 2: использовать деньги с пользовательским масштабом

Если вам нужно работать с заданной точностью, скажем, 5 десятичных знаков, вы можете указать это при создании Money:

use Brick\Money\Money;
use Brick\Money\Context\CustomContext;
use Brick\Math\RoundingMode;

$invoiceTotal = Money::of('1.55', 'USD', new CustomContext(5)); // USD 1.55000
$taxRate = '0.065';

$totalWithTax = $invoiceTotal->multipliedBy($taxRate); // USD 0.10075

Если результат не помещается в 5 десятичных разрядах, вам необходимо предоставить RoundingMode, или вы получите исключение.

Вариант 3: использовать деньги с автоматическим масштабированием

Используйте этот метод, чтобы автоматически настроить масштаб результата на правильное количество десятичных разрядов:

use Brick\Money\Money;
use Brick\Money\Context\AutoContext;
use Brick\Math\RoundingMode;

$invoiceTotal = Money::of('1.55', 'USD', new AutoContext()); // USD 1.55
$taxRate = '0.065';

$totalWithTax = $invoiceTotal->multipliedBy($taxRate); // USD 0.10075

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

Вариант 4: использовать RationalMoney

RationalMoney денежный объект, который представляет его сумму в виде рационального числа (дроби). Это особенно полезно, когда вам нужно объединить несколько операций без округления бы то ни было:

use Brick\Money\Money;
use Brick\Math\RoundingMode;

$amount = Money::of('1.55', 'USD'); // USD 1.55
$amount = $amount->toRational(); // USD 155/100

$amount = $amount->dividedBy(3); // USD 155/300
$amount = $amount->dividedBy(7); // USD 155/2100

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

use Brick\Money\Context\DefaultContext;
use Brick\Money\Context\CustomContext;

$amount->to(new DefaultContext(), RoundingMode::DOWN); // USD 0.07
$amount->to(new CustomContext(6), RoundingMode::DOWN); // USD 0.073809

Заключительные соображения

кирпич / деньги Пакет предлагает форматирование, округление наличных, распределение денег, конвертацию валюты и многое другое. Он основан на кирпич / математика пакет, который выполняет вычисления по номерам любого масштаба. Не стесняйтесь попробовать!

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]