Add party's address to the SEPA mandate

Use explicit address selection to display on the SEPA mandate instead of the
default first address.

Closes #14229
This commit is contained in:
Cédric Krier
2025-09-14 12:23:08 +02:00
parent 47b79131dc
commit d96260f590
8 changed files with 67 additions and 13 deletions
+20
View File
@@ -14,6 +14,26 @@ a database from another series.
.. warning::
You cannot skip more than 2 series ending with ``.0``.
7.8
---
After
~~~~~
* If ``account_payment_sepa`` module is activated, fill the address of
validated mandates with default value with the ``trytond-console``:
.. code-block:: python
Mandate = pool.get('account.payment.sepa.mandate')
mandates = Mandate.search([
('state', '=', 'validated'),
('address', '=', None),
])
for mandate in mandates:
mandate.address = mandate.on_change_party()
Mandate.save(mandates)
7.6
---
+1
View File
@@ -1,3 +1,4 @@
* Add party's address to the mandate
Version 7.6.0 - 2025-04-28
--------------------------
+9 -9
View File
@@ -753,7 +753,7 @@
<text:p text:style-name="P16">Your address</text:p>
</table:table-cell>
<table:table-cell table:style-name="Table1.B1" table:number-columns-spanned="2" office:value-type="string">
<text:p text:style-name="P13"><text:placeholder text:placeholder-type="text">&lt;mandate.party.addresses[0].street if mandate.party.addresses else &apos;&apos;&gt;</text:placeholder></text:p>
<text:p text:style-name="P13"><text:placeholder text:placeholder-type="text">&lt;mandate.address.street if mandate.address else &apos;&apos;&gt;</text:placeholder></text:p>
</table:table-cell>
<table:covered-table-cell/>
</table:table-row>
@@ -771,10 +771,10 @@
<text:p text:style-name="P15"/>
</table:table-cell>
<table:table-cell table:style-name="Table1.B5" office:value-type="string">
<text:p text:style-name="Table_20_Contents"><text:placeholder text:placeholder-type="text">&lt;mandate.party.addresses[0].postal_code if mandate.party.addresses else &apos;&apos;&gt;</text:placeholder></text:p>
<text:p text:style-name="Table_20_Contents"><text:placeholder text:placeholder-type="text">&lt;mandate.address.postal_code if mandate.address else &apos;&apos;&gt;</text:placeholder></text:p>
</table:table-cell>
<table:table-cell table:style-name="Table1.B1" office:value-type="string">
<text:p text:style-name="P13"><text:placeholder text:placeholder-type="text">&lt;mandate.party.addresses[0].city if mandate.party.addresses else &apos;&apos;&gt;</text:placeholder></text:p>
<text:p text:style-name="P13"><text:placeholder text:placeholder-type="text">&lt;mandate.address.city if mandate.address else &apos;&apos;&gt;</text:placeholder></text:p>
</table:table-cell>
</table:table-row>
<table:table-row>
@@ -793,7 +793,7 @@
<text:p text:style-name="P21"/>
</table:table-cell>
<table:table-cell table:style-name="Table1.B1" table:number-columns-spanned="2" office:value-type="string">
<text:p text:style-name="P13"><text:placeholder text:placeholder-type="text">&lt;mandate.party.addresses[0].country.rec_name if mandate.party.addresses and mandate.party.addresses[0].country else &apos;&apos;&gt;</text:placeholder></text:p>
<text:p text:style-name="P13"><text:placeholder text:placeholder-type="text">&lt;mandate.address.country.rec_name if mandate.address and mandate.address.country else &apos;&apos;&gt;</text:placeholder></text:p>
</table:table-cell>
<table:covered-table-cell/>
</table:table-row>
@@ -883,7 +883,7 @@
<text:p text:style-name="P15"/>
</table:table-cell>
<table:table-cell table:style-name="Table1.B1" table:number-columns-spanned="2" office:value-type="string">
<text:p text:style-name="P14"><text:placeholder text:placeholder-type="text">&lt;mandate.company.party.addresses[0].street if mandate.company.party.addresses else &apos;&apos;&gt;</text:placeholder></text:p>
<text:p text:style-name="P14"><text:placeholder text:placeholder-type="text">&lt;mandate.company_address.street if mandate.company_address else &apos;&apos;&gt;</text:placeholder></text:p>
</table:table-cell>
<table:covered-table-cell/>
</table:table-row>
@@ -901,10 +901,10 @@
<text:p text:style-name="P15"/>
</table:table-cell>
<table:table-cell table:style-name="Table1.B5" office:value-type="string">
<text:p text:style-name="P14"><text:placeholder text:placeholder-type="text">&lt;mandate.company.party.addresses[0].postal_code if mandate.company.party.addresses else &apos;&apos;&gt;</text:placeholder></text:p>
<text:p text:style-name="P14"><text:placeholder text:placeholder-type="text">&lt;mandate.company_address.postal_code if mandate.company_address else &apos;&apos;&gt;</text:placeholder></text:p>
</table:table-cell>
<table:table-cell table:style-name="Table1.B1" office:value-type="string">
<text:p text:style-name="P14"><text:placeholder text:placeholder-type="text">&lt;mandate.company.party.addresses[0].city if mandate.company.party.addresses else &apos;&apos;&gt;</text:placeholder></text:p>
<text:p text:style-name="P14"><text:placeholder text:placeholder-type="text">&lt;mandate.company_address.city if mandate.company_address else &apos;&apos;&gt;</text:placeholder></text:p>
</table:table-cell>
</table:table-row>
<table:table-row>
@@ -923,7 +923,7 @@
<text:p text:style-name="P15"/>
</table:table-cell>
<table:table-cell table:style-name="Table1.B1" table:number-columns-spanned="2" office:value-type="string">
<text:p text:style-name="P14"><text:placeholder text:placeholder-type="text">&lt;mandate.company.party.addresses[0].country.rec_name if mandate.company.party.addresses and mandate.company.party.addresses[0].country else &apos;&apos;&gt;</text:placeholder></text:p>
<text:p text:style-name="P14"><text:placeholder text:placeholder-type="text">&lt;mandate.company_address.country.rec_name if mandate.company_address and mandate.company_address.country else &apos;&apos;&gt;</text:placeholder></text:p>
</table:table-cell>
<table:covered-table-cell/>
</table:table-row>
@@ -1018,4 +1018,4 @@
<text:p text:style-name="P31"><text:placeholder text:placeholder-type="text">&lt;/for&gt;</text:placeholder></text:p>
</office:text>
</office:body>
</office:document>
</office:document>
+24 -4
View File
@@ -26,7 +26,8 @@ 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)
cached_property, grouped_slice, is_full_text, lstrip_wildcard, reduce_ids,
sortable_values)
from trytond.transaction import Transaction
from .sepa_handler import CAMT054
@@ -503,12 +504,19 @@ class Mandate(Workflow, ModelSQL, ModelView):
'company': Eval('company', -1),
},
depends={'company'})
address = fields.Many2One(
'party.address', "Address",
domain=[
('party', '=', Eval('party', -1)),
],
states={
'readonly': Eval('state').in_(['validated', 'cancelled']),
'required': Eval('state') == 'validated',
})
account_number = fields.Many2One('bank.account.number', 'Account Number',
ondelete='RESTRICT',
states={
'readonly': (
Eval('state').in_(['validated', 'cancelled'])
| ~Eval('party')),
'readonly': Eval('state').in_(['validated', 'cancelled']),
'required': Eval('state') == 'validated',
},
domain=[
@@ -603,6 +611,14 @@ class Mandate(Workflow, ModelSQL, ModelView):
t, (t.state, Index.Equality(cardinality='low')),
where=t.state.in_(['draft', 'requested'])))
@fields.depends('party', '_parent_party.id')
def on_change_party(self):
if self.party and self.party.id >= 0:
self.address = self.party.address_get()
else:
self.address = None
self.account_number = None
@staticmethod
def default_company():
return Transaction().context.get('company')
@@ -612,6 +628,10 @@ class Mandate(Workflow, ModelSQL, ModelView):
self.identification_readonly = self.default_identification_readonly(
company=self.company.id if self.company else None)
@cached_property
def company_address(self):
return self.company.party.address_get()
@staticmethod
def default_type():
return 'recurrent'
@@ -82,6 +82,12 @@ Create mandate::
>>> mandate.identification = 'MANDATE'
>>> mandate.type = 'recurrent'
>>> mandate.click('request')
>>> mandate.state
'requested'
>>> mandate_report = Report('account.payment.sepa.mandate')
>>> _ = mandate_report.execute([mandate])
>>> mandate.signature_date = today
>>> mandate.click('validate_mandate')
>>> mandate.state
@@ -74,6 +74,7 @@ def setup_mandate(company, customer, account):
return Mandate.create([{
'company': company,
'party': customer,
'address': customer.addresses[0],
'account_number': account.numbers[0],
'identification': 'MANDATE',
'type': 'recurrent',
@@ -4,8 +4,13 @@ this repository contains the full copyright notices and license terms. -->
<form>
<label name="party"/>
<field name="party"/>
<label name="address"/>
<field name="address"/>
<label name="account_number"/>
<field name="account_number"/>
<newline/>
<label name="company"/>
<field name="company"/>
<newline/>
@@ -4,6 +4,7 @@ this repository contains the full copyright notices and license terms. -->
<tree>
<field name="company" expand="1" optional="1"/>
<field name="party" expand="2"/>
<field name="address" expand="1" optional="1"/>
<field name="account_number" expand="1"/>
<field name="identification" expand="1"/>
<field name="type"/>