Skip to content

phil/tax

alpha

Several taxes on one sale, each computed on the same base and itemised to the cent.

phil/tax computes multi-rate taxation on a shared base: a sale taxed by several taxes at once, a federal and a provincial tax for instance, each computed on the same base, each rounded on its own line and itemised on the invoice. It also extracts the taxes a tax-included price contains. It does not decide which rates apply to a sale, whether a seller must collect tax, which jurisdiction taxes a sale, or what a receipt must mention. It holds no current rates and never compounds one tax on another. Those belong to the application or to the tax engine behind it.

It is for any PHP code that issues invoices, receipts or credit notes and must show each tax on its own line. phil/commerce-bundle uses it to tax each order line; an application without a store can call it directly.

It is a plain PHP library whose only dependency is phil/money, whose Money it takes and returns. Rates are held in parts per million, never in a float. Each tax is rounded half away from zero in integer arithmetic, so a credit note reverses an invoice exactly.

The design is small: a TaxRate value, a MultiRateTaxCalculator that applies a list of rates, and a TaxBreakdown of TaxLines that the invoice prints.

Status

PartState
TaxRate: code, parts per million, percentage read and printed, tax on a baseImplemented and tested
TaxLine: computed or reported by an external engineImplemented and tested
TaxBreakdown: lines on one base, totals, line by code, credit-note reversalImplemented and tested
MultiRateTaxCalculator: every rate on the same baseImplemented and tested
Exceptions under one TaxException interfaceImplemented and tested

Documentation

DocumentWhat it covers
InstallationRequirements and installing.
RatesTaxRate: codes, parts per million, percentages, rounding and the largest base.
BreakdownsTaxLine, TaxBreakdown and MultiRateTaxCalculator: one base, line-by-line rounding, reversal.
Choosing the ratesWhat the library leaves to the application, and a resolver it may write.
ExceptionsTaxException and the three exceptions, with their messages.
Extension pointsThe ports, arguments and data an application chooses or replaces.
TestingThe library's tests and mutation bar, and how to test code that taxes.
ReferenceEvery type of the library, with its role.

Quick start

composer require phil/tax
use Phil\Money\Currency;
use Phil\Money\Money;
use Phil\Tax\MultiRateTaxCalculator;
use Phil\Tax\TaxRate;

$breakdown = new MultiRateTaxCalculator()->calculate(Money::ofDecimal('19.99', Currency::of('CAD')), [
    TaxRate::ofPercent('GST', '5'),
    TaxRate::ofPercent('QST', '9.975'),
]);

$breakdown->line('QST')?->amount->toDecimal(); // "1.99", on 19.99 and not on 19.99 plus GST
$breakdown->totalWithTax()->toDecimal();       // "22.98"
$credit = $breakdown->reversed();              // every line negated

Requirements

PHP 8.5 or later, and phil/money 0.1.

Contributing

Contributions are welcome on the PHIL monorepo: read the contribution guide and the code of conduct. Report a vulnerability privately, as the security policy explains, never in a public issue.

License

MIT, © Philippe Gamache, doing business as Le Gnome Archiviste; a Parler Haut Interagir Librement project. See LICENSE.