Skip to main content

OpenSalesTax connector for Odoo 19 — destination-based US sales tax via the OpenSalesTax engine

Project description

opensalestax-odoo

PyPI License: LGPL v3 Odoo 16.0 Odoo 17.0 Odoo 18.0 Odoo 19.0

Destination-based US sales tax for Odoo Community. Replaces static tax-rate configuration with live calculation against an OpenSalesTax engine — your own self-hosted instance, no per-transaction fees, no SaaS lock-in.

The free, self-hostable answer to Avalara on Odoo Community Edition. Available on all four current Odoo major versions — 16.0, 17.0, 18.0, and 19.0 — same module, branch-per-version per the OCA convention.

Branch matrix

Pick the branch matching your Odoo install. Releases are independent per branch.

Odoo version Branch PyPI artifact Status
16.0 16.0 odoo-addon-account-ostax==16.0.* shipping
17.0 17.0 odoo-addon-account-ostax==17.0.* shipping
18.0 18.0 odoo-addon-account-ostax==18.0.* shipping (default)
19.0 19.0 odoo-addon-account-ostax==19.0.* shipping (Odoo 19 GA confirmed)

What you get

  • Sales orders, customer invoices, credit notes/refunds, POS — all with destination-based per-jurisdiction US tax
  • Per-jurisdiction breakdown stored on every move (state / county / city / district), rendered on the form view for full audit trail
  • Per-product taxability category (product.template.ostax_category — general / clothing / groceries / prescription_drugs / prepared_food / digital_goods); engine applies per-state taxability rules (e.g. Minnesota exempts clothing, New York taxes prepared food differently than groceries)
  • Per-category default with parent-walk inheritance — mark "Apparel" as clothing once on product.category, every product underneath inherits unless overridden. Closest-ancestor wins.
  • Per-worker engine-response cache (~1 hour sliding TTL) — repeat calculations within the same hour for the same line shape skip the engine. Helpful for batch invoicing, recurring orders, multi-line carts.
  • Customer exemption certificates on res.partner
  • Multi-company support — settings scoped per company
  • Fiscal-position interop — non-US partners route through Odoo's standard "Export" mapping; the connector only engages for US shipping addresses
  • Settings page with engine connection test, fail-soft toggle
  • Optional admin debug log of recent calculations
  • Optional 90-day archive cron for jurisdictions you've stopped shipping to

What's deferred to v0.2

  • Vendor bills + use-tax accrual. Use tax is owed at the buyer's location, not the vendor's; v0.1 doesn't yet implement the buyer-location code path. Vendor bills (and any purchase-typed catalog tax) bypass the connector and fall through to Odoo's standard catalog rates — see v0.1.15.
  • POS live-quote. Server-authoritative compute on order close works; per-line live JS-side round-trip on each line-add is a v0.2 enhancement.

Install

# Match the branch to your Odoo major:
pip install opensalestax  # the Python SDK
pip install 'odoo-addon-account-ostax>=19.0.0.1.15,<20.0'  # for Odoo 19
# (use >=16.0.0.1.12,<17.0 / >=17.0.0.1.15,<18.0 / >=18.0.0.1.15,<19.0
# for the other branches)

# Or install from source:
git clone -b 19.0 https://github.com/ejosterberg/opensalestax-odoo.git
cd opensalestax-odoo
# Symlink or copy account_ostax/ into your Odoo addons-path

Note for Odoo 16 users: The 16.0.0.1.11 wheel is broken (a tools.ormcache annotation-stripping bug — see CHANGELOG for v0.1.12). Pin >=16.0.0.1.12 or use the latest.

Then in Odoo: Apps → search "OpenSalesTax" → Install, then Settings → Accounting → OpenSalesTax to configure the engine URL.

Configuring per-product / per-category taxability

For most products, leave everything at the defaults — the engine treats unflagged products as general taxable goods.

For products in special-taxability categories (clothing, groceries, prescription drugs, prepared food, digital goods), set the category on:

  • The product (Inventory → Products → form view → Accounting tab → OST tax category), OR
  • The product's internal category (Inventory → Configuration → Product Categories → form view → OST tax category default) — every descendant product inherits unless overridden.

The lookup precedence is: per-product → product's category → walk up parent_id until a value is found → fall back to general.

How it works

The connector overrides account.tax.compute_all. When a US partner with a valid 5-digit ZIP is on a sale order / invoice / POS order / vendor bill, compute_all calls the OpenSalesTax engine via the Python SDK and replaces the static catalog rate with the engine's per-jurisdiction breakdown. Non-US partners fall through to Odoo's standard fiscal-position handling.

Calculation only

Tax calculations are provided as-is for convenience. The merchant is solely responsible for tax-collection accuracy and remittance to the appropriate jurisdictions. Verify against your state Department of Revenue before remitting.

This module does NOT file returns, remit collected tax, validate addresses, or provide legal/tax advice.

License

LGPL-3 (or-later) per the project's per-platform license carve-out. Apache-2.0 SDK consumed. DCO sign-off required on every commit; no AI co-author trailers. See CONTRIBUTING.md.

Status

Production-grade across all four Odoo majors. v0.1.15 is shipping on PyPI as odoo-addon-account-ostax==<branch>.0.1.15 for 16.0, 17.0, 18.0, and 19.0. Per-branch test workflows green on every branch; 49 unit tests pass on real Odoo + Postgres in Docker.

What works on every branch:

  • Real destination-based per-jurisdiction US sales tax on every customer invoice, sale order, credit note (state / county / city / district splits in the totals area)
  • Line-level OST jurisdiction tags persisted on posted invoices
  • Engine audit JSON captured on _post() (engine version, calc timestamp, full per-jurisdiction detail)
  • Per-product + per-category OST taxability mapping
  • Per-worker engine-response cache (~1h sliding TTL)
  • Customer exemption certificate handling
  • Multi-company isolation
  • Settings page + Test Connection action
  • Optional admin debug log
  • Optional 90-day archive cron for jurisdictions you've stopped shipping to

How it's wired:

  • Odoo 18 + 19 override account.tax._add_tax_details_in_base_lines using the official manual_tax_amounts injection mechanism — same hook the proprietary Avalara module uses, no internal-API fragility.
  • Odoo 16 + 17 override the legacy compute_all method (the new batch engine arrived in 18.0).
  • Per-version settings xpath: 16 uses //div[@data-key='account']; 17/18/19 use //app[@name='account'].

Verified end-to-end on real Odoo + Postgres in Docker against the live engine, including Odoo's official US chart of accounts (l10n_us): $100 invoice to MSP (ZIP 55401) produces amount_tax=9.03 with 6 per-jurisdiction lines.

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 Distribution

odoo_addon_account_ostax-19.0.0.1.16.tar.gz (37.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

File details

Details for the file odoo_addon_account_ostax-19.0.0.1.16.tar.gz.

File metadata

File hashes

Hashes for odoo_addon_account_ostax-19.0.0.1.16.tar.gz
Algorithm Hash digest
SHA256 d35f51145ff6db5030cf285fb23a662682a2441c7eddf9f2fe986050f7cd76b1
MD5 9d3187bb5bc59b8076a885731926011f
BLAKE2b-256 f8ee65e2757035ae371785681818598f238a621a6e769601198eabbbd5650ec9

See more details on using hashes here.

Provenance

The following attestation bundles were made for odoo_addon_account_ostax-19.0.0.1.16.tar.gz:

Publisher: publish.yml on ejosterberg/opensalestax-odoo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file odoo_addon_account_ostax-19.0.0.1.16-py3-none-any.whl.

File metadata

File hashes

Hashes for odoo_addon_account_ostax-19.0.0.1.16-py3-none-any.whl
Algorithm Hash digest
SHA256 8310a5d392da5e0356081e708c6d87ecc6edfd10b248867a196e450a8f45bc8b
MD5 4ef53a09bc318c0bf6d9a2a1d49c8270
BLAKE2b-256 3d7a36c92b1f5a2d1ee40e313e260a0cf401fc101f0331477d55d48cbdb2d780

See more details on using hashes here.

Provenance

The following attestation bundles were made for odoo_addon_account_ostax-19.0.0.1.16-py3-none-any.whl:

Publisher: publish.yml on ejosterberg/opensalestax-odoo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page