Skip to content

2.3.0

Released: TBD

Highlights

  • Unify Tax-Rate Models — MIGRATE guards. A tax rate referenced by items or invoice lines can no longer be hard-deleted (it's retired via valid_to instead), the unified rate list is now readable by non-accountant pickers, and purchase orders read the rate from the unified TaxRate. Part of the Unify Tax-Rate Models rollout.

Added

  • Ungated taxRates query (Q4). The unified rate list is no longer TAX_FILINGS-gated, so non-accountant item/invoice pickers can read it (display name, percent, etc.). The single-rate taxRate get stays gated.

Changed

  • purchaseOrder lines read the unified rate. The supplier-quote→PO factory now reads the operational percent from Item.taxRate (ratePercent bridges the 0.0700 fraction → 7.00), falling back to the legacy ITBMS rate until the CONTRACT phase. Same tax amount — just sourced from the unified model.

Fixed

  • deleteTaxRate no longer raw-errors on a referenced rate. It now refuses with a clear "in use by N items/invoice lines" message when the rate is referenced by items.tax_rate_id, invoice_details.tax_rate_id, or supplier_invoice_details.tax_rate_id (Q3 pin policy — retire via valid_to instead of deleting).

Migrations

  • None.

Frontend impact

  • taxRates is now ungated — pickers can read the unified rate list without the TAX_FILINGS permission. ⚠️ This list exposes the TaxRate type's GL-account and code fields to any authenticated user (the Q4 trade-off); avoid surfacing those fields in non-accountant UI. deleteTaxRate can now return an "in use" error — surface it instead of treating delete as always-succeeding.

Versioning notes

  • Bumped with uv run python scripts/bump_version.py 2.3.0 --changelog-stub. MINOR — additive query exposure + a delete-safety fix; no breaking schema change. The behavioral read-flip of the items value-match repo onto TaxRate (the rate_percent fail-loud rewrite) and the removal of ITBMSTaxRate remain for the CONTRACT phase.