Hybrid USA Sales Tax engine: local DB first, external API fallback, full audit trail.
Project description
US Sales Tax Engine
Hybrid US Sales Tax engine for Odoo: resolves the combined state + county + city + district rate for a ZIP code, applies it to sale orders and invoices, and keeps a full audit trail of every calculation.
Resolution order: local rate database first, external API providers as fallback (configured independently in their own l10n_us_sales_tax_provider_* modules — this module never imports their code directly). Tracks nexus per state, taxability per product category, and caches external API responses to control call volume.
Table of contents
Usage
Loading local rate data
The local provider needs three things before it can resolve a tax rate for a ZIP code: a Jurisdiction (county/city), a ZIP Mapping pointing that ZIP to the jurisdiction, and a Tax Rate on that jurisdiction. None of these ship pre-loaded — only product categories and the provider registry are seeded on install.
Import Tax Rates wizard
US Sales Tax → Rate Database → Import Rates always requires a file upload — there is no “instant, no file” option in the wizard.
Florida DOR: upload the official Master Address List CSV from https://pointmatch.floridarevenue.com/General/AddressFiles.aspx (select a county and effective date, then download). This creates the jurisdiction, the rate, and the ZIP mapping for every row — full ZIP-level resolution.
Generic CSV (any state): any file with ZIP, COUNTY/CITY, and a rate column works the same way.
Manual setup (quick test, single ZIP)
For testing a single ZIP without downloading a file, create the three records by hand under US Sales Tax → Rate Database:
Jurisdictions — name, type (county/city), state.
ZIP Mappings — the ZIP code, pointing to that jurisdiction.
Tax Rates — the actual rate values on that jurisdiction.
Nexus is independent of rate data
Creating a Nexus record (US Sales Tax → Configuration → Nexus) only marks that the company has a legal obligation to collect tax in that state — it does not create or require any jurisdiction, ZIP mapping, or rate. Both are needed independently before a sale order calculates a non-zero local tax.
Zero-tax lines always carry an explicit tax, never an empty tax field
When a line ends up with 0% tax, the engine always assigns a real account.tax record rather than leaving the line untaxed:
Exempt product category or no nexus in that state — assigned the shared US Sales Tax - Exempt (0%) tax (one tax for both reasons, across all states).
A state with a genuine 0% combined rate (e.g. Oregon, Montana — states with no sales tax at all) — assigned US Sales Tax {state} 0%, the same per-state-and-rate tax used for any other rate.
This is deliberate: an empty tax_id is indistinguishable from “tax was never calculated” on an invoice or in a tax report filtered/grouped by account.tax/account.tax.group. An explicit 0% tax record shows that the line was evaluated and a deliberate “no tax due” determination was made — the kind of audit trail a sales-tax-exempt line should leave behind.
The specific reason for a 0% line (which product category, which state, nexus or no nexus) is not encoded in the tax’s name — that level of detail already lives on us.tax.calculation.log, one record per calculation. The tax itself only needs to answer “was this evaluated, and is it taxable” at a glance.
Migration note: if you had ad-hoc reports filtering for lines with no tax_id/tax_ids at all to flag “missing tax” cases, those lines will stop matching once they carry the explicit 0% tax — this is the intended effect of this change, not a regression.
Bug Tracker
Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed feedback.
Do not contact contributors directly about support or help with technical issues.
Credits
Contributors
Carlos R. Rodriguez <c.rodriguez@binhex.cloud>
Maintainers
This module is maintained by the OCA.
OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use.
Current maintainer:
This module is part of the OCA/l10n-usa project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file odoo_addon_l10n_us_sales_tax_engine-18.0.1.2.0-py3-none-any.whl.
File metadata
- Download URL: odoo_addon_l10n_us_sales_tax_engine-18.0.1.2.0-py3-none-any.whl
- Upload date:
- Size: 3.1 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4a9b80453fa4956c21cb5e9c9357225f0293b770b1a51736d029a412859ed532
|
|
| MD5 |
149c3c0920ec58eb6387d96cd0431730
|
|
| BLAKE2b-256 |
c7ad14891960abad61b8e3b75eb93dd6235e4b853047b81e0a7763f696edb94d
|