// Package tax provides the tax computation seam: a Provider interface // (mirroring PaymentProvider and ShippingProvider patterns), the shared Compute // formula, and a stateless Static provider for dev/test. // // SCALE: all tax rates are integer **basis points of a percent** — rate × 100, // so 25% = 2500, 12.5% = 1250, 8.1% = 810. This is the single platform-wide // scale (Price.VatRates, CartItem.Tax, OrderLine.tax_rate, the payment-provider // wire). Integer basis points support fractional VAT rates (Ireland 13.5%, // France 5.5%, Finland 25.5%) exactly without ever using a float. package tax // Provider computes taxes for orders and line items. type Provider interface { // Name returns the provider name for identification (logging, metrics). Name() string // Compute computes the VAT portion from a gross (inc-VAT) total and tax // rate. Both total and return value are in minor currency units (öre). // rateBp is basis points of a percent (2500 = 25%, 1250 = 12.5%). // // Ex-VAT-first integer math: exVat = total*10000/(10000+rateBp); tax = total - exVat. // When rateBp <= 0 the result is 0 (untaxed / zero-rated items). Compute(total int64, rateBp int) int64 // DefaultTaxRate returns the default VAT rate for a country in basis points // (2500 = 25%). Used for deliveries and items where no explicit rate was // recorded at add-to-cart time. Returns 0 if the country is unknown/untaxed. DefaultTaxRate(country string) int } // Compute returns the VAT portion of an inc-VAT total using integer (cent) // arithmetic only, ex-VAT-first so exVat + tax == total exactly and the result // matches the payment-provider convention (no per-line rounding drift): // // exVat = total * 10000 / (10000 + rateBp) // tax = total - exVat // // rateBp is basis points of a percent (2500 = 25%, 1250 = 12.5%) — the single // platform-wide rate scale. When rateBp <= 0 the result is 0 (untaxed). func Compute(total int64, rateBp int) int64 { if rateBp <= 0 { return 0 } exVat := total * 10000 / int64(10000+rateBp) return total - exVat } // Static is a stateless, always-available Provider that simply runs the // formula without any country-specific rates. Use for local dev, tests, // and as a no-dependency default. type Static struct{} var _ Provider = (*Static)(nil) // NewStatic returns a new Static provider. func NewStatic() *Static { return &Static{} } func (p *Static) Name() string { return "static" } func (p *Static) Compute(total int64, taxRate int) int64 { return Compute(total, taxRate) } func (p *Static) DefaultTaxRate(_ string) int { return 0 }