Skip to Content

Returnable packaging and PEPPOL: a challenge Odoo keeps getting better at

Deposits done right on your electronic invoice: where standard Odoo is already enough and where you need to adjust
February 27, 2026 by
Returnable packaging and PEPPOL: a challenge Odoo keeps getting better at
Abstractive BV, Vincent Baggerman
In short. Odoo supports returnable packaging in PEPPOL invoices better with every version. Since Odoo 17, deposits automatically go on a separate invoice line, and in Odoo 19 you set the VAT category and exemption reason yourself. The specific Belgian empties text is not yet standard in Odoo, and for more complex scenarios you need extra modules.

Since January 1, 2026, Belgian companies are required to send their invoices electronically via PEPPOL, the secure network for e-invoicing. Beverage wholesalers, breweries and other wholesalers run into a surprising problem there: getting deposits on crates, bottles and cases right on the electronic invoice. What works fine on paper is sometimes rejected in PEPPOL invoices.

In this article you will read how returnable packaging support in Odoo evolved version by version, when the standard is enough and when you need extra help. Not yet familiar with the obligation itself? Then first read why electronic invoicing via PEPPOL has been mandatory since January 1, 2026.

What does the PEPPOL standard say?

The PEPPOL BIS Billing 3.0 standard is clear about returnable packaging (vidange/empties/consignes):

  • Deposits belong on a separate invoice line, separated from the trade goods
  • That line gets VAT category "E" (Exempt) with 0% VAT
  • It must include an exemption reason (in the standard, that field is called BT-120)
  • The VAT totals must be exactly right per category: the sum of all E lines must match the E subtotal, and the same for S lines

The Belgian PEPPOL working group has worked this out further in a specific scenario for consumer empties. It prescribes that the product name on empties lines must contain the fixed text Leeggoed/Vidange/Empties, and that the exemption reason in the VAT totals must be a specific statement such as Leeggoed/Vidange/Empties (Saldo consumer empties).

Sounds simple. But deposits rarely come alone: the combination with excise duties, recycling contributions and VAT makes it a lot more complex in practice.

How did support evolve across the Odoo versions?

Over the last few versions, Odoo has taken big steps in supporting returnable packaging on PEPPOL invoices. Each version builds on the previous one:

Feature v16 v17 v18 v19
Returnable packaging as a separate invoice line no yes yes yes
VAT category E on empties lines no yes yes yes
Calculated deposits (code type) no no yes yes
Configurable VAT category per tax no no no yes
Configurable exemption reason (VATEX code) no no no yes
Belgian exemption reason for returnable packaging no no no no*

* In Odoo 19 the exemption reason is configurable, but you have to enter the Belgian empties text yourself. There is no official VATEX code specifically for consumer empties yet.

Odoo 16: the basics

In Odoo 16, the PEPPOL module focused on correctly exporting standard invoices. Fixed taxes such as RECUPEL and BEBAT were already supported as charges on the invoice line, but there was no specific treatment for returnable packaging yet. Deposits were treated like any other fixed tax.

Odoo 17: the breakthrough

Version 17 brought an important improvement. The development team added the method _split_fixed_taxes which smartly splits fixed taxes:

  • Recycling contributions (RECUPEL, AUVIBEL, BEBAT) remain a charge on the invoice line
  • Returnable packaging automatically becomes a separate invoice line with VAT category E

The difference lies in the include_base_amount setting on the tax. If it is on, the amount counts toward the VAT calculation and Odoo treats it as a recycling contribution (charge). If it is off, it falls outside the VAT calculation and becomes returnable packaging (separate invoice line with category E). The accompanying tests confirm this with a tax named "Vidange".

However, the exemption reason that Odoo 17 sends along in the XML is the generic English text "Exempt from tax" (source code). The Belgian PEPPOL specification expects "Leeggoed/Vidange/Empties (Saldo consumer empties)" here. Technically valid, but not in line with the Belgian recommendation.

Odoo 18: broader recognition

Odoo 18 brought a new export architecture and extended the recognition of returnable packaging. The improved method now also recognizes calculated deposits: taxes that work with a formula instead of a fixed amount per unit. That matters for beverage suppliers with more complex deposit calculations based on product configuration.

In addition, there are now clear helper methods that distinguish between recycling contributions, excise duties and returnable packaging. Here too, the exemption reason remains "Exempt from tax".

Odoo 19: full configuration

Odoo 19 goes a step further with a configurable VAT category field directly on the tax. You now explicitly set per tax which PEPPOL category (S, E, AE, K, G, ...) should be used. No more guesswork by the system.

The same applies to the exemption reason: a selection list with all official VATEX codes, the European standard codes that indicate the reason for a VAT exemption. In earlier versions, this was the fixed text "Exempt from tax". However, Odoo 19 does not include a specific VATEX code for returnable packaging, because it does not yet exist at the European level. So you still have to configure the Belgian empties text manually.

When is the standard enough?

For many companies, standard Odoo 18 or 19 works fine. If you meet these conditions, you probably do not need extra modules:

  • Your deposit is configured as a fixed tax (a fixed amount) per unit
  • The include_base_amount option is off on your deposit tax
  • You do not work with price-included excise duties on the same products
  • You invoice in relatively simple scenarios without complex combinations

Want a broader check of whether you are ready for electronic invoicing? On our page with PEPPOL tips we list the most important points to watch.

When do you need more?

In practice, we see that companies in the beverage industry often fall just outside this standard. Some common situations:

Older Odoo versions

Still running Odoo 16? Then returnable packaging support for PEPPOL is not part of the standard yet. On version 17 it works for fixed amounts, but not for calculated deposits. Considering an upgrade? Then read what is involved in a migration to a new Odoo version.

Complex deposit calculations

Crates of 24 bottles, returned bottles at a different rate than new ones, combinations of cases and bottles: these kinds of calculations often use a formula-based tax. Correct handling of those is only available from Odoo 18.

Price-included levies

With beverages, excise duties or recycling contributions are often built into the sales price. In combination with empties lines, that can lead to rounding differences in the VAT totals. PEPPOL validation is strict: one cent of difference and your invoice is rejected.

Exemption reason and product name

In Odoo 17 and 18, the exemption reason on empties lines is the generic English text "Exempt from tax". The Belgian PEPPOL specification expects a more specific trilingual statement here: "Leeggoed/Vidange/Empties (Saldo consumer empties)". Only in Odoo 19 is the exemption reason freely configurable, but the Belgian empties text is not in the selection list by default.

In addition, the specification expects the fixed product name "Leeggoed/Vidange/Empties" on empties lines. Odoo uses the name of the tax here, which deviates from that convention.

How do we handle this?

We developed specific Odoo modules that work on top of the standard PEPPOL export. The starting point: the way you work in Odoo does not change. Your accounting, your taxes, your PDF invoices: everything stays the same. The modules only adjust the XML export so that:

  • Returnable packaging appears as separate invoice lines with the correct VAT category E and exemption reason
  • The product name on empties lines automatically contains the prescribed trilingual text
  • The VAT totals add up correctly, even with complex combinations of deposits, excise duties and discounts
  • It works on all Odoo versions, regardless of the standard support

In doing so, we build as much as possible on Odoo's own architecture. The source code links in this article show that we know the standard thoroughly. That way we add exactly what is needed, without duplicating the standard. We apply that philosophy, as much standard as possible and custom development only where it pays off, throughout your accounting. Read more about it on accounting with Odoo.

Does this only affect beverage suppliers?

No. We encounter the problem most often at beverage wholesalers and breweries, but it affects everyone who works with deposits: gas cylinders, pallet deposits, reusable packaging in the food industry. Anywhere you send along something the customer can bring back.

Validation errors with returnable packaging?

Do you recognize problems when sending electronic invoices with deposits? Or do you want to be sure everything is correct before it reaches your customers? Schedule a no-obligation introductory call.

Deposits done right on your PEPPOL invoice?

Thirty minutes, concrete answers to your situation.

Schedule an introductory call
Insights
Migrating to a new Odoo version: what does it involve?
Why regular upgrades pay off, who does what, and how we approach every migration in two clear phases.