Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
238 changes: 238 additions & 0 deletions hr_expense_tax_distribution/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
===========================
HR Expense Tax Distribution
===========================

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:0476c5fd066cdf175cd41e20c63f841a57c19060386e77869a5fd7fde731aa38
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fhr--expense-lightgray.png?logo=github
:target: https://github.com/OCA/hr-expense/tree/18.0/hr_expense_tax_distribution
:alt: OCA/hr-expense
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/hr-expense-18-0/hr-expense-18-0-hr_expense_tax_distribution
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/builds?repo=OCA/hr-expense&target_branch=18.0
:alt: Try me on Runboat

|badge1| |badge2| |badge3| |badge4| |badge5|

In standard Odoo, an expense record accepts a **single set of taxes**
applied to the full total amount. This works well when a receipt is
entirely subject to one VAT rate, but breaks down for mixed receipts
where different line items are taxed at different rates.

A typical example in France is a **restaurant bill**, where the
applicable VAT rates depend on what was consumed:

- **5.5 %** on food (solid items)
- **10 %** on non-alcoholic beverages
- **20 %** on alcoholic beverages

With the standard module, the user is forced to pick a single tax for
the whole amount, which leads to an incorrect tax breakdown in the final
accounting entry and, consequently, to wrong VAT reporting figures.

This module solves the problem by introducing **tax distribution lines**
on the ``hr.expense`` form. When an expense carries more than one tax,
the user can split the total receipt amount across as many distribution
lines as needed — one per applicable tax rate. Each line holds:

- the **tax** that applies to that portion of the receipt,
- the **base amount (tax excluded)** entered by the user,
- the **tax amount** and the **total (tax included)** computed
automatically.

A validation constraint ensures that the sum of the distribution line
totals equals the expense total before the expense report can be
submitted.

When the expense report is posted, the accounting entry is built from
the distribution lines instead of the single ``tax_ids`` / total pair,
producing a correct and auditable VAT breakdown for each applicable
rate.

The module is fully **backward compatible**: expenses with a single tax
or no distribution lines behave exactly as in standard Odoo.

**Table of contents**

.. contents::
:local:

Installation
============

This module depends on the standard ``hr_expense`` module. No
third-party dependency is required.

Install the module in the usual way (Apps menu or
``-i hr_expense_tax_distribution`` on the command line). The *Tax
Distribution* table appears automatically on the expense form as soon as
the module is installed — no migration of existing data is needed.

Configuration
=============

No specific configuration is required after installation.

The *Tax Distribution* table is displayed automatically on the expense
form whenever distribution lines exist on the record. Distribution lines
are generated automatically when more than one tax is added to the
*Taxes* field (via the ``tax_ids`` onchange), but they can also be
created or modified manually.

**Purchase taxes**

Only taxes with *Tax Scope* set to ``Purchase`` or ``All`` are available
in the distribution line *Tax* field. Make sure your VAT rates are
configured accordingly (Accounting > Configuration > Taxes).

**Company currency**

All amounts in the distribution lines are expressed in the **expense
currency** (``currency_id``), consistent with the standard *Total* field
on the expense. Multi-currency conversion is handled by the existing
Odoo expense mechanism and is not affected by this module.

Usage
=====

**Typical workflow — restaurant receipt (France)**

Consider a receipt for 86.75 € (tax included) with three different VAT
rates:

======================= ========= ===== ======== ===========
Item Base (HT) Rate Tax Total (TTC)
======================= ========= ===== ======== ===========
Food 50.00 EUR 5.5 % 2.75 EUR 52.75 EUR
Non-alcoholic beverages 20.00 EUR 10 % 2.00 EUR 22.00 EUR
Alcoholic beverages 10.00 EUR 20 % 2.00 EUR 12.00 EUR
**Total** 80.00 EUR 6.75 EUR 86.75 EUR
======================= ========= ===== ======== ===========

**Step-by-step**

1. Go to **Expenses > My Expenses** and create a new expense (or open an
existing draft one).

2. Fill in the standard fields: *Product*, *Total* (``86.75``),
*Employee*, *Date*, etc.

3. In the **Taxes** field, add **all** the VAT rates that appear on the
receipt (e.g. *TVA 5.5%*, *TVA 10%*, *TVA 20%*).

As soon as more than one tax is present, the **Tax Distribution**
table appears automatically below the *Taxes* field, with one
pre-created line per tax.

4. For each line in the *Tax Distribution* table, enter the **Base
Amount (Tax Excl.)** — the portion of the receipt that is subject to
that particular rate.

The *Tax Amount* and *Total (Tax Incl.)* columns are computed and
updated instantly.

5. Verify that the sum of the *Total (Tax Incl.)* column equals the
expense *Total* field. Odoo will block submission if there is a
discrepancy.

6. Submit and approve the expense report as usual.

**Result in the accounting entry**

Instead of a single expense line with a blended tax, the generated
journal entry contains **one base line and one tax line per distribution
entry**, providing an accurate and auditable VAT breakdown that feeds
correctly into the tax declaration (e.g. French CA3 return).

**Single-tax expenses**

If the expense has only one tax in the *Taxes* field, the *Tax
Distribution* table is not shown and the standard Odoo behaviour applies
unchanged. You can still manually add a distribution line if needed (for
instance, to split a single-rate receipt across two accounts), but this
is an edge case.

**Manual adjustments**

Distribution lines can be added, removed, or edited manually at any time
while the expense is in draft or submitted state (subject to the usual
edit permissions). Use the *handle* icon to reorder them.

Known issues / Roadmap
======================

- **Analytic distribution per line** — the current implementation copies
the ``analytic_distribution`` from the parent expense to every
distribution line. A future improvement could allow setting a distinct
analytic distribution on each tax distribution line.
- **Automatic total update** — when the user adjusts the distribution
lines, the expense *Total* field is not automatically recalculated.
The user must ensure consistency manually. A future improvement could
offer a *Recompute Total* helper button.
- **Import / OCR integration** — receipts parsed by the Odoo AI/OCR
feature do not currently populate distribution lines. Integration with
the attachment extraction pipeline is a possible future improvement.

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/OCA/hr-expense/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 <https://github.com/OCA/hr-expense/issues/new?body=module:%20hr_expense_tax_distribution%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

Do not contact contributors directly about support or help with technical issues.

Credits
=======

Authors
-------

* Akretion

Contributors
------------

- `Akretion <https://www.akretion.com/>`__:

- Guillaume Masson <guillaume.masson@akretion.com>

Maintainers
-----------

This module is maintained by the OCA.

.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org

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.

.. |maintainer-metaminux| image:: https://github.com/metaminux.png?size=40px
:target: https://github.com/metaminux
:alt: metaminux

Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:

|maintainer-metaminux|

This module is part of the `OCA/hr-expense <https://github.com/OCA/hr-expense/tree/18.0/hr_expense_tax_distribution>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
5 changes: 5 additions & 0 deletions hr_expense_tax_distribution/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Copyright 2026 Akretion
# @author Guillaume MASSON <guillaume.masson@akretion.com>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from . import models
25 changes: 25 additions & 0 deletions hr_expense_tax_distribution/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Copyright 2026 Akretion
# @author Guillaume MASSON <guillaume.masson@akretion.com>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

{
"name": "HR Expense Tax Distribution",
"summary": (
"Allows to distribute a single expense amount across multiple tax rates "
"by defining per-tax base amounts. Produces correct tax lines in the "
"accounting entry when multiple VAT rates apply to the same receipt."
),
"version": "18.0.1.0.0",
"category": "Human Resources/Expenses",
"website": "https://github.com/OCA/hr-expense",
"author": "Akretion, Odoo Community Association (OCA)",
"license": "AGPL-3",
"depends": ["hr_expense"],
"data": [
"security/ir.model.access.csv",
"views/hr_expense_tax_distribution_views.xml",
],
"installable": True,
"development_status": "Beta",
"maintainers": ["metaminux"],
}
6 changes: 6 additions & 0 deletions hr_expense_tax_distribution/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Copyright 2026 Akretion
# @author Guillaume MASSON <guillaume.masson@akretion.com>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from . import hr_expense
from . import hr_expense_tax_line
Loading
Loading