Overview
Lunar provides manual tax rules to implement the correct sales tax for each order. For complex taxation scenarios (e.g. US states), integrating with a service such as TaxJar is recommended.Tax Classes
Tax Classes are assigned to products and allow classification into taxable groups that may have differing tax rates.Fields
Tax Zones
Tax Zones specify a geographic zone for tax rates to be applied. They can be based on countries, states, or zip/postcodes.Fields
Tax-inclusive versus tax-exclusive price display is no longer stored on the tax zone. It is a per-Region preference (
Region::displaysPricesIncludingTax()), falling back to the global config('lunar.pricing.stored_inclusive_of_tax') default when the region has no override. The tax arithmetic (whether stored prices already include tax) is always driven by that global config, never by the zone or region.Tax Zone Countries
Tax Zone States
State lookups are scoped to the address country, so a state zone only applies to addresses in that state’s own country. This matters because state codes are reused across countries:
WA is both Washington and Western Australia.Tax Zone Postcodes
Tax Zone Customer Groups
Zone resolution
Lunar\Core\Actions\Taxes\GetTaxZone resolves the tax zone for an address, checking each type of zone in turn and returning the first match:
- Postcode — matched against the address postcode, honoring wildcards.
- State — matched against the address state, scoped to the address country.
- Country — matched against the address country.
- Default — the tax zone flagged as the default, returned when nothing above matches.
Tax Rates
Tax Zones have one or many tax rates. For example, a zone might have a tax rate for the state and also the city, which collectively make up the total tax amount.Fields
Tax Rate Amounts
Settings
- Shipping and other specific costs are assigned to tax classes in the settings.
- Tax calculation can be based on the shipping or billing address.
- A default Tax Zone can be configured.
The tax driver
Tax calculation for a cart line is delegated to aLunar\Core\Drivers\TaxDriver implementation, resolved through Lunar\Core\Facades\Taxes (backed by Lunar\Core\Contracts\TaxManager). The driver receives the shipping and billing addresses, the currency, and the purchasable/cart line being priced, and returns a Lunar\Core\ValueObjects\Cart\TaxBreakdown describing the tax amount per rate.
setTaxZone() lets a caller override zone resolution entirely — for example to tax on IP-derived location — bypassing the address-derived lookup.
Lunar ships one built-in driver, Lunar\Core\Drivers\SystemTaxDriver, which resolves the tax zone via GetsTaxZone (or the overridden zone), looks up the tax class’s rates in that zone, and calculates each rate’s share of the sub total.
Extending
Sometimes the standard tax calculations are not sufficient, and custom logic may be needed, perhaps connecting to a tax service such as TaxJar. Lunar allows custom tax drivers to be implemented viaTaxes::extend(). See the Extending Taxation section for more information.