diff --git a/modules/account_payment_sepa/CHANGELOG b/modules/account_payment_sepa/CHANGELOG
index 84e3bc9424..7de2a4f4b7 100644
--- a/modules/account_payment_sepa/CHANGELOG
+++ b/modules/account_payment_sepa/CHANGELOG
@@ -1,3 +1,4 @@
+* Allow messages to be downloaded at once
Version 7.4.0 - 2024-11-04
--------------------------
diff --git a/modules/account_payment_sepa/__init__.py b/modules/account_payment_sepa/__init__.py
index 927f4dad2a..181f298e5a 100644
--- a/modules/account_payment_sepa/__init__.py
+++ b/modules/account_payment_sepa/__init__.py
@@ -23,4 +23,5 @@ def register():
module='account_payment_sepa', type_='wizard')
Pool.register(
payment.MandateReport,
+ payment.MessageReport,
module='account_payment_sepa', type_='report')
diff --git a/modules/account_payment_sepa/payment.py b/modules/account_payment_sepa/payment.py
index ed8a7e67c9..0724688385 100644
--- a/modules/account_payment_sepa/payment.py
+++ b/modules/account_payment_sepa/payment.py
@@ -24,6 +24,7 @@ from trytond.modules.account_payment.exceptions import ProcessError
from trytond.modules.company import CompanyReport
from trytond.pool import Pool, PoolMeta
from trytond.pyson import Eval, If
+from trytond.report import Report
from trytond.tools import (
grouped_slice, is_full_text, lstrip_wildcard, reduce_ids, sortable_values)
from trytond.transaction import Transaction
@@ -905,6 +906,12 @@ class Message(Workflow, ModelSQL, ModelView):
models = cls._get_origin()
return [(None, '')] + [(m, get_name(m)) for m in models]
+ def get_rec_name(self, name):
+ if self.origin:
+ return self.origin.rec_name
+ else:
+ return f'({self.id})'
+
@classmethod
@ModelView.button
@Workflow.transition('draft')
@@ -966,3 +973,12 @@ class Message(Workflow, ModelSQL, ModelView):
def send(self):
pass
+
+
+class MessageReport(Report):
+ __name__ = 'account.payment.sepa.message'
+
+ @classmethod
+ def render(cls, action, report_context):
+ record = report_context['record']
+ return record.message
diff --git a/modules/account_payment_sepa/payment.xml b/modules/account_payment_sepa/payment.xml
index 071b0f7de8..241bee8736 100644
--- a/modules/account_payment_sepa/payment.xml
+++ b/modules/account_payment_sepa/payment.xml
@@ -303,6 +303,20 @@ this repository contains the full copyright notices and license terms. -->
Generate SEPA Message
+
+ Message
+ account.payment.sepa.message
+ account.payment.sepa.message
+
+
+ xml
+
+
+ form_print
+ account.payment.sepa.message,-1
+
+
+
Mandate
account.payment.sepa.mandate
diff --git a/modules/account_payment_sepa/setup.py b/modules/account_payment_sepa/setup.py
index a13e7dc5d3..65ee47e7b0 100755
--- a/modules/account_payment_sepa/setup.py
+++ b/modules/account_payment_sepa/setup.py
@@ -50,7 +50,7 @@ for dep in info.get('depends', []):
requires.append(get_require_version('trytond_%s' % dep))
requires.append(get_require_version('trytond'))
-tests_require = []
+tests_require = [get_require_version('proteus')]
setup(name=name,
version=version,
diff --git a/modules/account_payment_sepa/tests/scenario_account_payment_sepa.rst b/modules/account_payment_sepa/tests/scenario_account_payment_sepa.rst
new file mode 100644
index 0000000000..bc08ec86f2
--- /dev/null
+++ b/modules/account_payment_sepa/tests/scenario_account_payment_sepa.rst
@@ -0,0 +1,134 @@
+=============================
+Account Payment SEPA Scenario
+=============================
+
+Imports::
+
+ >>> import datetime as dt
+ >>> from decimal import Decimal
+
+ >>> from proteus import Model, Report
+ >>> from trytond.modules.account.tests.tools import (
+ ... create_chart, create_fiscalyear, get_accounts)
+ >>> from trytond.modules.company.tests.tools import create_company, get_company
+ >>> from trytond.tests.tools import activate_modules
+
+ >>> today = dt.date.today()
+
+Activate modules::
+
+ >>> config = activate_modules(
+ ... 'account_payment_sepa', create_company, create_chart, create_fiscalyear)
+
+ >>> Bank = Model.get('bank')
+ >>> BankAccount = Model.get('bank.account')
+ >>> Mandate = Model.get('account.payment.sepa.mandate')
+ >>> Message = Model.get('account.payment.sepa.message')
+ >>> Party = Model.get('party.party')
+ >>> Payment = Model.get('account.payment')
+ >>> PaymentJournal = Model.get('account.payment.journal')
+
+ >>> company = get_company()
+ >>> accounts = get_accounts()
+
+Create parties::
+
+ >>> customer = Party(name='Customer')
+ >>> customer.save()
+ >>> supplier = Party(name='Supplier')
+ >>> supplier.save()
+
+Setup SEPA Identifier::
+
+ >>> identifier = company.party.identifiers.new()
+ >>> identifier.type = 'eu_at_02'
+ >>> identifier.code = 'ES23ZZZ47690558N'
+ >>> company.party.save()
+
+Create bank accounts::
+
+ >>> bank_party = Party(name="EU Bank")
+ >>> bank_party.save()
+
+ >>> company_bank = Bank(party=bank_party, bic='CTBKBEBX')
+ >>> company_bank.save()
+ >>> company_account = BankAccount(bank=company_bank)
+ >>> company_account.owners.append(company.party)
+ >>> company_account_number = company_account.numbers.new()
+ >>> company_account_number.type = 'iban'
+ >>> company_account_number.number = 'BE70953368654125'
+ >>> company_account.save()
+
+ >>> customer_bank = Bank(party=bank_party, bic='KREDBEBB')
+ >>> customer_bank.save()
+ >>> customer_account = BankAccount(bank=customer_bank)
+ >>> customer_account.owners.append(customer)
+ >>> customer_account_number = customer_account.numbers.new()
+ >>> customer_account_number.type = 'iban'
+ >>> customer_account_number.number = 'BE85735556927306'
+ >>> customer_account.save()
+
+ >>> supplier_account = BankAccount(bank=company_bank)
+ >>> supplier_account.owners.append(supplier)
+ >>> supplier_account_number = supplier_account.numbers.new()
+ >>> supplier_account_number.type = 'iban'
+ >>> supplier_account_number.number = 'BE07131673267766'
+ >>> supplier_account.save()
+
+Create mandate::
+
+ >>> mandate = Mandate(party=customer)
+ >>> mandate.account_number = customer_account.numbers[0]
+ >>> mandate.identification = 'MANDATE'
+ >>> mandate.type = 'recurrent'
+ >>> mandate.click('request')
+ >>> mandate.signature_date = today
+ >>> mandate.click('validate_mandate')
+ >>> mandate.state
+ 'validated'
+
+Create payment journal::
+
+ >>> payment_journal = PaymentJournal(name="Journal")
+ >>> payment_journal.process_method = 'sepa'
+ >>> payment_journal.sepa_bank_account_number = company_account.numbers[0]
+ >>> payment_journal.sepa_payable_flavor = 'pain.001.001.03'
+ >>> payment_journal.sepa_receivable_flavor = 'pain.008.001.02'
+ >>> payment_journal.save()
+
+Create payments::
+
+ >>> payments = []
+ >>> payment = Payment(party=customer, kind='receivable')
+ >>> payment.journal = payment_journal
+ >>> payment.amount = Decimal('100.00')
+ >>> payment.date = today
+ >>> payment.save()
+ >>> payment.click('submit')
+ >>> payments.append(payment)
+
+ >>> payment = Payment(party=supplier, kind='payable')
+ >>> payment.journal = payment_journal
+ >>> payment.amount = Decimal('500.00')
+ >>> payment.date = today
+ >>> payment.save()
+ >>> payment.click('submit')
+ >>> payment.click('approve')
+ >>> payments.append(payment)
+
+Process payments::
+
+ >>> process_payment = Payment.click(payments, 'process_wizard')
+ >>> groups, = process_payment.actions
+ >>> len(groups)
+ 2
+ >>> messages = [m for g in groups for m in g.sepa_messages]
+ >>> len(messages)
+ 2
+
+ >>> message_report = Report('account.payment.sepa.message')
+ >>> _ = message_report.execute(messages)
+
+ >>> Message.click(messages, 'do')
+ >>> [m.state for m in messages]
+ ['done', 'done']
diff --git a/modules/account_payment_sepa/tests/test_scenario.py b/modules/account_payment_sepa/tests/test_scenario.py
new file mode 100644
index 0000000000..dc1d23e7e5
--- /dev/null
+++ b/modules/account_payment_sepa/tests/test_scenario.py
@@ -0,0 +1,8 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.tests.test_tryton import load_doc_tests
+
+
+def load_tests(*args, **kwargs):
+ return load_doc_tests(__name__, __file__, *args, **kwargs)