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
108 changes: 108 additions & 0 deletions account_invoice_ubl_payment_mandate/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
.. image:: https://odoo-community.org/readme-banner-image
:target: https://odoo-community.org/get-involved?utm_source=readme
:alt: Odoo Community Association

===================================
Account Invoice Ubl Payment Mandate
===================================

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

.. |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/license-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%2Fedi-lightgray.png?logo=github
:target: https://github.com/OCA/edi/tree/16.0/account_invoice_ubl_payment_mandate
:alt: OCA/edi
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/edi-16-0/edi-16-0-account_invoice_ubl_payment_mandate
: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/edi&target_branch=16.0
:alt: Try me on Runboat

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

This module extends the UBL invoice generation to include direct debit
mandate information in the ``PaymentMeans`` block.

When the invoice payment means code is ``49`` (Direct debit) or ``59``
(SEPA direct debit), the generated UBL XML contains a ``PaymentMandate``
node with the mandate reference and the payer bank account.

**Table of contents**

.. contents::
:local:

Use Cases / Context
===================

Peppol BIS Billing rule PEPPOL-EN16931-R061 requires a mandate reference
when an invoice uses direct debit as payment means.

This module is useful when customer invoices are exported as UBL and
paid by direct debit, especially for SEPA direct debit flows managed
with banking mandates.

The module acts as glue between ``account_invoice_ubl``,
``base_ubl_payment``, and ``account_banking_mandate``. It reuses the
mandate set on the invoice to fill the UBL ``PaymentMandate``
information.

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

Bugs are tracked on `GitHub Issues <https://github.com/OCA/edi/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/edi/issues/new?body=module:%20account_invoice_ubl_payment_mandate%0Aversion:%2016.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
-------

* ACSONE SA/NV

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

- Souheil Bejaoui souheil.bejaoui@acsone.eu (https://acsone.eu)

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-sbejaoui| image:: https://github.com/sbejaoui.png?size=40px
:target: https://github.com/sbejaoui
:alt: sbejaoui

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

|maintainer-sbejaoui|

This module is part of the `OCA/edi <https://github.com/OCA/edi/tree/16.0/account_invoice_ubl_payment_mandate>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
1 change: 1 addition & 0 deletions account_invoice_ubl_payment_mandate/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import models
19 changes: 19 additions & 0 deletions account_invoice_ubl_payment_mandate/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Copyright 2026 ACSONE SA/NV
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

{
"name": "Account Invoice Ubl Payment Mandate",
"summary": "Add UBL payment mandate details for direct debit invoices",
"version": "16.0.1.0.0",
"license": "AGPL-3",
"author": "ACSONE SA/NV,Odoo Community Association (OCA)",
"maintainers": ["sbejaoui"],
"website": "https://github.com/OCA/edi",
"depends": [
"account_banking_mandate",
"account_invoice_ubl",
"base_ubl_payment",
],
"data": [],
"demo": [],
}
1 change: 1 addition & 0 deletions account_invoice_ubl_payment_mandate/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import base_ubl
81 changes: 81 additions & 0 deletions account_invoice_ubl_payment_mandate/models/base_ubl.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Copyright 2026 ACSONE SA/NV
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from lxml import etree

from odoo import _, api, models
from odoo.exceptions import UserError


class BaseUbl(models.AbstractModel):
_inherit = "base.ubl"

@api.model
def _ubl_add_payment_means(
self,
partner_bank,
payment_mode,
date_due,
parent_node,
ns,
payment_identifier=None,
version="2.1",
):
res = super()._ubl_add_payment_means(
partner_bank,
payment_mode,
date_due,
parent_node,
ns,
payment_identifier=payment_identifier,
version=version,
)
self._ubl_add_payment_mandate(parent_node, ns)
return res

@api.model
def _ubl_add_payment_mandate(self, parent_node, ns):
payment_means_nodes = parent_node.findall(ns["cac"] + "PaymentMeans")
if not payment_means_nodes:
# nothing to do if the payment block was not generated
return

payment_means = payment_means_nodes[-1]
payment_means_code = payment_means.find(ns["cbc"] + "PaymentMeansCode")
if payment_means_code is None or payment_means_code.text not in ("49", "59"):
# peppol only requires PaymentMandate for direct debit means
return

if not self.mandate_id:
# direct debit invoices must carry a mandate reference
raise UserError(
_(
"A mandate reference must be provided for direct debit "
"payment means code %(code)s.",
code=payment_means_code.text,
)
)

payer_bank = self.mandate_id.partner_bank_id
payer_iban = payer_bank.sanitized_acc_number
if not payer_iban:
raise UserError(
_("The direct debit mandate must have a payer bank account.")
)

payment_mandate = etree.SubElement(
payment_means,
ns["cac"] + "PaymentMandate",
)
mandate_id = etree.SubElement(payment_mandate, ns["cbc"] + "ID")
mandate_id.text = self.mandate_id.unique_mandate_reference

payer_financial_account = etree.SubElement(
payment_mandate,
ns["cac"] + "PayerFinancialAccount",
)
payer_financial_account_id = etree.SubElement(
payer_financial_account,
ns["cbc"] + "ID",
)
payer_financial_account_id.text = payer_iban
10 changes: 10 additions & 0 deletions account_invoice_ubl_payment_mandate/readme/CONTEXT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Peppol BIS Billing rule PEPPOL-EN16931-R061 requires a mandate reference when
an invoice uses direct debit as payment means.

This module is useful when customer invoices are exported as UBL and paid by
direct debit, especially for SEPA direct debit flows managed with banking
mandates.

The module acts as glue between `account_invoice_ubl`, `base_ubl_payment`, and
`account_banking_mandate`. It reuses the mandate set on the invoice to fill the
UBL `PaymentMandate` information.
1 change: 1 addition & 0 deletions account_invoice_ubl_payment_mandate/readme/CONTRIBUTORS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Souheil Bejaoui <souheil.bejaoui@acsone.eu> (https://acsone.eu)
6 changes: 6 additions & 0 deletions account_invoice_ubl_payment_mandate/readme/DESCRIPTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
This module extends the UBL invoice generation to include direct debit mandate
information in the `PaymentMeans` block.

When the invoice payment means code is `49` (Direct debit) or `59` (SEPA direct
debit), the generated UBL XML contains a `PaymentMandate` node with the mandate
reference and the payer bank account.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading