Store sepa message id and sepa payment info id
issue11052 review389451002
This commit is contained in:
1 parent
9ca39f5781
commit
eb57a814a8
14 files changed
+100
-13
No files matched your search
@@ -1,3 +1,4 @@
|
||||
* Store sepa message id and sepa payment info id
|
||||
* Add support for Python 3.10
|
||||
* Remove support for Python 3.6
|
||||
* Rename generate_message button to sepa_generate_message
|
||||
|
||||
+61
-7
@@ -3,6 +3,7 @@
|
||||
import datetime
|
||||
import os
|
||||
import unicodedata
|
||||
import uuid
|
||||
from io import BytesIO
|
||||
from itertools import groupby
|
||||
|
||||
@@ -23,7 +24,8 @@ 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.tools import grouped_slice, reduce_ids, sortable_values
|
||||
from trytond.tools import (
|
||||
grouped_slice, lstrip_wildcard, reduce_ids, sortable_values)
|
||||
from trytond.transaction import Transaction
|
||||
|
||||
from .sepa_handler import CAMT054
|
||||
@@ -189,6 +191,10 @@ class Group(metaclass=PoolMeta):
|
||||
'invisible': ~Eval('sepa_messages'),
|
||||
},
|
||||
depends=['company'])
|
||||
sepa_id = fields.Char("SEPA ID", readonly=True, size=35,
|
||||
states={
|
||||
'invisible': ~Eval('sepa_id'),
|
||||
})
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
@@ -238,6 +244,15 @@ class Group(metaclass=PoolMeta):
|
||||
gettext('account_payment_sepa'
|
||||
'.msg_payment_process_no_iban',
|
||||
payment=payment.rec_name))
|
||||
to_write = []
|
||||
for key, payments in self.sepa_payments:
|
||||
to_write.append(payments)
|
||||
to_write.append({
|
||||
'sepa_info_id': self.sepa_group_payment_id(key),
|
||||
})
|
||||
if to_write:
|
||||
Payment.write(*to_write)
|
||||
self.sepa_id = uuid.uuid4().hex
|
||||
self.sepa_generate_message(_save=False)
|
||||
|
||||
@dualmethod
|
||||
@@ -267,17 +282,17 @@ class Group(metaclass=PoolMeta):
|
||||
return self.company.party
|
||||
|
||||
def sepa_group_payment_key(self, payment):
|
||||
key = (('date', payment.date),)
|
||||
key = (
|
||||
('payment_info', payment.sepa_info_id),
|
||||
('date', payment.date),
|
||||
)
|
||||
if self.kind == 'receivable':
|
||||
key += (('sequence_type', payment.sepa_mandate_sequence_type),)
|
||||
key += (('scheme', payment.sepa_mandate.scheme),)
|
||||
return key
|
||||
|
||||
def sepa_group_payment_id(self, key):
|
||||
payment_id = str(key['date'].toordinal())
|
||||
if self.kind == 'receivable':
|
||||
payment_id += '-' + key['sequence_type']
|
||||
return payment_id
|
||||
return key['payment_info'] or uuid.uuid4().hex
|
||||
|
||||
@property
|
||||
def sepa_payments(self):
|
||||
@@ -292,7 +307,23 @@ class Group(metaclass=PoolMeta):
|
||||
|
||||
@property
|
||||
def sepa_message_id(self):
|
||||
return self.number
|
||||
return self.sepa_id or self.number
|
||||
|
||||
@classmethod
|
||||
def search_rec_name(cls, name, clause):
|
||||
if clause[1].startswith('!') or clause[1].startswith('not '):
|
||||
bool_op = 'AND'
|
||||
else:
|
||||
bool_op = 'OR'
|
||||
code_value = clause[2]
|
||||
if clause[1].endswith('like'):
|
||||
code_value = lstrip_wildcard(clause[2])
|
||||
domain = super().search_rec_name(name, clause)
|
||||
return [
|
||||
bool_op,
|
||||
domain,
|
||||
('sepa_id', clause[1], code_value) + tuple(clause[3:]),
|
||||
]
|
||||
|
||||
|
||||
class Payment(metaclass=PoolMeta):
|
||||
@@ -335,6 +366,10 @@ class Payment(metaclass=PoolMeta):
|
||||
'get_sepa_end_to_end_id', searcher='search_end_to_end_id')
|
||||
sepa_instruction_id = fields.Function(fields.Char('SEPA Instruction ID'),
|
||||
'get_sepa_instruction_id', searcher='search_sepa_instruction_id')
|
||||
sepa_info_id = fields.Char("SEPA Info ID", readonly=True, size=35,
|
||||
states={
|
||||
'invisible': ~Eval('sepa_info_id'),
|
||||
})
|
||||
|
||||
@classmethod
|
||||
def copy(cls, payments, default=None):
|
||||
@@ -417,6 +452,25 @@ class Payment(metaclass=PoolMeta):
|
||||
}),
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def search_rec_name(cls, name, clause):
|
||||
domain = super().search_rec_name(name, clause)
|
||||
if domain:
|
||||
if clause[1].startswith('!') or clause[1].startswith('not '):
|
||||
bool_op = 'AND'
|
||||
else:
|
||||
bool_op = 'OR'
|
||||
domain = [
|
||||
bool_op,
|
||||
domain,
|
||||
]
|
||||
code_value = clause[2]
|
||||
if clause[1].endswith('like'):
|
||||
code_value = lstrip_wildcard(clause[2])
|
||||
domain.append(
|
||||
('sepa_info_id', clause[1], code_value) + tuple(clause[3:]))
|
||||
return domain
|
||||
|
||||
|
||||
class Mandate(Workflow, ModelSQL, ModelView):
|
||||
'SEPA Mandate'
|
||||
|
||||
+10
@@ -14,12 +14,22 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="inherit" ref="account_payment.payment_group_view_form"/>
|
||||
<field name="name">payment_group_form</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="group_list">
|
||||
<field name="model">account.payment.group</field>
|
||||
<field name="inherit" ref="account_payment.payment_group_view_list"/>
|
||||
<field name="name">payment_group_list</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="payment_view_form">
|
||||
<field name="model">account.payment</field>
|
||||
<field name="inherit" ref="account_payment.payment_view_form"/>
|
||||
<field name="name">payment_form</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="payment_view_list">
|
||||
<field name="model">account.payment</field>
|
||||
<field name="inherit" ref="account_payment.payment_view_list"/>
|
||||
<field name="name">payment_list</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="mandate_view_form">
|
||||
<field name="model">account.payment.sepa.mandate</field>
|
||||
|
||||
@@ -41,7 +41,7 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<!-- FwdgAgt -->
|
||||
</GrpHdr>
|
||||
<PmtInf py:for="key, payments in group.sepa_payments">
|
||||
<PmtInfId>${group.sepa_group_payment_id(key)[:35]}</PmtInfId>
|
||||
<PmtInfId>${key['payment_info'][:35]}</PmtInfId>
|
||||
<PmtMtd>TRF</PmtMtd>
|
||||
<BtchBookg>${'true' if group.journal.sepa_batch_booking else 'false'}</BtchBookg>
|
||||
<NbOfTxs>${len(payments)}</NbOfTxs>
|
||||
|
||||
@@ -22,7 +22,7 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<!-- FwdgAgt -->
|
||||
</GrpHdr>
|
||||
<PmtInf py:for="key, payments in group.sepa_payments">
|
||||
<PmtInfId>${group.sepa_group_payment_id(key)[:35]}</PmtInfId>
|
||||
<PmtInfId>${key['payment_info'][:35]}</PmtInfId>
|
||||
<PmtMtd>TRF</PmtMtd>
|
||||
<BtchBookg>${'true' if group.journal.sepa_batch_booking else 'false'}</BtchBookg>
|
||||
<NbOfTxs>${len(payments)}</NbOfTxs>
|
||||
|
||||
@@ -21,7 +21,7 @@ this repository contains the full copyright notices and license terms. -->
|
||||
</InitgPty>
|
||||
</GrpHdr>
|
||||
<PmtInf py:for="key, payments in group.sepa_payments">
|
||||
<PmtInfId>${group.sepa_group_payment_id(key)[:35]}</PmtInfId>
|
||||
<PmtInfId>${key['payment_info'][:35]}</PmtInfId>
|
||||
<PmtMtd>TRF</PmtMtd>
|
||||
<BtchBookg>${'true' if group.journal.sepa_batch_booking else 'false'}</BtchBookg>
|
||||
<NbOfTxs>${len(payments)}</NbOfTxs>
|
||||
|
||||
@@ -41,7 +41,7 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<!-- FwdgAgt -->
|
||||
</GrpHdr>
|
||||
<PmtInf py:for="key, payments in group.sepa_payments">
|
||||
<PmtInfId>${group.sepa_group_payment_id(key)[:35]}</PmtInfId>
|
||||
<PmtInfId>${key['payment_info'][:35]}</PmtInfId>
|
||||
<PmtMtd>DD</PmtMtd>
|
||||
<BtchBookg>${'true' if group.journal.sepa_batch_booking else 'false'}</BtchBookg>
|
||||
<NbOfTxs>${len(payments)}</NbOfTxs>
|
||||
|
||||
@@ -22,7 +22,7 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<!-- FwdgAgt -->
|
||||
</GrpHdr>
|
||||
<PmtInf py:for="key, payments in group.sepa_payments">
|
||||
<PmtInfId>${group.sepa_group_payment_id(key)[:35]}</PmtInfId>
|
||||
<PmtInfId>${key['payment_info'][:35]}</PmtInfId>
|
||||
<PmtMtd>DD</PmtMtd>
|
||||
<BtchBookg>${'true' if group.journal.sepa_batch_booking else 'false'}</BtchBookg>
|
||||
<NbOfTxs>${len(payments)}</NbOfTxs>
|
||||
|
||||
@@ -21,7 +21,7 @@ this repository contains the full copyright notices and license terms. -->
|
||||
</InitgPty>
|
||||
</GrpHdr>
|
||||
<PmtInf py:for="key, payments in group.sepa_payments">
|
||||
<PmtInfId>${group.sepa_group_payment_id(key)[:35]}</PmtInfId>
|
||||
<PmtInfId>${key['payment_info'][:35]}</PmtInfId>
|
||||
<PmtMtd>DD</PmtMtd>
|
||||
<BtchBookg>${'true' if group.journal.sepa_batch_booking else 'false'}</BtchBookg>
|
||||
<NbOfTxs>${len(payments)}</NbOfTxs>
|
||||
|
||||
@@ -355,6 +355,8 @@ class AccountPaymentSepaTestCase(CompanyTestMixin, ModuleTestCase):
|
||||
|
||||
for payment in payments:
|
||||
self.assertEqual(payment.sepa_mandate_sequence_type, 'RCUR')
|
||||
self.assertTrue(payment.sepa_info_id)
|
||||
self.assertIsNotNone(payment.group.sepa_id)
|
||||
|
||||
@with_transaction()
|
||||
def handle_camt054(self, flavor):
|
||||
|
||||
@@ -5,6 +5,8 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<xpath expr="//notebook/page[@id='info']" position="inside">
|
||||
<label name="sepa_mandate"/>
|
||||
<field name="sepa_mandate"/>
|
||||
<label name="sepa_info_id"/>
|
||||
<field name="sepa_info_id"/>
|
||||
<separator id="sepa_return_reason" string="Return Reason" colspan="4"/>
|
||||
<label name="sepa_return_reason_code" string="Code"/>
|
||||
<field name="sepa_return_reason_code"/>
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<data>
|
||||
<xpath expr="/form/field[@name='kind']" position="after">
|
||||
<label name="sepa_id"/>
|
||||
<field name="sepa_id" colspan="3"/>
|
||||
<field name="sepa_messages" colspan="4"/>
|
||||
<button name="sepa_generate_message" colspan="4"/>
|
||||
</xpath>
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<data>
|
||||
<xpath expr="/tree/field[@name='kind']" position="after">
|
||||
<field name="sepa_id" optional="0" expand="1"/>
|
||||
</xpath>
|
||||
</data>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<data>
|
||||
<xpath expr="/tree/field[@name='party']" position="after">
|
||||
<field name="sepa_info_id" expand="1" optional="0"/>
|
||||
</xpath>
|
||||
</data>
|
||||
Reference in new issue
Block a user