From 77a9e732f75d981f0d43462666b55e9fce4d9696 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Sat, 3 Aug 2013 01:12:36 +0200 Subject: [PATCH 01/43] Add module account_banking_sepa_direct_debit that implements pain.008.001.02, pain.008.001.03 and pain.008.001.04. This module is not ready yet : the management of mandates is still missing. I am currently trying to get more information about these mandates to decide what is the best implemtation of the data model of the mandates (O2M on res.partner ? O2M os res.partner.bank ?). --- account_banking_sepa_direct_debit/__init__.py | 26 + .../__openerp__.py | 50 + .../account_banking_sdd.py | 77 ++ .../account_banking_sdd_view.xml | 83 ++ account_banking_sepa_direct_debit/company.py | 75 ++ .../company_view.xml | 22 + .../data/pain.008.001.02.xsd | 879 +++++++++++++++++ .../data/pain.008.001.03.xsd | 925 ++++++++++++++++++ .../data/pain.008.001.04.xsd | 892 +++++++++++++++++ .../data/payment_type_sdd.xml | 37 + .../security/ir.model.access.csv | 2 + .../wizard/__init__.py | 23 + .../wizard/export_sdd.py | 391 ++++++++ .../wizard/export_sdd_view.xml | 41 + 14 files changed, 3523 insertions(+) create mode 100644 account_banking_sepa_direct_debit/__init__.py create mode 100644 account_banking_sepa_direct_debit/__openerp__.py create mode 100644 account_banking_sepa_direct_debit/account_banking_sdd.py create mode 100644 account_banking_sepa_direct_debit/account_banking_sdd_view.xml create mode 100644 account_banking_sepa_direct_debit/company.py create mode 100644 account_banking_sepa_direct_debit/company_view.xml create mode 100644 account_banking_sepa_direct_debit/data/pain.008.001.02.xsd create mode 100644 account_banking_sepa_direct_debit/data/pain.008.001.03.xsd create mode 100644 account_banking_sepa_direct_debit/data/pain.008.001.04.xsd create mode 100644 account_banking_sepa_direct_debit/data/payment_type_sdd.xml create mode 100644 account_banking_sepa_direct_debit/security/ir.model.access.csv create mode 100644 account_banking_sepa_direct_debit/wizard/__init__.py create mode 100644 account_banking_sepa_direct_debit/wizard/export_sdd.py create mode 100644 account_banking_sepa_direct_debit/wizard/export_sdd_view.xml diff --git a/account_banking_sepa_direct_debit/__init__.py b/account_banking_sepa_direct_debit/__init__.py new file mode 100644 index 000000000..bda7501b7 --- /dev/null +++ b/account_banking_sepa_direct_debit/__init__.py @@ -0,0 +1,26 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# SEPA Direct Debit module for OpenERP +# Copyright (C) 2013 Akretion (http://www.akretion.com) +# @author: Alexis de Lattre +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +import company +import wizard +import account_banking_sdd + diff --git a/account_banking_sepa_direct_debit/__openerp__.py b/account_banking_sepa_direct_debit/__openerp__.py new file mode 100644 index 000000000..fc329a073 --- /dev/null +++ b/account_banking_sepa_direct_debit/__openerp__.py @@ -0,0 +1,50 @@ +############################################################################## +# +# SEPA Direct Debit module for OpenERP +# Copyright (C) 2013 Akretion (http://www.akretion.com) +# @author: Alexis de Lattre +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## +{ + 'name': 'Account Banking SEPA Direct Debit', + 'summary': 'Create SEPA XML files for Direct Debit', + 'version': '0.1', + 'license': 'AGPL-3', + 'author': 'Akretion', + 'website': 'http://www.akretion.com', + 'category': 'Banking addons', + 'depends': ['account_direct_debit'], + 'data': [ + 'account_banking_sdd_view.xml', + 'company_view.xml', + 'wizard/export_sdd_view.xml', + 'data/payment_type_sdd.xml', + 'security/ir.model.access.csv', + ], + 'description': ''' +Module to export direct debit payment orders in SEPA XML file format. + +SEPA PAIN (PAyment INitiation) is the new european standard for Customer-to-Bank payment instructions. This module implements SEPA Direct Debit (SDD), more specifically PAIN versions 008.001.02, 008.001.03 and 008.001.04. It is part of the ISO 20022 standard, available on http://www.iso20022.org. + +The Implementation Guidelines for SEPA Direct Debit published by the European Payments Council (http://http://www.europeanpaymentscouncil.eu) use PAIN version 008.001.02. So if you don't know which version your bank supports, you should try version 008.001.02 first. + +This module uses the framework provided by the banking addons, cf https://launchpad.net/banking-addons + +Please contact Alexis de Lattre from Akretion for any help or question about this module. + ''', + 'active': False, + 'installable': True, +} diff --git a/account_banking_sepa_direct_debit/account_banking_sdd.py b/account_banking_sepa_direct_debit/account_banking_sdd.py new file mode 100644 index 000000000..aa08918a2 --- /dev/null +++ b/account_banking_sepa_direct_debit/account_banking_sdd.py @@ -0,0 +1,77 @@ +############################################################################## +# +# SEPA Direct Debit module for OpenERP +# Copyright (C) 2013 Akretion (http://www.akretion.com) +# @author: Alexis de Lattre +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp.osv import orm, fields +import time +from openerp.tools.translate import _ +from openerp.addons.decimal_precision import decimal_precision as dp + + +class banking_export_sdd(orm.Model): + '''SEPA Direct Debit export''' + _name = 'banking.export.sdd' + _description = __doc__ + _rec_name = 'msg_identification' + + def _generate_filename(self, cr, uid, ids, name, arg, context=None): + res = {} + for sepa_file in self.browse(cr, uid, ids, context=context): + res[sepa_file.id] = 'sdd_' + (sepa_file.msg_identification or '') + '.xml' + return res + + _columns = { + 'payment_order_ids': fields.many2many( + 'payment.order', + 'account_payment_order_sdd_rel', + 'banking_export_sepa_id', 'account_order_id', + 'Payment orders', + readonly=True), + 'requested_collec_date': fields.date('Requested collection date', readonly=True), + 'nb_transactions': fields.integer('Number of transactions', readonly=True), + 'total_amount': fields.float('Total amount', + digits_compute=dp.get_precision('Account'), readonly=True), + 'msg_identification': fields.char('Message identification', size=35, + readonly=True), + 'batch_booking': fields.boolean('Batch booking', readonly=True, + help="If true, the bank statement will display only one credit line for all the direct debits of the SEPA XML file ; if false, the bank statement will display one credit line per direct debit of the SEPA XML file."), + 'charge_bearer': fields.selection([ + ('SHAR', 'Shared'), + ('CRED', 'Borne by creditor'), + ('DEBT', 'Borne by debtor'), + ('SLEV', 'Following service level'), + ], 'Charge bearer', readonly=True, + help='Shared : transaction charges on the sender side are to be borne by the debtor, transaction charges on the receiver side are to be borne by the creditor (most transfers use this). Borne by creditor : all transaction charges are to be borne by the creditor. Borne by debtor : all transaction charges are to be borne by the debtor. Following service level : transaction charges are to be applied following the rules agreed in the service level and/or scheme.'), + 'generation_date': fields.datetime('Generation date', + readonly=True), + 'file': fields.binary('SEPA XML file', readonly=True), + 'filename': fields.function(_generate_filename, type='char', size=256, + method=True, string='Filename', readonly=True), + 'state': fields.selection([ + ('draft', 'Draft'), + ('sent', 'Sent'), + ('done', 'Reconciled'), + ], 'State', readonly=True), + } + + _defaults = { + 'generation_date': fields.date.context_today, + 'state': 'draft', + } diff --git a/account_banking_sepa_direct_debit/account_banking_sdd_view.xml b/account_banking_sepa_direct_debit/account_banking_sdd_view.xml new file mode 100644 index 000000000..6dcfb903f --- /dev/null +++ b/account_banking_sepa_direct_debit/account_banking_sdd_view.xml @@ -0,0 +1,83 @@ + + + + + + + account.banking.export.sdd.form + banking.export.sdd + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + + account.banking.export.sdd.tree + banking.export.sdd + + + + + + + + + + + + + Generated SEPA Direct Debit XML files + banking.export.sdd + form + tree,form + + + + + + + +
+
diff --git a/account_banking_sepa_direct_debit/company.py b/account_banking_sepa_direct_debit/company.py new file mode 100644 index 000000000..d85fc6fd7 --- /dev/null +++ b/account_banking_sepa_direct_debit/company.py @@ -0,0 +1,75 @@ +############################################################################## +# +# SEPA Direct Debit module for OpenERP +# Copyright (C) 2013 Akretion (http://www.akretion.com) +# @author: Alexis de Lattre +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp.osv import orm, fields +import logging + +logger = logging.getLogger(__name__) + +class res_company(orm.Model): + _inherit = 'res.company' + + _columns = { + 'sepa_creditor_identifier': fields.char('SEPA Creditor Identifier', size=35, + help="Enter the Creditor Identifier that has been attributed to your company to make SEPA Direct Debits. This identifier is composed of :\n- your country ISO code (2 letters)\n- a 2-digits checkum\n- a 3-letters business code\n- a country-specific identifier"), + } + + + def is_sepa_creditor_identifier_valid(self, cr, uid, sepa_creditor_identifier, context=None): + """Check if SEPA Creditor Identifier is valid + @param sepa_creditor_identifier: SEPA Creditor Identifier as str or unicode + @return: True if valid, False otherwise + """ + if not isinstance(sepa_creditor_identifier, (str, unicode)): + return False + try: + sci_str = str(sepa_creditor_identifier) + except: + logger.warning("SEPA Creditor ID should contain only ASCII caracters.") + return False + sci = sci_str.lower() + if len(sci) < 9: + return False + before_replacement = sci[7:] + sci[0:2] + '00' + logger.debug("SEPA ID check before_replacement = %s" % before_replacement) + after_replacement = '' + for char in before_replacement: + if char.isalpha(): + after_replacement += str(ord(char)-87) + else: + after_replacement += char + logger.debug("SEPA ID check after_replacement = %s" % after_replacement) + if int(sci[2:4]) == (98 - (int(after_replacement) % 97)): + return True + else: + return False + + + def _check_sepa_creditor_identifier(self, cr, uid, ids): + for company in self.browse(cr, uid, ids): + if company.sepa_creditor_identifier: + if not self.is_sepa_creditor_identifier_valid(cr, uid, company.sepa_creditor_identifier): + return False + return True + + _constraints = [ + (_check_sepa_creditor_identifier, "Invalid SEPA Creditor Identifier.", ['sepa_creditor_identifier']), + ] diff --git a/account_banking_sepa_direct_debit/company_view.xml b/account_banking_sepa_direct_debit/company_view.xml new file mode 100644 index 000000000..7691844c1 --- /dev/null +++ b/account_banking_sepa_direct_debit/company_view.xml @@ -0,0 +1,22 @@ + + + + + + + sepa_direct_debit.res.company.form + res.company + + + + + + + + + + diff --git a/account_banking_sepa_direct_debit/data/pain.008.001.02.xsd b/account_banking_sepa_direct_debit/data/pain.008.001.02.xsd new file mode 100644 index 000000000..ceafe505f --- /dev/null +++ b/account_banking_sepa_direct_debit/data/pain.008.001.02.xsd @@ -0,0 +1,879 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account_banking_sepa_direct_debit/data/pain.008.001.03.xsd b/account_banking_sepa_direct_debit/data/pain.008.001.03.xsd new file mode 100644 index 000000000..358480dec --- /dev/null +++ b/account_banking_sepa_direct_debit/data/pain.008.001.03.xsd @@ -0,0 +1,925 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/account_banking_sepa_direct_debit/data/pain.008.001.04.xsd b/account_banking_sepa_direct_debit/data/pain.008.001.04.xsd new file mode 100644 index 000000000..ba8c68346 --- /dev/null +++ b/account_banking_sepa_direct_debit/data/pain.008.001.04.xsd @@ -0,0 +1,892 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account_banking_sepa_direct_debit/data/payment_type_sdd.xml b/account_banking_sepa_direct_debit/data/payment_type_sdd.xml new file mode 100644 index 000000000..5ce4b5b1b --- /dev/null +++ b/account_banking_sepa_direct_debit/data/payment_type_sdd.xml @@ -0,0 +1,37 @@ + + + + + + + + SEPA Direct Debit v02 + pain.008.001.02 + + + payment + + + + SEPA Direct Debit v03 + pain.008.001.03 + + + payment + + + + SEPA Direct Debit v04 + pain.008.001.04 + + + payment + + + + + + diff --git a/account_banking_sepa_direct_debit/security/ir.model.access.csv b/account_banking_sepa_direct_debit/security/ir.model.access.csv new file mode 100644 index 000000000..0cd579511 --- /dev/null +++ b/account_banking_sepa_direct_debit/security/ir.model.access.csv @@ -0,0 +1,2 @@ +"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" +"access_banking_export_sdd","Full access on banking.export.sdd","model_banking_export_sdd","account_payment.group_account_payment",1,1,1,1 diff --git a/account_banking_sepa_direct_debit/wizard/__init__.py b/account_banking_sepa_direct_debit/wizard/__init__.py new file mode 100644 index 000000000..169d0b13d --- /dev/null +++ b/account_banking_sepa_direct_debit/wizard/__init__.py @@ -0,0 +1,23 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# SEPA Direct Debit module for OpenERP +# Copyright (C) 2013 Akretion (http://www.akretion.com) +# @author: Alexis de Lattre +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +import export_sdd diff --git a/account_banking_sepa_direct_debit/wizard/export_sdd.py b/account_banking_sepa_direct_debit/wizard/export_sdd.py new file mode 100644 index 000000000..60456ab1a --- /dev/null +++ b/account_banking_sepa_direct_debit/wizard/export_sdd.py @@ -0,0 +1,391 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# SEPA Direct Debit module for OpenERP +# Copyright (C) 2013 Akretion (http://www.akretion.com) +# @author: Alexis de Lattre +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + + +from openerp.osv import orm, fields +import base64 +from datetime import datetime, timedelta +from openerp.tools.translate import _ +from openerp import tools, netsvc +from lxml import etree +import logging + +_logger = logging.getLogger(__name__) + + +class banking_export_sdd_wizard(orm.TransientModel): + _name = 'banking.export.sdd.wizard' + _description = 'Export SEPA Direct Debit XML file' + _columns = { + 'state': fields.selection([('create', 'Create'), ('finish', 'Finish')], + 'State', readonly=True), + 'msg_identification': fields.char('Message identification', size=35, + # Can't set required=True on the field because it blocks + # the launch of the wizard -> I set it as required in the view + help='This is the message identification of the entire SEPA XML file. 35 characters max.'), + 'batch_booking': fields.boolean('Batch booking', + help="If true, the bank statement will display only one debit line for all the wire transfers of the SEPA XML file ; if false, the bank statement will display one debit line per wire transfer of the SEPA XML file."), + 'requested_collec_date': fields.date('Requested collection date', + help='This is the date on which the collection should be made by the bank. Please keep in mind that banks only execute on working days.'), + 'charge_bearer': fields.selection([ + ('SHAR', 'Shared'), + ('CRED', 'Borne by creditor'), + ('DEBT', 'Borne by debtor'), + ('SLEV', 'Following service level'), + ], 'Charge bearer', required=True, + help='Shared : transaction charges on the sender side are to be borne by the debtor, transaction charges on the receiver side are to be borne by the creditor (most transfers use this). Borne by creditor : all transaction charges are to be borne by the creditor. Borne by debtor : all transaction charges are to be borne by the debtor. Following service level : transaction charges are to be applied following the rules agreed in the service level and/or scheme.'), + 'nb_transactions': fields.related('file_id', 'nb_transactions', + type='integer', string='Number of transactions', readonly=True), + 'total_amount': fields.related('file_id', 'total_amount', type='float', + string='Total amount', readonly=True), + 'file_id': fields.many2one('banking.export.sdd', 'SDD XML file', readonly=True), + 'file': fields.related('file_id', 'file', string="File", type='binary', + readonly=True), + 'filename': fields.related('file_id', 'filename', string="Filename", + type='char', size=256, readonly=True), + 'payment_order_ids': fields.many2many('payment.order', + 'wiz_sdd_payorders_rel', 'wizard_id', 'payment_order_id', + 'Payment orders', readonly=True), + } + + _defaults = { + 'charge_bearer': 'SLEV', + 'state': 'create', + } + + + def _check_msg_identification(self, cr, uid, ids): + '''Check that the msg_identification is unique''' + for export_sdd in self.browse(cr, uid, ids): + res = self.pool.get('banking.export.sdd').search(cr, uid, + [('msg_identification', '=', export_sdd.msg_identification)]) + if len(res) > 1: + return False + return True + + + _constraints = [ + (_check_msg_identification, "The field 'Message Identification' should be uniue. Another SEPA Direct Debit file already exists with the same 'Message Identification'.", ['msg_identification']) + ] + + + def _validate_iban(self, cr, uid, iban, context=None): + '''if IBAN is valid, returns IBAN + if IBAN is NOT valid, raises an error message''' + partner_bank_obj = self.pool.get('res.partner.bank') + if partner_bank_obj.is_iban_valid(cr, uid, iban, context=context): + return iban.replace(' ', '') + else: + raise orm.except_orm(_('Error :'), _("This IBAN is not valid : %s") % iban) + + def create(self, cr, uid, vals, context=None): + payment_order_ids = context.get('active_ids', []) + vals.update({ + 'payment_order_ids': [[6, 0, payment_order_ids]], + }) + return super(banking_export_sdd_wizard, self).create(cr, uid, + vals, context=context) + + + def _prepare_field(self, cr, uid, field_name, field_value, max_size=0, sepa_export=False, line=False, context=None): + try: + value = eval(field_value) + except: + if line: + raise orm.except_orm(_('Error :'), _("Cannot compute the '%s' of the Payment Line with Invoice Reference '%s'.") % (field_name, self.pool['account.invoice'].name_get(cr, uid, [line.ml_inv_ref.id], context=context)[0][1])) + else: + raise orm.except_orm(_('Error :'), _("Cannot compute the '%s'.") % field_name) + if not isinstance(value, (str, unicode)): + raise orm.except_orm(_('Field type error :'), _("The '%s' is a(n) %s. It should be a string or unicode.") % (field_name, type(value))) + if not value: + raise orm.except_orm(_('Error :'), _("The '%s' is empty or 0. It should have a non-null value.") % field_name) + if max_size and len(value) > max_size: + value = value[0:max_size] + return value + + + def create_sepa(self, cr, uid, ids, context=None): + ''' + Creates the SEPA Direct Debit file. That's the important code ! + ''' + payment_order_obj = self.pool.get('payment.order') + + sepa_export = self.browse(cr, uid, ids[0], context=context) + + pain_flavor = sepa_export.payment_order_ids[0].mode.type.code + if pain_flavor == 'pain.008.001.02': + bic_xml_tag = 'BIC' + name_maxsize = 70 + root_xml_tag = 'CstmrDrctDbtInitn' + elif pain_flavor == 'pain.008.001.03': + bic_xml_tag = 'BICFI' + name_maxsize = 140 + root_xml_tag = 'CstmrDrctDbtInitn' + elif pain_flavor == 'pain.008.001.04': + bic_xml_tag = 'BICFI' + name_maxsize = 140 + root_xml_tag = 'CstmrDrctDbtInitn' + else: + raise orm.except_orm(_('Error :'), _("Payment Type Code '%s' is not supported. The only Payment Type Code supported for SEPA Direct Debit are 'pain.008.001.02', 'pain.008.001.03' and 'pain.008.001.04'.") % pain_flavor) + if sepa_export.requested_collec_date: + my_requested_collec_date = sepa_export.requested_collec_date + else: + my_requested_collec_date = datetime.strftime(datetime.today() + timedelta(days=1), '%Y-%m-%d') + + pain_ns = { + 'xsi': 'http://www.w3.org/2001/XMLSchema-instance', + None: 'urn:iso:std:iso:20022:tech:xsd:%s' % pain_flavor, + } + + root = etree.Element('Document', nsmap=pain_ns) + pain_root = etree.SubElement(root, root_xml_tag) + + my_company_name = self._prepare_field(cr, uid, 'Company Name', + 'sepa_export.payment_order_ids[0].company_id.name', + name_maxsize, sepa_export, context=context) + + # A. Group header + group_header_1_0 = etree.SubElement(pain_root, 'GrpHdr') + message_identification_1_1 = etree.SubElement(group_header_1_0, 'MsgId') + message_identification_1_1.text = sepa_export.msg_identification + creation_date_time_1_2 = etree.SubElement(group_header_1_0, 'CreDtTm') + creation_date_time_1_2.text = datetime.strftime(datetime.today(), '%Y-%m-%dT%H:%M:%S') + nb_of_transactions_1_6 = etree.SubElement(group_header_1_0, 'NbOfTxs') + control_sum_1_7 = etree.SubElement(group_header_1_0, 'CtrlSum') + initiating_party_1_8 = etree.SubElement(group_header_1_0, 'InitgPty') + initiating_party_name = etree.SubElement(initiating_party_1_8, 'Nm') + initiating_party_name.text = my_company_name + + # B. Payment info + payment_info_2_0 = etree.SubElement(pain_root, 'PmtInf') + payment_info_identification_2_1 = etree.SubElement(payment_info_2_0, 'PmtInfId') + payment_info_identification_2_1.text = sepa_export.msg_identification + payment_method_2_2 = etree.SubElement(payment_info_2_0, 'PmtMtd') + payment_method_2_2.text = 'DD' + if pain_flavor in ['pain.008.001.02', 'pain.008.001.03', 'pain.008.001.04']: + # batch_booking is in "Payment Info" with pain.008.001.02/03 + batch_booking_2_3 = etree.SubElement(payment_info_2_0, 'BtchBookg') + batch_booking_2_3.text = str(sepa_export.batch_booking).lower() + # It may seem surprising, but the + # "SEPA Core Direct Debit Scheme Customer-to-bank Implementation guidelines" + # v6.0 says that control sum and nb_of_transactions should be present + # at both "group header" level and "payment info" level + if pain_flavor in ['pain.008.001.02', 'pain.008.001.03', 'pain.008.001.04']: + nb_of_transactions_2_4 = etree.SubElement(payment_info_2_0, 'NbOfTxs') + control_sum_2_5 = etree.SubElement(payment_info_2_0, 'CtrlSum') + payment_type_info_2_6 = etree.SubElement(payment_info_2_0, 'PmtTpInf') + service_level_2_8 = etree.SubElement(payment_type_info_2_6, 'SvcLvl') + service_level_code_2_9 = etree.SubElement(service_level_2_8, 'Cd') + service_level_code_2_9.text = 'SEPA' + local_instrument_2_11 = etree.SubElement(payment_type_info_2_6, 'LclInstrm') + local_instr_code_2_12 = etree.SubElement(local_instrument_2_11, 'Cd') + local_instr_code_2_12.text = 'CORE' + # TODO : 2.14 Sequence Type MANDATORY => I set it in section C (2.40) + # not B (2.14) so that we can have several different Sequence Types + # in the same XML file + # the Sample XML files show Seq type at C level + # BUT it may not be possible, + # 1. extract from CIC documentation : + # "Attention, les remises présentées devront être scindées par le créancier + # par type de séquence" + # In the guidelines, they only talk about B level + # If ‘Amendment Indicator’ is ‘true’, + # and ‘Original Debtor Agent’ is set to ‘SMNDA’, + # this message element must indicate ‘FRST + # 'FRST' = First ; 'OOFF' = One Off ; 'RCUR' : Recurring + # 'FNAL' = Final + requested_collec_date_2_18 = etree.SubElement(payment_info_2_0, 'ReqdColltnDt') + requested_collec_date_2_18.text = my_requested_collec_date + creditor_2_19 = etree.SubElement(payment_info_2_0, 'Cdtr') + creditor_name = etree.SubElement(creditor_2_19, 'Nm') + creditor_name.text = my_company_name + creditor_account_2_20 = etree.SubElement(payment_info_2_0, 'CdtrAcct') + creditor_account_id = etree.SubElement(creditor_account_2_20, 'Id') + creditor_account_iban = etree.SubElement(creditor_account_id, 'IBAN') + creditor_account_iban.text = self._validate_iban(cr, uid, + self._prepare_field(cr, uid, 'Company IBAN', + 'sepa_export.payment_order_ids[0].mode.bank_id.acc_number', + sepa_export=sepa_export, context=context), + context=context) + + creditor_agent_2_21 = etree.SubElement(payment_info_2_0, 'CdtrAgt') + creditor_agent_institution = etree.SubElement(creditor_agent_2_21, 'FinInstnId') + creditor_agent_bic = etree.SubElement(creditor_agent_institution, bic_xml_tag) + creditor_agent_bic.text = self._prepare_field(cr, uid, 'Company BIC', + 'sepa_export.payment_order_ids[0].mode.bank_id.bank.bic', + sepa_export=sepa_export, context=context) + + charge_bearer_2_24 = etree.SubElement(payment_info_2_0, 'ChrgBr') + charge_bearer_2_24.text = sepa_export.charge_bearer + + creditor_scheme_identification_2_27 = etree.SubElement(payment_info_2_0, 'CdtrSchmeId') + csi_id = etree.SubElement(creditor_scheme_identification_2_27, 'Id') + csi_orgid = csi_id = etree.SubElement(csi_id, 'OrgId') + csi_other = etree.SubElement(csi_orgid, 'Othr') + csi_other_id = etree.SubElement(csi_other, 'Id') + csi_other_id.text = self._prepare_field(cr, uid, + 'SEPA Creditor Identifier', + 'sepa_export.payment_order_ids[0].company_id.sepa_creditor_identifier', + sepa_export=sepa_export, context=context) + csi_scheme_name = etree.SubElement(csi_other, 'SchmeNm') + csi_scheme_name_proprietary = etree.SubElement(csi_scheme_name, 'Prtry') + csi_scheme_name_proprietary.text = 'SEPA' + + transactions_count = 0 + total_amount = 0.0 + amount_control_sum = 0.0 + # Iterate on payment orders + for payment_order in sepa_export.payment_order_ids: + total_amount = total_amount + payment_order.total + # Iterate each payment lines + for line in payment_order.line_ids: + transactions_count += 1 + # C. Direct Debit Transaction Info + dd_transaction_info_2_28 = etree.SubElement(payment_info_2_0, 'DrctDbtTxInf') + payment_identification_2_29 = etree.SubElement(dd_transaction_info_2_28, 'PmtId') + # Instruction identification (2.30) is not mandatory, so we don't use it + end2end_identification_2_31 = etree.SubElement(payment_identification_2_29, 'EndToEndId') + end2end_identification_2_31.text = self._prepare_field(cr, uid, + 'End to End Identification', 'line.communication', 35, + line=line, context=context) + payment_type_2_32 = etree.SubElement(dd_transaction_info_2_28, 'PmtTpInf') + # Sequence Type : do we have to set it at Payment Info level ? + #sequence_type_2_40 = etree.SubElement(payment_type_2_32, 'SeqTp') + #sequence_type_2_40.text = 'FRST' # TODO + currency_name = self._prepare_field(cr, uid, 'Currency Code', + 'line.currency.name', 3, line=line, context=context) + instructed_amount_2_44 = etree.SubElement(dd_transaction_info_2_28, 'InstdAmt', Ccy=currency_name) + instructed_amount_2_44.text = '%.2f' % line.amount_currency + amount_control_sum += line.amount_currency + dd_transaction_2_46 = etree.SubElement(dd_transaction_info_2_28, 'DrctDbtTx') + mandate_related_info_2_47 = etree.SubElement(dd_transaction_2_46, 'MndtRltdInf') + mandate_identification_2_48 = etree.SubElement(mandate_related_info_2_47, 'MndtId') + mandate_identification_2_48.text = 'RUM1242' # TODO + mandate_signature_date_2_49 = etree.SubElement(mandate_related_info_2_47, 'DtOfSgntr') + mandate_signature_date_2_49.text = '2013-02-20' # TODO + # TODO look at 2.50 "Amendment Indicator + debtor_agent_2_70 = etree.SubElement(dd_transaction_info_2_28, 'DbtrAgt') + debtor_agent_institution = etree.SubElement(debtor_agent_2_70, 'FinInstnId') + debtor_agent_bic = etree.SubElement(debtor_agent_institution, bic_xml_tag) + debtor_agent_bic.text = self._prepare_field(cr, uid, + 'Customer BIC', 'line.bank_id.bank.bic', + line=line, context=context) + debtor_2_72 = etree.SubElement(dd_transaction_info_2_28, 'Dbtr') + debtor_name = etree.SubElement(debtor_2_72, 'Nm') + debtor_name.text = self._prepare_field(cr, uid, + 'Customer Name', 'line.partner_id.name', + name_maxsize, line=line, context=context) + debtor_account_2_73 = etree.SubElement(dd_transaction_info_2_28, 'DbtrAcct') + debtor_account_id = etree.SubElement(debtor_account_2_73, 'Id') + debtor_account_iban = etree.SubElement(debtor_account_id, 'IBAN') + debtor_account_iban.text = self._validate_iban(cr, uid, + self._prepare_field(cr, uid, 'Customer IBAN', + 'line.bank_id.acc_number', line=line, + context=context), + context=context) + remittance_info_2_88 = etree.SubElement(dd_transaction_info_2_28, 'RmtInf') + # switch to Structured (Strdr) ? If we do it, beware that the format is not the same between pain 02 and pain 03 + remittance_info_unstructured_2_89 = etree.SubElement(remittance_info_2_88, 'Ustrd') + remittance_info_unstructured_2_89.text = self._prepare_field(cr, uid, + 'Remittance Information', 'line.communication', + 140, line=line, context=context) + + if pain_flavor in ['pain.008.001.02', 'pain.008.001.03', 'pain.008.001.04']: + nb_of_transactions_1_6.text = nb_of_transactions_2_4.text = str(transactions_count) + control_sum_1_7.text = control_sum_2_5.text = '%.2f' % amount_control_sum + + + xml_string = etree.tostring(root, pretty_print=True, encoding='UTF-8', xml_declaration=True) + _logger.debug("Generated SDD XML file in format %s below" % pain_flavor) + _logger.debug(xml_string) + xsd_etree_obj = etree.parse(tools.file_open('account_banking_sepa_direct_debit/data/%s.xsd' % pain_flavor)) + official_pain_schema = etree.XMLSchema(xsd_etree_obj) + _logger.debug("Printing %s XML Schema definition:" % pain_flavor) + _logger.debug(etree.tostring(xsd_etree_obj, pretty_print=True, encoding='UTF-8', xml_declaration=True)) + + try: + # If I do official_pain_schema.assertValid(root), then I get this + # error msg in the exception : + # The generated XML file is not valid against the official XML Schema Definition. The generated XML file and the full error have been written in the server logs. Here is the error, which may give you an idea on the cause of the problem : Element 'Document': No matching global declaration available for the validation root. + # So I re-import the SEPA XML from the string, and give this + # so validation + # If you know how I can avoid that, please tell me -- Alexis + root_to_validate = etree.fromstring(xml_string) + official_pain_schema.assertValid(root_to_validate) + except Exception, e: + _logger.warning("The XML file is invalid against the XML Schema Definition") + _logger.warning(xml_string) + _logger.warning(e) + raise orm.except_orm(_('Error :'), _('The generated XML file is not valid against the official XML Schema Definition. The generated XML file and the full error have been written in the server logs. Here is the error, which may give you an idea on the cause of the problem : %s') % str(e)) + + # CREATE the banking.export.sepa record + file_id = self.pool.get('banking.export.sdd').create(cr, uid, + { + 'msg_identification': sepa_export.msg_identification, + 'batch_booking': sepa_export.batch_booking, + 'charge_bearer': sepa_export.charge_bearer, + 'requested_collec_date': sepa_export.requested_collec_date, + 'total_amount': total_amount, + 'nb_transactions': transactions_count, + 'file': base64.encodestring(xml_string), + 'payment_order_ids': [ + (6, 0, [x.id for x in sepa_export.payment_order_ids]) + ], + }, context=context) + + self.write(cr, uid, ids, { + 'file_id': file_id, + 'state': 'finish', + }, context=context) + + action = { + 'name': 'SEPA Direct Debit XML', + 'type': 'ir.actions.act_window', + 'view_type': 'form', + 'view_mode': 'form,tree', + 'res_model': self._name, + 'res_id': ids[0], + 'target': 'new', + } + return action + + + def cancel_sepa(self, cr, uid, ids, context=None): + ''' + Cancel the SEPA Direct Debit file: just drop the file + ''' + sepa_export = self.browse(cr, uid, ids[0], context=context) + self.pool.get('banking.export.sdd').unlink(cr, uid, sepa_export.file_id.id, context=context) + return {'type': 'ir.actions.act_window_close'} + + + def save_sepa(self, cr, uid, ids, context=None): + ''' + Save the SEPA Direct Debit file: mark all payments in the file as 'sent'. + ''' + sepa_export = self.browse(cr, uid, ids[0], context=context) + sepa_file = self.pool.get('banking.export.sdd').write(cr, uid, + sepa_export.file_id.id, {'state': 'sent'}, context=context) + wf_service = netsvc.LocalService('workflow') + for order in sepa_export.payment_order_ids: + wf_service.trg_validate(uid, 'payment.order', order.id, 'sent', cr) + return {'type': 'ir.actions.act_window_close'} diff --git a/account_banking_sepa_direct_debit/wizard/export_sdd_view.xml b/account_banking_sepa_direct_debit/wizard/export_sdd_view.xml new file mode 100644 index 000000000..8357e3f5d --- /dev/null +++ b/account_banking_sepa_direct_debit/wizard/export_sdd_view.xml @@ -0,0 +1,41 @@ + + + + + + + banking.export.sdd.wizard.view + banking.export.sdd.wizard + +
+ + + + + + + + + + + + + + + +
+
+ +
+
+ +
+
From 05319329c63e79e326c84b62441d3ba84f73aaab Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Tue, 15 Oct 2013 23:29:28 +0200 Subject: [PATCH 02/43] First implementation of mandates, but I still have a lot of hesitation about the data model so it may change. Manage different sequence types in the same file ; we just have to separate them in different payment info blocks. --- account_banking_sepa_direct_debit/__init__.py | 6 +- .../__openerp__.py | 2 + .../account_banking_sdd.py | 85 ++++++ .../account_banking_sdd_view.xml | 102 +++++++ .../account_payment_view.xml | 26 ++ account_banking_sepa_direct_debit/company.py | 6 +- .../data/mandate_reference_sequence.xml | 21 ++ .../security/ir.model.access.csv | 2 + .../wizard/__init__.py | 2 +- .../wizard/export_sdd.py | 256 +++++++++++------- 10 files changed, 407 insertions(+), 101 deletions(-) create mode 100644 account_banking_sepa_direct_debit/account_payment_view.xml create mode 100644 account_banking_sepa_direct_debit/data/mandate_reference_sequence.xml diff --git a/account_banking_sepa_direct_debit/__init__.py b/account_banking_sepa_direct_debit/__init__.py index bda7501b7..ce46fda33 100644 --- a/account_banking_sepa_direct_debit/__init__.py +++ b/account_banking_sepa_direct_debit/__init__.py @@ -20,7 +20,7 @@ # ############################################################################## -import company -import wizard -import account_banking_sdd +from . import company +from . import wizard +from . import account_banking_sdd diff --git a/account_banking_sepa_direct_debit/__openerp__.py b/account_banking_sepa_direct_debit/__openerp__.py index fc329a073..2a44e1c06 100644 --- a/account_banking_sepa_direct_debit/__openerp__.py +++ b/account_banking_sepa_direct_debit/__openerp__.py @@ -29,9 +29,11 @@ 'depends': ['account_direct_debit'], 'data': [ 'account_banking_sdd_view.xml', + 'account_payment_view.xml', 'company_view.xml', 'wizard/export_sdd_view.xml', 'data/payment_type_sdd.xml', + 'data/mandate_reference_sequence.xml', 'security/ir.model.access.csv', ], 'description': ''' diff --git a/account_banking_sepa_direct_debit/account_banking_sdd.py b/account_banking_sepa_direct_debit/account_banking_sdd.py index aa08918a2..7e5a5d0f3 100644 --- a/account_banking_sepa_direct_debit/account_banking_sdd.py +++ b/account_banking_sepa_direct_debit/account_banking_sdd.py @@ -75,3 +75,88 @@ class banking_export_sdd(orm.Model): 'generation_date': fields.date.context_today, 'state': 'draft', } + + +class sdd_mandate(orm.Model): + '''SEPA Direct Debit Mandate''' + _name = 'sdd.mandate' + _description = __doc__ + _rec_name = 'unique_mandate_reference' + _order = 'signature_date desc' + + _columns = { + 'partner_bank_id': fields.many2one('res.partner.bank', 'Bank Account'), + 'partner_id': fields.related( + 'partner_bank_id', 'partner_id', type='many2one', + relation='res.partner', string='Partner', readonly=True), + 'company_id': fields.many2one('res.company', 'Company', required=True), + 'unique_mandate_reference': fields.char( + 'Unique Mandate Reference', size=35, readonly=True), + 'type': fields.selection([ + ('recurrent', 'Recurrent'), + ('oneoff', 'One-Off'), + ], 'Type of Mandate', required=True), + 'signature_date': fields.date('Date of Signature of the Mandate'), + 'scan': fields.binary('Scan of the mandate'), + 'last_debit_date': fields.date('Date of the Last Debit', + help="For recurrent mandates, this field is used to know if the SDD will be of type 'First' or 'Recurring'. For one-off mandates, this field is used to know if the SDD has already been used or not."), + 'state': fields.selection([ + ('valid', 'Valid'), + ('expired', 'Expired'), + ], 'Mandate Status', + help="For a recurrent mandate, this field indicate if the mandate is still valid or if it has expired (a recurrent mandate expires if it's not used during 36 months). For a one-off mandate, it expires after its first use."), + } + + _sql_constraints = [( + 'mandate_ref_company_uniq', + 'unique(unique_mandate_reference, company_id)', + 'A Mandate with the same reference already exists for this company !' + )] + + _defaults = { + 'company_id': lambda self, cr, uid, context: \ + self.pool['res.users'].browse(cr, uid, uid, context=context).\ + company_id.id, + 'unique_mandate_reference': lambda self, cr, uid, context: \ + self.pool['ir.sequence'].get(cr, uid, 'sdd.mandate.reference'), + 'state': 'valid', + } + + +class res_partner_bank(orm.Model): + _inherit = 'res.partner.bank' + + _columns = { + 'sdd_mandate_ids': fields.one2many( + 'sdd.mandate', 'partner_bank_id', 'SEPA Direct Debit Mandates'), + } + + +class payment_line(orm.Model): + _inherit = 'payment.line' + + _columns = { + 'sdd_mandate_id': fields.many2one( + 'sdd.mandate', 'SEPA Direct Debit Mandate'), + } + + def _check_sdd_mandate(self, cr, uid, ids): + for payline in self.browse(cr, uid, ids): + if payline.sdd_mandate_id and not payline.bank_id: + raise orm.except_orm( + _('Error :'), + _("Missing bank account on the payment line with SEPA\ + Direct Debit Mandate '%s'." + % payline.sdd_mandate_id.unique_mandate_reference)) + elif payline.sdd_mandate_id and payline.bank_id and payline.sdd_mandate_id.partner_bank_id != payline.bank_id.id: + raise orm.except_orm( + _('Error :'), + _("The SEPA Direct Debit Mandate '%s' is not related??")) + + return True + +# _constraints = [ +# (_check_sdd_mandate, "Mandate must be attached to bank account", ['bank_id', 'sdd_mandate_id']), +# ] + + # TODO inherit create to select the first mandate ?? diff --git a/account_banking_sepa_direct_debit/account_banking_sdd_view.xml b/account_banking_sepa_direct_debit/account_banking_sdd_view.xml index 6dcfb903f..32a289081 100644 --- a/account_banking_sepa_direct_debit/account_banking_sdd_view.xml +++ b/account_banking_sepa_direct_debit/account_banking_sdd_view.xml @@ -79,5 +79,107 @@ view_mode="tree,form" /> + + sdd.mandate.form + sdd.mandate + +
+
+ +
+ +
+

+

+
+ + + + + + + + + +
+
+
+
+ + + sdd.mandate.tree + sdd.mandate + + + + + + + + + + + + + + + SEPA Direct Debit Mandate + sdd.mandate + form + tree,form + {'sdd_mandate_main_view': True} + +

+ Click to create a new SEPA Direct Debit Mandate. +

+ The SEPA Direct Debit Mandate is a document signed by your customer that gives you the autorization to do one or several direct debits on his bank account. +

+
+
+ + + + + sdd.mandate.res.partner.bank.form + res.partner.bank + + + + + + + + + + + + sdd.mandate.res.partner.bank.tree + res.partner.bank + + + + + + + + + + + sdd.mandate.partner.form + res.partner + + + + + + + + diff --git a/account_banking_sepa_direct_debit/account_payment_view.xml b/account_banking_sepa_direct_debit/account_payment_view.xml new file mode 100644 index 000000000..795f30222 --- /dev/null +++ b/account_banking_sepa_direct_debit/account_payment_view.xml @@ -0,0 +1,26 @@ + + + + + + + sdd.payment.order.form + payment.order + + + + + + + + + + + + + + diff --git a/account_banking_sepa_direct_debit/company.py b/account_banking_sepa_direct_debit/company.py index d85fc6fd7..aed40f64b 100644 --- a/account_banking_sepa_direct_debit/company.py +++ b/account_banking_sepa_direct_debit/company.py @@ -24,15 +24,16 @@ import logging logger = logging.getLogger(__name__) + class res_company(orm.Model): _inherit = 'res.company' _columns = { - 'sepa_creditor_identifier': fields.char('SEPA Creditor Identifier', size=35, + 'sepa_creditor_identifier': fields.char( + 'SEPA Creditor Identifier', size=35, help="Enter the Creditor Identifier that has been attributed to your company to make SEPA Direct Debits. This identifier is composed of :\n- your country ISO code (2 letters)\n- a 2-digits checkum\n- a 3-letters business code\n- a country-specific identifier"), } - def is_sepa_creditor_identifier_valid(self, cr, uid, sepa_creditor_identifier, context=None): """Check if SEPA Creditor Identifier is valid @param sepa_creditor_identifier: SEPA Creditor Identifier as str or unicode @@ -62,7 +63,6 @@ class res_company(orm.Model): else: return False - def _check_sepa_creditor_identifier(self, cr, uid, ids): for company in self.browse(cr, uid, ids): if company.sepa_creditor_identifier: diff --git a/account_banking_sepa_direct_debit/data/mandate_reference_sequence.xml b/account_banking_sepa_direct_debit/data/mandate_reference_sequence.xml new file mode 100644 index 000000000..6a3143cca --- /dev/null +++ b/account_banking_sepa_direct_debit/data/mandate_reference_sequence.xml @@ -0,0 +1,21 @@ + + + + + + + SDD Mandate Reference + sdd.mandate.reference + + + + SDD Mandate Reference + sdd.mandate.reference + RUM + + + + + + + diff --git a/account_banking_sepa_direct_debit/security/ir.model.access.csv b/account_banking_sepa_direct_debit/security/ir.model.access.csv index 0cd579511..cf78ffb59 100644 --- a/account_banking_sepa_direct_debit/security/ir.model.access.csv +++ b/account_banking_sepa_direct_debit/security/ir.model.access.csv @@ -1,2 +1,4 @@ "id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" "access_banking_export_sdd","Full access on banking.export.sdd","model_banking_export_sdd","account_payment.group_account_payment",1,1,1,1 +"access_sdd_mandate","Full access on sdd.mandate","model_sdd_mandate","account_payment.group_account_payment",1,1,1,1 +"access_sdd_mandate_read","Read access on sdd.mandate","model_sdd_mandate","base.group_user",1,0,0,0 diff --git a/account_banking_sepa_direct_debit/wizard/__init__.py b/account_banking_sepa_direct_debit/wizard/__init__.py index 169d0b13d..3830e36d9 100644 --- a/account_banking_sepa_direct_debit/wizard/__init__.py +++ b/account_banking_sepa_direct_debit/wizard/__init__.py @@ -20,4 +20,4 @@ # ############################################################################## -import export_sdd +from . import export_sdd diff --git a/account_banking_sepa_direct_debit/wizard/export_sdd.py b/account_banking_sepa_direct_debit/wizard/export_sdd.py index 60456ab1a..3cc06e845 100644 --- a/account_banking_sepa_direct_debit/wizard/export_sdd.py +++ b/account_banking_sepa_direct_debit/wizard/export_sdd.py @@ -22,10 +22,10 @@ from openerp.osv import orm, fields -import base64 -from datetime import datetime, timedelta from openerp.tools.translate import _ from openerp import tools, netsvc +import base64 +from datetime import datetime, timedelta from lxml import etree import logging @@ -115,7 +115,7 @@ class banking_export_sdd_wizard(orm.TransientModel): else: raise orm.except_orm(_('Error :'), _("Cannot compute the '%s'.") % field_name) if not isinstance(value, (str, unicode)): - raise orm.except_orm(_('Field type error :'), _("The '%s' is a(n) %s. It should be a string or unicode.") % (field_name, type(value))) + raise orm.except_orm(_('Field type error :'), _("The type of the field '%s' is %s. It should be a string or unicode.") % (field_name, type(value))) if not value: raise orm.except_orm(_('Error :'), _("The '%s' is empty or 0. It should have a non-null value.") % field_name) if max_size and len(value) > max_size: @@ -175,90 +175,140 @@ class banking_export_sdd_wizard(orm.TransientModel): initiating_party_name = etree.SubElement(initiating_party_1_8, 'Nm') initiating_party_name.text = my_company_name - # B. Payment info - payment_info_2_0 = etree.SubElement(pain_root, 'PmtInf') - payment_info_identification_2_1 = etree.SubElement(payment_info_2_0, 'PmtInfId') - payment_info_identification_2_1.text = sepa_export.msg_identification - payment_method_2_2 = etree.SubElement(payment_info_2_0, 'PmtMtd') - payment_method_2_2.text = 'DD' - if pain_flavor in ['pain.008.001.02', 'pain.008.001.03', 'pain.008.001.04']: - # batch_booking is in "Payment Info" with pain.008.001.02/03 - batch_booking_2_3 = etree.SubElement(payment_info_2_0, 'BtchBookg') - batch_booking_2_3.text = str(sepa_export.batch_booking).lower() - # It may seem surprising, but the - # "SEPA Core Direct Debit Scheme Customer-to-bank Implementation guidelines" - # v6.0 says that control sum and nb_of_transactions should be present - # at both "group header" level and "payment info" level - if pain_flavor in ['pain.008.001.02', 'pain.008.001.03', 'pain.008.001.04']: - nb_of_transactions_2_4 = etree.SubElement(payment_info_2_0, 'NbOfTxs') - control_sum_2_5 = etree.SubElement(payment_info_2_0, 'CtrlSum') - payment_type_info_2_6 = etree.SubElement(payment_info_2_0, 'PmtTpInf') - service_level_2_8 = etree.SubElement(payment_type_info_2_6, 'SvcLvl') - service_level_code_2_9 = etree.SubElement(service_level_2_8, 'Cd') - service_level_code_2_9.text = 'SEPA' - local_instrument_2_11 = etree.SubElement(payment_type_info_2_6, 'LclInstrm') - local_instr_code_2_12 = etree.SubElement(local_instrument_2_11, 'Cd') - local_instr_code_2_12.text = 'CORE' - # TODO : 2.14 Sequence Type MANDATORY => I set it in section C (2.40) - # not B (2.14) so that we can have several different Sequence Types - # in the same XML file - # the Sample XML files show Seq type at C level - # BUT it may not be possible, - # 1. extract from CIC documentation : - # "Attention, les remises présentées devront être scindées par le créancier - # par type de séquence" - # In the guidelines, they only talk about B level - # If ‘Amendment Indicator’ is ‘true’, - # and ‘Original Debtor Agent’ is set to ‘SMNDA’, - # this message element must indicate ‘FRST - # 'FRST' = First ; 'OOFF' = One Off ; 'RCUR' : Recurring - # 'FNAL' = Final - requested_collec_date_2_18 = etree.SubElement(payment_info_2_0, 'ReqdColltnDt') - requested_collec_date_2_18.text = my_requested_collec_date - creditor_2_19 = etree.SubElement(payment_info_2_0, 'Cdtr') - creditor_name = etree.SubElement(creditor_2_19, 'Nm') - creditor_name.text = my_company_name - creditor_account_2_20 = etree.SubElement(payment_info_2_0, 'CdtrAcct') - creditor_account_id = etree.SubElement(creditor_account_2_20, 'Id') - creditor_account_iban = etree.SubElement(creditor_account_id, 'IBAN') - creditor_account_iban.text = self._validate_iban(cr, uid, - self._prepare_field(cr, uid, 'Company IBAN', - 'sepa_export.payment_order_ids[0].mode.bank_id.acc_number', - sepa_export=sepa_export, context=context), - context=context) - - creditor_agent_2_21 = etree.SubElement(payment_info_2_0, 'CdtrAgt') - creditor_agent_institution = etree.SubElement(creditor_agent_2_21, 'FinInstnId') - creditor_agent_bic = etree.SubElement(creditor_agent_institution, bic_xml_tag) - creditor_agent_bic.text = self._prepare_field(cr, uid, 'Company BIC', - 'sepa_export.payment_order_ids[0].mode.bank_id.bank.bic', - sepa_export=sepa_export, context=context) - - charge_bearer_2_24 = etree.SubElement(payment_info_2_0, 'ChrgBr') - charge_bearer_2_24.text = sepa_export.charge_bearer - - creditor_scheme_identification_2_27 = etree.SubElement(payment_info_2_0, 'CdtrSchmeId') - csi_id = etree.SubElement(creditor_scheme_identification_2_27, 'Id') - csi_orgid = csi_id = etree.SubElement(csi_id, 'OrgId') - csi_other = etree.SubElement(csi_orgid, 'Othr') - csi_other_id = etree.SubElement(csi_other, 'Id') - csi_other_id.text = self._prepare_field(cr, uid, - 'SEPA Creditor Identifier', - 'sepa_export.payment_order_ids[0].company_id.sepa_creditor_identifier', - sepa_export=sepa_export, context=context) - csi_scheme_name = etree.SubElement(csi_other, 'SchmeNm') - csi_scheme_name_proprietary = etree.SubElement(csi_scheme_name, 'Prtry') - csi_scheme_name_proprietary.text = 'SEPA' - - transactions_count = 0 + transactions_count_1_6 = 0 total_amount = 0.0 - amount_control_sum = 0.0 + amount_control_sum_1_7 = 0.0 + first_recur_lines = {} + # key = sequence type ; value = list of lines as objects # Iterate on payment orders for payment_order in sepa_export.payment_order_ids: total_amount = total_amount + payment_order.total # Iterate each payment lines for line in payment_order.line_ids: - transactions_count += 1 + transactions_count_1_6 += 1 + if not line.sdd_mandate_id: + raise orm.except_orm( + _('Error:'), + _("Missing SEPA Direct Debit mandate on the payment line with partner '%s' and Invoice ref '%s'.") + % (line.partner_id.name, + line.ml_inv_ref.number)) + if line.sdd_mandate_id.state != 'valid': + raise orm.except_orm( + _('Error:'), + _("The SEPA Direct Debit mandate with reference '%s' for partner '%s' has expired.") + % (line.sdd_mandate_id.unique_mandate_reference, + line.sdd_mandate_id.partner_id.name)) + + if not line.sdd_mandate_id.signature_date: + raise orm.except_orm( + _('Error:'), + _("Missing signature date on SEPA Direct Debit mandate with reference '%s' for partner '%s'.") + % (line.sdd_mandate_id.unique_mandate_reference, + line.sdd_mandate_id.partner_id.name)) + elif line.sdd_mandate_id.signature_date > datetime.today().strftime('%Y-%m-%d'): + raise orm.except_orm( + _('Error:'), + _("The signature date on SEPA Direct Debit mandate with reference '%s' for partner '%s' is '%s', which is in the future !") + % (line.sdd_mandate_id.unique_mandate_reference, + line.sdd_mandate_id.partner_id.name, + line.sdd_mandate_id.signature_date)) + + if line.sdd_mandate_id.type == 'oneoff': + if not line.sdd_mandate_id.last_debit_date: + if first_recur_lines.get('OOFF'): + first_recur_lines['OOFF'].append(line) + else: + first_recur_lines['OOFF'] = [line] + else: + raise orm.except_orm( + _('Error :'), + _("The mandate with reference '%s' for partner '%s' has type set to 'One-Off' and it has a last debit date set to '%s', so we can't use it.") + % (line.sdd_mandate_id.unique_mandate_reference, + line.sdd_mandate_id.partner_id.name, + line.sdd_mandate_id.last_debit_date)) + elif line.sdd_mandate_id.type == 'recurrent': + if line.sdd_mandate_id.last_debit_date: + if first_recur_lines.get('RCUR'): + first_recur_lines['RCUR'].append(line) + else: + first_recur_lines['RCUR'] = [line] + else: + if first_recur_lines.get('FRST'): + first_recur_lines['FRST'].append(line) + else: + first_recur_lines['FRST'] = [line] + + for sequence_type, lines in first_recur_lines.items(): + # B. Payment info + payment_info_2_0 = etree.SubElement(pain_root, 'PmtInf') + payment_info_identification_2_1 = etree.SubElement(payment_info_2_0, 'PmtInfId') + payment_info_identification_2_1.text = sepa_export.msg_identification + payment_method_2_2 = etree.SubElement(payment_info_2_0, 'PmtMtd') + payment_method_2_2.text = 'DD' + # batch_booking is in "Payment Info" with pain.008.001.02/03 + batch_booking_2_3 = etree.SubElement(payment_info_2_0, 'BtchBookg') + batch_booking_2_3.text = str(sepa_export.batch_booking).lower() + # The "SEPA Core Direct Debit Scheme Customer-to-bank + # Implementation guidelines" v6.0 says that control sum + # and nb_of_transactions should be present + # at both "group header" level and "payment info" level + nb_of_transactions_2_4 = etree.SubElement(payment_info_2_0, 'NbOfTxs') + control_sum_2_5 = etree.SubElement(payment_info_2_0, 'CtrlSum') + payment_type_info_2_6 = etree.SubElement(payment_info_2_0, 'PmtTpInf') + service_level_2_8 = etree.SubElement(payment_type_info_2_6, 'SvcLvl') + service_level_code_2_9 = etree.SubElement(service_level_2_8, 'Cd') + service_level_code_2_9.text = 'SEPA' + local_instrument_2_11 = etree.SubElement(payment_type_info_2_6, 'LclInstrm') + local_instr_code_2_12 = etree.SubElement(local_instrument_2_11, 'Cd') + local_instr_code_2_12.text = 'CORE' + # 2.14 Sequence Type MANDATORY + # this message element must indicate ‘FRST + # 'FRST' = First ; 'OOFF' = One Off ; 'RCUR' : Recurring + # 'FNAL' = Final + sequence_type_2_14 = etree.SubElement(payment_type_info_2_6, 'SeqTp') + sequence_type_2_14.text = sequence_type + + requested_collec_date_2_18 = etree.SubElement(payment_info_2_0, 'ReqdColltnDt') + requested_collec_date_2_18.text = my_requested_collec_date + creditor_2_19 = etree.SubElement(payment_info_2_0, 'Cdtr') + creditor_name = etree.SubElement(creditor_2_19, 'Nm') + creditor_name.text = my_company_name + creditor_account_2_20 = etree.SubElement(payment_info_2_0, 'CdtrAcct') + creditor_account_id = etree.SubElement(creditor_account_2_20, 'Id') + creditor_account_iban = etree.SubElement(creditor_account_id, 'IBAN') + creditor_account_iban.text = self._validate_iban(cr, uid, + self._prepare_field(cr, uid, 'Company IBAN', + 'sepa_export.payment_order_ids[0].mode.bank_id.acc_number', + sepa_export=sepa_export, context=context), + context=context) + + creditor_agent_2_21 = etree.SubElement(payment_info_2_0, 'CdtrAgt') + creditor_agent_institution = etree.SubElement(creditor_agent_2_21, 'FinInstnId') + creditor_agent_bic = etree.SubElement(creditor_agent_institution, bic_xml_tag) + creditor_agent_bic.text = self._prepare_field(cr, uid, 'Company BIC', + 'sepa_export.payment_order_ids[0].mode.bank_id.bank.bic', + sepa_export=sepa_export, context=context) + + charge_bearer_2_24 = etree.SubElement(payment_info_2_0, 'ChrgBr') + charge_bearer_2_24.text = sepa_export.charge_bearer + + creditor_scheme_identification_2_27 = etree.SubElement(payment_info_2_0, 'CdtrSchmeId') + csi_id = etree.SubElement(creditor_scheme_identification_2_27, 'Id') + csi_orgid = csi_id = etree.SubElement(csi_id, 'OrgId') + csi_other = etree.SubElement(csi_orgid, 'Othr') + csi_other_id = etree.SubElement(csi_other, 'Id') + csi_other_id.text = self._prepare_field(cr, uid, + 'SEPA Creditor Identifier', + 'sepa_export.payment_order_ids[0].company_id.sepa_creditor_identifier', + sepa_export=sepa_export, context=context) + csi_scheme_name = etree.SubElement(csi_other, 'SchmeNm') + csi_scheme_name_proprietary = etree.SubElement(csi_scheme_name, 'Prtry') + csi_scheme_name_proprietary.text = 'SEPA' + + transactions_count_2_4 = 0 + amount_control_sum_2_5 = 0.0 + for line in lines: + transactions_count_2_4 += 1 # C. Direct Debit Transaction Info dd_transaction_info_2_28 = etree.SubElement(payment_info_2_0, 'DrctDbtTxInf') payment_identification_2_29 = etree.SubElement(dd_transaction_info_2_28, 'PmtId') @@ -268,20 +318,26 @@ class banking_export_sdd_wizard(orm.TransientModel): 'End to End Identification', 'line.communication', 35, line=line, context=context) payment_type_2_32 = etree.SubElement(dd_transaction_info_2_28, 'PmtTpInf') - # Sequence Type : do we have to set it at Payment Info level ? - #sequence_type_2_40 = etree.SubElement(payment_type_2_32, 'SeqTp') - #sequence_type_2_40.text = 'FRST' # TODO currency_name = self._prepare_field(cr, uid, 'Currency Code', 'line.currency.name', 3, line=line, context=context) instructed_amount_2_44 = etree.SubElement(dd_transaction_info_2_28, 'InstdAmt', Ccy=currency_name) instructed_amount_2_44.text = '%.2f' % line.amount_currency - amount_control_sum += line.amount_currency + amount_control_sum_1_7 += line.amount_currency + amount_control_sum_2_5 += line.amount_currency dd_transaction_2_46 = etree.SubElement(dd_transaction_info_2_28, 'DrctDbtTx') mandate_related_info_2_47 = etree.SubElement(dd_transaction_2_46, 'MndtRltdInf') mandate_identification_2_48 = etree.SubElement(mandate_related_info_2_47, 'MndtId') - mandate_identification_2_48.text = 'RUM1242' # TODO - mandate_signature_date_2_49 = etree.SubElement(mandate_related_info_2_47, 'DtOfSgntr') - mandate_signature_date_2_49.text = '2013-02-20' # TODO + mandate_identification_2_48.text = self._prepare_field( + cr, uid, 'Unique Mandate Reference', + 'line.sdd_mandate_id.unique_mandate_reference', + 35, line=line, context=context) + mandate_signature_date_2_49 = etree.SubElement( + mandate_related_info_2_47, 'DtOfSgntr') + mandate_signature_date_2_49.text = self._prepare_field( + cr, uid, 'Mandate Signature Date', + 'line.sdd_mandate_id.signature_date', 10, + line=line, context=context) + # TODO look at 2.50 "Amendment Indicator debtor_agent_2_70 = etree.SubElement(dd_transaction_info_2_28, 'DbtrAgt') debtor_agent_institution = etree.SubElement(debtor_agent_2_70, 'FinInstnId') @@ -308,10 +364,10 @@ class banking_export_sdd_wizard(orm.TransientModel): remittance_info_unstructured_2_89.text = self._prepare_field(cr, uid, 'Remittance Information', 'line.communication', 140, line=line, context=context) - - if pain_flavor in ['pain.008.001.02', 'pain.008.001.03', 'pain.008.001.04']: - nb_of_transactions_1_6.text = nb_of_transactions_2_4.text = str(transactions_count) - control_sum_1_7.text = control_sum_2_5.text = '%.2f' % amount_control_sum + nb_of_transactions_2_4.text = str(transactions_count_2_4) + control_sum_2_5.text = '%.2f' % amount_control_sum_2_5 + nb_of_transactions_1_6.text = str(transactions_count_1_6) + control_sum_1_7.text = '%.2f' % amount_control_sum_1_7 xml_string = etree.tostring(root, pretty_print=True, encoding='UTF-8', xml_declaration=True) @@ -345,7 +401,7 @@ class banking_export_sdd_wizard(orm.TransientModel): 'charge_bearer': sepa_export.charge_bearer, 'requested_collec_date': sepa_export.requested_collec_date, 'total_amount': total_amount, - 'nb_transactions': transactions_count, + 'nb_transactions': transactions_count_1_6, 'file': base64.encodestring(xml_string), 'payment_order_ids': [ (6, 0, [x.id for x in sepa_export.payment_order_ids]) @@ -374,13 +430,15 @@ class banking_export_sdd_wizard(orm.TransientModel): Cancel the SEPA Direct Debit file: just drop the file ''' sepa_export = self.browse(cr, uid, ids[0], context=context) - self.pool.get('banking.export.sdd').unlink(cr, uid, sepa_export.file_id.id, context=context) + self.pool.get('banking.export.sdd').unlink( + cr, uid, sepa_export.file_id.id, context=context) return {'type': 'ir.actions.act_window_close'} def save_sepa(self, cr, uid, ids, context=None): ''' Save the SEPA Direct Debit file: mark all payments in the file as 'sent'. + Write 'last debit date' on mandate and set oneoff mandate to expired ''' sepa_export = self.browse(cr, uid, ids[0], context=context) sepa_file = self.pool.get('banking.export.sdd').write(cr, uid, @@ -388,4 +446,14 @@ class banking_export_sdd_wizard(orm.TransientModel): wf_service = netsvc.LocalService('workflow') for order in sepa_export.payment_order_ids: wf_service.trg_validate(uid, 'payment.order', order.id, 'sent', cr) + mandate_ids = [line.sdd_mandate_id.id for line in order.line_ids] + self.pool['sdd.mandate'].write( + cr, uid, mandate_ids, { + 'last_debit_date': datetime.today().strftime('%Y-%m-%d') + }, + context=context) + oneoff_mandate_ids = [line.sdd_mandate_id.id for line in order.line_ids if line.sdd_mandate_id.type == 'oneoff'] + self.pool['sdd.mandate'].write( + cr, uid, oneoff_mandate_ids, {'state': 'expired'}, + context=context) return {'type': 'ir.actions.act_window_close'} From 819be28513271442002100b49792e2246378dd0c Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Sat, 19 Oct 2013 17:29:17 +0200 Subject: [PATCH 03/43] [FIX] correct parent menu entry Remove unused variables --- account_banking_sepa_direct_debit/account_banking_sdd.py | 1 - .../account_banking_sdd_view.xml | 2 +- account_banking_sepa_direct_debit/wizard/export_sdd.py | 6 ++---- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/account_banking_sepa_direct_debit/account_banking_sdd.py b/account_banking_sepa_direct_debit/account_banking_sdd.py index 7e5a5d0f3..55c5921fd 100644 --- a/account_banking_sepa_direct_debit/account_banking_sdd.py +++ b/account_banking_sepa_direct_debit/account_banking_sdd.py @@ -20,7 +20,6 @@ ############################################################################## from openerp.osv import orm, fields -import time from openerp.tools.translate import _ from openerp.addons.decimal_precision import decimal_precision as dp diff --git a/account_banking_sepa_direct_debit/account_banking_sdd_view.xml b/account_banking_sepa_direct_debit/account_banking_sdd_view.xml index 32a289081..2f0d64c9d 100644 --- a/account_banking_sepa_direct_debit/account_banking_sdd_view.xml +++ b/account_banking_sepa_direct_debit/account_banking_sdd_view.xml @@ -65,7 +65,7 @@ diff --git a/account_banking_sepa_direct_debit/wizard/export_sdd.py b/account_banking_sepa_direct_debit/wizard/export_sdd.py index 3cc06e845..66e478188 100644 --- a/account_banking_sepa_direct_debit/wizard/export_sdd.py +++ b/account_banking_sepa_direct_debit/wizard/export_sdd.py @@ -127,8 +127,6 @@ class banking_export_sdd_wizard(orm.TransientModel): ''' Creates the SEPA Direct Debit file. That's the important code ! ''' - payment_order_obj = self.pool.get('payment.order') - sepa_export = self.browse(cr, uid, ids[0], context=context) pain_flavor = sepa_export.payment_order_ids[0].mode.type.code @@ -441,11 +439,11 @@ class banking_export_sdd_wizard(orm.TransientModel): Write 'last debit date' on mandate and set oneoff mandate to expired ''' sepa_export = self.browse(cr, uid, ids[0], context=context) - sepa_file = self.pool.get('banking.export.sdd').write(cr, uid, + self.pool.get('banking.export.sdd').write(cr, uid, sepa_export.file_id.id, {'state': 'sent'}, context=context) wf_service = netsvc.LocalService('workflow') for order in sepa_export.payment_order_ids: - wf_service.trg_validate(uid, 'payment.order', order.id, 'sent', cr) + wf_service.trg_validate(uid, 'payment.order', order.id, 'done', cr) mandate_ids = [line.sdd_mandate_id.id for line in order.line_ids] self.pool['sdd.mandate'].write( cr, uid, mandate_ids, { From 059c28ac04afa9aedc80b1675cc4905c6ded9279 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Wed, 23 Oct 2013 00:25:06 +0200 Subject: [PATCH 04/43] 2 modifications following a real-life SDD with a French bank: - convert accented chars to ascii chars (via the unidecode lib) - use "PrvtId" instead of "OrgId" in the XML Use the sequence of payment.order as the "Message identification" of the XML file (advantages : it is unique, users can easily customize the sequence and users can easily find the payment corresponding to the "Message Identification" in OpenERP). It is also used as the Payment Identification, combined with the sequence type. Use the sequence of payment.line in the "EndtoEnd Identification" field. Reduce flake8 warnings. --- account_banking_sepa_direct_debit/__init__.py | 1 - .../account_banking_sdd.py | 50 +- .../account_banking_sdd_view.xml | 3 +- account_banking_sepa_direct_debit/company.py | 22 +- .../data/mandate_reference_sequence.xml | 2 +- .../account_banking_sepa_direct_debit.pot | 494 ++++++++++++++++++ .../wizard/export_sdd.py | 73 ++- .../wizard/export_sdd_view.xml | 2 - 8 files changed, 567 insertions(+), 80 deletions(-) create mode 100644 account_banking_sepa_direct_debit/i18n/account_banking_sepa_direct_debit.pot diff --git a/account_banking_sepa_direct_debit/__init__.py b/account_banking_sepa_direct_debit/__init__.py index ce46fda33..f852fb7bd 100644 --- a/account_banking_sepa_direct_debit/__init__.py +++ b/account_banking_sepa_direct_debit/__init__.py @@ -23,4 +23,3 @@ from . import company from . import wizard from . import account_banking_sdd - diff --git a/account_banking_sepa_direct_debit/account_banking_sdd.py b/account_banking_sepa_direct_debit/account_banking_sdd.py index 55c5921fd..0a57ee839 100644 --- a/account_banking_sepa_direct_debit/account_banking_sdd.py +++ b/account_banking_sepa_direct_debit/account_banking_sdd.py @@ -22,18 +22,19 @@ from openerp.osv import orm, fields from openerp.tools.translate import _ from openerp.addons.decimal_precision import decimal_precision as dp +from unidecode import unidecode class banking_export_sdd(orm.Model): '''SEPA Direct Debit export''' _name = 'banking.export.sdd' _description = __doc__ - _rec_name = 'msg_identification' + _rec_name = 'filename' def _generate_filename(self, cr, uid, ids, name, arg, context=None): res = {} for sepa_file in self.browse(cr, uid, ids, context=context): - res[sepa_file.id] = 'sdd_' + (sepa_file.msg_identification or '') + '.xml' + res[sepa_file.id] = 'sdd_%s.xml' % (sepa_file.payment_order_ids[0].reference and unidecode(sepa_file.payment_order_ids[0].reference.replace('/', '-')) or 'error') return res _columns = { @@ -43,13 +44,15 @@ class banking_export_sdd(orm.Model): 'banking_export_sepa_id', 'account_order_id', 'Payment orders', readonly=True), - 'requested_collec_date': fields.date('Requested collection date', readonly=True), - 'nb_transactions': fields.integer('Number of transactions', readonly=True), - 'total_amount': fields.float('Total amount', - digits_compute=dp.get_precision('Account'), readonly=True), - 'msg_identification': fields.char('Message identification', size=35, + 'requested_collec_date': fields.date( + 'Requested collection date', readonly=True), + 'nb_transactions': fields.integer( + 'Number of transactions', readonly=True), + 'total_amount': fields.float( + 'Total amount', digits_compute=dp.get_precision('Account'), readonly=True), - 'batch_booking': fields.boolean('Batch booking', readonly=True, + 'batch_booking': fields.boolean( + 'Batch booking', readonly=True, help="If true, the bank statement will display only one credit line for all the direct debits of the SEPA XML file ; if false, the bank statement will display one credit line per direct debit of the SEPA XML file."), 'charge_bearer': fields.selection([ ('SHAR', 'Shared'), @@ -58,15 +61,15 @@ class banking_export_sdd(orm.Model): ('SLEV', 'Following service level'), ], 'Charge bearer', readonly=True, help='Shared : transaction charges on the sender side are to be borne by the debtor, transaction charges on the receiver side are to be borne by the creditor (most transfers use this). Borne by creditor : all transaction charges are to be borne by the creditor. Borne by debtor : all transaction charges are to be borne by the debtor. Following service level : transaction charges are to be applied following the rules agreed in the service level and/or scheme.'), - 'generation_date': fields.datetime('Generation date', - readonly=True), + 'generation_date': fields.datetime('Generation date', readonly=True), 'file': fields.binary('SEPA XML file', readonly=True), - 'filename': fields.function(_generate_filename, type='char', size=256, - method=True, string='Filename', readonly=True), + 'filename': fields.function( + _generate_filename, type='char', size=256, + string='Filename', readonly=True, store=True), 'state': fields.selection([ - ('draft', 'Draft'), - ('sent', 'Sent'), - ('done', 'Reconciled'), + ('draft', 'Draft'), + ('sent', 'Sent'), + ('done', 'Reconciled'), ], 'State', readonly=True), } @@ -97,7 +100,8 @@ class sdd_mandate(orm.Model): ], 'Type of Mandate', required=True), 'signature_date': fields.date('Date of Signature of the Mandate'), 'scan': fields.binary('Scan of the mandate'), - 'last_debit_date': fields.date('Date of the Last Debit', + 'last_debit_date': fields.date( + 'Date of the Last Debit', help="For recurrent mandates, this field is used to know if the SDD will be of type 'First' or 'Recurring'. For one-off mandates, this field is used to know if the SDD has already been used or not."), 'state': fields.selection([ ('valid', 'Valid'), @@ -113,10 +117,10 @@ class sdd_mandate(orm.Model): )] _defaults = { - 'company_id': lambda self, cr, uid, context: \ + 'company_id': lambda self, cr, uid, context: self.pool['res.users'].browse(cr, uid, uid, context=context).\ company_id.id, - 'unique_mandate_reference': lambda self, cr, uid, context: \ + 'unique_mandate_reference': lambda self, cr, uid, context: self.pool['ir.sequence'].get(cr, uid, 'sdd.mandate.reference'), 'state': 'valid', } @@ -143,15 +147,13 @@ class payment_line(orm.Model): for payline in self.browse(cr, uid, ids): if payline.sdd_mandate_id and not payline.bank_id: raise orm.except_orm( - _('Error :'), - _("Missing bank account on the payment line with SEPA\ - Direct Debit Mandate '%s'." - % payline.sdd_mandate_id.unique_mandate_reference)) + _('Error:'), + _("Missing bank account on the payment line with SEPA Direct Debit Mandate '%s'.") + % payline.sdd_mandate_id.unique_mandate_reference) elif payline.sdd_mandate_id and payline.bank_id and payline.sdd_mandate_id.partner_bank_id != payline.bank_id.id: raise orm.except_orm( - _('Error :'), + _('Error:'), _("The SEPA Direct Debit Mandate '%s' is not related??")) - return True # _constraints = [ diff --git a/account_banking_sepa_direct_debit/account_banking_sdd_view.xml b/account_banking_sepa_direct_debit/account_banking_sdd_view.xml index 2f0d64c9d..8249da13e 100644 --- a/account_banking_sepa_direct_debit/account_banking_sdd_view.xml +++ b/account_banking_sepa_direct_debit/account_banking_sdd_view.xml @@ -14,7 +14,6 @@
- @@ -47,7 +46,7 @@ banking.export.sdd - + diff --git a/account_banking_sepa_direct_debit/company.py b/account_banking_sepa_direct_debit/company.py index aed40f64b..eb3730d57 100644 --- a/account_banking_sepa_direct_debit/company.py +++ b/account_banking_sepa_direct_debit/company.py @@ -34,9 +34,11 @@ class res_company(orm.Model): help="Enter the Creditor Identifier that has been attributed to your company to make SEPA Direct Debits. This identifier is composed of :\n- your country ISO code (2 letters)\n- a 2-digits checkum\n- a 3-letters business code\n- a country-specific identifier"), } - def is_sepa_creditor_identifier_valid(self, cr, uid, sepa_creditor_identifier, context=None): + def is_sepa_creditor_identifier_valid( + self, cr, uid, sepa_creditor_identifier, context=None): """Check if SEPA Creditor Identifier is valid - @param sepa_creditor_identifier: SEPA Creditor Identifier as str or unicode + @param sepa_creditor_identifier: SEPA Creditor Identifier as str + or unicode @return: True if valid, False otherwise """ if not isinstance(sepa_creditor_identifier, (str, unicode)): @@ -44,20 +46,23 @@ class res_company(orm.Model): try: sci_str = str(sepa_creditor_identifier) except: - logger.warning("SEPA Creditor ID should contain only ASCII caracters.") + logger.warning( + "SEPA Creditor ID should contain only ASCII caracters.") return False sci = sci_str.lower() if len(sci) < 9: return False before_replacement = sci[7:] + sci[0:2] + '00' - logger.debug("SEPA ID check before_replacement = %s" % before_replacement) + logger.debug( + "SEPA ID check before_replacement = %s" % before_replacement) after_replacement = '' for char in before_replacement: if char.isalpha(): after_replacement += str(ord(char)-87) else: after_replacement += char - logger.debug("SEPA ID check after_replacement = %s" % after_replacement) + logger.debug( + "SEPA ID check after_replacement = %s" % after_replacement) if int(sci[2:4]) == (98 - (int(after_replacement) % 97)): return True else: @@ -66,10 +71,13 @@ class res_company(orm.Model): def _check_sepa_creditor_identifier(self, cr, uid, ids): for company in self.browse(cr, uid, ids): if company.sepa_creditor_identifier: - if not self.is_sepa_creditor_identifier_valid(cr, uid, company.sepa_creditor_identifier): + if not self.is_sepa_creditor_identifier_valid( + cr, uid, company.sepa_creditor_identifier): return False return True _constraints = [ - (_check_sepa_creditor_identifier, "Invalid SEPA Creditor Identifier.", ['sepa_creditor_identifier']), + (_check_sepa_creditor_identifier, + "Invalid SEPA Creditor Identifier.", + ['sepa_creditor_identifier']), ] diff --git a/account_banking_sepa_direct_debit/data/mandate_reference_sequence.xml b/account_banking_sepa_direct_debit/data/mandate_reference_sequence.xml index 6a3143cca..68075d526 100644 --- a/account_banking_sepa_direct_debit/data/mandate_reference_sequence.xml +++ b/account_banking_sepa_direct_debit/data/mandate_reference_sequence.xml @@ -1,6 +1,6 @@ - + diff --git a/account_banking_sepa_direct_debit/i18n/account_banking_sepa_direct_debit.pot b/account_banking_sepa_direct_debit/i18n/account_banking_sepa_direct_debit.pot new file mode 100644 index 000000000..6c772f970 --- /dev/null +++ b/account_banking_sepa_direct_debit/i18n/account_banking_sepa_direct_debit.pot @@ -0,0 +1,494 @@ +# Translation of OpenERP Server. +# This file contains the translation of the following modules: +# * account_banking_sepa_direct_debit +# +msgid "" +msgstr "" +"Project-Id-Version: OpenERP Server 7.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-10-21 21:21+0000\n" +"PO-Revision-Date: 2013-10-21 21:21+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd,file:0 +msgid "SEPA XML file" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd,nb_transactions:0 +#: field:banking.export.sdd.wizard,nb_transactions:0 +msgid "Number of transactions" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:79 +#, python-format +msgid "This IBAN is not valid : %s" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:132 +#, python-format +msgid "Payment Type Code '%s' is not supported. The only Payment Type Code supported for SEPA Direct Debit are 'pain.008.001.02', 'pain.008.001.03' and 'pain.008.001.04'." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: selection:banking.export.sdd.wizard,state:0 +msgid "Create" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: selection:sdd.mandate,type:0 +msgid "Recurrent" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,type:0 +msgid "Type of Mandate" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:192 +#, python-format +msgid "Missing signature date on SEPA Direct Debit mandate with reference '%s' for partner '%s'." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd,filename:0 +#: field:banking.export.sdd.wizard,filename:0 +msgid "Filename" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: model:ir.actions.act_window,name:account_banking_sepa_direct_debit.act_banking_export_sdd_payment_order +msgid "Generated SEPA Direct Debit files" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd,state:0 +#: field:banking.export.sdd.wizard,state:0 +msgid "State" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: selection:sdd.mandate,state:0 +msgid "Valid" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: selection:banking.export.sdd,state:0 +msgid "Draft" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:185 +#, python-format +msgid "The SEPA Direct Debit mandate with reference '%s' for partner '%s' has expired." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:100 +#, python-format +msgid "Cannot compute the '%s' of the Payment Line with Invoice Reference '%s'." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: view:res.partner.bank:0 +#: field:res.partner.bank,sdd_mandate_ids:0 +msgid "SEPA Direct Debit Mandates" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd,total_amount:0 +#: field:banking.export.sdd.wizard,total_amount:0 +msgid "Total amount" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: view:banking.export.sdd:0 +msgid "SEPA Direct Debit" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: view:sdd.mandate:0 +msgid "Type" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd,generation_date:0 +msgid "Generation date" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: selection:banking.export.sdd,state:0 +msgid "Sent" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,scan:0 +msgid "Scan of the mandate" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: help:banking.export.sdd.wizard,requested_collec_date:0 +msgid "This is the date on which the collection should be made by the bank. Please keep in mind that banks only execute on working days." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: model:ir.actions.act_window,name:account_banking_sepa_direct_debit.action_account_banking_sdd +#: model:ir.ui.menu,name:account_banking_sepa_direct_debit.menu_account_banking_sdd +msgid "Generated SEPA Direct Debit XML files" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: selection:banking.export.sdd.wizard,state:0 +msgid "Finish" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: view:res.partner:0 +#: view:res.partner.bank:0 +msgid "SDD Mandates" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:198 +#, python-format +msgid "The signature date on SEPA Direct Debit mandate with reference '%s' for partner '%s' is '%s', which is in the future !" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:res.company,sepa_creditor_identifier:0 +msgid "SEPA Creditor Identifier" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,company_id:0 +msgid "Company" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: selection:banking.export.sdd,charge_bearer:0 +#: selection:banking.export.sdd.wizard,charge_bearer:0 +msgid "Shared" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,unique_mandate_reference:0 +msgid "Unique Mandate Reference" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:102 +#, python-format +msgid "Cannot compute the '%s'." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:104 +#, python-format +msgid "The type of the field '%s' is %s. It should be a string or unicode." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: model:ir.model,name:account_banking_sepa_direct_debit.model_banking_export_sdd +msgid "SEPA Direct Debit export" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: model:ir.model,name:account_banking_sepa_direct_debit.model_payment_line +msgid "Payment Line" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: view:payment.order:0 +msgid "SDD Mandate" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:156 +#, python-format +msgid "The SEPA Direct Debit Mandate '%s' is not related??" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: selection:sdd.mandate,state:0 +msgid "Expired" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: view:banking.export.sdd.wizard:0 +msgid "Generate" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: model:ir.actions.act_window,name:account_banking_sepa_direct_debit.sdd_mandate_action +#: model:ir.model,name:account_banking_sepa_direct_debit.model_sdd_mandate +#: model:ir.ui.menu,name:account_banking_sepa_direct_debit.sdd_mandate_menu +#: field:payment.line,sdd_mandate_id:0 +#: view:sdd.mandate:0 +msgid "SEPA Direct Debit Mandate" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: help:res.company,sepa_creditor_identifier:0 +msgid "Enter the Creditor Identifier that has been attributed to your company to make SEPA Direct Debits. This identifier is composed of :\n" +"- your country ISO code (2 letters)\n" +"- a 2-digits checkum\n" +"- a 3-letters business code\n" +"- a country-specific identifier" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:151 +#, python-format +msgid "Missing bank account on the payment line with SEPA Direct Debit Mandate '%s'." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: view:sdd.mandate:0 +msgid "Status" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:385 +#, python-format +msgid "The generated XML file is not valid against the official XML Schema Definition. The generated XML file and the full error have been written in the server logs. Here is the error, which may give you an idea on the cause of the problem : %s" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: sql_constraint:sdd.mandate:0 +msgid "A Mandate with the same reference already exists for this company !" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:106 +#, python-format +msgid "The '%s' is empty or 0. It should have a non-null value." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:150 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:155 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:79 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:100 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:102 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:106 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:132 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:178 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:184 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:191 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:197 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:211 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:385 +#, python-format +msgid "Error:" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,partner_bank_id:0 +msgid "Bank Account" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: model:ir.model,name:account_banking_sepa_direct_debit.model_res_company +msgid "Companies" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: help:banking.export.sdd,charge_bearer:0 +#: help:banking.export.sdd.wizard,charge_bearer:0 +msgid "Shared : transaction charges on the sender side are to be borne by the debtor, transaction charges on the receiver side are to be borne by the creditor (most transfers use this). Borne by creditor : all transaction charges are to be borne by the creditor. Borne by debtor : all transaction charges are to be borne by the debtor. Following service level : transaction charges are to be applied following the rules agreed in the service level and/or scheme." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: selection:banking.export.sdd,charge_bearer:0 +#: selection:banking.export.sdd.wizard,charge_bearer:0 +msgid "Borne by creditor" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd,payment_order_ids:0 +#: field:banking.export.sdd.wizard,payment_order_ids:0 +msgid "Payment orders" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: view:sdd.mandate:0 +msgid "Signature Date" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: help:banking.export.sdd,batch_booking:0 +msgid "If true, the bank statement will display only one credit line for all the direct debits of the SEPA XML file ; if false, the bank statement will display one credit line per direct debit of the SEPA XML file." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: view:banking.export.sdd.wizard:0 +msgid "Processing details" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd.wizard,file_id:0 +msgid "SDD XML file" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: model:ir.model,name:account_banking_sepa_direct_debit.model_banking_export_sdd_wizard +msgid "Export SEPA Direct Debit XML file" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:104 +#, python-format +msgid "Field type error:" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: model:ir.actions.act_window,help:account_banking_sepa_direct_debit.sdd_mandate_action +msgid "

\n" +" Click to create a new SEPA Direct Debit Mandate.\n" +"

\n" +" The SEPA Direct Debit Mandate is a document signed by your customer that gives you the autorization to do one or several direct debits on his bank account.\n" +"

\n" +" " +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: selection:sdd.mandate,type:0 +msgid "One-Off" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:179 +#, python-format +msgid "Missing SEPA Direct Debit mandate on the payment line with partner '%s' and Invoice ref '%s'." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: view:banking.export.sdd.wizard:0 +msgid "Validate" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:212 +#, python-format +msgid "The mandate with reference '%s' for partner '%s' has type set to 'One-Off' and it has a last debit date set to '%s', so we can't use it." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: help:sdd.mandate,last_debit_date:0 +msgid "For recurrent mandates, this field is used to know if the SDD will be of type 'First' or 'Recurring'. For one-off mandates, this field is used to know if the SDD has already been used or not." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,signature_date:0 +msgid "Date of Signature of the Mandate" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,last_debit_date:0 +msgid "Date of the Last Debit" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: view:sdd.mandate:0 +msgid "Reference" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: constraint:res.company:0 +msgid "Invalid SEPA Creditor Identifier." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd,requested_collec_date:0 +#: field:banking.export.sdd.wizard,requested_collec_date:0 +msgid "Requested collection date" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: selection:banking.export.sdd,charge_bearer:0 +#: selection:banking.export.sdd.wizard,charge_bearer:0 +msgid "Borne by debtor" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: model:ir.model,name:account_banking_sepa_direct_debit.model_res_partner_bank +msgid "Bank Accounts" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: selection:banking.export.sdd,charge_bearer:0 +#: selection:banking.export.sdd.wizard,charge_bearer:0 +msgid "Following service level" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: view:banking.export.sdd:0 +msgid "Payment Orders" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: view:banking.export.sdd.wizard:0 +msgid "SEPA Direct Debit XML file generation" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: view:banking.export.sdd:0 +msgid "General Information" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd,charge_bearer:0 +#: field:banking.export.sdd.wizard,charge_bearer:0 +msgid "Charge bearer" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,state:0 +msgid "Mandate Status" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: help:banking.export.sdd.wizard,batch_booking:0 +msgid "If true, the bank statement will display only one debit line for all the wire transfers of the SEPA XML file ; if false, the bank statement will display one debit line per wire transfer of the SEPA XML file." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd.wizard,file:0 +msgid "File" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: view:banking.export.sdd.wizard:0 +msgid "Cancel" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,partner_id:0 +msgid "Partner" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: help:sdd.mandate,state:0 +msgid "For a recurrent mandate, this field indicate if the mandate is still valid or if it has expired (a recurrent mandate expires if it's not used during 36 months). For a one-off mandate, it expires after its first use." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd,batch_booking:0 +#: field:banking.export.sdd.wizard,batch_booking:0 +msgid "Batch booking" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: selection:banking.export.sdd,state:0 +msgid "Reconciled" +msgstr "" + diff --git a/account_banking_sepa_direct_debit/wizard/export_sdd.py b/account_banking_sepa_direct_debit/wizard/export_sdd.py index 66e478188..0e935aa7f 100644 --- a/account_banking_sepa_direct_debit/wizard/export_sdd.py +++ b/account_banking_sepa_direct_debit/wizard/export_sdd.py @@ -28,6 +28,7 @@ import base64 from datetime import datetime, timedelta from lxml import etree import logging +from unidecode import unidecode _logger = logging.getLogger(__name__) @@ -38,10 +39,6 @@ class banking_export_sdd_wizard(orm.TransientModel): _columns = { 'state': fields.selection([('create', 'Create'), ('finish', 'Finish')], 'State', readonly=True), - 'msg_identification': fields.char('Message identification', size=35, - # Can't set required=True on the field because it blocks - # the launch of the wizard -> I set it as required in the view - help='This is the message identification of the entire SEPA XML file. 35 characters max.'), 'batch_booking': fields.boolean('Batch booking', help="If true, the bank statement will display only one debit line for all the wire transfers of the SEPA XML file ; if false, the bank statement will display one debit line per wire transfer of the SEPA XML file."), 'requested_collec_date': fields.date('Requested collection date', @@ -72,22 +69,6 @@ class banking_export_sdd_wizard(orm.TransientModel): 'state': 'create', } - - def _check_msg_identification(self, cr, uid, ids): - '''Check that the msg_identification is unique''' - for export_sdd in self.browse(cr, uid, ids): - res = self.pool.get('banking.export.sdd').search(cr, uid, - [('msg_identification', '=', export_sdd.msg_identification)]) - if len(res) > 1: - return False - return True - - - _constraints = [ - (_check_msg_identification, "The field 'Message Identification' should be uniue. Another SEPA Direct Debit file already exists with the same 'Message Identification'.", ['msg_identification']) - ] - - def _validate_iban(self, cr, uid, iban, context=None): '''if IBAN is valid, returns IBAN if IBAN is NOT valid, raises an error message''' @@ -95,7 +76,7 @@ class banking_export_sdd_wizard(orm.TransientModel): if partner_bank_obj.is_iban_valid(cr, uid, iban, context=context): return iban.replace(' ', '') else: - raise orm.except_orm(_('Error :'), _("This IBAN is not valid : %s") % iban) + raise orm.except_orm(_('Error:'), _("This IBAN is not valid : %s") % iban) def create(self, cr, uid, vals, context=None): payment_order_ids = context.get('active_ids', []) @@ -105,24 +86,27 @@ class banking_export_sdd_wizard(orm.TransientModel): return super(banking_export_sdd_wizard, self).create(cr, uid, vals, context=context) - - def _prepare_field(self, cr, uid, field_name, field_value, max_size=0, sepa_export=False, line=False, context=None): + def _prepare_field(self, cr, uid, field_name, field_value, max_size=0, sepa_export=False, line=False, sequence_type=False, context=None): try: - value = eval(field_value) + # SEPA uses XML, and XML = UTF-8 with support for all characters... + # But we are dealing with banks + # and many banks don't want non-ASCCI characters ! + # cf section 1.4 "Character set" of the SEPA Core Direct Debit + # Customer-to-bank implementation guidelines version 6.0 + value = unidecode(eval(field_value)) except: if line: - raise orm.except_orm(_('Error :'), _("Cannot compute the '%s' of the Payment Line with Invoice Reference '%s'.") % (field_name, self.pool['account.invoice'].name_get(cr, uid, [line.ml_inv_ref.id], context=context)[0][1])) + raise orm.except_orm(_('Error:'), _("Cannot compute the '%s' of the Payment Line with Invoice Reference '%s'.") % (field_name, self.pool['account.invoice'].name_get(cr, uid, [line.ml_inv_ref.id], context=context)[0][1])) else: - raise orm.except_orm(_('Error :'), _("Cannot compute the '%s'.") % field_name) + raise orm.except_orm(_('Error:'), _("Cannot compute the '%s'.") % field_name) if not isinstance(value, (str, unicode)): - raise orm.except_orm(_('Field type error :'), _("The type of the field '%s' is %s. It should be a string or unicode.") % (field_name, type(value))) + raise orm.except_orm(_('Field type error:'), _("The type of the field '%s' is %s. It should be a string or unicode.") % (field_name, type(value))) if not value: - raise orm.except_orm(_('Error :'), _("The '%s' is empty or 0. It should have a non-null value.") % field_name) + raise orm.except_orm(_('Error:'), _("The '%s' is empty or 0. It should have a non-null value.") % field_name) if max_size and len(value) > max_size: value = value[0:max_size] return value - def create_sepa(self, cr, uid, ids, context=None): ''' Creates the SEPA Direct Debit file. That's the important code ! @@ -143,7 +127,7 @@ class banking_export_sdd_wizard(orm.TransientModel): name_maxsize = 140 root_xml_tag = 'CstmrDrctDbtInitn' else: - raise orm.except_orm(_('Error :'), _("Payment Type Code '%s' is not supported. The only Payment Type Code supported for SEPA Direct Debit are 'pain.008.001.02', 'pain.008.001.03' and 'pain.008.001.04'.") % pain_flavor) + raise orm.except_orm(_('Error:'), _("Payment Type Code '%s' is not supported. The only Payment Type Code supported for SEPA Direct Debit are 'pain.008.001.02', 'pain.008.001.03' and 'pain.008.001.04'.") % pain_flavor) if sepa_export.requested_collec_date: my_requested_collec_date = sepa_export.requested_collec_date else: @@ -158,13 +142,16 @@ class banking_export_sdd_wizard(orm.TransientModel): pain_root = etree.SubElement(root, root_xml_tag) my_company_name = self._prepare_field(cr, uid, 'Company Name', - 'sepa_export.payment_order_ids[0].company_id.name', - name_maxsize, sepa_export, context=context) + 'sepa_export.payment_order_ids[0].company_id.partner_id.name', + name_maxsize, sepa_export=sepa_export, context=context) # A. Group header group_header_1_0 = etree.SubElement(pain_root, 'GrpHdr') message_identification_1_1 = etree.SubElement(group_header_1_0, 'MsgId') - message_identification_1_1.text = sepa_export.msg_identification + message_identification_1_1.text = self._prepare_field(cr, uid, + 'Message Identification', + 'sepa_export.payment_order_ids[0].reference', 35, + sepa_export=sepa_export, context=context) creation_date_time_1_2 = etree.SubElement(group_header_1_0, 'CreDtTm') creation_date_time_1_2.text = datetime.strftime(datetime.today(), '%Y-%m-%dT%H:%M:%S') nb_of_transactions_1_6 = etree.SubElement(group_header_1_0, 'NbOfTxs') @@ -219,7 +206,7 @@ class banking_export_sdd_wizard(orm.TransientModel): first_recur_lines['OOFF'] = [line] else: raise orm.except_orm( - _('Error :'), + _('Error:'), _("The mandate with reference '%s' for partner '%s' has type set to 'One-Off' and it has a last debit date set to '%s', so we can't use it.") % (line.sdd_mandate_id.unique_mandate_reference, line.sdd_mandate_id.partner_id.name, @@ -240,7 +227,11 @@ class banking_export_sdd_wizard(orm.TransientModel): # B. Payment info payment_info_2_0 = etree.SubElement(pain_root, 'PmtInf') payment_info_identification_2_1 = etree.SubElement(payment_info_2_0, 'PmtInfId') - payment_info_identification_2_1.text = sepa_export.msg_identification + payment_info_identification_2_1.text = self._prepare_field( + cr, uid, 'Payment Information Identification', + "sequence_type + '-' + sepa_export.payment_order_ids[0].reference", + 35, sepa_export=sepa_export, sequence_type=sequence_type, + context=context) payment_method_2_2 = etree.SubElement(payment_info_2_0, 'PmtMtd') payment_method_2_2.text = 'DD' # batch_booking is in "Payment Info" with pain.008.001.02/03 @@ -292,8 +283,8 @@ class banking_export_sdd_wizard(orm.TransientModel): creditor_scheme_identification_2_27 = etree.SubElement(payment_info_2_0, 'CdtrSchmeId') csi_id = etree.SubElement(creditor_scheme_identification_2_27, 'Id') - csi_orgid = csi_id = etree.SubElement(csi_id, 'OrgId') - csi_other = etree.SubElement(csi_orgid, 'Othr') + csi_privateid = csi_id = etree.SubElement(csi_id, 'PrvtId') + csi_other = etree.SubElement(csi_privateid, 'Othr') csi_other_id = etree.SubElement(csi_other, 'Id') csi_other_id.text = self._prepare_field(cr, uid, 'SEPA Creditor Identifier', @@ -313,9 +304,8 @@ class banking_export_sdd_wizard(orm.TransientModel): # Instruction identification (2.30) is not mandatory, so we don't use it end2end_identification_2_31 = etree.SubElement(payment_identification_2_29, 'EndToEndId') end2end_identification_2_31.text = self._prepare_field(cr, uid, - 'End to End Identification', 'line.communication', 35, + 'End to End Identification', 'line.name', 35, line=line, context=context) - payment_type_2_32 = etree.SubElement(dd_transaction_info_2_28, 'PmtTpInf') currency_name = self._prepare_field(cr, uid, 'Currency Code', 'line.currency.name', 3, line=line, context=context) instructed_amount_2_44 = etree.SubElement(dd_transaction_info_2_28, 'InstdAmt', Ccy=currency_name) @@ -389,12 +379,11 @@ class banking_export_sdd_wizard(orm.TransientModel): _logger.warning("The XML file is invalid against the XML Schema Definition") _logger.warning(xml_string) _logger.warning(e) - raise orm.except_orm(_('Error :'), _('The generated XML file is not valid against the official XML Schema Definition. The generated XML file and the full error have been written in the server logs. Here is the error, which may give you an idea on the cause of the problem : %s') % str(e)) + raise orm.except_orm(_('Error:'), _('The generated XML file is not valid against the official XML Schema Definition. The generated XML file and the full error have been written in the server logs. Here is the error, which may give you an idea on the cause of the problem : %s') % str(e)) # CREATE the banking.export.sepa record file_id = self.pool.get('banking.export.sdd').create(cr, uid, { - 'msg_identification': sepa_export.msg_identification, 'batch_booking': sepa_export.batch_booking, 'charge_bearer': sepa_export.charge_bearer, 'requested_collec_date': sepa_export.requested_collec_date, @@ -422,7 +411,6 @@ class banking_export_sdd_wizard(orm.TransientModel): } return action - def cancel_sepa(self, cr, uid, ids, context=None): ''' Cancel the SEPA Direct Debit file: just drop the file @@ -432,7 +420,6 @@ class banking_export_sdd_wizard(orm.TransientModel): cr, uid, sepa_export.file_id.id, context=context) return {'type': 'ir.actions.act_window_close'} - def save_sepa(self, cr, uid, ids, context=None): ''' Save the SEPA Direct Debit file: mark all payments in the file as 'sent'. diff --git a/account_banking_sepa_direct_debit/wizard/export_sdd_view.xml b/account_banking_sepa_direct_debit/wizard/export_sdd_view.xml index 8357e3f5d..4afa6bb01 100644 --- a/account_banking_sepa_direct_debit/wizard/export_sdd_view.xml +++ b/account_banking_sepa_direct_debit/wizard/export_sdd_view.xml @@ -18,8 +18,6 @@ - - From 9dc7762aa4d67ac30e75302e2e7c7f763a90cc2a Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Wed, 6 Nov 2013 10:02:09 +0100 Subject: [PATCH 05/43] Add python lib dependencies. --- account_banking_sepa_direct_debit/__openerp__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/account_banking_sepa_direct_debit/__openerp__.py b/account_banking_sepa_direct_debit/__openerp__.py index 2a44e1c06..8c6a69ef5 100644 --- a/account_banking_sepa_direct_debit/__openerp__.py +++ b/account_banking_sepa_direct_debit/__openerp__.py @@ -27,6 +27,9 @@ 'website': 'http://www.akretion.com', 'category': 'Banking addons', 'depends': ['account_direct_debit'], + 'external_dependencies': { + 'python': ['unidecode', 'lxml'], + }, 'data': [ 'account_banking_sdd_view.xml', 'account_payment_view.xml', From 30e5a45acdd8a76bc2048a686078924fa344dfcf Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Thu, 7 Nov 2013 12:52:08 +0100 Subject: [PATCH 06/43] Reduce pep8 warnings Use create_date instead of a dedicated datetime field The creation of the SEPA file now has a _prepare function Other improvements in the code. --- .../account_banking_sdd.py | 43 ++- .../account_banking_sdd_view.xml | 4 +- .../data/payment_type_sdd.xml | 2 +- .../wizard/export_sdd.py | 365 +++++++++++------- .../wizard/export_sdd_view.xml | 1 - 5 files changed, 252 insertions(+), 163 deletions(-) diff --git a/account_banking_sepa_direct_debit/account_banking_sdd.py b/account_banking_sepa_direct_debit/account_banking_sdd.py index 0a57ee839..ffbe8ee89 100644 --- a/account_banking_sepa_direct_debit/account_banking_sdd.py +++ b/account_banking_sepa_direct_debit/account_banking_sdd.py @@ -34,7 +34,12 @@ class banking_export_sdd(orm.Model): def _generate_filename(self, cr, uid, ids, name, arg, context=None): res = {} for sepa_file in self.browse(cr, uid, ids, context=context): - res[sepa_file.id] = 'sdd_%s.xml' % (sepa_file.payment_order_ids[0].reference and unidecode(sepa_file.payment_order_ids[0].reference.replace('/', '-')) or 'error') + ref = sepa_file.payment_order_ids[0].reference + if ref: + label = unidecode(ref.replace('/', '-')) + else: + label = 'error' + res[sepa_file.id] = 'sdd_%s.xml' % label return res _columns = { @@ -42,27 +47,27 @@ class banking_export_sdd(orm.Model): 'payment.order', 'account_payment_order_sdd_rel', 'banking_export_sepa_id', 'account_order_id', - 'Payment orders', + 'Payment Orders', readonly=True), 'requested_collec_date': fields.date( - 'Requested collection date', readonly=True), + 'Requested Collection Date', readonly=True), 'nb_transactions': fields.integer( - 'Number of transactions', readonly=True), + 'Number of Transactions', readonly=True), 'total_amount': fields.float( - 'Total amount', digits_compute=dp.get_precision('Account'), + 'Total Amount', digits_compute=dp.get_precision('Account'), readonly=True), 'batch_booking': fields.boolean( - 'Batch booking', readonly=True, + 'Batch Booking', readonly=True, help="If true, the bank statement will display only one credit line for all the direct debits of the SEPA XML file ; if false, the bank statement will display one credit line per direct debit of the SEPA XML file."), 'charge_bearer': fields.selection([ ('SHAR', 'Shared'), - ('CRED', 'Borne by creditor'), - ('DEBT', 'Borne by debtor'), - ('SLEV', 'Following service level'), - ], 'Charge bearer', readonly=True, + ('CRED', 'Borne by Creditor'), + ('DEBT', 'Borne by Debtor'), + ('SLEV', 'Following Service Level'), + ], 'Charge Bearer', readonly=True, help='Shared : transaction charges on the sender side are to be borne by the debtor, transaction charges on the receiver side are to be borne by the creditor (most transfers use this). Borne by creditor : all transaction charges are to be borne by the creditor. Borne by debtor : all transaction charges are to be borne by the debtor. Following service level : transaction charges are to be applied following the rules agreed in the service level and/or scheme.'), - 'generation_date': fields.datetime('Generation date', readonly=True), - 'file': fields.binary('SEPA XML file', readonly=True), + 'create_date': fields.datetime('Generation Date', readonly=True), + 'file': fields.binary('SEPA XML File', readonly=True), 'filename': fields.function( _generate_filename, type='char', size=256, string='Filename', readonly=True, store=True), @@ -74,7 +79,6 @@ class banking_export_sdd(orm.Model): } _defaults = { - 'generation_date': fields.date.context_today, 'state': 'draft', } @@ -117,10 +121,9 @@ class sdd_mandate(orm.Model): )] _defaults = { - 'company_id': lambda self, cr, uid, context: - self.pool['res.users'].browse(cr, uid, uid, context=context).\ - company_id.id, - 'unique_mandate_reference': lambda self, cr, uid, context: + 'company_id': lambda self, cr, uid, ctx: + self.pool['res.users'].browse(cr, uid, uid, ctx=ctx).company_id.id, + 'unique_mandate_reference': lambda self, cr, uid, ctx: self.pool['ir.sequence'].get(cr, uid, 'sdd.mandate.reference'), 'state': 'valid', } @@ -150,10 +153,12 @@ class payment_line(orm.Model): _('Error:'), _("Missing bank account on the payment line with SEPA Direct Debit Mandate '%s'.") % payline.sdd_mandate_id.unique_mandate_reference) - elif payline.sdd_mandate_id and payline.bank_id and payline.sdd_mandate_id.partner_bank_id != payline.bank_id.id: + elif (payline.sdd_mandate_id and payline.bank_id and + payline.sdd_mandate_id.partner_bank_id != + payline.bank_id.id): raise orm.except_orm( _('Error:'), - _("The SEPA Direct Debit Mandate '%s' is not related??")) + _("The SEPA Direct Debit Mandate '%s' is not related???")) return True # _constraints = [ diff --git a/account_banking_sepa_direct_debit/account_banking_sdd_view.xml b/account_banking_sepa_direct_debit/account_banking_sdd_view.xml index 8249da13e..db0b255a2 100644 --- a/account_banking_sepa_direct_debit/account_banking_sdd_view.xml +++ b/account_banking_sepa_direct_debit/account_banking_sdd_view.xml @@ -19,7 +19,7 @@ - + @@ -48,7 +48,7 @@ - + diff --git a/account_banking_sepa_direct_debit/data/payment_type_sdd.xml b/account_banking_sepa_direct_debit/data/payment_type_sdd.xml index 5ce4b5b1b..97e63d25e 100644 --- a/account_banking_sepa_direct_debit/data/payment_type_sdd.xml +++ b/account_banking_sepa_direct_debit/data/payment_type_sdd.xml @@ -5,7 +5,7 @@ - SEPA Direct Debit v02 + SEPA Direct Debit v02 (recommended) pain.008.001.02 diff --git a/account_banking_sepa_direct_debit/wizard/export_sdd.py b/account_banking_sepa_direct_debit/wizard/export_sdd.py index 0e935aa7f..df08915bd 100644 --- a/account_banking_sepa_direct_debit/wizard/export_sdd.py +++ b/account_banking_sepa_direct_debit/wizard/export_sdd.py @@ -23,6 +23,7 @@ from openerp.osv import orm, fields from openerp.tools.translate import _ +from openerp.tools.safe_eval import safe_eval from openerp import tools, netsvc import base64 from datetime import datetime, timedelta @@ -35,33 +36,41 @@ _logger = logging.getLogger(__name__) class banking_export_sdd_wizard(orm.TransientModel): _name = 'banking.export.sdd.wizard' - _description = 'Export SEPA Direct Debit XML file' + _description = 'Export SEPA Direct Debit File' _columns = { - 'state': fields.selection([('create', 'Create'), ('finish', 'Finish')], - 'State', readonly=True), - 'batch_booking': fields.boolean('Batch booking', + 'state': fields.selection([ + ('create', 'Create'), + ('finish', 'Finish'), + ], 'State', readonly=True), + 'batch_booking': fields.boolean( + 'Batch Booking', help="If true, the bank statement will display only one debit line for all the wire transfers of the SEPA XML file ; if false, the bank statement will display one debit line per wire transfer of the SEPA XML file."), - 'requested_collec_date': fields.date('Requested collection date', + 'requested_collec_date': fields.date( + 'Requested Collection Date', help='This is the date on which the collection should be made by the bank. Please keep in mind that banks only execute on working days.'), 'charge_bearer': fields.selection([ ('SHAR', 'Shared'), - ('CRED', 'Borne by creditor'), - ('DEBT', 'Borne by debtor'), - ('SLEV', 'Following service level'), - ], 'Charge bearer', required=True, + ('CRED', 'Borne by Creditor'), + ('DEBT', 'Borne by Debtor'), + ('SLEV', 'Following Service Level'), + ], 'Charge Bearer', required=True, help='Shared : transaction charges on the sender side are to be borne by the debtor, transaction charges on the receiver side are to be borne by the creditor (most transfers use this). Borne by creditor : all transaction charges are to be borne by the creditor. Borne by debtor : all transaction charges are to be borne by the debtor. Following service level : transaction charges are to be applied following the rules agreed in the service level and/or scheme.'), - 'nb_transactions': fields.related('file_id', 'nb_transactions', - type='integer', string='Number of transactions', readonly=True), - 'total_amount': fields.related('file_id', 'total_amount', type='float', - string='Total amount', readonly=True), - 'file_id': fields.many2one('banking.export.sdd', 'SDD XML file', readonly=True), - 'file': fields.related('file_id', 'file', string="File", type='binary', + 'nb_transactions': fields.related( + 'file_id', 'nb_transactions', type='integer', + string='Number of Transactions', readonly=True), + 'total_amount': fields.related( + 'file_id', 'total_amount', type='float', string='Total Amount', readonly=True), - 'filename': fields.related('file_id', 'filename', string="Filename", - type='char', size=256, readonly=True), - 'payment_order_ids': fields.many2many('payment.order', - 'wiz_sdd_payorders_rel', 'wizard_id', 'payment_order_id', - 'Payment orders', readonly=True), + 'file_id': fields.many2one( + 'banking.export.sdd', 'SDD XML File', readonly=True), + 'file': fields.related( + 'file_id', 'file', string="File", type='binary', readonly=True), + 'filename': fields.related( + 'file_id', 'filename', string="Filename", type='char', size=256, + readonly=True), + 'payment_order_ids': fields.many2many( + 'payment.order', 'wiz_sdd_payorders_rel', 'wizard_id', + 'payment_order_id', 'Payment Orders', readonly=True), } _defaults = { @@ -76,37 +85,94 @@ class banking_export_sdd_wizard(orm.TransientModel): if partner_bank_obj.is_iban_valid(cr, uid, iban, context=context): return iban.replace(' ', '') else: - raise orm.except_orm(_('Error:'), _("This IBAN is not valid : %s") % iban) + raise orm.except_orm( + _('Error:'), _("This IBAN is not valid : %s") % iban) def create(self, cr, uid, vals, context=None): payment_order_ids = context.get('active_ids', []) vals.update({ 'payment_order_ids': [[6, 0, payment_order_ids]], }) - return super(banking_export_sdd_wizard, self).create(cr, uid, - vals, context=context) + return super(banking_export_sdd_wizard, self).create( + cr, uid, vals, context=context) - def _prepare_field(self, cr, uid, field_name, field_value, max_size=0, sepa_export=False, line=False, sequence_type=False, context=None): + def _prepare_field( + self, cr, uid, field_name, field_value, max_size=0, + sepa_export=False, line=False, sequence_type=False, context=None): + '''This function is designed to be inherited !''' + eval_ctx = { + 'sepa_export': sepa_export, + 'line': line, + 'sequence_type': sequence_type, + } try: - # SEPA uses XML, and XML = UTF-8 with support for all characters... - # But we are dealing with banks + # SEPA uses XML ; XML = UTF-8 ; UTF-8 = support for all characters + # But we are dealing with banks... # and many banks don't want non-ASCCI characters ! # cf section 1.4 "Character set" of the SEPA Core Direct Debit - # Customer-to-bank implementation guidelines version 6.0 - value = unidecode(eval(field_value)) + # Customer-to-bank implementation guidelines + value = unidecode(safe_eval(field_value, eval_ctx)) except: if line: - raise orm.except_orm(_('Error:'), _("Cannot compute the '%s' of the Payment Line with Invoice Reference '%s'.") % (field_name, self.pool['account.invoice'].name_get(cr, uid, [line.ml_inv_ref.id], context=context)[0][1])) + raise orm.except_orm( + _('Error:'), + _("Cannot compute the '%s' of the Payment Line with Invoice Reference '%s'.") + % (field_name, self.pool['account.invoice'].name_get( + cr, uid, [line.ml_inv_ref.id], context=context)[0][1])) else: - raise orm.except_orm(_('Error:'), _("Cannot compute the '%s'.") % field_name) + raise orm.except_orm( + _('Error:'), + _("Cannot compute the '%s'.") % field_name) if not isinstance(value, (str, unicode)): - raise orm.except_orm(_('Field type error:'), _("The type of the field '%s' is %s. It should be a string or unicode.") % (field_name, type(value))) + raise orm.except_orm( + _('Field type error:'), + _("The type of the field '%s' is %s. It should be a string or unicode.") + % (field_name, type(value))) if not value: - raise orm.except_orm(_('Error:'), _("The '%s' is empty or 0. It should have a non-null value.") % field_name) + raise orm.except_orm( + _('Error:'), + _("The '%s' is empty or 0. It should have a non-null value.") + % field_name) if max_size and len(value) > max_size: value = value[0:max_size] return value + def _prepare_export_sepa( + self, cr, uid, sepa_export, total_amount, transactions_count, + xml_string, context=None): + return { + 'batch_booking': sepa_export.batch_booking, + 'charge_bearer': sepa_export.charge_bearer, + 'requested_collec_date': sepa_export.requested_collec_date, + 'total_amount': total_amount, + 'nb_transactions': transactions_count, + 'file': base64.encodestring(xml_string), + 'payment_order_ids': [ + (6, 0, [x.id for x in sepa_export.payment_order_ids]) + ], + } + + def _validate_xml(self, cr, uid, xml_string, pain_flavor): + xsd_etree_obj = etree.parse( + tools.file_open( + 'account_banking_sepa_direct_debit/data/%s.xsd' + % pain_flavor)) + official_pain_schema = etree.XMLSchema(xsd_etree_obj) + + try: + root_to_validate = etree.fromstring(xml_string) + official_pain_schema.assertValid(root_to_validate) + except Exception, e: + _logger.warning( + "The XML file is invalid against the XML Schema Definition") + _logger.warning(xml_string) + _logger.warning(e) + raise orm.except_orm( + _('Error:'), + _('The generated XML file is not valid against the official XML Schema Definition. The generated XML file and the full error have been written in the server logs. Here is the error, which may give you an idea on the cause of the problem : %s') + % str(e)) + return True + def create_sepa(self, cr, uid, ids, context=None): ''' Creates the SEPA Direct Debit file. That's the important code ! @@ -131,7 +197,8 @@ class banking_export_sdd_wizard(orm.TransientModel): if sepa_export.requested_collec_date: my_requested_collec_date = sepa_export.requested_collec_date else: - my_requested_collec_date = datetime.strftime(datetime.today() + timedelta(days=1), '%Y-%m-%d') + my_requested_collec_date = datetime.strftime( + datetime.today() + timedelta(days=1), '%Y-%m-%d') pain_ns = { 'xsi': 'http://www.w3.org/2001/XMLSchema-instance', @@ -141,19 +208,22 @@ class banking_export_sdd_wizard(orm.TransientModel): root = etree.Element('Document', nsmap=pain_ns) pain_root = etree.SubElement(root, root_xml_tag) - my_company_name = self._prepare_field(cr, uid, 'Company Name', - 'sepa_export.payment_order_ids[0].company_id.partner_id.name', - name_maxsize, sepa_export=sepa_export, context=context) + my_company_name = self._prepare_field( + cr, uid, 'Company Name', + 'sepa_export.payment_order_ids[0].company_id.partner_id.name', + name_maxsize, sepa_export=sepa_export, context=context) # A. Group header group_header_1_0 = etree.SubElement(pain_root, 'GrpHdr') - message_identification_1_1 = etree.SubElement(group_header_1_0, 'MsgId') - message_identification_1_1.text = self._prepare_field(cr, uid, - 'Message Identification', + message_identification_1_1 = etree.SubElement( + group_header_1_0, 'MsgId') + message_identification_1_1.text = self._prepare_field( + cr, uid, 'Message Identification', 'sepa_export.payment_order_ids[0].reference', 35, sepa_export=sepa_export, context=context) creation_date_time_1_2 = etree.SubElement(group_header_1_0, 'CreDtTm') - creation_date_time_1_2.text = datetime.strftime(datetime.today(), '%Y-%m-%dT%H:%M:%S') + creation_date_time_1_2.text = datetime.strftime( + datetime.today(), '%Y-%m-%dT%H:%M:%S') nb_of_transactions_1_6 = etree.SubElement(group_header_1_0, 'NbOfTxs') control_sum_1_7 = etree.SubElement(group_header_1_0, 'CtrlSum') initiating_party_1_8 = etree.SubElement(group_header_1_0, 'InitgPty') @@ -176,7 +246,7 @@ class banking_export_sdd_wizard(orm.TransientModel): _('Error:'), _("Missing SEPA Direct Debit mandate on the payment line with partner '%s' and Invoice ref '%s'.") % (line.partner_id.name, - line.ml_inv_ref.number)) + line.ml_inv_ref.number)) if line.sdd_mandate_id.state != 'valid': raise orm.except_orm( _('Error:'), @@ -190,7 +260,8 @@ class banking_export_sdd_wizard(orm.TransientModel): _("Missing signature date on SEPA Direct Debit mandate with reference '%s' for partner '%s'.") % (line.sdd_mandate_id.unique_mandate_reference, line.sdd_mandate_id.partner_id.name)) - elif line.sdd_mandate_id.signature_date > datetime.today().strftime('%Y-%m-%d'): + elif (line.sdd_mandate_id.signature_date > + datetime.today().strftime('%Y-%m-%d')): raise orm.except_orm( _('Error:'), _("The signature date on SEPA Direct Debit mandate with reference '%s' for partner '%s' is '%s', which is in the future !") @@ -206,11 +277,11 @@ class banking_export_sdd_wizard(orm.TransientModel): first_recur_lines['OOFF'] = [line] else: raise orm.except_orm( - _('Error:'), - _("The mandate with reference '%s' for partner '%s' has type set to 'One-Off' and it has a last debit date set to '%s', so we can't use it.") - % (line.sdd_mandate_id.unique_mandate_reference, - line.sdd_mandate_id.partner_id.name, - line.sdd_mandate_id.last_debit_date)) + _('Error:'), + _("The mandate with reference '%s' for partner '%s' has type set to 'One-Off' and it has a last debit date set to '%s', so we can't use it.") + % (line.sdd_mandate_id.unique_mandate_reference, + line.sdd_mandate_id.partner_id.name, + line.sdd_mandate_id.last_debit_date)) elif line.sdd_mandate_id.type == 'recurrent': if line.sdd_mandate_id.last_debit_date: if first_recur_lines.get('RCUR'): @@ -226,7 +297,8 @@ class banking_export_sdd_wizard(orm.TransientModel): for sequence_type, lines in first_recur_lines.items(): # B. Payment info payment_info_2_0 = etree.SubElement(pain_root, 'PmtInf') - payment_info_identification_2_1 = etree.SubElement(payment_info_2_0, 'PmtInfId') + payment_info_identification_2_1 = etree.SubElement( + payment_info_2_0, 'PmtInfId') payment_info_identification_2_1.text = self._prepare_field( cr, uid, 'Payment Information Identification', "sequence_type + '-' + sepa_export.payment_order_ids[0].reference", @@ -241,57 +313,73 @@ class banking_export_sdd_wizard(orm.TransientModel): # Implementation guidelines" v6.0 says that control sum # and nb_of_transactions should be present # at both "group header" level and "payment info" level - nb_of_transactions_2_4 = etree.SubElement(payment_info_2_0, 'NbOfTxs') + nb_of_transactions_2_4 = etree.SubElement( + payment_info_2_0, 'NbOfTxs') control_sum_2_5 = etree.SubElement(payment_info_2_0, 'CtrlSum') - payment_type_info_2_6 = etree.SubElement(payment_info_2_0, 'PmtTpInf') - service_level_2_8 = etree.SubElement(payment_type_info_2_6, 'SvcLvl') + payment_type_info_2_6 = etree.SubElement( + payment_info_2_0, 'PmtTpInf') + service_level_2_8 = etree.SubElement( + payment_type_info_2_6, 'SvcLvl') service_level_code_2_9 = etree.SubElement(service_level_2_8, 'Cd') service_level_code_2_9.text = 'SEPA' - local_instrument_2_11 = etree.SubElement(payment_type_info_2_6, 'LclInstrm') - local_instr_code_2_12 = etree.SubElement(local_instrument_2_11, 'Cd') + local_instrument_2_11 = etree.SubElement( + payment_type_info_2_6, 'LclInstrm') + local_instr_code_2_12 = etree.SubElement( + local_instrument_2_11, 'Cd') local_instr_code_2_12.text = 'CORE' # 2.14 Sequence Type MANDATORY # this message element must indicate ‘FRST # 'FRST' = First ; 'OOFF' = One Off ; 'RCUR' : Recurring # 'FNAL' = Final - sequence_type_2_14 = etree.SubElement(payment_type_info_2_6, 'SeqTp') + sequence_type_2_14 = etree.SubElement( + payment_type_info_2_6, 'SeqTp') sequence_type_2_14.text = sequence_type - requested_collec_date_2_18 = etree.SubElement(payment_info_2_0, 'ReqdColltnDt') + requested_collec_date_2_18 = etree.SubElement( + payment_info_2_0, 'ReqdColltnDt') requested_collec_date_2_18.text = my_requested_collec_date creditor_2_19 = etree.SubElement(payment_info_2_0, 'Cdtr') creditor_name = etree.SubElement(creditor_2_19, 'Nm') creditor_name.text = my_company_name - creditor_account_2_20 = etree.SubElement(payment_info_2_0, 'CdtrAcct') + creditor_account_2_20 = etree.SubElement( + payment_info_2_0, 'CdtrAcct') creditor_account_id = etree.SubElement(creditor_account_2_20, 'Id') - creditor_account_iban = etree.SubElement(creditor_account_id, 'IBAN') - creditor_account_iban.text = self._validate_iban(cr, uid, - self._prepare_field(cr, uid, 'Company IBAN', + creditor_account_iban = etree.SubElement( + creditor_account_id, 'IBAN') + creditor_account_iban.text = self._validate_iban( + cr, uid, self._prepare_field( + cr, uid, 'Company IBAN', 'sepa_export.payment_order_ids[0].mode.bank_id.acc_number', sepa_export=sepa_export, context=context), context=context) creditor_agent_2_21 = etree.SubElement(payment_info_2_0, 'CdtrAgt') - creditor_agent_institution = etree.SubElement(creditor_agent_2_21, 'FinInstnId') - creditor_agent_bic = etree.SubElement(creditor_agent_institution, bic_xml_tag) - creditor_agent_bic.text = self._prepare_field(cr, uid, 'Company BIC', + creditor_agent_institution = etree.SubElement( + creditor_agent_2_21, 'FinInstnId') + creditor_agent_bic = etree.SubElement( + creditor_agent_institution, bic_xml_tag) + creditor_agent_bic.text = self._prepare_field( + cr, uid, 'Company BIC', 'sepa_export.payment_order_ids[0].mode.bank_id.bank.bic', sepa_export=sepa_export, context=context) charge_bearer_2_24 = etree.SubElement(payment_info_2_0, 'ChrgBr') charge_bearer_2_24.text = sepa_export.charge_bearer - creditor_scheme_identification_2_27 = etree.SubElement(payment_info_2_0, 'CdtrSchmeId') - csi_id = etree.SubElement(creditor_scheme_identification_2_27, 'Id') + creditor_scheme_identification_2_27 = etree.SubElement( + payment_info_2_0, 'CdtrSchmeId') + csi_id = etree.SubElement( + creditor_scheme_identification_2_27, 'Id') csi_privateid = csi_id = etree.SubElement(csi_id, 'PrvtId') csi_other = etree.SubElement(csi_privateid, 'Othr') csi_other_id = etree.SubElement(csi_other, 'Id') - csi_other_id.text = self._prepare_field(cr, uid, - 'SEPA Creditor Identifier', + csi_other_id.text = self._prepare_field( + cr, uid, 'SEPA Creditor Identifier', 'sepa_export.payment_order_ids[0].company_id.sepa_creditor_identifier', sepa_export=sepa_export, context=context) csi_scheme_name = etree.SubElement(csi_other, 'SchmeNm') - csi_scheme_name_proprietary = etree.SubElement(csi_scheme_name, 'Prtry') + csi_scheme_name_proprietary = etree.SubElement( + csi_scheme_name, 'Prtry') csi_scheme_name_proprietary.text = 'SEPA' transactions_count_2_4 = 0 @@ -299,22 +387,29 @@ class banking_export_sdd_wizard(orm.TransientModel): for line in lines: transactions_count_2_4 += 1 # C. Direct Debit Transaction Info - dd_transaction_info_2_28 = etree.SubElement(payment_info_2_0, 'DrctDbtTxInf') - payment_identification_2_29 = etree.SubElement(dd_transaction_info_2_28, 'PmtId') - # Instruction identification (2.30) is not mandatory, so we don't use it - end2end_identification_2_31 = etree.SubElement(payment_identification_2_29, 'EndToEndId') - end2end_identification_2_31.text = self._prepare_field(cr, uid, - 'End to End Identification', 'line.name', 35, + dd_transaction_info_2_28 = etree.SubElement( + payment_info_2_0, 'DrctDbtTxInf') + payment_identification_2_29 = etree.SubElement( + dd_transaction_info_2_28, 'PmtId') + end2end_identification_2_31 = etree.SubElement( + payment_identification_2_29, 'EndToEndId') + end2end_identification_2_31.text = self._prepare_field( + cr, uid, 'End to End Identification', 'line.name', 35, line=line, context=context) - currency_name = self._prepare_field(cr, uid, 'Currency Code', - 'line.currency.name', 3, line=line, context=context) - instructed_amount_2_44 = etree.SubElement(dd_transaction_info_2_28, 'InstdAmt', Ccy=currency_name) + currency_name = self._prepare_field( + cr, uid, 'Currency Code', 'line.currency.name', 3, + line=line, context=context) + instructed_amount_2_44 = etree.SubElement( + dd_transaction_info_2_28, 'InstdAmt', Ccy=currency_name) instructed_amount_2_44.text = '%.2f' % line.amount_currency amount_control_sum_1_7 += line.amount_currency amount_control_sum_2_5 += line.amount_currency - dd_transaction_2_46 = etree.SubElement(dd_transaction_info_2_28, 'DrctDbtTx') - mandate_related_info_2_47 = etree.SubElement(dd_transaction_2_46, 'MndtRltdInf') - mandate_identification_2_48 = etree.SubElement(mandate_related_info_2_47, 'MndtId') + dd_transaction_2_46 = etree.SubElement( + dd_transaction_info_2_28, 'DrctDbtTx') + mandate_related_info_2_47 = etree.SubElement( + dd_transaction_2_46, 'MndtRltdInf') + mandate_identification_2_48 = etree.SubElement( + mandate_related_info_2_47, 'MndtId') mandate_identification_2_48.text = self._prepare_field( cr, uid, 'Unique Mandate Reference', 'line.sdd_mandate_id.unique_mandate_reference', @@ -327,81 +422,67 @@ class banking_export_sdd_wizard(orm.TransientModel): line=line, context=context) # TODO look at 2.50 "Amendment Indicator - debtor_agent_2_70 = etree.SubElement(dd_transaction_info_2_28, 'DbtrAgt') - debtor_agent_institution = etree.SubElement(debtor_agent_2_70, 'FinInstnId') - debtor_agent_bic = etree.SubElement(debtor_agent_institution, bic_xml_tag) - debtor_agent_bic.text = self._prepare_field(cr, uid, - 'Customer BIC', 'line.bank_id.bank.bic', + debtor_agent_2_70 = etree.SubElement( + dd_transaction_info_2_28, 'DbtrAgt') + debtor_agent_institution = etree.SubElement( + debtor_agent_2_70, 'FinInstnId') + debtor_agent_bic = etree.SubElement( + debtor_agent_institution, bic_xml_tag) + debtor_agent_bic.text = self._prepare_field( + cr, uid, 'Customer BIC', 'line.bank_id.bank.bic', line=line, context=context) - debtor_2_72 = etree.SubElement(dd_transaction_info_2_28, 'Dbtr') + debtor_2_72 = etree.SubElement( + dd_transaction_info_2_28, 'Dbtr') debtor_name = etree.SubElement(debtor_2_72, 'Nm') - debtor_name.text = self._prepare_field(cr, uid, - 'Customer Name', 'line.partner_id.name', + debtor_name.text = self._prepare_field( + cr, uid, 'Customer Name', 'line.partner_id.name', name_maxsize, line=line, context=context) - debtor_account_2_73 = etree.SubElement(dd_transaction_info_2_28, 'DbtrAcct') + debtor_account_2_73 = etree.SubElement( + dd_transaction_info_2_28, 'DbtrAcct') debtor_account_id = etree.SubElement(debtor_account_2_73, 'Id') - debtor_account_iban = etree.SubElement(debtor_account_id, 'IBAN') - debtor_account_iban.text = self._validate_iban(cr, uid, - self._prepare_field(cr, uid, 'Customer IBAN', + debtor_account_iban = etree.SubElement( + debtor_account_id, 'IBAN') + debtor_account_iban.text = self._validate_iban( + cr, uid, self._prepare_field( + cr, uid, 'Customer IBAN', 'line.bank_id.acc_number', line=line, - context=context), - context=context) - remittance_info_2_88 = etree.SubElement(dd_transaction_info_2_28, 'RmtInf') + context=context), + context=context) + remittance_info_2_88 = etree.SubElement( + dd_transaction_info_2_28, 'RmtInf') # switch to Structured (Strdr) ? If we do it, beware that the format is not the same between pain 02 and pain 03 - remittance_info_unstructured_2_89 = etree.SubElement(remittance_info_2_88, 'Ustrd') - remittance_info_unstructured_2_89.text = self._prepare_field(cr, uid, - 'Remittance Information', 'line.communication', + remittance_info_unstructured_2_89 = etree.SubElement( + remittance_info_2_88, 'Ustrd') + remittance_info_unstructured_2_89.text = self._prepare_field( + cr, uid, 'Remittance Information', 'line.communication', 140, line=line, context=context) nb_of_transactions_2_4.text = str(transactions_count_2_4) control_sum_2_5.text = '%.2f' % amount_control_sum_2_5 nb_of_transactions_1_6.text = str(transactions_count_1_6) control_sum_1_7.text = '%.2f' % amount_control_sum_1_7 - - xml_string = etree.tostring(root, pretty_print=True, encoding='UTF-8', xml_declaration=True) - _logger.debug("Generated SDD XML file in format %s below" % pain_flavor) + xml_string = etree.tostring( + root, pretty_print=True, encoding='UTF-8', xml_declaration=True) + _logger.debug( + "Generated SDD XML file in format %s below" % pain_flavor) _logger.debug(xml_string) - xsd_etree_obj = etree.parse(tools.file_open('account_banking_sepa_direct_debit/data/%s.xsd' % pain_flavor)) - official_pain_schema = etree.XMLSchema(xsd_etree_obj) - _logger.debug("Printing %s XML Schema definition:" % pain_flavor) - _logger.debug(etree.tostring(xsd_etree_obj, pretty_print=True, encoding='UTF-8', xml_declaration=True)) - - try: - # If I do official_pain_schema.assertValid(root), then I get this - # error msg in the exception : - # The generated XML file is not valid against the official XML Schema Definition. The generated XML file and the full error have been written in the server logs. Here is the error, which may give you an idea on the cause of the problem : Element 'Document': No matching global declaration available for the validation root. - # So I re-import the SEPA XML from the string, and give this - # so validation - # If you know how I can avoid that, please tell me -- Alexis - root_to_validate = etree.fromstring(xml_string) - official_pain_schema.assertValid(root_to_validate) - except Exception, e: - _logger.warning("The XML file is invalid against the XML Schema Definition") - _logger.warning(xml_string) - _logger.warning(e) - raise orm.except_orm(_('Error:'), _('The generated XML file is not valid against the official XML Schema Definition. The generated XML file and the full error have been written in the server logs. Here is the error, which may give you an idea on the cause of the problem : %s') % str(e)) + self._validate_xml(cr, uid, xml_string, pain_flavor) # CREATE the banking.export.sepa record - file_id = self.pool.get('banking.export.sdd').create(cr, uid, - { - 'batch_booking': sepa_export.batch_booking, - 'charge_bearer': sepa_export.charge_bearer, - 'requested_collec_date': sepa_export.requested_collec_date, - 'total_amount': total_amount, - 'nb_transactions': transactions_count_1_6, - 'file': base64.encodestring(xml_string), - 'payment_order_ids': [ - (6, 0, [x.id for x in sepa_export.payment_order_ids]) - ], - }, context=context) + file_id = self.pool.get('banking.export.sdd').create( + cr, uid, self._prepare_export_sepa( + cr, uid, sepa_export, total_amount, transactions_count_1_6, + xml_string, context=context), + context=context) - self.write(cr, uid, ids, { - 'file_id': file_id, - 'state': 'finish', + self.write( + cr, uid, ids, { + 'file_id': file_id, + 'state': 'finish', }, context=context) action = { - 'name': 'SEPA Direct Debit XML', + 'name': 'SEPA Direct Debit File', 'type': 'ir.actions.act_window', 'view_type': 'form', 'view_mode': 'form,tree', @@ -422,12 +503,14 @@ class banking_export_sdd_wizard(orm.TransientModel): def save_sepa(self, cr, uid, ids, context=None): ''' - Save the SEPA Direct Debit file: mark all payments in the file as 'sent'. - Write 'last debit date' on mandate and set oneoff mandate to expired + Save the SEPA Direct Debit file: mark all payments in the file + as 'sent'. Write 'last debit date' on mandate and set oneoff + mandate to expired ''' sepa_export = self.browse(cr, uid, ids[0], context=context) - self.pool.get('banking.export.sdd').write(cr, uid, - sepa_export.file_id.id, {'state': 'sent'}, context=context) + self.pool.get('banking.export.sdd').write( + cr, uid, sepa_export.file_id.id, {'state': 'sent'}, + context=context) wf_service = netsvc.LocalService('workflow') for order in sepa_export.payment_order_ids: wf_service.trg_validate(uid, 'payment.order', order.id, 'done', cr) @@ -437,7 +520,9 @@ class banking_export_sdd_wizard(orm.TransientModel): 'last_debit_date': datetime.today().strftime('%Y-%m-%d') }, context=context) - oneoff_mandate_ids = [line.sdd_mandate_id.id for line in order.line_ids if line.sdd_mandate_id.type == 'oneoff'] + oneoff_mandate_ids = \ + [line.sdd_mandate_id.id for line in order.line_ids + if line.sdd_mandate_id.type == 'oneoff'] self.pool['sdd.mandate'].write( cr, uid, oneoff_mandate_ids, {'state': 'expired'}, context=context) diff --git a/account_banking_sepa_direct_debit/wizard/export_sdd_view.xml b/account_banking_sepa_direct_debit/wizard/export_sdd_view.xml index 4afa6bb01..c1b8a77c2 100644 --- a/account_banking_sepa_direct_debit/wizard/export_sdd_view.xml +++ b/account_banking_sepa_direct_debit/wizard/export_sdd_view.xml @@ -14,7 +14,6 @@ - From 112511e3b54a350058ec9df5345d18ba098c75b7 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Thu, 7 Nov 2013 12:57:26 +0100 Subject: [PATCH 07/43] FIX payment_order_type : payment -> debit --- account_banking_sepa_direct_debit/data/payment_type_sdd.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/account_banking_sepa_direct_debit/data/payment_type_sdd.xml b/account_banking_sepa_direct_debit/data/payment_type_sdd.xml index 97e63d25e..fcc742531 100644 --- a/account_banking_sepa_direct_debit/data/payment_type_sdd.xml +++ b/account_banking_sepa_direct_debit/data/payment_type_sdd.xml @@ -10,7 +10,7 @@ - payment + debit @@ -19,7 +19,7 @@ - payment + debit @@ -28,7 +28,7 @@ - payment + debit From 7aba0f0a002fc766b11870844a151d07f90d81e7 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Thu, 7 Nov 2013 23:22:19 +0100 Subject: [PATCH 08/43] More work on mandates : - constraints - display related payment lines - set mandates to expired after 36 months of inactivity (via a cron) - add tracking/chatter - add default draft state + validate button [FIX] In Debit mode, don't use the partner_bank_id of the customer invoice ! In the wizard 'Select invoices to pay', add maturity date in the view of the account move lines --- account_banking_payment/__openerp__.py | 1 + .../model/account_payment.py | 1 + .../view/payment_order_create_view.xml | 22 +++ .../__openerp__.py | 1 + .../account_banking_sdd.py | 140 ++++++++++++++---- .../account_banking_sdd_view.xml | 59 ++++++-- .../mandate_expire_cron.xml | 26 ++++ .../model/account_move_line.py | 31 ++++ 8 files changed, 244 insertions(+), 37 deletions(-) create mode 100644 account_banking_payment/view/payment_order_create_view.xml create mode 100644 account_banking_sepa_direct_debit/mandate_expire_cron.xml diff --git a/account_banking_payment/__openerp__.py b/account_banking_payment/__openerp__.py index a0984398f..033485126 100644 --- a/account_banking_payment/__openerp__.py +++ b/account_banking_payment/__openerp__.py @@ -39,6 +39,7 @@ 'view/banking_transaction_wizard.xml', 'view/payment_mode.xml', 'view/payment_mode_type.xml', + 'view/payment_order_create_view.xml', 'workflow/account_payment.xml', ], 'description': ''' diff --git a/account_banking_payment/model/account_payment.py b/account_banking_payment/model/account_payment.py index 608c49dd9..bfe33fb2f 100644 --- a/account_banking_payment/model/account_payment.py +++ b/account_banking_payment/model/account_payment.py @@ -107,6 +107,7 @@ class payment_order(orm.Model): 'payment_order_type': fields.selection( [('payment', 'Payment'),('debit', 'Direct debit')], 'Payment order type', required=True, + readonly=True, states={'draft': [('readonly', False)]}, ), 'date_sent': fields.date('Send date', readonly=True), } diff --git a/account_banking_payment/view/payment_order_create_view.xml b/account_banking_payment/view/payment_order_create_view.xml new file mode 100644 index 000000000..bf205e160 --- /dev/null +++ b/account_banking_payment/view/payment_order_create_view.xml @@ -0,0 +1,22 @@ + + + + + + + add.context.to.display.maturity.date + payment.order.create + + + + {'journal_type': 'sale'} + + + + + + diff --git a/account_banking_sepa_direct_debit/__openerp__.py b/account_banking_sepa_direct_debit/__openerp__.py index 8c6a69ef5..e02e72914 100644 --- a/account_banking_sepa_direct_debit/__openerp__.py +++ b/account_banking_sepa_direct_debit/__openerp__.py @@ -34,6 +34,7 @@ 'account_banking_sdd_view.xml', 'account_payment_view.xml', 'company_view.xml', + 'mandate_expire_cron.xml', 'wizard/export_sdd_view.xml', 'data/payment_type_sdd.xml', 'data/mandate_reference_sequence.xml', diff --git a/account_banking_sepa_direct_debit/account_banking_sdd.py b/account_banking_sepa_direct_debit/account_banking_sdd.py index ffbe8ee89..33b7d1bd1 100644 --- a/account_banking_sepa_direct_debit/account_banking_sdd.py +++ b/account_banking_sepa_direct_debit/account_banking_sdd.py @@ -23,6 +23,13 @@ from openerp.osv import orm, fields from openerp.tools.translate import _ from openerp.addons.decimal_precision import decimal_precision as dp from unidecode import unidecode +from datetime import datetime +from dateutil.relativedelta import relativedelta +import logging + +NUMBER_OF_UNUSED_MONTHS_BEFORE_EXPIRY = 36 + +logger = logging.getLogger(__name__) class banking_export_sdd(orm.Model): @@ -88,7 +95,16 @@ class sdd_mandate(orm.Model): _name = 'sdd.mandate' _description = __doc__ _rec_name = 'unique_mandate_reference' + _inherit = ['mail.thread'] _order = 'signature_date desc' + _track = { + 'state': { + 'account_banking_sepa_direct_debit.mandate_valid': + lambda self, cr, uid, obj, ctx=None: obj['state'] == 'valid', + 'account_banking_sepa_direct_debit.mandate_expired': + lambda self, cr, uid, obj, ctx=None: obj['state'] == 'expired', + } + } _columns = { 'partner_bank_id': fields.many2one('res.partner.bank', 'Bank Account'), @@ -108,25 +124,98 @@ class sdd_mandate(orm.Model): 'Date of the Last Debit', help="For recurrent mandates, this field is used to know if the SDD will be of type 'First' or 'Recurring'. For one-off mandates, this field is used to know if the SDD has already been used or not."), 'state': fields.selection([ + ('draft', 'Draft'), ('valid', 'Valid'), ('expired', 'Expired'), + # Do we have to handle cancellation of mandate by customer ? ], 'Mandate Status', help="For a recurrent mandate, this field indicate if the mandate is still valid or if it has expired (a recurrent mandate expires if it's not used during 36 months). For a one-off mandate, it expires after its first use."), + 'payment_line_ids': fields.one2many( + 'payment.line', 'sdd_mandate_id', "Related Payment Lines"), } + _defaults = { + 'company_id': lambda self, cr, uid, context: + self.pool['res.company'].\ + _company_default_get(cr, uid, 'sdd.mandate', context=context), + 'unique_mandate_reference': lambda self, cr, uid, ctx: + self.pool['ir.sequence'].get(cr, uid, 'sdd.mandate.reference'), + 'state': 'draft', + } + _sql_constraints = [( 'mandate_ref_company_uniq', 'unique(unique_mandate_reference, company_id)', 'A Mandate with the same reference already exists for this company !' )] - _defaults = { - 'company_id': lambda self, cr, uid, ctx: - self.pool['res.users'].browse(cr, uid, uid, ctx=ctx).company_id.id, - 'unique_mandate_reference': lambda self, cr, uid, ctx: - self.pool['ir.sequence'].get(cr, uid, 'sdd.mandate.reference'), - 'state': 'valid', - } + def _check_sdd_mandate(self, cr, uid, ids, context=None): + for mandate in self.read(cr, uid, ids, [ + 'last_debit_date', 'signature_date', + 'unique_mandate_reference', 'state', 'partner_bank_id' + ], context=context): + if (mandate['signature_date'] and + mandate['signature_date'] > + datetime.today().strftime('%Y-%m-%d')): + raise orm.except_orm( + _('Error:'), + _("The date of signature of mandate '%s' is in the future!") + % mandate['unique_mandate_reference']) + if mandate['state'] == 'valid' and not mandate['signature_date']: + raise orm.except_orm( + _('Error:'), + _("Cannot validate the mandate '%s' without a date of signature.") + % mandate['unique_mandate_reference']) + if mandate['state'] == 'valid' and not mandate['partner_bank_id']: + raise orm.except_orm( + _('Error:'), + _("Cannot validate the mandate '%s' because it is not linked to a bank account.") + % mandate['unique_mandate_reference']) + + if (mandate['signature_date'] and mandate['last_debit_date'] and + mandate['signature_date'] > mandate['last_debit_date']): + raise orm.except_orm( + _('Error:'), + _("The mandate '%s' can't have a date of last debit before the date of signature.") + % mandate['unique_mandate_reference']) + return True + + _constraints = [ + (_check_sdd_mandate, "Error msg in raise", + ['last_debit_date', 'signature_date', 'state', 'partner_bank_id']), + ] + + def validate(self, cr, uid, ids, context=None): + to_validate_ids = [] + for mandate in self.browse(cr, uid, ids, context=context): + assert mandate.state == 'draft', 'Mandate should be in draft state' + to_validate_ids.append(mandate.id) + self.write( + cr, uid, to_validate_ids, {'state': 'valid'}, context=context) + return True + + def _sdd_mandate_set_state_to_expired(self, cr, uid, context=None): + logger.info('Searching for SDD Mandates that must be set to Expired') + expire_limit_date = datetime.today() + \ + relativedelta(months=-NUMBER_OF_UNUSED_MONTHS_BEFORE_EXPIRY) + expire_limit_date_str = expire_limit_date.strftime('%Y-%m-%d') + expired_mandate_ids = self.search(cr, uid, [ + '|', + ('last_debit_date', '=', False), + ('last_debit_date', '<=', expire_limit_date_str), + ('state', '=', 'valid'), + ('signature_date', '<=', expire_limit_date_str), + ], context=context) + if expired_mandate_ids: + self.write( + cr, uid, expired_mandate_ids, {'state': 'expired'}, + context=context) + logger.info( + 'The following SDD Mandate IDs has been set to expired: %s' + % expired_mandate_ids) + else: + logger.info('0 SDD Mandates must be set to Expired') + return True class res_partner_bank(orm.Model): @@ -146,23 +235,20 @@ class payment_line(orm.Model): 'sdd.mandate', 'SEPA Direct Debit Mandate'), } - def _check_sdd_mandate(self, cr, uid, ids): - for payline in self.browse(cr, uid, ids): - if payline.sdd_mandate_id and not payline.bank_id: - raise orm.except_orm( - _('Error:'), - _("Missing bank account on the payment line with SEPA Direct Debit Mandate '%s'.") - % payline.sdd_mandate_id.unique_mandate_reference) - elif (payline.sdd_mandate_id and payline.bank_id and - payline.sdd_mandate_id.partner_bank_id != - payline.bank_id.id): - raise orm.except_orm( - _('Error:'), - _("The SEPA Direct Debit Mandate '%s' is not related???")) - return True - -# _constraints = [ -# (_check_sdd_mandate, "Mandate must be attached to bank account", ['bank_id', 'sdd_mandate_id']), -# ] - - # TODO inherit create to select the first mandate ?? + def create(self, cr, uid, vals, context=None): + '''Take the first valid mandate of the bank account by default''' + if context is None: + context = {} + if not vals: + vals = {} + partner_bank_id = vals.get('bank_id') + if (context.get('default_payment_order_type') == 'debit' + and partner_bank_id + and 'sdd_mandate_id' not in vals): + mandate_ids = self.pool['sdd.mandate'].search(cr, uid, [ + ('partner_bank_id', '=', partner_bank_id), + ('state', '=', 'valid'), + ], context=context) + if mandate_ids: + vals['sdd_mandate_id'] = mandate_ids[0] + return super(payment_line, self).create(cr, uid, vals, context=context) diff --git a/account_banking_sepa_direct_debit/account_banking_sdd_view.xml b/account_banking_sepa_direct_debit/account_banking_sdd_view.xml index db0b255a2..5f191e693 100644 --- a/account_banking_sepa_direct_debit/account_banking_sdd_view.xml +++ b/account_banking_sepa_direct_debit/account_banking_sdd_view.xml @@ -56,7 +56,7 @@ - Generated SEPA Direct Debit XML files + Generated SEPA Direct Debit Files banking.export.sdd form tree,form @@ -66,11 +66,11 @@
+

-

- + - + - + + + +
+
+ + +
@@ -111,9 +118,9 @@ sdd.mandate.tree sdd.mandate - + - + @@ -123,8 +130,23 @@ + + sdd.mandate.search + sdd.mandate + + + + + + + + + + + + - SEPA Direct Debit Mandate + SEPA Direct Debit Mandates sdd.mandate form tree,form @@ -144,6 +166,23 @@ sequence="20" /> + + + Mandate Validated + sdd.mandate + + SEPA Direct Debit Mandate Validated + + + + Mandate Expired + sdd.mandate + + SEPA Direct Debit Mandate has Expired + + + + sdd.mandate.res.partner.bank.form res.partner.bank diff --git a/account_banking_sepa_direct_debit/mandate_expire_cron.xml b/account_banking_sepa_direct_debit/mandate_expire_cron.xml new file mode 100644 index 000000000..4cb0693d2 --- /dev/null +++ b/account_banking_sepa_direct_debit/mandate_expire_cron.xml @@ -0,0 +1,26 @@ + + + + + + + + + Set SEPA Direct Debit Mandates to Expired + + + 1 + days + -1 + + + + + + + + diff --git a/account_direct_debit/model/account_move_line.py b/account_direct_debit/model/account_move_line.py index b60a58669..a90c2945a 100644 --- a/account_direct_debit/model/account_move_line.py +++ b/account_direct_debit/model/account_move_line.py @@ -87,6 +87,37 @@ class account_move_line(orm.Model): return [('id', '=', '0')] return [('id', 'in', map(lambda x:x[0], res))] + def line2bank(self, cr, uid, ids, payment_mode_id=None, context=None): + '''I have to inherit this function for direct debits to fix the + following issue : if the customer invoice has a value for + 'partner_bank_id', then it will take this partner_bank_id + in the payment line... but, on a customer invoice, + the partner_bank_id is the bank account of the company, + not the bank account of the customer ! + ''' + if context is None: + context = {} + pay_mode_obj = self.pool['payment.mode'] + payment_mode_id = ( + payment_mode_id or context.get('_fix_payment_mode_id')) + if payment_mode_id: + pay_mode = pay_mode_obj.browse( + cr, uid, payment_mode_id, context=context) + if pay_mode.type.payment_order_type == 'debit': + line2bank = {} + bank_type = pay_mode_obj.suitable_bank_types( + cr, uid, payment_mode_id, context=context) + for line in self.browse(cr, uid, ids, context=context): + line2bank[line.id] = False + if line.partner_id: + for bank in line.partner_id.bank_ids: + if bank.state in bank_type: + line2bank[line.id] = bank.id + break + return line2bank + return super(account_move_line, self).line2bank( + cr, uid, ids, payment_mode_id=payment_mode_id, context=context) + _columns = { 'amount_to_receive': fields.function( amount_to_receive, method=True, From 46fbbebdd894495a7c96e5d398f8b32bd538bf20 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Fri, 8 Nov 2013 19:20:30 +0100 Subject: [PATCH 09/43] Fix a wrong import (osv was used but not imported !) Coding style fix --- account_direct_debit/model/account_invoice.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/account_direct_debit/model/account_invoice.py b/account_direct_debit/model/account_invoice.py index c49db4cd4..b522c45b9 100644 --- a/account_direct_debit/model/account_invoice.py +++ b/account_direct_debit/model/account_invoice.py @@ -22,7 +22,7 @@ # ############################################################################## -from openerp.osv import orm, fields +from openerp.osv import orm from openerp.tools.translate import _ """ @@ -143,11 +143,11 @@ class account_invoice(orm.Model): if self.test_paid(cr, uid, [invoice_id], context): number = self.read( cr, uid, invoice_id, ['number'], context=context)['number'] - raise osv.except_osv( + raise orm.except_orm( _('Error !'), _('You cannot set invoice \'%s\' to state \'debit denied\', ' + 'as it is still reconciled.') % number) - self.write(cr, uid, ids, {'state':'debit_denied'}, context=context) + self.write(cr, uid, ids, {'state': 'debit_denied'}, context=context) for inv_id, name in self.name_get(cr, uid, ids, context=context): message = _("Invoice '%s': direct debit is denied.") % name self.log(cr, uid, inv_id, message) From d8c36c2cef934240eaec7a07e2f1316bd0566c77 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Sat, 9 Nov 2013 15:05:07 +0100 Subject: [PATCH 10/43] Add the ability to cancel a mandate. Add a field "SDD Mandate" on the customer invoice, to handle the scenario where one customer has multiple mandates with the company. --- .../view/payment_order_create_view.xml | 1 + .../__openerp__.py | 1 + .../account_banking_sdd.py | 58 +++++++++++++++---- .../account_banking_sdd_view.xml | 9 ++- .../account_invoice_view.xml | 22 +++++++ 5 files changed, 79 insertions(+), 12 deletions(-) create mode 100644 account_banking_sepa_direct_debit/account_invoice_view.xml diff --git a/account_banking_payment/view/payment_order_create_view.xml b/account_banking_payment/view/payment_order_create_view.xml index bf205e160..8a6d69a47 100644 --- a/account_banking_payment/view/payment_order_create_view.xml +++ b/account_banking_payment/view/payment_order_create_view.xml @@ -14,6 +14,7 @@ {'journal_type': 'sale'} + 1 diff --git a/account_banking_sepa_direct_debit/__openerp__.py b/account_banking_sepa_direct_debit/__openerp__.py index e02e72914..30aef6211 100644 --- a/account_banking_sepa_direct_debit/__openerp__.py +++ b/account_banking_sepa_direct_debit/__openerp__.py @@ -35,6 +35,7 @@ 'account_payment_view.xml', 'company_view.xml', 'mandate_expire_cron.xml', + 'account_invoice_view.xml', 'wizard/export_sdd_view.xml', 'data/payment_type_sdd.xml', 'data/mandate_reference_sequence.xml', diff --git a/account_banking_sepa_direct_debit/account_banking_sdd.py b/account_banking_sepa_direct_debit/account_banking_sdd.py index 33b7d1bd1..dc42188d0 100644 --- a/account_banking_sepa_direct_debit/account_banking_sdd.py +++ b/account_banking_sepa_direct_debit/account_banking_sdd.py @@ -103,6 +103,8 @@ class sdd_mandate(orm.Model): lambda self, cr, uid, obj, ctx=None: obj['state'] == 'valid', 'account_banking_sepa_direct_debit.mandate_expired': lambda self, cr, uid, obj, ctx=None: obj['state'] == 'expired', + 'account_banking_sepa_direct_debit.mandate_cancel': + lambda self, cr, uid, obj, ctx=None: obj['state'] == 'cancel', } } @@ -127,9 +129,9 @@ class sdd_mandate(orm.Model): ('draft', 'Draft'), ('valid', 'Valid'), ('expired', 'Expired'), - # Do we have to handle cancellation of mandate by customer ? + ('cancel', 'Cancelled'), ], 'Mandate Status', - help="For a recurrent mandate, this field indicate if the mandate is still valid or if it has expired (a recurrent mandate expires if it's not used during 36 months). For a one-off mandate, it expires after its first use."), + help="For a recurrent mandate, this field indicate if the mandate is still valid or if it has expired (a recurrent mandate expires if it's not used during 36 months). For a one-off mandate, it expires after its first use."), # TODO : update help 'payment_line_ids': fields.one2many( 'payment.line', 'sdd_mandate_id', "Related Payment Lines"), } @@ -194,6 +196,16 @@ class sdd_mandate(orm.Model): cr, uid, to_validate_ids, {'state': 'valid'}, context=context) return True + def cancel(self, cr, uid, ids, context=None): + to_cancel_ids = [] + for mandate in self.browse(cr, uid, ids, context=context): + assert mandate.state in ('draft', 'valid'),\ + 'Mandate should be in draft or valid state' + to_cancel_ids.append(mandate.id) + self.write( + cr, uid, to_cancel_ids, {'state': 'cancel'}, context=context) + return True + def _sdd_mandate_set_state_to_expired(self, cr, uid, context=None): logger.info('Searching for SDD Mandates that must be set to Expired') expire_limit_date = datetime.today() + \ @@ -232,23 +244,47 @@ class payment_line(orm.Model): _columns = { 'sdd_mandate_id': fields.many2one( - 'sdd.mandate', 'SEPA Direct Debit Mandate'), + 'sdd.mandate', 'SEPA Direct Debit Mandate', + domain=[('state', '=', 'valid')]), } def create(self, cr, uid, vals, context=None): - '''Take the first valid mandate of the bank account by default''' + '''If the customer invoice has a mandate, take it + otherwise, take the first valid mandate of the bank account''' if context is None: context = {} if not vals: vals = {} partner_bank_id = vals.get('bank_id') + move_line_id = vals.get('move_line_id') if (context.get('default_payment_order_type') == 'debit' - and partner_bank_id and 'sdd_mandate_id' not in vals): - mandate_ids = self.pool['sdd.mandate'].search(cr, uid, [ - ('partner_bank_id', '=', partner_bank_id), - ('state', '=', 'valid'), - ], context=context) - if mandate_ids: - vals['sdd_mandate_id'] = mandate_ids[0] + if move_line_id: + line = self.pool['account.move.line'].browse( + cr, uid, move_line_id, context=context) + if (line.invoice and line.invoice.type == 'out_invoice' + and line.invoice.sdd_mandate_id): + vals.update({ + 'sdd_mandate_id': line.invoice.sdd_mandate_id.id, + 'bank_id': + line.invoice.sdd_mandate_id.partner_bank_id.id, + }) + if partner_bank_id and 'sdd_mandate_id' not in vals: + mandate_ids = self.pool['sdd.mandate'].search(cr, uid, [ + ('partner_bank_id', '=', partner_bank_id), + ('state', '=', 'valid'), + ], context=context) + if mandate_ids: + vals['sdd_mandate_id'] = mandate_ids[0] return super(payment_line, self).create(cr, uid, vals, context=context) + + +class account_invoice(orm.Model): + _inherit = 'account.invoice' + + _columns = { + 'sdd_mandate_id': fields.many2one( + 'sdd.mandate', 'SEPA Direct Debit Mandate', + domain=[('state', '=', 'valid')], readonly=True, + states={'draft': [('readonly', False)]}) + } diff --git a/account_banking_sepa_direct_debit/account_banking_sdd_view.xml b/account_banking_sepa_direct_debit/account_banking_sdd_view.xml index 5f191e693..5bb77ecf0 100644 --- a/account_banking_sepa_direct_debit/account_banking_sdd_view.xml +++ b/account_banking_sepa_direct_debit/account_banking_sdd_view.xml @@ -85,6 +85,7 @@
@@ -166,7 +167,7 @@ sequence="20" /> - + Mandate Validated sdd.mandate @@ -181,6 +182,12 @@ SEPA Direct Debit Mandate has Expired + + Mandate Cancelled + sdd.mandate + + SEPA Direct Debit Mandate Cancelled + diff --git a/account_banking_sepa_direct_debit/account_invoice_view.xml b/account_banking_sepa_direct_debit/account_invoice_view.xml new file mode 100644 index 000000000..2ca480e54 --- /dev/null +++ b/account_banking_sepa_direct_debit/account_invoice_view.xml @@ -0,0 +1,22 @@ + + + + + + + add.sdd.mandate.on.customer.invoice.form + account.invoice + + + + + + + + + + From 004832acba2ded9593decb6b06a9666b59a8ae21 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Mon, 11 Nov 2013 02:10:35 +0100 Subject: [PATCH 11/43] New field "recurrent_sequence_type" on mandate with tracking. The field "last_debit_date" is not used to compute the sequence type any more. When the bank account changes, the sequence type is set back to first FIX xml_id of expired mandate mail.message.subtype --- .../account_banking_sdd.py | 63 ++++++++++++++++--- .../account_banking_sdd_view.xml | 33 ++++++++-- .../wizard/export_sdd.py | 57 ++++++++++------- 3 files changed, 117 insertions(+), 36 deletions(-) diff --git a/account_banking_sepa_direct_debit/account_banking_sdd.py b/account_banking_sepa_direct_debit/account_banking_sdd.py index dc42188d0..bfe49d544 100644 --- a/account_banking_sepa_direct_debit/account_banking_sdd.py +++ b/account_banking_sepa_direct_debit/account_banking_sdd.py @@ -105,6 +105,17 @@ class sdd_mandate(orm.Model): lambda self, cr, uid, obj, ctx=None: obj['state'] == 'expired', 'account_banking_sepa_direct_debit.mandate_cancel': lambda self, cr, uid, obj, ctx=None: obj['state'] == 'cancel', + }, + 'recurrent_sequence_type': { + 'account_banking_sepa_direct_debit.recurrent_sequence_type_first': + lambda self, cr, uid, obj, ctx=None: + obj['recurrent_sequence_type'] == 'first', + 'account_banking_sepa_direct_debit.recurrent_sequence_type_recurring': + lambda self, cr, uid, obj, ctx=None: + obj['recurrent_sequence_type'] == 'recurring', + 'account_banking_sepa_direct_debit.recurrent_sequence_type_final': + lambda self, cr, uid, obj, ctx=None: + obj['recurrent_sequence_type'] == 'final', } } @@ -120,17 +131,22 @@ class sdd_mandate(orm.Model): ('recurrent', 'Recurrent'), ('oneoff', 'One-Off'), ], 'Type of Mandate', required=True), + 'recurrent_sequence_type': fields.selection([ + ('first', 'First'), + ('recurring', 'Recurring'), + ('final', 'Final'), + ], 'Sequence Type for Next Debit', + help="This field is only used for Recurrent mandates, not for One-Off mandates."), 'signature_date': fields.date('Date of Signature of the Mandate'), 'scan': fields.binary('Scan of the mandate'), 'last_debit_date': fields.date( - 'Date of the Last Debit', - help="For recurrent mandates, this field is used to know if the SDD will be of type 'First' or 'Recurring'. For one-off mandates, this field is used to know if the SDD has already been used or not."), + 'Date of the Last Debit', readonly=True), 'state': fields.selection([ ('draft', 'Draft'), ('valid', 'Valid'), ('expired', 'Expired'), ('cancel', 'Cancelled'), - ], 'Mandate Status', + ], 'Status', help="For a recurrent mandate, this field indicate if the mandate is still valid or if it has expired (a recurrent mandate expires if it's not used during 36 months). For a one-off mandate, it expires after its first use."), # TODO : update help 'payment_line_ids': fields.one2many( 'payment.line', 'sdd_mandate_id', "Related Payment Lines"), @@ -154,7 +170,8 @@ class sdd_mandate(orm.Model): def _check_sdd_mandate(self, cr, uid, ids, context=None): for mandate in self.read(cr, uid, ids, [ 'last_debit_date', 'signature_date', - 'unique_mandate_reference', 'state', 'partner_bank_id' + 'unique_mandate_reference', 'state', 'partner_bank_id', + 'type', 'recurrent_sequence_type', ], context=context): if (mandate['signature_date'] and mandate['signature_date'] > @@ -171,7 +188,7 @@ class sdd_mandate(orm.Model): if mandate['state'] == 'valid' and not mandate['partner_bank_id']: raise orm.except_orm( _('Error:'), - _("Cannot validate the mandate '%s' because it is not linked to a bank account.") + _("Cannot validate the mandate '%s' because it is not attached to a bank account.") % mandate['unique_mandate_reference']) if (mandate['signature_date'] and mandate['last_debit_date'] and @@ -180,13 +197,45 @@ class sdd_mandate(orm.Model): _('Error:'), _("The mandate '%s' can't have a date of last debit before the date of signature.") % mandate['unique_mandate_reference']) + if (mandate['type'] == 'recurrent' + and not mandate['recurrent_sequence_type']): + raise orm.except_orm( + _('Error:'), + _("The recurrent mandate '%s' must have a sequence type.") + % mandate['unique_mandate_reference']) return True _constraints = [ - (_check_sdd_mandate, "Error msg in raise", - ['last_debit_date', 'signature_date', 'state', 'partner_bank_id']), + (_check_sdd_mandate, "Error msg in raise", [ + 'last_debit_date', 'signature_date', 'state', 'partner_bank_id', + 'type', 'recurrent_sequence_type', + ]), ] + def mandate_type_change(self, cr, uid, ids, type): + if type == 'recurrent': + recurrent_sequence_type = 'first' + else: + recurrent_sequence_type = False + res = {'value': {'recurrent_sequence_type': recurrent_sequence_type}} + return res + + def mandate_partner_bank_change( + self, cr, uid, ids, partner_bank_id, type, recurrent_sequence_type, + last_debit_date, state): + if (state == 'valid' and partner_bank_id + and type == 'recurrent' + and recurrent_sequence_type != 'first'): + return { + 'value': {'recurrent_sequence_type': first}, + 'warning': { + 'title': _('Mandate update'), + 'message': _("As you changed the bank account attached to this mandate, the 'Sequence Type' has been set back to 'First'."), + } + } + else: + return True + def validate(self, cr, uid, ids, context=None): to_validate_ids = [] for mandate in self.browse(cr, uid, ids, context=context): diff --git a/account_banking_sepa_direct_debit/account_banking_sdd_view.xml b/account_banking_sepa_direct_debit/account_banking_sdd_view.xml index 5bb77ecf0..54a5a6669 100644 --- a/account_banking_sepa_direct_debit/account_banking_sdd_view.xml +++ b/account_banking_sepa_direct_debit/account_banking_sdd_view.xml @@ -97,11 +97,12 @@ - + + - + @@ -119,14 +120,14 @@ sdd.mandate.tree sdd.mandate - + - + @@ -139,6 +140,7 @@ + @@ -175,7 +177,7 @@ SEPA Direct Debit Mandate Validated - + Mandate Expired sdd.mandate @@ -189,6 +191,27 @@ SEPA Direct Debit Mandate Cancelled + + Sequence Type set to First + sdd.mandate + + Sequence Type set to First + + + + Sequence Type set to Recurring + sdd.mandate + + Sequence Type set to Recurring + + + + Sequence Type set to Final + sdd.mandate + + Sequence Type set to Final + + sdd.mandate.res.partner.bank.form diff --git a/account_banking_sepa_direct_debit/wizard/export_sdd.py b/account_banking_sepa_direct_debit/wizard/export_sdd.py index df08915bd..60dda58fe 100644 --- a/account_banking_sepa_direct_debit/wizard/export_sdd.py +++ b/account_banking_sepa_direct_debit/wizard/export_sdd.py @@ -233,7 +233,7 @@ class banking_export_sdd_wizard(orm.TransientModel): transactions_count_1_6 = 0 total_amount = 0.0 amount_control_sum_1_7 = 0.0 - first_recur_lines = {} + lines_per_seq_type = {} # key = sequence type ; value = list of lines as objects # Iterate on payment orders for payment_order in sepa_export.payment_order_ids: @@ -253,7 +253,6 @@ class banking_export_sdd_wizard(orm.TransientModel): _("The SEPA Direct Debit mandate with reference '%s' for partner '%s' has expired.") % (line.sdd_mandate_id.unique_mandate_reference, line.sdd_mandate_id.partner_id.name)) - if not line.sdd_mandate_id.signature_date: raise orm.except_orm( _('Error:'), @@ -268,13 +267,12 @@ class banking_export_sdd_wizard(orm.TransientModel): % (line.sdd_mandate_id.unique_mandate_reference, line.sdd_mandate_id.partner_id.name, line.sdd_mandate_id.signature_date)) - if line.sdd_mandate_id.type == 'oneoff': if not line.sdd_mandate_id.last_debit_date: - if first_recur_lines.get('OOFF'): - first_recur_lines['OOFF'].append(line) + if lines_per_seq_type.get('OOFF'): + lines_per_seq_type['OOFF'].append(line) else: - first_recur_lines['OOFF'] = [line] + lines_per_seq_type['OOFF'] = [line] else: raise orm.except_orm( _('Error:'), @@ -283,18 +281,20 @@ class banking_export_sdd_wizard(orm.TransientModel): line.sdd_mandate_id.partner_id.name, line.sdd_mandate_id.last_debit_date)) elif line.sdd_mandate_id.type == 'recurrent': - if line.sdd_mandate_id.last_debit_date: - if first_recur_lines.get('RCUR'): - first_recur_lines['RCUR'].append(line) - else: - first_recur_lines['RCUR'] = [line] + seq_type_map = { + 'recurring': 'RCUR', + 'first': 'FRST', + 'final': 'FNAL', + } + seq_type_label = line.sdd_mandate_id.recurrent_sequence_type + assert seq_type_label is not False + seq_type = seq_type_map[seq_type_label] + if lines_per_seq_type.get(seq_type): + lines_per_seq_type[seq_type].append(line) else: - if first_recur_lines.get('FRST'): - first_recur_lines['FRST'].append(line) - else: - first_recur_lines['FRST'] = [line] + lines_per_seq_type[seq_type] = [line] - for sequence_type, lines in first_recur_lines.items(): + for sequence_type, lines in lines_per_seq_type.items(): # B. Payment info payment_info_2_0 = etree.SubElement(pain_root, 'PmtInf') payment_info_identification_2_1 = etree.SubElement( @@ -516,14 +516,23 @@ class banking_export_sdd_wizard(orm.TransientModel): wf_service.trg_validate(uid, 'payment.order', order.id, 'done', cr) mandate_ids = [line.sdd_mandate_id.id for line in order.line_ids] self.pool['sdd.mandate'].write( - cr, uid, mandate_ids, { - 'last_debit_date': datetime.today().strftime('%Y-%m-%d') - }, + cr, uid, mandate_ids, + {'last_debit_date': datetime.today().strftime('%Y-%m-%d')}, context=context) - oneoff_mandate_ids = \ - [line.sdd_mandate_id.id for line in order.line_ids - if line.sdd_mandate_id.type == 'oneoff'] + to_expire_ids = [] + first_mandate_ids = [] + for line in order.line_ids: + if line.sdd_mandate_id.type == 'oneoff': + to_expire_ids.append(line.sdd_mandate_id.id) + elif line.sdd_mandate_id.type == 'recurrent': + seq_type = line.sdd_mandate_id.recurrent_sequence_type + if seq_type == 'final': + to_expire_ids.append(line.sdd_mandate_id.id) + elif seq_type == 'first': + first_mandate_ids.append(line.sdd_mandate_id.id) self.pool['sdd.mandate'].write( - cr, uid, oneoff_mandate_ids, {'state': 'expired'}, - context=context) + cr, uid, to_expire_ids, {'state': 'expired'}, context=context) + self.pool['sdd.mandate'].write( + cr, uid, first_mandate_ids, + {'recurrent_sequence_type': 'recurring'}, context=context) return {'type': 'ir.actions.act_window_close'} From ad0331ab10312881dfc0f30a5efd04a33ef40914 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Mon, 11 Nov 2013 06:11:26 +0100 Subject: [PATCH 12/43] Now fully manage the scenario where the customer has a new bank account (in the same bank or in another bank) Warning : the signature of the function _prepare_field() has been changed --- .../account_banking_sdd.py | 8 +- .../account_banking_sdd_view.xml | 5 +- .../wizard/export_sdd.py | 118 ++++++++++++++---- 3 files changed, 99 insertions(+), 32 deletions(-) diff --git a/account_banking_sepa_direct_debit/account_banking_sdd.py b/account_banking_sepa_direct_debit/account_banking_sdd.py index bfe49d544..56eb7097a 100644 --- a/account_banking_sepa_direct_debit/account_banking_sdd.py +++ b/account_banking_sepa_direct_debit/account_banking_sdd.py @@ -147,7 +147,7 @@ class sdd_mandate(orm.Model): ('expired', 'Expired'), ('cancel', 'Cancelled'), ], 'Status', - help="For a recurrent mandate, this field indicate if the mandate is still valid or if it has expired (a recurrent mandate expires if it's not used during 36 months). For a one-off mandate, it expires after its first use."), # TODO : update help + help="Only valid mandates can be used in a payment line. A cancelled mandate is a mandate that has been cancelled by the customer. A one-off mandate expires after its first use. A recurrent mandate expires after it's final use or if it hasn't been used for 36 months."), 'payment_line_ids': fields.one2many( 'payment.line', 'sdd_mandate_id', "Related Payment Lines"), } @@ -198,7 +198,7 @@ class sdd_mandate(orm.Model): _("The mandate '%s' can't have a date of last debit before the date of signature.") % mandate['unique_mandate_reference']) if (mandate['type'] == 'recurrent' - and not mandate['recurrent_sequence_type']): + and not mandate['recurrent_sequence_type']): raise orm.except_orm( _('Error:'), _("The recurrent mandate '%s' must have a sequence type.") @@ -227,7 +227,7 @@ class sdd_mandate(orm.Model): and type == 'recurrent' and recurrent_sequence_type != 'first'): return { - 'value': {'recurrent_sequence_type': first}, + 'value': {'recurrent_sequence_type': 'first'}, 'warning': { 'title': _('Mandate update'), 'message': _("As you changed the bank account attached to this mandate, the 'Sequence Type' has been set back to 'First'."), @@ -324,7 +324,7 @@ class payment_line(orm.Model): ('state', '=', 'valid'), ], context=context) if mandate_ids: - vals['sdd_mandate_id'] = mandate_ids[0] + vals['sdd_mandate_id'] = mandate_ids[0] return super(payment_line, self).create(cr, uid, vals, context=context) diff --git a/account_banking_sepa_direct_debit/account_banking_sdd_view.xml b/account_banking_sepa_direct_debit/account_banking_sdd_view.xml index 54a5a6669..cf6c98fb5 100644 --- a/account_banking_sepa_direct_debit/account_banking_sdd_view.xml +++ b/account_banking_sepa_direct_debit/account_banking_sdd_view.xml @@ -102,7 +102,10 @@ - + diff --git a/account_banking_sepa_direct_debit/wizard/export_sdd.py b/account_banking_sepa_direct_debit/wizard/export_sdd.py index 60dda58fe..c217770c1 100644 --- a/account_banking_sepa_direct_debit/wizard/export_sdd.py +++ b/account_banking_sepa_direct_debit/wizard/export_sdd.py @@ -97,14 +97,10 @@ class banking_export_sdd_wizard(orm.TransientModel): cr, uid, vals, context=context) def _prepare_field( - self, cr, uid, field_name, field_value, max_size=0, - sepa_export=False, line=False, sequence_type=False, context=None): + self, cr, uid, field_name, field_value, eval_ctx, max_size=0, + context=None): '''This function is designed to be inherited !''' - eval_ctx = { - 'sepa_export': sepa_export, - 'line': line, - 'sequence_type': sequence_type, - } + assert isinstance(eval_ctx, dict), 'eval_ctx must contain a dict' try: # SEPA uses XML ; XML = UTF-8 ; UTF-8 = support for all characters # But we are dealing with banks... @@ -113,6 +109,7 @@ class banking_export_sdd_wizard(orm.TransientModel): # Customer-to-bank implementation guidelines value = unidecode(safe_eval(field_value, eval_ctx)) except: + line = eval_ctx.get('line') if line: raise orm.except_orm( _('Error:'), @@ -173,6 +170,32 @@ class banking_export_sdd_wizard(orm.TransientModel): % str(e)) return True + def _get_previous_bank(self, cr, uid, payline, context=None): + payline_obj = self.pool['payment.line'] + previous_bank = False + payline_ids = payline_obj.search( + cr, uid, [ + ('sdd_mandate_id', '=', payline.sdd_mandate_id.id), + ('bank_id', '!=', payline.bank_id.id), + ], + context=context) + if payline_ids: + older_lines = payline_obj.browse( + cr, uid, payline_ids, context=context) + previous_date = False + previous_payline_id = False + for older_line in older_lines: + older_line_date_sent = older_line.order_id.date_sent + if (older_line_date_sent + and older_line_date_sent > previous_date): + previous_date = older_line_date_sent + previous_payline_id = older_line.id + if previous_payline_id: + previous_payline = payline_obj.browse( + cr, uid, previous_payline_id, context=context) + previous_bank = previous_payline.bank_id + return previous_bank + def create_sepa(self, cr, uid, ids, context=None): ''' Creates the SEPA Direct Debit file. That's the important code ! @@ -211,7 +234,7 @@ class banking_export_sdd_wizard(orm.TransientModel): my_company_name = self._prepare_field( cr, uid, 'Company Name', 'sepa_export.payment_order_ids[0].company_id.partner_id.name', - name_maxsize, sepa_export=sepa_export, context=context) + {'sepa_export': sepa_export}, name_maxsize, context=context) # A. Group header group_header_1_0 = etree.SubElement(pain_root, 'GrpHdr') @@ -219,8 +242,8 @@ class banking_export_sdd_wizard(orm.TransientModel): group_header_1_0, 'MsgId') message_identification_1_1.text = self._prepare_field( cr, uid, 'Message Identification', - 'sepa_export.payment_order_ids[0].reference', 35, - sepa_export=sepa_export, context=context) + 'sepa_export.payment_order_ids[0].reference', + {'sepa_export': sepa_export}, 35, context=context) creation_date_time_1_2 = etree.SubElement(group_header_1_0, 'CreDtTm') creation_date_time_1_2.text = datetime.strftime( datetime.today(), '%Y-%m-%dT%H:%M:%S') @@ -302,8 +325,8 @@ class banking_export_sdd_wizard(orm.TransientModel): payment_info_identification_2_1.text = self._prepare_field( cr, uid, 'Payment Information Identification', "sequence_type + '-' + sepa_export.payment_order_ids[0].reference", - 35, sepa_export=sepa_export, sequence_type=sequence_type, - context=context) + {'sepa_export': sepa_export, 'sequence_type': sequence_type}, + 35, context=context) payment_method_2_2 = etree.SubElement(payment_info_2_0, 'PmtMtd') payment_method_2_2.text = 'DD' # batch_booking is in "Payment Info" with pain.008.001.02/03 @@ -350,7 +373,7 @@ class banking_export_sdd_wizard(orm.TransientModel): cr, uid, self._prepare_field( cr, uid, 'Company IBAN', 'sepa_export.payment_order_ids[0].mode.bank_id.acc_number', - sepa_export=sepa_export, context=context), + {'sepa_export': sepa_export}, context=context), context=context) creditor_agent_2_21 = etree.SubElement(payment_info_2_0, 'CdtrAgt') @@ -361,7 +384,7 @@ class banking_export_sdd_wizard(orm.TransientModel): creditor_agent_bic.text = self._prepare_field( cr, uid, 'Company BIC', 'sepa_export.payment_order_ids[0].mode.bank_id.bank.bic', - sepa_export=sepa_export, context=context) + {'sepa_export': sepa_export}, context=context) charge_bearer_2_24 = etree.SubElement(payment_info_2_0, 'ChrgBr') charge_bearer_2_24.text = sepa_export.charge_bearer @@ -376,7 +399,7 @@ class banking_export_sdd_wizard(orm.TransientModel): csi_other_id.text = self._prepare_field( cr, uid, 'SEPA Creditor Identifier', 'sepa_export.payment_order_ids[0].company_id.sepa_creditor_identifier', - sepa_export=sepa_export, context=context) + {'sepa_export': sepa_export}, context=context) csi_scheme_name = etree.SubElement(csi_other, 'SchmeNm') csi_scheme_name_proprietary = etree.SubElement( csi_scheme_name, 'Prtry') @@ -394,11 +417,11 @@ class banking_export_sdd_wizard(orm.TransientModel): end2end_identification_2_31 = etree.SubElement( payment_identification_2_29, 'EndToEndId') end2end_identification_2_31.text = self._prepare_field( - cr, uid, 'End to End Identification', 'line.name', 35, - line=line, context=context) + cr, uid, 'End to End Identification', 'line.name', + {'line': line}, 35, context=context) currency_name = self._prepare_field( - cr, uid, 'Currency Code', 'line.currency.name', 3, - line=line, context=context) + cr, uid, 'Currency Code', 'line.currency.name', + {'line': line}, 3, context=context) instructed_amount_2_44 = etree.SubElement( dd_transaction_info_2_28, 'InstdAmt', Ccy=currency_name) instructed_amount_2_44.text = '%.2f' % line.amount_currency @@ -413,15 +436,56 @@ class banking_export_sdd_wizard(orm.TransientModel): mandate_identification_2_48.text = self._prepare_field( cr, uid, 'Unique Mandate Reference', 'line.sdd_mandate_id.unique_mandate_reference', - 35, line=line, context=context) + {'line': line}, 35, context=context) mandate_signature_date_2_49 = etree.SubElement( mandate_related_info_2_47, 'DtOfSgntr') mandate_signature_date_2_49.text = self._prepare_field( cr, uid, 'Mandate Signature Date', - 'line.sdd_mandate_id.signature_date', 10, - line=line, context=context) + 'line.sdd_mandate_id.signature_date', + {'line': line}, 10, context=context) + if (sequence_type == 'FRST' + and line.sdd_mandate_id.last_debit_date): + previous_bank = self._get_previous_bank( + cr, uid, line, context=context) + if previous_bank: + amendment_indicator_2_50 = etree.SubElement( + mandate_related_info_2_47, 'AmdmntInd') + amendment_indicator_2_50.text = 'true' + amendment_info_details_2_51 = etree.SubElement( + mandate_related_info_2_47, 'AmdmntInfDtls') + if previous_bank.bank.bic == line.bank_id.bank.bic: + ori_debtor_account_2_57 = etree.SubElement( + amendment_info_details_2_51, 'OrgnlDbtrAcct') + ori_debtor_account_id = etree.SubElement( + ori_debtor_account_2_57, 'Id') + ori_debtor_account_iban = etree.SubElement( + ori_debtor_account_id, 'IBAN') + ori_debtor_account_iban.text = self._validate_iban( + cr, uid, self._prepare_field( + cr, uid, 'Original Debtor Account', + 'previous_bank.acc_number', + {'previous_bank': previous_bank}, + context=context), + context=context) + else: + ori_debtor_agent_2_58 = etree.SubElement( + amendment_info_details_2_51, 'OrgnlDbtrAgt') + ori_debtor_agent_institution = etree.SubElement( + ori_debtor_agent_2_58, 'FinInstnId') + ori_debtor_agent_bic = etree.SubElement( + ori_debtor_agent_institution, bic_xml_tag) + ori_debtor_agent_bic.text = self._prepare_field( + cr, uid, 'Original Debtor Agent', + 'previous_bank.bank.bic', + {'previous_bank': previous_bank}, + context=context) + ori_debtor_agent_other = etree.SubElement( + ori_debtor_agent_institution, 'Othr') + ori_debtor_agent_other_id = etree.SubElement( + ori_debtor_agent_other, 'Id') + ori_debtor_agent_other_id.text = 'SMNDA' + # SMNDA = Same Mandate New Debtor Agent - # TODO look at 2.50 "Amendment Indicator debtor_agent_2_70 = etree.SubElement( dd_transaction_info_2_28, 'DbtrAgt') debtor_agent_institution = etree.SubElement( @@ -430,13 +494,13 @@ class banking_export_sdd_wizard(orm.TransientModel): debtor_agent_institution, bic_xml_tag) debtor_agent_bic.text = self._prepare_field( cr, uid, 'Customer BIC', 'line.bank_id.bank.bic', - line=line, context=context) + {'line': line}, context=context) debtor_2_72 = etree.SubElement( dd_transaction_info_2_28, 'Dbtr') debtor_name = etree.SubElement(debtor_2_72, 'Nm') debtor_name.text = self._prepare_field( cr, uid, 'Customer Name', 'line.partner_id.name', - name_maxsize, line=line, context=context) + {'line': line}, name_maxsize, context=context) debtor_account_2_73 = etree.SubElement( dd_transaction_info_2_28, 'DbtrAcct') debtor_account_id = etree.SubElement(debtor_account_2_73, 'Id') @@ -445,7 +509,7 @@ class banking_export_sdd_wizard(orm.TransientModel): debtor_account_iban.text = self._validate_iban( cr, uid, self._prepare_field( cr, uid, 'Customer IBAN', - 'line.bank_id.acc_number', line=line, + 'line.bank_id.acc_number', {'line': line}, context=context), context=context) remittance_info_2_88 = etree.SubElement( @@ -455,7 +519,7 @@ class banking_export_sdd_wizard(orm.TransientModel): remittance_info_2_88, 'Ustrd') remittance_info_unstructured_2_89.text = self._prepare_field( cr, uid, 'Remittance Information', 'line.communication', - 140, line=line, context=context) + {'line': line}, 140, context=context) nb_of_transactions_2_4.text = str(transactions_count_2_4) control_sum_2_5.text = '%.2f' % amount_control_sum_2_5 nb_of_transactions_1_6.text = str(transactions_count_1_6) From 37bfc5161b70537a23eecbb4ab9720161d16a400 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Mon, 11 Nov 2013 11:56:49 +0100 Subject: [PATCH 13/43] Add constraint in payment line to check that the mandate is linked to the bank account Fix in mandate views Move mandate and partner views in dedicated files --- .../__openerp__.py | 2 + .../account_banking_sdd.py | 23 +++ .../account_banking_sdd_view.xml | 174 ------------------ .../account_payment_view.xml | 2 +- .../res_partner_bank_view.xml | 48 +++++ .../sdd_mandate_view.xml | 147 +++++++++++++++ 6 files changed, 221 insertions(+), 175 deletions(-) create mode 100644 account_banking_sepa_direct_debit/res_partner_bank_view.xml create mode 100644 account_banking_sepa_direct_debit/sdd_mandate_view.xml diff --git a/account_banking_sepa_direct_debit/__openerp__.py b/account_banking_sepa_direct_debit/__openerp__.py index 30aef6211..1a05f730f 100644 --- a/account_banking_sepa_direct_debit/__openerp__.py +++ b/account_banking_sepa_direct_debit/__openerp__.py @@ -32,6 +32,8 @@ }, 'data': [ 'account_banking_sdd_view.xml', + 'sdd_mandate_view.xml', + 'res_partner_bank_view.xml', 'account_payment_view.xml', 'company_view.xml', 'mandate_expire_cron.xml', diff --git a/account_banking_sepa_direct_debit/account_banking_sdd.py b/account_banking_sepa_direct_debit/account_banking_sdd.py index 56eb7097a..14c01a6c4 100644 --- a/account_banking_sepa_direct_debit/account_banking_sdd.py +++ b/account_banking_sepa_direct_debit/account_banking_sdd.py @@ -327,6 +327,29 @@ class payment_line(orm.Model): vals['sdd_mandate_id'] = mandate_ids[0] return super(payment_line, self).create(cr, uid, vals, context=context) + def _check_mandate_bank_link(self, cr, uid, ids): + for payline in self.browse(cr, uid, ids): + if (payline.sdd_mandate_id and payline.bank_id + and payline.sdd_mandate_id.partner_bank_id.id != + payline.bank_id.id): + raise orm.except_orm( + _('Error:'), + _("The payment line with reference '%s' has a bank account '%s' which is not attached to the mandate '%s' (this mandate is attached to the bank account '%s').") + % (payline.name, + self.pool['res.partner.bank'].name_get( + cr, uid, [payline.bank_id.id])[0][1], + payline.sdd_mandate_id.unique_mandate_reference, + self.pool['res.partner.bank'].name_get( + cr, uid, + [payline.sdd_mandate_id.partner_bank_id.id])[0][1], + )) + return True + + _constraints = [ + (_check_mandate_bank_link, 'Error msg in raise', + ['sdd_mandate_id', 'bank_id']), + ] + class account_invoice(orm.Model): _inherit = 'account.invoice' diff --git a/account_banking_sepa_direct_debit/account_banking_sdd_view.xml b/account_banking_sepa_direct_debit/account_banking_sdd_view.xml index cf6c98fb5..079e2023b 100644 --- a/account_banking_sepa_direct_debit/account_banking_sdd_view.xml +++ b/account_banking_sepa_direct_debit/account_banking_sdd_view.xml @@ -78,179 +78,5 @@ view_mode="tree,form" /> - - sdd.mandate.form - sdd.mandate - - -
-
- -
-

- -

-
- - - - - - - - - - - - - -
-
- - -
- -
-
- - - sdd.mandate.tree - sdd.mandate - - - - - - - - - - - - - - - sdd.mandate.search - sdd.mandate - - - - - - - - - - - - - - - SEPA Direct Debit Mandates - sdd.mandate - form - tree,form - {'sdd_mandate_main_view': True} - -

- Click to create a new SEPA Direct Debit Mandate. -

- The SEPA Direct Debit Mandate is a document signed by your customer that gives you the autorization to do one or several direct debits on his bank account. -

-
-
- - - - - - Mandate Validated - sdd.mandate - - SEPA Direct Debit Mandate Validated - - - - Mandate Expired - sdd.mandate - - SEPA Direct Debit Mandate has Expired - - - - Mandate Cancelled - sdd.mandate - - SEPA Direct Debit Mandate Cancelled - - - - Sequence Type set to First - sdd.mandate - - Sequence Type set to First - - - - Sequence Type set to Recurring - sdd.mandate - - Sequence Type set to Recurring - - - - Sequence Type set to Final - sdd.mandate - - Sequence Type set to Final - - - - - sdd.mandate.res.partner.bank.form - res.partner.bank - - - - - - - - - - - - sdd.mandate.res.partner.bank.tree - res.partner.bank - - - - - - - - - - - sdd.mandate.partner.form - res.partner - - - - - - - -
diff --git a/account_banking_sepa_direct_debit/account_payment_view.xml b/account_banking_sepa_direct_debit/account_payment_view.xml index 795f30222..74098c44e 100644 --- a/account_banking_sepa_direct_debit/account_payment_view.xml +++ b/account_banking_sepa_direct_debit/account_payment_view.xml @@ -13,7 +13,7 @@ - + diff --git a/account_banking_sepa_direct_debit/res_partner_bank_view.xml b/account_banking_sepa_direct_debit/res_partner_bank_view.xml new file mode 100644 index 000000000..0b32e9f1c --- /dev/null +++ b/account_banking_sepa_direct_debit/res_partner_bank_view.xml @@ -0,0 +1,48 @@ + + + + + + + sdd.mandate.res.partner.bank.form + res.partner.bank + + + + + + + + + + + + sdd.mandate.res.partner.bank.tree + res.partner.bank + + + + + + + + + + + sdd.mandate.partner.form + res.partner + + + + + + + + + + diff --git a/account_banking_sepa_direct_debit/sdd_mandate_view.xml b/account_banking_sepa_direct_debit/sdd_mandate_view.xml new file mode 100644 index 000000000..0d73d00f3 --- /dev/null +++ b/account_banking_sepa_direct_debit/sdd_mandate_view.xml @@ -0,0 +1,147 @@ + + + + + + + sdd.mandate.form + sdd.mandate + +
+
+
+ +
+

+ +

+
+ + + + + + + + + + + + + +
+
+ + +
+
+
+
+ + + sdd.mandate.tree + sdd.mandate + + + + + + + + + + + + + + + sdd.mandate.search + sdd.mandate + + + + + + + + + + + + + + + SEPA Direct Debit Mandates + sdd.mandate + form + tree,form + +

+ Click to create a new SEPA Direct Debit Mandate. +

+ The SEPA Direct Debit Mandate is a document signed by your customer that gives you the autorization to do one or several direct debits on his bank account. +

+
+
+ + + + + + Mandate Validated + sdd.mandate + + SEPA Direct Debit Mandate Validated + + + + Mandate Expired + sdd.mandate + + SEPA Direct Debit Mandate has Expired + + + + Mandate Cancelled + sdd.mandate + + SEPA Direct Debit Mandate Cancelled + + + + Sequence Type set to First + sdd.mandate + + Sequence Type set to First + + + + Sequence Type set to Recurring + sdd.mandate + + Sequence Type set to Recurring + + + + Sequence Type set to Final + sdd.mandate + + Sequence Type set to Final + + +
+
From 22310df7e4aee20d37c3a69ba1f0684c4108d5dd Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Mon, 11 Nov 2013 15:51:20 +0100 Subject: [PATCH 14/43] Remove code that is not relevant any more because we now have constraints on the mandates. Update strings. Add French translation. --- .../__openerp__.py | 2 +- .../account_banking_sdd.py | 12 +- .../account_banking_sepa_direct_debit.pot | 883 ++++++++++-------- account_banking_sepa_direct_debit/i18n/fr.po | 652 +++++++++++++ .../sdd_mandate_view.xml | 2 +- .../wizard/export_sdd.py | 24 +- 6 files changed, 1181 insertions(+), 394 deletions(-) create mode 100644 account_banking_sepa_direct_debit/i18n/fr.po diff --git a/account_banking_sepa_direct_debit/__openerp__.py b/account_banking_sepa_direct_debit/__openerp__.py index 1a05f730f..44c744a4a 100644 --- a/account_banking_sepa_direct_debit/__openerp__.py +++ b/account_banking_sepa_direct_debit/__openerp__.py @@ -20,7 +20,7 @@ ############################################################################## { 'name': 'Account Banking SEPA Direct Debit', - 'summary': 'Create SEPA XML files for Direct Debit', + 'summary': 'Create SEPA files for Direct Debit', 'version': '0.1', 'license': 'AGPL-3', 'author': 'Akretion', diff --git a/account_banking_sepa_direct_debit/account_banking_sdd.py b/account_banking_sepa_direct_debit/account_banking_sdd.py index 14c01a6c4..52c3b6f11 100644 --- a/account_banking_sepa_direct_debit/account_banking_sdd.py +++ b/account_banking_sepa_direct_debit/account_banking_sdd.py @@ -65,16 +65,16 @@ class banking_export_sdd(orm.Model): readonly=True), 'batch_booking': fields.boolean( 'Batch Booking', readonly=True, - help="If true, the bank statement will display only one credit line for all the direct debits of the SEPA XML file ; if false, the bank statement will display one credit line per direct debit of the SEPA XML file."), + help="If true, the bank statement will display only one credit line for all the direct debits of the SEPA file ; if false, the bank statement will display one credit line per direct debit of the SEPA file."), 'charge_bearer': fields.selection([ + ('SLEV', 'Following Service Level'), ('SHAR', 'Shared'), ('CRED', 'Borne by Creditor'), ('DEBT', 'Borne by Debtor'), - ('SLEV', 'Following Service Level'), ], 'Charge Bearer', readonly=True, - help='Shared : transaction charges on the sender side are to be borne by the debtor, transaction charges on the receiver side are to be borne by the creditor (most transfers use this). Borne by creditor : all transaction charges are to be borne by the creditor. Borne by debtor : all transaction charges are to be borne by the debtor. Following service level : transaction charges are to be applied following the rules agreed in the service level and/or scheme.'), + help='Following service level : transaction charges are to be applied following the rules agreed in the service level and/or scheme (SEPA Core messages must use this). Shared : transaction charges on the creditor side are to be borne by the creditor, transaction charges on the debtor side are to be borne by the debtor. Borne by creditor : all transaction charges are to be borne by the creditor. Borne by debtor : all transaction charges are to be borne by the debtor.'), 'create_date': fields.datetime('Generation Date', readonly=True), - 'file': fields.binary('SEPA XML File', readonly=True), + 'file': fields.binary('SEPA File', readonly=True), 'filename': fields.function( _generate_filename, type='char', size=256, string='Filename', readonly=True, store=True), @@ -138,7 +138,7 @@ class sdd_mandate(orm.Model): ], 'Sequence Type for Next Debit', help="This field is only used for Recurrent mandates, not for One-Off mandates."), 'signature_date': fields.date('Date of Signature of the Mandate'), - 'scan': fields.binary('Scan of the mandate'), + 'scan': fields.binary('Scan of the Mandate'), 'last_debit_date': fields.date( 'Date of the Last Debit', readonly=True), 'state': fields.selection([ @@ -334,7 +334,7 @@ class payment_line(orm.Model): payline.bank_id.id): raise orm.except_orm( _('Error:'), - _("The payment line with reference '%s' has a bank account '%s' which is not attached to the mandate '%s' (this mandate is attached to the bank account '%s').") + _("The payment line with reference '%s' has the bank account '%s' which is not attached to the mandate '%s' (this mandate is attached to the bank account '%s').") % (payline.name, self.pool['res.partner.bank'].name_get( cr, uid, [payline.bank_id.id])[0][1], diff --git a/account_banking_sepa_direct_debit/i18n/account_banking_sepa_direct_debit.pot b/account_banking_sepa_direct_debit/i18n/account_banking_sepa_direct_debit.pot index 6c772f970..c33a775b4 100644 --- a/account_banking_sepa_direct_debit/i18n/account_banking_sepa_direct_debit.pot +++ b/account_banking_sepa_direct_debit/i18n/account_banking_sepa_direct_debit.pot @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: OpenERP Server 7.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-10-21 21:21+0000\n" -"PO-Revision-Date: 2013-10-21 21:21+0000\n" +"POT-Creation-Date: 2013-11-11 14:28+0000\n" +"PO-Revision-Date: 2013-11-11 14:28+0000\n" "Last-Translator: <>\n" "Language-Team: \n" "MIME-Version: 1.0\n" @@ -16,47 +16,8 @@ msgstr "" "Plural-Forms: \n" #. module: account_banking_sepa_direct_debit -#: field:banking.export.sdd,file:0 -msgid "SEPA XML file" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: field:banking.export.sdd,nb_transactions:0 -#: field:banking.export.sdd.wizard,nb_transactions:0 -msgid "Number of transactions" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:79 -#, python-format -msgid "This IBAN is not valid : %s" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:132 -#, python-format -msgid "Payment Type Code '%s' is not supported. The only Payment Type Code supported for SEPA Direct Debit are 'pain.008.001.02', 'pain.008.001.03' and 'pain.008.001.04'." -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: selection:banking.export.sdd.wizard,state:0 -msgid "Create" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: selection:sdd.mandate,type:0 -msgid "Recurrent" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: field:sdd.mandate,type:0 -msgid "Type of Mandate" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:192 -#, python-format -msgid "Missing signature date on SEPA Direct Debit mandate with reference '%s' for partner '%s'." +#: model:mail.message.subtype,description:account_banking_sepa_direct_debit.mandate_valid +msgid "SEPA Direct Debit Mandate Validated" msgstr "" #. module: account_banking_sepa_direct_debit @@ -66,84 +27,26 @@ msgid "Filename" msgstr "" #. module: account_banking_sepa_direct_debit -#: model:ir.actions.act_window,name:account_banking_sepa_direct_debit.act_banking_export_sdd_payment_order -msgid "Generated SEPA Direct Debit files" +#: field:banking.export.sdd,requested_collec_date:0 +#: field:banking.export.sdd.wizard,requested_collec_date:0 +msgid "Requested Collection Date" msgstr "" #. module: account_banking_sepa_direct_debit -#: field:banking.export.sdd,state:0 -#: field:banking.export.sdd.wizard,state:0 -msgid "State" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: selection:sdd.mandate,state:0 -msgid "Valid" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: selection:banking.export.sdd,state:0 -msgid "Draft" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:185 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:276 #, python-format msgid "The SEPA Direct Debit mandate with reference '%s' for partner '%s' has expired." msgstr "" #. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:100 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:186 #, python-format -msgid "Cannot compute the '%s' of the Payment Line with Invoice Reference '%s'." +msgid "Cannot validate the mandate '%s' without a date of signature." msgstr "" #. module: account_banking_sepa_direct_debit -#: view:res.partner.bank:0 -#: field:res.partner.bank,sdd_mandate_ids:0 -msgid "SEPA Direct Debit Mandates" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: field:banking.export.sdd,total_amount:0 -#: field:banking.export.sdd.wizard,total_amount:0 -msgid "Total amount" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: view:banking.export.sdd:0 -msgid "SEPA Direct Debit" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: view:sdd.mandate:0 -msgid "Type" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: field:banking.export.sdd,generation_date:0 -msgid "Generation date" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: selection:banking.export.sdd,state:0 -msgid "Sent" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: field:sdd.mandate,scan:0 -msgid "Scan of the mandate" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: help:banking.export.sdd.wizard,requested_collec_date:0 -msgid "This is the date on which the collection should be made by the bank. Please keep in mind that banks only execute on working days." -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: model:ir.actions.act_window,name:account_banking_sepa_direct_debit.action_account_banking_sdd -#: model:ir.ui.menu,name:account_banking_sepa_direct_debit.menu_account_banking_sdd -msgid "Generated SEPA Direct Debit XML files" +#: selection:sdd.mandate,recurrent_sequence_type:0 +msgid "Final" msgstr "" #. module: account_banking_sepa_direct_debit @@ -158,14 +61,9 @@ msgid "SDD Mandates" msgstr "" #. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:198 -#, python-format -msgid "The signature date on SEPA Direct Debit mandate with reference '%s' for partner '%s' is '%s', which is in the future !" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: field:res.company,sepa_creditor_identifier:0 -msgid "SEPA Creditor Identifier" +#: constraint:payment.line:0 +#: constraint:sdd.mandate:0 +msgid "Error msg in raise" msgstr "" #. module: account_banking_sepa_direct_debit @@ -173,53 +71,35 @@ msgstr "" msgid "Company" msgstr "" +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,recurrent_sequence_type:0 +msgid "Sequence Type for Next Debit" +msgstr "" + #. module: account_banking_sepa_direct_debit #: selection:banking.export.sdd,charge_bearer:0 #: selection:banking.export.sdd.wizard,charge_bearer:0 -msgid "Shared" +msgid "Borne by Creditor" msgstr "" #. module: account_banking_sepa_direct_debit -#: field:sdd.mandate,unique_mandate_reference:0 -msgid "Unique Mandate Reference" +#: model:ir.actions.act_window,name:account_banking_sepa_direct_debit.sdd_mandate_action +#: model:ir.ui.menu,name:account_banking_sepa_direct_debit.sdd_mandate_menu +#: view:res.partner.bank:0 +#: field:res.partner.bank,sdd_mandate_ids:0 +msgid "SEPA Direct Debit Mandates" msgstr "" #. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:102 -#, python-format -msgid "Cannot compute the '%s'." +#: view:banking.export.sdd.wizard:0 +#: view:sdd.mandate:0 +msgid "Validate" msgstr "" #. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:104 -#, python-format -msgid "The type of the field '%s' is %s. It should be a string or unicode." -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: model:ir.model,name:account_banking_sepa_direct_debit.model_banking_export_sdd -msgid "SEPA Direct Debit export" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: model:ir.model,name:account_banking_sepa_direct_debit.model_payment_line -msgid "Payment Line" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: view:payment.order:0 -msgid "SDD Mandate" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:156 -#, python-format -msgid "The SEPA Direct Debit Mandate '%s' is not related??" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: selection:sdd.mandate,state:0 -msgid "Expired" +#: model:mail.message.subtype,description:account_banking_sepa_direct_debit.recurrent_sequence_type_recurring +#: model:mail.message.subtype,name:account_banking_sepa_direct_debit.recurrent_sequence_type_recurring +msgid "Sequence Type set to Recurring" msgstr "" #. module: account_banking_sepa_direct_debit @@ -228,12 +108,197 @@ msgid "Generate" msgstr "" #. module: account_banking_sepa_direct_debit -#: model:ir.actions.act_window,name:account_banking_sepa_direct_debit.sdd_mandate_action -#: model:ir.model,name:account_banking_sepa_direct_debit.model_sdd_mandate -#: model:ir.ui.menu,name:account_banking_sepa_direct_debit.sdd_mandate_menu -#: field:payment.line,sdd_mandate_id:0 +#: model:mail.message.subtype,description:account_banking_sepa_direct_debit.mandate_cancel +msgid "SEPA Direct Debit Mandate Cancelled" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: selection:banking.export.sdd,charge_bearer:0 +#: selection:banking.export.sdd.wizard,charge_bearer:0 +msgid "Borne by Debtor" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:180 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:185 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:190 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:197 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:203 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:336 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:89 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:115 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:121 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:130 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:168 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:219 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:269 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:275 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:287 +#, python-format +msgid "Error:" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,message_ids:0 +msgid "Messages" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:131 +#, python-format +msgid "The '%s' is empty or 0. It should have a non-null value." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:89 +#, python-format +msgid "This IBAN is not valid : %s" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: model:ir.model,name:account_banking_sepa_direct_debit.model_banking_export_sdd_wizard +msgid "Export SEPA Direct Debit XML file" +msgstr "" + +#. module: account_banking_sepa_direct_debit #: view:sdd.mandate:0 -msgid "SEPA Direct Debit Mandate" +#: selection:sdd.mandate,state:0 +msgid "Cancelled" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:219 +#, python-format +msgid "Payment Type Code '%s' is not supported. The only Payment Type Code supported for SEPA Direct Debit are 'pain.008.001.02', 'pain.008.001.03' and 'pain.008.001.04'." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: help:sdd.mandate,message_unread:0 +msgid "If checked new messages require your attention." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd.wizard,file_id:0 +msgid "SDD File" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: model:mail.message.subtype,description:account_banking_sepa_direct_debit.mandate_expired +msgid "SEPA Direct Debit Mandate has Expired" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: help:banking.export.sdd,charge_bearer:0 +#: help:banking.export.sdd.wizard,charge_bearer:0 +msgid "Following service level : transaction charges are to be applied following the rules agreed in the service level and/or scheme (SEPA Core messages must use this). Shared : transaction charges on the creditor side are to be borne by the creditor, transaction charges on the debtor side are to be borne by the debtor. Borne by creditor : all transaction charges are to be borne by the creditor. Borne by debtor : all transaction charges are to be borne by the debtor." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: view:sdd.mandate:0 +msgid "Reference" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: view:banking.export.sdd:0 +msgid "SEPA Direct Debit" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: view:banking.export.sdd.wizard:0 +msgid "SEPA Direct Debit XML file generation" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: help:sdd.mandate,message_summary:0 +msgid "Holds the Chatter summary (number of messages, ...). This summary is directly in html format in order to be inserted in kanban views." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: help:banking.export.sdd.wizard,requested_collec_date:0 +msgid "This is the date on which you would like the collection to be made by the bank. Please keep in mind that there are minimum delays for SEPA direct debits that depend on the type of mandate and the type of sequence." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: model:ir.model,name:account_banking_sepa_direct_debit.model_payment_line +msgid "Payment Line" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd,create_date:0 +msgid "Generation Date" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:337 +#, python-format +msgid "The payment line with reference '%s' has the bank account '%s' which is not attached to the mandate '%s' (this mandate is attached to the bank account '%s')." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: selection:banking.export.sdd.wizard,state:0 +msgid "Create" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd,nb_transactions:0 +#: field:banking.export.sdd.wizard,nb_transactions:0 +msgid "Number of Transactions" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: view:sdd.mandate:0 +#: selection:sdd.mandate,type:0 +msgid "One-Off" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd,state:0 +#: field:banking.export.sdd.wizard,state:0 +msgid "State" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:204 +#, python-format +msgid "The recurrent mandate '%s' must have a sequence type." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,message_follower_ids:0 +msgid "Followers" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,message_unread:0 +msgid "Unread Messages" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: view:banking.export.sdd:0 +#: field:banking.export.sdd,payment_order_ids:0 +#: field:banking.export.sdd.wizard,payment_order_ids:0 +msgid "Payment Orders" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: view:sdd.mandate:0 +msgid "Type" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: selection:banking.export.sdd,state:0 +msgid "Sent" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: selection:sdd.mandate,recurrent_sequence_type:0 +msgid "Recurring" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:181 +#, python-format +msgid "The date of signature of mandate '%s' is in the future!" msgstr "" #. module: account_banking_sepa_direct_debit @@ -245,78 +310,19 @@ msgid "Enter the Creditor Identifier that has been attributed to your company to "- a country-specific identifier" msgstr "" -#. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:151 -#, python-format -msgid "Missing bank account on the payment line with SEPA Direct Debit Mandate '%s'." -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: view:sdd.mandate:0 -msgid "Status" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:385 -#, python-format -msgid "The generated XML file is not valid against the official XML Schema Definition. The generated XML file and the full error have been written in the server logs. Here is the error, which may give you an idea on the cause of the problem : %s" -msgstr "" - #. module: account_banking_sepa_direct_debit #: sql_constraint:sdd.mandate:0 msgid "A Mandate with the same reference already exists for this company !" msgstr "" #. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:106 -#, python-format -msgid "The '%s' is empty or 0. It should have a non-null value." +#: help:sdd.mandate,state:0 +msgid "Only valid mandates can be used in a payment line. A cancelled mandate is a mandate that has been cancelled by the customer. A one-off mandate expires after its first use. A recurrent mandate expires after it's final use or if it hasn't been used for 36 months." msgstr "" #. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:150 -#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:155 -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:79 -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:100 -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:102 -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:106 -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:132 -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:178 -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:184 -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:191 -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:197 -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:211 -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:385 -#, python-format -msgid "Error:" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: field:sdd.mandate,partner_bank_id:0 -msgid "Bank Account" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: model:ir.model,name:account_banking_sepa_direct_debit.model_res_company -msgid "Companies" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: help:banking.export.sdd,charge_bearer:0 -#: help:banking.export.sdd.wizard,charge_bearer:0 -msgid "Shared : transaction charges on the sender side are to be borne by the debtor, transaction charges on the receiver side are to be borne by the creditor (most transfers use this). Borne by creditor : all transaction charges are to be borne by the creditor. Borne by debtor : all transaction charges are to be borne by the debtor. Following service level : transaction charges are to be applied following the rules agreed in the service level and/or scheme." -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: selection:banking.export.sdd,charge_bearer:0 -#: selection:banking.export.sdd.wizard,charge_bearer:0 -msgid "Borne by creditor" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: field:banking.export.sdd,payment_order_ids:0 -#: field:banking.export.sdd.wizard,payment_order_ids:0 -msgid "Payment orders" +#: help:sdd.mandate,recurrent_sequence_type:0 +msgid "This field is only used for Recurrent mandates, not for One-Off mandates." msgstr "" #. module: account_banking_sepa_direct_debit @@ -324,151 +330,10 @@ msgstr "" msgid "Signature Date" msgstr "" -#. module: account_banking_sepa_direct_debit -#: help:banking.export.sdd,batch_booking:0 -msgid "If true, the bank statement will display only one credit line for all the direct debits of the SEPA XML file ; if false, the bank statement will display one credit line per direct debit of the SEPA XML file." -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: view:banking.export.sdd.wizard:0 -msgid "Processing details" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: field:banking.export.sdd.wizard,file_id:0 -msgid "SDD XML file" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: model:ir.model,name:account_banking_sepa_direct_debit.model_banking_export_sdd_wizard -msgid "Export SEPA Direct Debit XML file" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:104 -#, python-format -msgid "Field type error:" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: model:ir.actions.act_window,help:account_banking_sepa_direct_debit.sdd_mandate_action -msgid "

\n" -" Click to create a new SEPA Direct Debit Mandate.\n" -"

\n" -" The SEPA Direct Debit Mandate is a document signed by your customer that gives you the autorization to do one or several direct debits on his bank account.\n" -"

\n" -" " -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: selection:sdd.mandate,type:0 -msgid "One-Off" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:179 -#, python-format -msgid "Missing SEPA Direct Debit mandate on the payment line with partner '%s' and Invoice ref '%s'." -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: view:banking.export.sdd.wizard:0 -msgid "Validate" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:212 -#, python-format -msgid "The mandate with reference '%s' for partner '%s' has type set to 'One-Off' and it has a last debit date set to '%s', so we can't use it." -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: help:sdd.mandate,last_debit_date:0 -msgid "For recurrent mandates, this field is used to know if the SDD will be of type 'First' or 'Recurring'. For one-off mandates, this field is used to know if the SDD has already been used or not." -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: field:sdd.mandate,signature_date:0 -msgid "Date of Signature of the Mandate" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: field:sdd.mandate,last_debit_date:0 -msgid "Date of the Last Debit" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: view:sdd.mandate:0 -msgid "Reference" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: constraint:res.company:0 -msgid "Invalid SEPA Creditor Identifier." -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: field:banking.export.sdd,requested_collec_date:0 -#: field:banking.export.sdd.wizard,requested_collec_date:0 -msgid "Requested collection date" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: selection:banking.export.sdd,charge_bearer:0 -#: selection:banking.export.sdd.wizard,charge_bearer:0 -msgid "Borne by debtor" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: model:ir.model,name:account_banking_sepa_direct_debit.model_res_partner_bank -msgid "Bank Accounts" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: selection:banking.export.sdd,charge_bearer:0 -#: selection:banking.export.sdd.wizard,charge_bearer:0 -msgid "Following service level" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: view:banking.export.sdd:0 -msgid "Payment Orders" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: view:banking.export.sdd.wizard:0 -msgid "SEPA Direct Debit XML file generation" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: view:banking.export.sdd:0 -msgid "General Information" -msgstr "" - #. module: account_banking_sepa_direct_debit #: field:banking.export.sdd,charge_bearer:0 #: field:banking.export.sdd.wizard,charge_bearer:0 -msgid "Charge bearer" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: field:sdd.mandate,state:0 -msgid "Mandate Status" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: help:banking.export.sdd.wizard,batch_booking:0 -msgid "If true, the bank statement will display only one debit line for all the wire transfers of the SEPA XML file ; if false, the bank statement will display one debit line per wire transfer of the SEPA XML file." -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: field:banking.export.sdd.wizard,file:0 -msgid "File" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: view:banking.export.sdd.wizard:0 -msgid "Cancel" +msgid "Charge Bearer" msgstr "" #. module: account_banking_sepa_direct_debit @@ -477,14 +342,31 @@ msgid "Partner" msgstr "" #. module: account_banking_sepa_direct_debit -#: help:sdd.mandate,state:0 -msgid "For a recurrent mandate, this field indicate if the mandate is still valid or if it has expired (a recurrent mandate expires if it's not used during 36 months). For a one-off mandate, it expires after its first use." +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:125 +#, python-format +msgid "Field type error:" msgstr "" #. module: account_banking_sepa_direct_debit -#: field:banking.export.sdd,batch_booking:0 -#: field:banking.export.sdd.wizard,batch_booking:0 -msgid "Batch booking" +#: selection:sdd.mandate,recurrent_sequence_type:0 +msgid "First" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,signature_date:0 +msgid "Date of Signature of the Mandate" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: model:mail.message.subtype,name:account_banking_sepa_direct_debit.mandate_cancel +msgid "Mandate Cancelled" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: model:ir.actions.act_window,name:account_banking_sepa_direct_debit.act_banking_export_sdd_payment_order +#: model:ir.actions.act_window,name:account_banking_sepa_direct_debit.action_account_banking_sdd +#: model:ir.ui.menu,name:account_banking_sepa_direct_debit.menu_account_banking_sdd +msgid "Generated SEPA Direct Debit Files" msgstr "" #. module: account_banking_sepa_direct_debit @@ -492,3 +374,270 @@ msgstr "" msgid "Reconciled" msgstr "" +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:191 +#, python-format +msgid "Cannot validate the mandate '%s' because it is not attached to a bank account." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: selection:banking.export.sdd,state:0 +#: view:sdd.mandate:0 +#: selection:sdd.mandate,state:0 +msgid "Draft" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:232 +#, python-format +msgid "Mandate update" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:116 +#, python-format +msgid "Cannot compute the '%s' of the Payment Line with Invoice Reference '%s'." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: selection:banking.export.sdd,charge_bearer:0 +#: selection:banking.export.sdd.wizard,charge_bearer:0 +msgid "Shared" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd,batch_booking:0 +#: field:banking.export.sdd.wizard,batch_booking:0 +msgid "Batch Booking" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,state:0 +msgid "Status" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd,total_amount:0 +#: field:banking.export.sdd.wizard,total_amount:0 +msgid "Total Amount" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: help:banking.export.sdd,batch_booking:0 +#: help:banking.export.sdd.wizard,batch_booking:0 +msgid "If true, the bank statement will display only one credit line for all the direct debits of the SEPA file ; if false, the bank statement will display one credit line per direct debit of the SEPA file." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: selection:banking.export.sdd,charge_bearer:0 +#: selection:banking.export.sdd.wizard,charge_bearer:0 +msgid "Following Service Level" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:198 +#, python-format +msgid "The mandate '%s' can't have a date of last debit before the date of signature." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: model:mail.message.subtype,description:account_banking_sepa_direct_debit.recurrent_sequence_type_final +#: model:mail.message.subtype,name:account_banking_sepa_direct_debit.recurrent_sequence_type_final +msgid "Sequence Type set to Final" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,message_is_follower:0 +msgid "Is a Follower" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: view:payment.order:0 +msgid "SDD Mandate" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: model:ir.model,name:account_banking_sepa_direct_debit.model_res_company +msgid "Companies" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,message_summary:0 +msgid "Summary" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:account.invoice,sdd_mandate_id:0 +#: model:ir.model,name:account_banking_sepa_direct_debit.model_sdd_mandate +#: field:payment.line,sdd_mandate_id:0 +#: view:sdd.mandate:0 +msgid "SEPA Direct Debit Mandate" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:270 +#, python-format +msgid "Missing SEPA Direct Debit mandate on the payment line with partner '%s' and Invoice ref '%s'." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:288 +#, python-format +msgid "The mandate with reference '%s' for partner '%s' has type set to 'One-Off' and it has a last debit date set to '%s', so we can't use it." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,scan:0 +msgid "Scan of the Mandate" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,last_debit_date:0 +msgid "Date of the Last Debit" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: model:mail.message.subtype,name:account_banking_sepa_direct_debit.mandate_expired +msgid "Mandate Expired" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: constraint:res.company:0 +msgid "Invalid SEPA Creditor Identifier." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: model:ir.model,name:account_banking_sepa_direct_debit.model_res_partner_bank +msgid "Bank Accounts" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: model:ir.actions.act_window,help:account_banking_sepa_direct_debit.sdd_mandate_action +msgid "

\n" +" Click to create a new SEPA Direct Debit Mandate.\n" +"

\n" +" A SEPA Direct Debit Mandate is a document signed by your customer that gives you the autorization to do one or several direct debits on his bank account.\n" +"

\n" +" " +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: view:banking.export.sdd:0 +msgid "General Information" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: view:sdd.mandate:0 +#: selection:sdd.mandate,state:0 +msgid "Valid" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: model:ir.model,name:account_banking_sepa_direct_debit.model_account_invoice +msgid "Invoice" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: view:banking.export.sdd.wizard:0 +#: view:sdd.mandate:0 +msgid "Cancel" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: view:sdd.mandate:0 +#: field:sdd.mandate,payment_line_ids:0 +msgid "Related Payment Lines" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:169 +#, python-format +msgid "The generated XML file is not valid against the official XML Schema Definition. The generated XML file and the full error have been written in the server logs. Here is the error, which may give you an idea on the cause of the problem : %s" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: view:sdd.mandate:0 +#: selection:sdd.mandate,type:0 +msgid "Recurrent" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,type:0 +msgid "Type of Mandate" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: model:mail.message.subtype,name:account_banking_sepa_direct_debit.mandate_valid +msgid "Mandate Validated" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd,file:0 +msgid "SEPA File" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:res.company,sepa_creditor_identifier:0 +msgid "SEPA Creditor Identifier" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:122 +#, python-format +msgid "Cannot compute the '%s'." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:126 +#, python-format +msgid "The type of the field '%s' is %s. It should be a string or unicode." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: model:ir.model,name:account_banking_sepa_direct_debit.model_banking_export_sdd +msgid "SEPA Direct Debit export" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: view:sdd.mandate:0 +#: selection:sdd.mandate,state:0 +msgid "Expired" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,partner_bank_id:0 +msgid "Bank Account" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: model:mail.message.subtype,description:account_banking_sepa_direct_debit.recurrent_sequence_type_first +#: model:mail.message.subtype,name:account_banking_sepa_direct_debit.recurrent_sequence_type_first +msgid "Sequence Type set to First" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:233 +#, python-format +msgid "As you changed the bank account attached to this mandate, the 'Sequence Type' has been set back to 'First'." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: help:sdd.mandate,message_ids:0 +msgid "Messages and communication history" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: view:sdd.mandate:0 +msgid "Search SEPA Direct Debit Mandates" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,unique_mandate_reference:0 +msgid "Unique Mandate Reference" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd.wizard,file:0 +msgid "File" +msgstr "" + diff --git a/account_banking_sepa_direct_debit/i18n/fr.po b/account_banking_sepa_direct_debit/i18n/fr.po new file mode 100644 index 000000000..c823791c8 --- /dev/null +++ b/account_banking_sepa_direct_debit/i18n/fr.po @@ -0,0 +1,652 @@ +# Translation of OpenERP Server. +# This file contains the translation of the following modules: +# * account_banking_sepa_direct_debit +# +msgid "" +msgstr "" +"Project-Id-Version: OpenERP Server 7.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-11-11 14:04+0000\n" +"PO-Revision-Date: 2013-11-11 14:04+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: account_banking_sepa_direct_debit +#: model:mail.message.subtype,description:account_banking_sepa_direct_debit.mandate_valid +msgid "SEPA Direct Debit Mandate Validated" +msgstr "Mandat de prélèvement SEPA validé" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd,filename:0 +#: field:banking.export.sdd.wizard,filename:0 +msgid "Filename" +msgstr "Nom du fichier" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd,requested_collec_date:0 +#: field:banking.export.sdd.wizard,requested_collec_date:0 +msgid "Requested Collection Date" +msgstr "Date de collecte demandée" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:276 +#, python-format +msgid "The SEPA Direct Debit mandate with reference '%s' for partner '%s' has expired." +msgstr "Le mandat de prélèvement SEPA portant la référence '%s' pour le partenaire '%s' a expiré." + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:186 +#, python-format +msgid "Cannot validate the mandate '%s' without a date of signature." +msgstr "Impossible de valider le mandat '%s' sans date de signature." + +#. module: account_banking_sepa_direct_debit +#: selection:sdd.mandate,recurrent_sequence_type:0 +msgid "Final" +msgstr "Final" + +#. module: account_banking_sepa_direct_debit +#: selection:banking.export.sdd.wizard,state:0 +msgid "Finish" +msgstr "Finir" + +#. module: account_banking_sepa_direct_debit +#: view:res.partner:0 +#: view:res.partner.bank:0 +msgid "SDD Mandates" +msgstr "Mandats SEPA" + +#. module: account_banking_sepa_direct_debit +#: constraint:payment.line:0 +#: constraint:sdd.mandate:0 +msgid "Error msg in raise" +msgstr "Error msg in raise" + +#. module: account_banking_sepa_direct_debit +#: selection:banking.export.sdd,state:0 +msgid "Reconciled" +msgstr "Réconcilié" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,recurrent_sequence_type:0 +msgid "Sequence Type for Next Debit" +msgstr "Type de séquence pour le prochain prélèvement" + +#. module: account_banking_sepa_direct_debit +#: selection:banking.export.sdd,charge_bearer:0 +#: selection:banking.export.sdd.wizard,charge_bearer:0 +msgid "Borne by Creditor" +msgstr "Supportés par le créancier" + +#. module: account_banking_sepa_direct_debit +#: model:ir.actions.act_window,name:account_banking_sepa_direct_debit.sdd_mandate_action +#: model:ir.ui.menu,name:account_banking_sepa_direct_debit.sdd_mandate_menu +#: view:res.partner.bank:0 +#: field:res.partner.bank,sdd_mandate_ids:0 +msgid "SEPA Direct Debit Mandates" +msgstr "Mandats de prélèvement SEPA" + +#. module: account_banking_sepa_direct_debit +#: view:banking.export.sdd.wizard:0 +#: view:sdd.mandate:0 +msgid "Validate" +msgstr "Valider" + +#. module: account_banking_sepa_direct_debit +#: model:mail.message.subtype,description:account_banking_sepa_direct_debit.recurrent_sequence_type_recurring +#: model:mail.message.subtype,name:account_banking_sepa_direct_debit.recurrent_sequence_type_recurring +msgid "Sequence Type set to Recurring" +msgstr "Type de séquence mis à Recurring" + +#. module: account_banking_sepa_direct_debit +#: view:banking.export.sdd.wizard:0 +msgid "Generate" +msgstr "Générer" + +#. module: account_banking_sepa_direct_debit +#: model:mail.message.subtype,description:account_banking_sepa_direct_debit.mandate_cancel +msgid "SEPA Direct Debit Mandate Cancelled" +msgstr "Mandat de prélèvement SEPA annulé" + +#. module: account_banking_sepa_direct_debit +#: selection:banking.export.sdd,charge_bearer:0 +#: selection:banking.export.sdd.wizard,charge_bearer:0 +msgid "Borne by Debtor" +msgstr "Supportés par le débiteur" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:180 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:185 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:190 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:197 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:203 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:336 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:89 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:115 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:121 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:130 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:168 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:219 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:269 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:275 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:287 +#, python-format +msgid "Error:" +msgstr "Erreur :" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,message_ids:0 +msgid "Messages" +msgstr "Messages" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:131 +#, python-format +msgid "The '%s' is empty or 0. It should have a non-null value." +msgstr "Le champ '%s' est vide ou nul. Il doit avoir une valeur non nulle." + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:89 +#, python-format +msgid "This IBAN is not valid : %s" +msgstr "Cet IBAN n'est pas valide : %s" + +#. module: account_banking_sepa_direct_debit +#: model:ir.model,name:account_banking_sepa_direct_debit.model_banking_export_sdd_wizard +msgid "Export SEPA Direct Debit XML file" +msgstr "Export des fichiers de prélèvement SEPA" + +#. module: account_banking_sepa_direct_debit +#: view:sdd.mandate:0 +#: selection:sdd.mandate,state:0 +msgid "Cancelled" +msgstr "Annulé" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:219 +#, python-format +msgid "Payment Type Code '%s' is not supported. The only Payment Type Code supported for SEPA Direct Debit are 'pain.008.001.02', 'pain.008.001.03' and 'pain.008.001.04'." +msgstr "Le code du Type de paiement '%s' n'est pas supporté. Les seuls codes de Type de paiement supportés pour les prélèvements SEPA sont 'pain.008.001.02', 'pain.008.001.03' et 'pain.008.001.04'." + +#. module: account_banking_sepa_direct_debit +#: help:sdd.mandate,message_unread:0 +msgid "If checked new messages require your attention." +msgstr "If checked new messages require your attention." + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd.wizard,file_id:0 +msgid "SDD File" +msgstr "Fichier de prélèvement SEPA" + +#. module: account_banking_sepa_direct_debit +#: model:mail.message.subtype,description:account_banking_sepa_direct_debit.mandate_expired +msgid "SEPA Direct Debit Mandate has Expired" +msgstr "Le mandat de prélèvement SEPA a expiré" + +#. module: account_banking_sepa_direct_debit +#: help:banking.export.sdd,charge_bearer:0 +#: help:banking.export.sdd.wizard,charge_bearer:0 +msgid "Following service level : transaction charges are to be applied following the rules agreed in the service level and/or scheme (SEPA Core messages must use this). Shared : transaction charges on the creditor side are to be borne by the creditor, transaction charges on the debtor side are to be borne by the debtor. Borne by creditor : all transaction charges are to be borne by the creditor. Borne by debtor : all transaction charges are to be borne by the debtor." +msgstr "Suivant le niveau de service : la répartition des frais bancaires suit les règles pré-établies dans le schema ou dans le contrat avec la banque (les messages SEPA Core doivent utiliser ce paramètre). Partagés : les frais bancaires côté débiteur sont à la charge du débiteur, les frais bancaires côté créditeur sont à la charge du créditeur. Supportés par le créancier : tous les frais bancaires sont à la charge du créancier. Supportés par le débiteur : tous les frais bancaires sont à la charge du débiteur." + +#. module: account_banking_sepa_direct_debit +#: view:sdd.mandate:0 +msgid "Reference" +msgstr "Référence" + +#. module: account_banking_sepa_direct_debit +#: view:banking.export.sdd:0 +msgid "SEPA Direct Debit" +msgstr "Prélèvement SEPA" + +#. module: account_banking_sepa_direct_debit +#: view:banking.export.sdd.wizard:0 +msgid "SEPA Direct Debit XML file generation" +msgstr "Génération de fichiers de prélèvement SEPA XML" + +#. module: account_banking_sepa_direct_debit +#: help:sdd.mandate,message_summary:0 +msgid "Holds the Chatter summary (number of messages, ...). This summary is directly in html format in order to be inserted in kanban views." +msgstr "Holds the Chatter summary (number of messages, ...). This summary is directly in html format in order to be inserted in kanban views." + +#. module: account_banking_sepa_direct_debit +#: model:ir.model,name:account_banking_sepa_direct_debit.model_payment_line +msgid "Payment Line" +msgstr "Ligne de paiement" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd,create_date:0 +msgid "Generation Date" +msgstr "Date de génération" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:337 +#, python-format +msgid "The payment line with reference '%s' has the bank account '%s' which is not attached to the mandate '%s' (this mandate is attached to the bank account '%s')." +msgstr "La ligne de paiement portant la référence '%s' est configurée avec le compte bancaire '%s' qui n'est pas rattaché au mandat '%s' (ce mandat est rattaché au compte bancaire '%s')." + +#. module: account_banking_sepa_direct_debit +#: selection:banking.export.sdd.wizard,state:0 +msgid "Create" +msgstr "Créer" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd,nb_transactions:0 +#: field:banking.export.sdd.wizard,nb_transactions:0 +msgid "Number of Transactions" +msgstr "Nombre de transactions" + +#. module: account_banking_sepa_direct_debit +#: view:sdd.mandate:0 +#: selection:sdd.mandate,type:0 +msgid "One-Off" +msgstr "One-Off" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd,state:0 +#: field:banking.export.sdd.wizard,state:0 +msgid "State" +msgstr "État" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:204 +#, python-format +msgid "The recurrent mandate '%s' must have a sequence type." +msgstr "Le mandat récurrent '%s' doit avoir un type de séquence." + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,message_follower_ids:0 +msgid "Followers" +msgstr "Followers" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,message_unread:0 +msgid "Unread Messages" +msgstr "Unread Messages" + +#. module: account_banking_sepa_direct_debit +#: view:banking.export.sdd:0 +#: field:banking.export.sdd,payment_order_ids:0 +#: field:banking.export.sdd.wizard,payment_order_ids:0 +msgid "Payment Orders" +msgstr "Ordres de paiement" + +#. module: account_banking_sepa_direct_debit +#: view:sdd.mandate:0 +msgid "Type" +msgstr "Type" + +#. module: account_banking_sepa_direct_debit +#: selection:banking.export.sdd,state:0 +msgid "Sent" +msgstr "Envoyé" + +#. module: account_banking_sepa_direct_debit +#: selection:sdd.mandate,recurrent_sequence_type:0 +msgid "Recurring" +msgstr "Recurring" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:181 +#, python-format +msgid "The date of signature of mandate '%s' is in the future!" +msgstr "La date de signature du mandat '%s' est dans le futur !" + +#. module: account_banking_sepa_direct_debit +#: help:res.company,sepa_creditor_identifier:0 +msgid "Enter the Creditor Identifier that has been attributed to your company to make SEPA Direct Debits. This identifier is composed of :\n" +"- your country ISO code (2 letters)\n" +"- a 2-digits checkum\n" +"- a 3-letters business code\n" +"- a country-specific identifier" +msgstr "Entrez l'Identifiant créancier qui a été attribué à votre société pour réaliser des prélèvements SEPA. Cet identifiant est composé de :\n" +"- du code ISO de votre pays (2 lettres)\n" +"- un code de contrôle à 2 chiffres\n" +"- un code d'activité à 3 lettres\n" +"- un identifiant national" + +#. module: account_banking_sepa_direct_debit +#: sql_constraint:sdd.mandate:0 +msgid "A Mandate with the same reference already exists for this company !" +msgstr "Un mandat avec la même référence existe déjà pour cette société !" + +#. module: account_banking_sepa_direct_debit +#: help:sdd.mandate,state:0 +msgid "Only valid mandates can be used in a payment line. A cancelled mandate is a mandate that has been cancelled by the customer. A one-off mandate expires after its first use. A recurrent mandate expires after it's final use or if it hasn't been used for 36 months." +msgstr "Seuls des mandats valides peuvent être utilisés dans une ligne de paiement. Un mandate annulé est un mandat qui a été annulé par le client. Un mandat One-Off expire à l'issue de sa première utilisation. Un mandate récurrent expire après sa dernière utilisation ou si il n'a pas été utilisé pendant 36 mois." + +#. module: account_banking_sepa_direct_debit +#: help:sdd.mandate,recurrent_sequence_type:0 +msgid "This field is only used for Recurrent mandates, not for One-Off mandates." +msgstr "Ce champ n'est utilisé que pour les mandats récurrents, pas pour les mandats One-Off." + +#. module: account_banking_sepa_direct_debit +#: view:sdd.mandate:0 +msgid "Signature Date" +msgstr "Date de signature" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd,charge_bearer:0 +#: field:banking.export.sdd.wizard,charge_bearer:0 +msgid "Charge Bearer" +msgstr "Répartition des frais" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,partner_id:0 +msgid "Partner" +msgstr "Partenaire" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:125 +#, python-format +msgid "Field type error:" +msgstr "Erreur de type de champ :" + +#. module: account_banking_sepa_direct_debit +#: selection:sdd.mandate,recurrent_sequence_type:0 +msgid "First" +msgstr "First" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,signature_date:0 +msgid "Date of Signature of the Mandate" +msgstr "Date de signature du mandat" + +#. module: account_banking_sepa_direct_debit +#: model:mail.message.subtype,name:account_banking_sepa_direct_debit.mandate_cancel +msgid "Mandate Cancelled" +msgstr "Mandat annulé" + +#. module: account_banking_sepa_direct_debit +#: model:ir.actions.act_window,name:account_banking_sepa_direct_debit.act_banking_export_sdd_payment_order +#: model:ir.actions.act_window,name:account_banking_sepa_direct_debit.action_account_banking_sdd +#: model:ir.ui.menu,name:account_banking_sepa_direct_debit.menu_account_banking_sdd +msgid "Generated SEPA Direct Debit Files" +msgstr "Fichiers de prélèvement SEPA générés" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,company_id:0 +msgid "Company" +msgstr "Société" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:191 +#, python-format +msgid "Cannot validate the mandate '%s' because it is not attached to a bank account." +msgstr "Impossible de valider le mandat '%s' car il n'est pas rattaché à un compte bancaire." + +#. module: account_banking_sepa_direct_debit +#: selection:banking.export.sdd,state:0 +#: view:sdd.mandate:0 +#: selection:sdd.mandate,state:0 +msgid "Draft" +msgstr "Brouillon" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:232 +#, python-format +msgid "Mandate update" +msgstr "Mise-à-jour du mandat" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:116 +#, python-format +msgid "Cannot compute the '%s' of the Payment Line with Invoice Reference '%s'." +msgstr "Impossible de générer le '%s' de la ligne de paiement ayant la référence de facture '%s'." + +#. module: account_banking_sepa_direct_debit +#: selection:banking.export.sdd,charge_bearer:0 +#: selection:banking.export.sdd.wizard,charge_bearer:0 +msgid "Shared" +msgstr "Partagée" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd,batch_booking:0 +#: field:banking.export.sdd.wizard,batch_booking:0 +msgid "Batch Booking" +msgstr "Crédit groupé" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,state:0 +msgid "Status" +msgstr "Statut" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd,total_amount:0 +#: field:banking.export.sdd.wizard,total_amount:0 +msgid "Total Amount" +msgstr "Montant total" + +#. module: account_banking_sepa_direct_debit +#: help:banking.export.sdd,batch_booking:0 +#: help:banking.export.sdd.wizard,batch_booking:0 +msgid "If true, the bank statement will display only one credit line for all the direct debits of the SEPA file ; if false, the bank statement will display one credit line per direct debit of the SEPA file." +msgstr "Si activé, le relevé de compte ne fera apparaître qu'une ligne de crédit pour tous les prélèvements du fichier SEPA ; si désactivé, le relevé de banque fera apparaître une ligne de crédit pour chaque prélèvement du fichier SEPA." + +#. module: account_banking_sepa_direct_debit +#: selection:banking.export.sdd,charge_bearer:0 +#: selection:banking.export.sdd.wizard,charge_bearer:0 +msgid "Following Service Level" +msgstr "Suivant le niveau de service" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:198 +#, python-format +msgid "The mandate '%s' can't have a date of last debit before the date of signature." +msgstr "Le mandat '%s' ne peut pas avoir une date de dernier débit antérieure à la date de signature." + +#. module: account_banking_sepa_direct_debit +#: model:mail.message.subtype,description:account_banking_sepa_direct_debit.recurrent_sequence_type_final +#: model:mail.message.subtype,name:account_banking_sepa_direct_debit.recurrent_sequence_type_final +msgid "Sequence Type set to Final" +msgstr "Type de Séquence mis à Final" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,message_is_follower:0 +msgid "Is a Follower" +msgstr "Is a Follower" + +#. module: account_banking_sepa_direct_debit +#: view:payment.order:0 +msgid "SDD Mandate" +msgstr "Mandat de prélèvement" + +#. module: account_banking_sepa_direct_debit +#: model:ir.model,name:account_banking_sepa_direct_debit.model_res_company +msgid "Companies" +msgstr "Sociétés" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,message_summary:0 +msgid "Summary" +msgstr "Résumé" + +#. module: account_banking_sepa_direct_debit +#: field:account.invoice,sdd_mandate_id:0 +#: model:ir.model,name:account_banking_sepa_direct_debit.model_sdd_mandate +#: field:payment.line,sdd_mandate_id:0 +#: view:sdd.mandate:0 +msgid "SEPA Direct Debit Mandate" +msgstr "Mandat de prélèvement SEPA" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:270 +#, python-format +msgid "Missing SEPA Direct Debit mandate on the payment line with partner '%s' and Invoice ref '%s'." +msgstr "Mandat de prélèvement SEPA manquant sur la ligne de paiement ayant pour partenaire '%s' et pour référence de facture '%s'." + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:288 +#, python-format +msgid "The mandate with reference '%s' for partner '%s' has type set to 'One-Off' and it has a last debit date set to '%s', so we can't use it." +msgstr "Le mandat portant la référence '%s' pour le partenaire '%s' est de type 'One-Off' et il a une date de dernier débit au '%s', donc il n'est pas utilisable." + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,scan:0 +msgid "Scan of the Mandate" +msgstr "Scan du mandat" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,last_debit_date:0 +msgid "Date of the Last Debit" +msgstr "Date du dernier prélèvement" + +#. module: account_banking_sepa_direct_debit +#: model:mail.message.subtype,name:account_banking_sepa_direct_debit.mandate_expired +msgid "Mandate Expired" +msgstr "Mandat expiré" + +#. module: account_banking_sepa_direct_debit +#: constraint:res.company:0 +msgid "Invalid SEPA Creditor Identifier." +msgstr "Identifiant créancier SEPA invalide." + +#. module: account_banking_sepa_direct_debit +#: model:ir.model,name:account_banking_sepa_direct_debit.model_res_partner_bank +msgid "Bank Accounts" +msgstr "Comptes bancaires" + +#. module: account_banking_sepa_direct_debit +#: view:banking.export.sdd:0 +msgid "General Information" +msgstr "Informations générales" + +#. module: account_banking_sepa_direct_debit +#: view:sdd.mandate:0 +#: selection:sdd.mandate,state:0 +msgid "Valid" +msgstr "Valide" + +#. module: account_banking_sepa_direct_debit +#: model:ir.model,name:account_banking_sepa_direct_debit.model_account_invoice +msgid "Invoice" +msgstr "Facture" + +#. module: account_banking_sepa_direct_debit +#: view:banking.export.sdd.wizard:0 +#: view:sdd.mandate:0 +msgid "Cancel" +msgstr "Annuler" + +#. module: account_banking_sepa_direct_debit +#: view:sdd.mandate:0 +#: field:sdd.mandate,payment_line_ids:0 +msgid "Related Payment Lines" +msgstr "Lignes de paiement associées" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:169 +#, python-format +msgid "The generated XML file is not valid against the official XML Schema Definition. The generated XML file and the full error have been written in the server logs. Here is the error, which may give you an idea on the cause of the problem : %s" +msgstr "Le fichier XML généré n'est pas valide par rapport à la Définition du Schéma XML officiel. Le fichier XML généré et le message d'erreur complet ont été écrits dans les logs du serveur. Voici l'erreur, qui vous donnera peut-être une idée sur la cause du problème : %s" + +#. module: account_banking_sepa_direct_debit +#: view:sdd.mandate:0 +#: selection:sdd.mandate,type:0 +msgid "Recurrent" +msgstr "Récurrent" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,type:0 +msgid "Type of Mandate" +msgstr "Type de mandat" + +#. module: account_banking_sepa_direct_debit +#: model:mail.message.subtype,name:account_banking_sepa_direct_debit.mandate_valid +msgid "Mandate Validated" +msgstr "Mandat validé" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd,file:0 +msgid "SEPA File" +msgstr "SEPA File" + +#. module: account_banking_sepa_direct_debit +#: field:res.company,sepa_creditor_identifier:0 +msgid "SEPA Creditor Identifier" +msgstr "Identifiant créancier SEPA" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:122 +#, python-format +msgid "Cannot compute the '%s'." +msgstr "Impossible de calculer le '%s'." + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:126 +#, python-format +msgid "The type of the field '%s' is %s. It should be a string or unicode." +msgstr "Le champ '%s' est de type %s. Il devrait être de type string ou unicode." + +#. module: account_banking_sepa_direct_debit +#: model:ir.model,name:account_banking_sepa_direct_debit.model_banking_export_sdd +msgid "SEPA Direct Debit export" +msgstr "Export de prélèvement SEPA" + +#. module: account_banking_sepa_direct_debit +#: view:sdd.mandate:0 +#: selection:sdd.mandate,state:0 +msgid "Expired" +msgstr "Expiré" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,partner_bank_id:0 +msgid "Bank Account" +msgstr "Compte bancaire" + +#. module: account_banking_sepa_direct_debit +#: model:mail.message.subtype,description:account_banking_sepa_direct_debit.recurrent_sequence_type_first +#: model:mail.message.subtype,name:account_banking_sepa_direct_debit.recurrent_sequence_type_first +msgid "Sequence Type set to First" +msgstr "Type de Séquence mis à First" + +#. module: account_banking_sepa_direct_debit +#: model:ir.actions.act_window,help:account_banking_sepa_direct_debit.sdd_mandate_action +msgid "

\n" +" Click to create a new SEPA Direct Debit Mandate.\n" +"

\n" +" A SEPA Direct Debit Mandate is a document signed by your customer that gives you the autorization to do one or several direct debits on his bank account.\n" +"

\n" +" " +msgstr "

\n" +" Cliquez pour créer un mandat de prélèvement SEPA.\n" +"

\n" +" Un mandat de prélèvement SEPA est un document signé par votre client qui vous donne l'autorisation de réaliser un ou plusieurs prélèvements sur son compte bancaire.\n" +"

\n" +" " + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:233 +#, python-format +msgid "As you changed the bank account attached to this mandate, the 'Sequence Type' has been set back to 'First'." +msgstr "Etant donné que vous avez changé le compte bancaire associé à ce mandat, le 'Type de séquence' a été remis à 'First'." + +#. module: account_banking_sepa_direct_debit +#: help:sdd.mandate,message_ids:0 +msgid "Messages and communication history" +msgstr "Messages and communication history" + +#. module: account_banking_sepa_direct_debit +#: view:sdd.mandate:0 +msgid "Search SEPA Direct Debit Mandates" +msgstr "Recherche dans les mandats de prélèvement SEPA" + +#. module: account_banking_sepa_direct_debit +#: help:banking.export.sdd.wizard,requested_collec_date:0 +msgid "This is the date on which you would like the collection to be made by the bank. Please keep in mind that there are minimum delays for SEPA direct debits that depend on the type of mandate and the type of sequence." +msgstr "Entrez la date à laquelle vous voudriez que le prélèvement soit effectué par la banque. Gardez en mémoire qu'il y a un délai minimum pour les prélèvements SEPA qui dépend du type de mandat et du type de séquence." + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,unique_mandate_reference:0 +msgid "Unique Mandate Reference" +msgstr "Référence unique de mandat" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd.wizard,file:0 +msgid "File" +msgstr "Fichier" + diff --git a/account_banking_sepa_direct_debit/sdd_mandate_view.xml b/account_banking_sepa_direct_debit/sdd_mandate_view.xml index 0d73d00f3..9e6e17991 100644 --- a/account_banking_sepa_direct_debit/sdd_mandate_view.xml +++ b/account_banking_sepa_direct_debit/sdd_mandate_view.xml @@ -89,7 +89,7 @@

Click to create a new SEPA Direct Debit Mandate.

- The SEPA Direct Debit Mandate is a document signed by your customer that gives you the autorization to do one or several direct debits on his bank account. + A SEPA Direct Debit Mandate is a document signed by your customer that gives you the autorization to do one or several direct debits on his bank account.

diff --git a/account_banking_sepa_direct_debit/wizard/export_sdd.py b/account_banking_sepa_direct_debit/wizard/export_sdd.py index c217770c1..1f68674a7 100644 --- a/account_banking_sepa_direct_debit/wizard/export_sdd.py +++ b/account_banking_sepa_direct_debit/wizard/export_sdd.py @@ -44,17 +44,17 @@ class banking_export_sdd_wizard(orm.TransientModel): ], 'State', readonly=True), 'batch_booking': fields.boolean( 'Batch Booking', - help="If true, the bank statement will display only one debit line for all the wire transfers of the SEPA XML file ; if false, the bank statement will display one debit line per wire transfer of the SEPA XML file."), + help="If true, the bank statement will display only one credit line for all the direct debits of the SEPA file ; if false, the bank statement will display one credit line per direct debit of the SEPA file."), 'requested_collec_date': fields.date( 'Requested Collection Date', - help='This is the date on which the collection should be made by the bank. Please keep in mind that banks only execute on working days.'), + help='This is the date on which you would like the collection to be made by the bank. Please keep in mind that there are minimum delays for SEPA direct debits that depend on the type of mandate and the type of sequence.'), 'charge_bearer': fields.selection([ + ('SLEV', 'Following Service Level'), ('SHAR', 'Shared'), ('CRED', 'Borne by Creditor'), ('DEBT', 'Borne by Debtor'), - ('SLEV', 'Following Service Level'), ], 'Charge Bearer', required=True, - help='Shared : transaction charges on the sender side are to be borne by the debtor, transaction charges on the receiver side are to be borne by the creditor (most transfers use this). Borne by creditor : all transaction charges are to be borne by the creditor. Borne by debtor : all transaction charges are to be borne by the debtor. Following service level : transaction charges are to be applied following the rules agreed in the service level and/or scheme.'), + help='Following service level : transaction charges are to be applied following the rules agreed in the service level and/or scheme (SEPA Core messages must use this). Shared : transaction charges on the creditor side are to be borne by the creditor, transaction charges on the debtor side are to be borne by the debtor. Borne by creditor : all transaction charges are to be borne by the creditor. Borne by debtor : all transaction charges are to be borne by the debtor.'), 'nb_transactions': fields.related( 'file_id', 'nb_transactions', type='integer', string='Number of Transactions', readonly=True), @@ -62,7 +62,7 @@ class banking_export_sdd_wizard(orm.TransientModel): 'file_id', 'total_amount', type='float', string='Total Amount', readonly=True), 'file_id': fields.many2one( - 'banking.export.sdd', 'SDD XML File', readonly=True), + 'banking.export.sdd', 'SDD File', readonly=True), 'file': fields.related( 'file_id', 'file', string="File", type='binary', readonly=True), 'filename': fields.related( @@ -276,20 +276,6 @@ class banking_export_sdd_wizard(orm.TransientModel): _("The SEPA Direct Debit mandate with reference '%s' for partner '%s' has expired.") % (line.sdd_mandate_id.unique_mandate_reference, line.sdd_mandate_id.partner_id.name)) - if not line.sdd_mandate_id.signature_date: - raise orm.except_orm( - _('Error:'), - _("Missing signature date on SEPA Direct Debit mandate with reference '%s' for partner '%s'.") - % (line.sdd_mandate_id.unique_mandate_reference, - line.sdd_mandate_id.partner_id.name)) - elif (line.sdd_mandate_id.signature_date > - datetime.today().strftime('%Y-%m-%d')): - raise orm.except_orm( - _('Error:'), - _("The signature date on SEPA Direct Debit mandate with reference '%s' for partner '%s' is '%s', which is in the future !") - % (line.sdd_mandate_id.unique_mandate_reference, - line.sdd_mandate_id.partner_id.name, - line.sdd_mandate_id.signature_date)) if line.sdd_mandate_id.type == 'oneoff': if not line.sdd_mandate_id.last_debit_date: if lines_per_seq_type.get('OOFF'): From 3f6075541a061b68bb0d03aa67812dcbfe747a6a Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Mon, 11 Nov 2013 23:49:39 +0100 Subject: [PATCH 15/43] Add logo. --- .../static/src/img/icon.png | Bin 0 -> 6892 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 account_banking_sepa_direct_debit/static/src/img/icon.png diff --git a/account_banking_sepa_direct_debit/static/src/img/icon.png b/account_banking_sepa_direct_debit/static/src/img/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..6d1d923b6506b33ca0825af17ed0ae36c9bd0dc6 GIT binary patch literal 6892 zcmVPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2i*$` z7B3e|!Eq@702*vbL_t(|+RdAHcwFVR?tgpFo<5^8Ga8M0v1A#^k}b=Yja)D`;hH!h zp@cw^OL9)Yq+CcN<6E5%AqMj|;G$)Txm zv~I!^I(n+U|IaV%J#*-PEC8EIvy(P$%HNgdO88Wo)4Jx^$zJiqnE@oNL}_sbt5#-` zn{6jC!MNykqR|+A0~0j24O4rvo6#{JPP>^cm3fMya-x68^T%U{J0Cw#*ERV+0)Xw? z^PE*Hm)%;JXZu1R7){^3zgZMD8a}eEn2qa~A&T!EDNduL$l2G| z?|I^Ib>}0m9&R7`rvY&Lm$vLGD@wn^;}2!--hWoi&vSCawd=523?E3mswy0=Zs#vA zoun|&&brdfuKK2dAOG~%haUe>0oZjz#fp-mjE6JR61P43w|dd#O5!uut;cB4@?ovo zQ$0NQ{Bb_Au|UyC!v5;ou3Mk^+v&3(H~?R}sp@l8Yx3{!=oxn%sq5p*|9S~&uEY<; z=<3=oDl2klUdLhz&puy6PtO=1-C8(wx_RhpKY8?x=ibRRHSgrhKe+w!`!|&5-t)J8 zO$jE8iLc(g^#gPF`Bo?##g=Sl+#MhkiefhDDJ#h!H^;$m|5#(WxIF8s%JMAJKMuF= zdtU*ls6e{y3s*c@R+N6rZ(lg6`Q*peu(_)6JsINC$> zNhT&HgP;mn%z8%0{G_=O*>rIsFYKuov(u8Qwr?!RaR*!X3=X2a=MdPs73ou#eexMs ziuLN>zgRDR`R1)SY?gOqY+y`e0MUY=F=MeNqS0tTRZ&$1k7p7^_M^o7sPY7A z%#FnmMHJ)L@cF~+ef=z18A+^NoilUoqcxpuSerNV`oEt!g59jeYSI7cg#$0%aNq#) zdjjCc-`(+KNs;TuXZ}_%e&yy%m+bP9D8z(xM13|%wroUEL`4NuR7IKon;8I9Rh@pR z#NPw_zA?gqZgj#3MtzKl$sk&-hSv5GBGDL?YjO!rg)y7-^z^yO&a?sWm)&((w4f^L z2#y}Y&K93A-N&ee=ehSBM@H+}zGm)-xa za=>@Ly7l^XtFrFfeV|2i-L;k2lFS#}@Kn@}*>NdJjv^$jVLGPO_yIn>dVBi_27_2E z=U-1<;P1GHXfzTAlbyCsFDWSw%=$1Ula8J~H^=L`iOMp|3sNx|bcDk)k%-Ki)j7O= zq+KXpmQq=iXKy-G)7`ja57>1>#fplOjGxvu4oaJ<3Q0{#Sk!PiCJ>d%NX^}e+2WXo zz^L^0_HpRYVVav;@cDf2$|EF6OHxWX<5Rf=L-7bU8?@Mx%=Gk45Q`}cjd+>#1OfQp z*KgopZMRf*QTl^7UbSlZk^v~aDC=QaQJoQ0q~xNE#f?`abV=JtNn0}~iw6P$nwy(B z@cJ8^ZEhhH3Zbeh$;rv@=>*BiDZ&?7hR%@4%Hj-s{s?uadpTCyg(Qh6(@rFc0-wIR zlDej$^tG#V9$r!ieCNxT?pj-xdFz`ed&TRnUdLi5Q&iSrw0#6?Vg{ht1qR|*5V_pC@ZYZRobyQqkoPNjFisiFnR675~=CXpXI_;Lsu0fxepPRCv z@rnZarnWu>U9ir4EU5{b~()`rL9o%7qI`kM zNfN56@Vlq~fXCxy-)n#2uP^Qa;MLdu!6jR&`0Qt{QhlQIW@n4;oLanAmJf|bXA^(0MA&0KTMm3;Xt-=wiIUei=U3aaCS0QF(oH@4m@s#B4U9 zo|hB;_=l%BR$as1egELb&wq(MFFnVmEjxJW#b-%OOh8o>+S)qs`vW}rn}=|vrlP6} zimLGYXJ6okPhZ8vq=(*qHxZ=(gE)#t6zCtEM3!TetVl_Vs0p-u~@s;UrEVmRzJ1Odjz-8k%abUF?F{R6}TC(%kWvaFDn znutz!E+NXY!ttXmihDBfz#aF!@@)|y$zrH-dx9)4T=?#)8Ykui*OG|JeD0r=lz=2j z7m&PE#>Xe-yl*rZiALpFNmo%6L{WpmU?4Lijo!X~Iy!qm5Qzzn>0?ryVTI?|q=-4e zAX=^ZDgbePSw^PQVJQnm6mhX)M`tNmGE;NA-E-rA3G8opWCWkji`P4wDx1wF91a`V zS(!wmQ2-JX6H%1dIoGzB(CM@Yf`A}7h{fVQ6pBRW<{h05m)*L$;-VavSW%X}Ex~Hg znHDi#RRt`G1xq$QcHYL`y0bQ$eZk)}Hl1b16;~6Q3Zo)$@utgXeV&+@fJP(Y_4+Ux zjWeM#JTe+5N$p*PLlNYtJZ+$fsA8PqERo3U{n%|*bUKY;?Hbo*qSIwv24FE87CHJ7 z(dtY~0$_aHJ*OtnXf)XE^Ls!z9A?j+S1B)F6|WFgm1BqZ&Kp+2;1r38Rzl%0$;nCN z=48bUmNZCO39artQC6@{eZg~GT}Q+ZU+pnWAtON)Q^JnnBYnJ}4*^LjvW@kP|0sAJ3KDxz|XhBJ*6m#m<^p^>XTu@j@w z$jQ3XJo?B3yuAB4{_^}&05qIwV$;UT8RG$JYU;?%%{rF?G$IjMo#`LUsb>TMK@v@( zMkAW^+6#1agr&6)CfxJI|NP-|*=1Y#Kev99y1IHcZ>~Zk3Y=+dV&@f?Q(Iey#bV** zSN5@b)k?m4+qb!5=XLBqaEMd&4eYpl8@GM^4t8GoS@yiLm!6(JoT(|?e9P?&3=E%_ z2Q-X~`Z#r_pA+@H3=VtFM*xi=ScJ##xn?js%jR@tITs}OCg-)7ttlvqf*>$26AXt# z?B9QYxHqY&N?gb&E?z;JEA=g2x1cIKF)>LX5I`e|bai$!G(1Yhnle;HrLplW7Zn%L z($b2-U?3|q9Tk-mC+b;KUdqVG810>1tgkGmq2VkA%W}{g^mLwmjc{m+43Ac~dv;9M2ET#m{S8V1d0`d~#e{@cfq^b%|r*lc(qtok%#bQLGG8&Br zqap6zo!vc@l*ARJNJK``NV8a7ykiu?F#Y|g97B>M!r=&G6Fzct?C5k7MuV1&v_u95 zJu{+4OjZ42OjUz#v8DxifE;{R>@P7f5lLEF_?V1FT&`5)XcRdXBQO=B`uGWa=dr>- zAb`aZ&qu-F6lQb$sEdRn#N-%tb!S+XpM@kzOiXxiIV>z+<|KW(cPR)0k%&C4O(?`< zB`AXG7J-S$z{1Cy?0Z+|zs+V_GJj}nYUavMT#q1%$k7-sr-RCMYi8v0uC5+_^1vgQ zEoP!o8L!um)oNkqm7gUXj*^j)77t1Ftv!c$d+Ff|L@*e&(_n@`z%5QqMSCPkWNIq1 zu>L1|7Tvth=O+{j&7r?``@#T(!(oPoMsT|)h(@CvJb0Lm8#kaTDxuI68clqoxjET1 zx3+Qc&7%|*6{68-$j;8d7x3e-+t~f$(*%M+%oZ~#4m*AQgK_Yabol%cqSGWO7E>7- z@sOPv=OmGktONql9w`u(I{>1Qh2uOD7+4g5(b183>+8Ho5;YoZHe0;Bov+d9@gd7m zt@N73>ET3g#GDK4V6whoueNq%lNu~>|; zF*hx(?L76{=XmgEchhv%PitEz*)Ek8g{jokbz`?#@OXn1U77kTL6$7t{9WYwxt5)!Ta?&&}9 zgCE|@8wU?_#g31#e0d=a4NWvOH1YfkyUEVVL?cOjao0CUNKD|FXJ4SRtB1S(<337? zizqC}Lm*D4FJ6~VYKoP0<+)^}B~5FIqgYH@dWR?5#QM_%`#rv?NN6g$;87q5Dt=Gf zyq^W9rsj?R#nNg|PcH_8o}d5xF>b!;3%FdVtSl);r_=GXpZ$`?re-3M2(RrufZ1%~ zc+Cmyb{luy^=(c!G!YI**t_?2%2$`NEI)@!w{GOlJHEl)Km2a|R0w*J!ya_g%JAC< zv%;Y;et#r%;^fGF@y(OH14CoJx>UQ7p5F0=!@xg301c-b=I!hIyuKNg=k2*65{c)V z*4B0k3zyN*(8#)VYlz7TjZMw`_4%i1s6WE-WBUO(c<3nk`MG!|y%ZMYV>IfiJJrCl z{9FbGhdEwTM_z6=k#GdPPDfg*NKs)b&XoBnd}u1n@VKw8wyAqa1PJ(|hjm(sfdTiz zWH2^Dz&mta40||steVNm`KQ&Q(I}_t>*s*r_4?3HQ`n6gH}D_d{}GK%&8%Bjfuh8? z>XSRU=DN?bvg~4d`}zTRzgwq zOec)so(wWN<|7oEEr^Vb`w>-D@dQGLW;DT1?I_vw`RglRZ||94%Oxe^d>x@lPmobh zB8J3rCMG5cO$CY5LiIdN@O-uxXM&QXA;n?GY&K&uo3PuH85!tQ0pBo**$Cx{XYSN&d~BYBs;{(&?ibfX24bo{j5rcV?$2rFZmB3iAy;b##w2;U2~pG=Lz1 zsv=1ef+!G+#fZfeWla-l)q>am0q99^4 z>abYM)4V~QAuZ?k2Hz4pe11RO-MtJBk5E{UKl44UR?E~>5Tn?M$sjU1?x($T42Rt^ zlM7T8T3Y(?`9jqXJod&9X7vSn`zHTfkmFc8*fIjE=k^AQi(J#{kV;Cp1|_)^>P1x+eb1VKdRx)W>2sM4dW~XQGpT*7EuNjEsz(OSq9K#8@w)2#1cf zQ(M;qz~Jz?1byIOGt2YrN_UU@H^+{(dFO49AFJ(ncx2qyQ&yC!?EOdM!U~ZH;fdD? z`iB200C*<7jE%dei#i!Oa1xh8k03yDk_oGIw!j+*Mi?EQBovmrUOCqEiv{NcUOw11 zcB*mk?xX|*UXPz~_re8|MvUSgc@^JzN8^XRVsZpI*ojdW!erK?s*viil46gK@vU4D zpKf_^PaPMp$x==>^xb{rNS}Mr5t*Mn_Qn$}9bmo*#f(sQcNbQ}C`rZvtY(S!u2Gs=hDmW)>Fsy3EH5RV z11tvofiO?~{!OmfvOIF6rfb))eqViX$p8QxuIWCrJlB!1wk&Hyd*`U&3r5LIPriUR zOc4pRpxbi^z^$Q{r7ubxqZ?7UMSvVP1`Fe37I8T6*((v>bix2Vc(+R zaIPN+TG59_>0@&IEJ6PWp`edwBt$4Iqc<35866A;3HU|{1%?QC+nMq-U=({WXnklU z6`w!M;p%o|S)sHzgA}_3lSxP4z+@Z%qmD7RpNAja&-EWGRl55op8x9`FWuDDwfMyN zk{+0-s6hJEWmo)a^~#JJ51;532gick@-JIvRM~gB6h*}!lu=bNt|TckMuRwKvg_@u z{!Blq&IHUR9o>CyN{Z6(`9fH&25L|Bu;-OieE#YRrLk@3iC2!i{N)QxiZ96n00sw9 z_P*Kn*P>+(8XJpR<1!iu7_clE%8APDGn8Vq_7y-q-{*UStuEh@c_`N_|9 z%!HH0tVfbWo_h8O1HGeMvtwoC#F>Hn?!5o+U%$|ue@6hkwf=FqeP3!yLQ7tzZPUeT zvdvFDS1q)(k5F2iu_OcD>vFpTq&O^SG$IzWp1RY0JowAKtS`$@iVITv57l&k>7GaS zKm1Ovsd=ZHIC`S{j80;Y$)qp3d~;!*2GRyK(-j~PZ7FsC|%XG73jE5iF zk9*9^jaQc|V-tZ_4;TO1sk|iP-%{+B+@mMD#Y45-tXZAI z&dWJSP9G?v0 z4@L=vqR5JZ$*9AqldxEHWTqyNnU&-T=)lS5-hmHtfBzqpiy;_LBaChU0000 Date: Tue, 12 Nov 2013 22:36:13 +0100 Subject: [PATCH 16/43] FIX FR translation. --- account_banking_sepa_direct_debit/i18n/fr.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/account_banking_sepa_direct_debit/i18n/fr.po b/account_banking_sepa_direct_debit/i18n/fr.po index c823791c8..25b2df96f 100644 --- a/account_banking_sepa_direct_debit/i18n/fr.po +++ b/account_banking_sepa_direct_debit/i18n/fr.po @@ -191,7 +191,7 @@ msgstr "Le mandat de prélèvement SEPA a expiré" #: help:banking.export.sdd,charge_bearer:0 #: help:banking.export.sdd.wizard,charge_bearer:0 msgid "Following service level : transaction charges are to be applied following the rules agreed in the service level and/or scheme (SEPA Core messages must use this). Shared : transaction charges on the creditor side are to be borne by the creditor, transaction charges on the debtor side are to be borne by the debtor. Borne by creditor : all transaction charges are to be borne by the creditor. Borne by debtor : all transaction charges are to be borne by the debtor." -msgstr "Suivant le niveau de service : la répartition des frais bancaires suit les règles pré-établies dans le schema ou dans le contrat avec la banque (les messages SEPA Core doivent utiliser ce paramètre). Partagés : les frais bancaires côté débiteur sont à la charge du débiteur, les frais bancaires côté créditeur sont à la charge du créditeur. Supportés par le créancier : tous les frais bancaires sont à la charge du créancier. Supportés par le débiteur : tous les frais bancaires sont à la charge du débiteur." +msgstr "Suivant le niveau de service : la répartition des frais bancaires suit les règles pré-établies dans le schema ou dans le contrat avec la banque (les messages SEPA Core doivent utiliser ce paramètre). Partagés : les frais bancaires côté débiteur sont à la charge du débiteur, les frais bancaires côté créancier sont à la charge du créancier. Supportés par le créancier : tous les frais bancaires sont à la charge du créancier. Supportés par le débiteur : tous les frais bancaires sont à la charge du débiteur." #. module: account_banking_sepa_direct_debit #: view:sdd.mandate:0 From 708949e735652f0e31976c8ee6efa6ad813445cf Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Wed, 13 Nov 2013 21:53:00 +0100 Subject: [PATCH 17/43] Now OpenERP only propose 'debit' payment modes on Direct Debits and 'payment' payment modes on Payment Orders. --- account_banking_payment/model/__init__.py | 2 +- account_banking_payment/model/payment_mode.py | 4 ++++ account_banking_payment/view/payment_mode.xml | 1 + account_direct_debit/view/account_payment.xml | 3 +++ 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/account_banking_payment/model/__init__.py b/account_banking_payment/model/__init__.py index e7ae81724..cf509d816 100644 --- a/account_banking_payment/model/__init__.py +++ b/account_banking_payment/model/__init__.py @@ -1,7 +1,7 @@ import account_payment import payment_line -import payment_mode import payment_mode_type +import payment_mode import payment_order_create import banking_import_transaction import banking_transaction_wizard diff --git a/account_banking_payment/model/payment_mode.py b/account_banking_payment/model/payment_mode.py index 6237593b6..0ce7d2837 100644 --- a/account_banking_payment/model/payment_mode.py +++ b/account_banking_payment/model/payment_mode.py @@ -50,4 +50,8 @@ class payment_mode(orm.Model): help=('Limit selected invoices to invoices with these payment ' 'terms') ), + 'payment_order_type': fields.related( + 'type', 'payment_order_type', readonly=True, type='selection', + selection=[('payment', 'Payment'), ('debit', 'Direct debit')], + string="Payment Order Type"), } diff --git a/account_banking_payment/view/payment_mode.xml b/account_banking_payment/view/payment_mode.xml index c46823c8d..95d250652 100644 --- a/account_banking_payment/view/payment_mode.xml +++ b/account_banking_payment/view/payment_mode.xml @@ -11,6 +11,7 @@ + + + [('payment_order_type', '=', payment_order_type)] + From 56a6652e0e20cacf635d05d61bab461d4a55d80d Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Thu, 21 Nov 2013 00:24:56 +0100 Subject: [PATCH 18/43] Remove fields_view_get() on payment.order because dynamic domain is now possible and I implemented it in a previous commit. Minor usability improvements in mandate menu and views Refresh partner_id field on mandate in the on_change of partner_bank_id --- .../account_banking_sdd.py | 15 ++++++---- .../sdd_mandate_view.xml | 10 +++---- account_direct_debit/model/account_payment.py | 28 ------------------- 3 files changed, 14 insertions(+), 39 deletions(-) diff --git a/account_banking_sepa_direct_debit/account_banking_sdd.py b/account_banking_sepa_direct_debit/account_banking_sdd.py index 52c3b6f11..d65aff415 100644 --- a/account_banking_sepa_direct_debit/account_banking_sdd.py +++ b/account_banking_sepa_direct_debit/account_banking_sdd.py @@ -223,18 +223,21 @@ class sdd_mandate(orm.Model): def mandate_partner_bank_change( self, cr, uid, ids, partner_bank_id, type, recurrent_sequence_type, last_debit_date, state): + res = {'value': {}} + if partner_bank_id: + partner_bank_read = self.pool['res.partner.bank'].read( + cr, uid, partner_bank_id, ['partner_id'])['partner_id'] + if partner_bank_read: + res['value']['partner_id'] = partner_bank_read[0] if (state == 'valid' and partner_bank_id and type == 'recurrent' and recurrent_sequence_type != 'first'): - return { - 'value': {'recurrent_sequence_type': 'first'}, - 'warning': { + res['value']['recurrent_sequence_type'] = 'first' + res['warning'] = { 'title': _('Mandate update'), 'message': _("As you changed the bank account attached to this mandate, the 'Sequence Type' has been set back to 'First'."), - } } - else: - return True + return res def validate(self, cr, uid, ids, context=None): to_validate_ids = [] diff --git a/account_banking_sepa_direct_debit/sdd_mandate_view.xml b/account_banking_sepa_direct_debit/sdd_mandate_view.xml index 9e6e17991..ad11d8804 100644 --- a/account_banking_sepa_direct_debit/sdd_mandate_view.xml +++ b/account_banking_sepa_direct_debit/sdd_mandate_view.xml @@ -25,16 +25,16 @@ + - @@ -95,7 +95,7 @@ diff --git a/account_direct_debit/model/account_payment.py b/account_direct_debit/model/account_payment.py index a36ac2ae4..1b4ce9298 100644 --- a/account_direct_debit/model/account_payment.py +++ b/account_direct_debit/model/account_payment.py @@ -6,34 +6,6 @@ from tools.translate import _ class payment_order(orm.Model): _inherit = 'payment.order' - def fields_view_get(self, cr, user, view_id=None, view_type='form', - context=None, toolbar=False, submenu=False): - """ - We use the same form for payment and debit orders, but they - are accessible through different menu items. The user should only - be allowed to select a payment mode that applies to the type of order - i.e. payment or debit. - - A pretty awful workaround is needed for the fact that no dynamic - domain is possible on the selection widget. This domain is encoded - in the context of the menu item. - """ - if not context: - context = {} - res = super(payment_order, self).fields_view_get( - cr, user, view_id, view_type, context, toolbar, submenu) - if context.get('search_payment_order_type', False) and view_type == 'form': - if 'mode' in res['fields'] and 'selection' in res['fields']['mode']: - mode_obj = self.pool.get('payment.mode') - domain = ['|', ('type', '=', False), ('type.payment_order_type', '=', - context['search_payment_order_type'])] - # the magic is in the value of the selection - res['fields']['mode']['selection'] = mode_obj._name_search( - cr, user, args=domain, context=context) - # also update the domain - res['fields']['mode']['domain'] = domain - return res - def test_undo_done(self, cr, uid, ids, context=None): """ Called from the workflow. Used to unset done state on From 0125648c775d53e938410a9b845cc5aad51c6cd4 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Fri, 22 Nov 2013 00:41:32 +0100 Subject: [PATCH 19/43] Akretion-Noviat code sprint dated 2013-11-21: - add module account_banking_pain_base - add support for initiating party identification, priority and structured remittance info in XML file - the requested execution date now uses the fields date_prefered and date_scheduled (the field of the wizard has been removed) - the 'convert to ascii' feature is now an option of the payment mode (enabled by default) - set 'communication' field of payment.line to 140 chars and hide field 'communicatio n2' --- account_banking_pain_base/__init__.py | 25 ++ account_banking_pain_base/__openerp__.py | 47 +++ account_banking_pain_base/company.py | 53 ++++ account_banking_pain_base/company_view.xml | 24 ++ account_banking_pain_base/payment_line.py | 49 +++ .../payment_line_view.xml | 41 +++ account_banking_pain_base/payment_mode.py | 37 +++ .../payment_mode_view.xml | 22 ++ .../__openerp__.py | 2 +- .../account_banking_sepa.py | 2 - .../account_banking_sepa_view.xml | 2 - .../wizard/export_sepa.py | 298 ++++++++++++------ .../wizard/export_sepa_view.xml | 1 - 13 files changed, 495 insertions(+), 108 deletions(-) create mode 100644 account_banking_pain_base/__init__.py create mode 100644 account_banking_pain_base/__openerp__.py create mode 100644 account_banking_pain_base/company.py create mode 100644 account_banking_pain_base/company_view.xml create mode 100644 account_banking_pain_base/payment_line.py create mode 100644 account_banking_pain_base/payment_line_view.xml create mode 100644 account_banking_pain_base/payment_mode.py create mode 100644 account_banking_pain_base/payment_mode_view.xml diff --git a/account_banking_pain_base/__init__.py b/account_banking_pain_base/__init__.py new file mode 100644 index 000000000..a54725775 --- /dev/null +++ b/account_banking_pain_base/__init__.py @@ -0,0 +1,25 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# PAIN Base module for OpenERP +# Copyright (C) 2013 Akretion (http://www.akretion.com) +# @author: Alexis de Lattre +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from . import payment_line +from . import payment_mode +from . import company diff --git a/account_banking_pain_base/__openerp__.py b/account_banking_pain_base/__openerp__.py new file mode 100644 index 000000000..8a66aaafa --- /dev/null +++ b/account_banking_pain_base/__openerp__.py @@ -0,0 +1,47 @@ +############################################################################## +# +# PAIN base module for OpenERP +# Copyright (C) 2013 Akretion (http://www.akretion.com) +# @author: Alexis de Lattre +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## +{ + 'name': 'Account Banking PAIN Base Module', + 'summary': 'Base module for PAIN file generation', + 'version': '0.1', + 'license': 'AGPL-3', + 'author': 'Akretion, Noviat', + 'website': 'http://openerp-community-association.org/', + 'category': 'Hidden', + 'depends': ['account_banking_payment_export'], + 'data': [ + 'payment_line_view.xml', + 'payment_mode_view.xml', + 'company_view.xml', + ], + 'description': ''' +Base module for PAIN file generation +==================================== + +This module contains fields and functions that are used by the module for SEPA Credit Transfer (account_banking_sepa_credit_transfer) and SEPA Direct Debit (account_banking_sepa_direct_debit). This module doesn't provide any functionnality by itself. + +This module is part of the banking addons: https://launchpad.net/banking-addons + +This module was developped during the Akretion-Noviat code sprint of November 21st 2013 in Epiais les Louvres (France). + ''', + 'active': False, + 'installable': True, +} diff --git a/account_banking_pain_base/company.py b/account_banking_pain_base/company.py new file mode 100644 index 000000000..b40f64440 --- /dev/null +++ b/account_banking_pain_base/company.py @@ -0,0 +1,53 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# PAIN Base module for OpenERP +# Copyright (C) 2013 Akretion (http://www.akretion.com) +# Copyright (C) 2013 Noviat (http://www.noviat.com) +# @author: Alexis de Lattre +# @author: Luc de Meyer (Noviat) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp.osv import orm, fields + + +class res_company(orm.Model): + _inherit = 'res.company' + + _columns = { + 'initiating_party_issuer': fields.char( + 'Initiating Party Issuer', size=35, + help="This will be used as the 'Initiating Party Issuer' in the PAIN files generated by OpenERP."), + } + + def _get_initiating_party_identifier( + self, cr, uid, company_id, context=None): + '''This function is designed to be inherited by localization modules''' + assert isinstance(company_id, int), 'Only one company ID' + return False + + def _initiating_party_issuer_default(self, cr, uid, context=None): + '''This function is designed to be inherited by localization modules''' + return '' + + def _initiating_party_issuer_def(self, cr, uid, context=None): + return self._initiating_party_issuer_default( + cr, uid, context=context) + + _defaults = { + 'initiating_party_issuer': _initiating_party_issuer_def, + } diff --git a/account_banking_pain_base/company_view.xml b/account_banking_pain_base/company_view.xml new file mode 100644 index 000000000..a98d9b641 --- /dev/null +++ b/account_banking_pain_base/company_view.xml @@ -0,0 +1,24 @@ + + + + + + + pain.group.on.res.company.form + res.company + + + + + + + + + + + + diff --git a/account_banking_pain_base/payment_line.py b/account_banking_pain_base/payment_line.py new file mode 100644 index 000000000..11d597e4d --- /dev/null +++ b/account_banking_pain_base/payment_line.py @@ -0,0 +1,49 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# PAIN Base module for OpenERP +# Copyright (C) 2013 Akretion (http://www.akretion.com) +# @author: Alexis de Lattre +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp.osv import orm, fields + + +class payment_line(orm.Model): + _inherit = 'payment.line' + + def _get_struct_communication_types(self, cr, uid, context=None): + return [('ISO', 'ISO')] + + _columns = { + 'priority': fields.selection([ + ('NORM', 'Normal'), + ('HIGH', 'High'), + ], 'Priority', + help="This field will be used as the 'Instruction Priority' in the generated PAIN files."), + # Update size from 64 to 140, because PAIN allows 140 caracters + 'communication': fields.char( + 'Communication', size=140, required=True, + help="Used as the message between ordering customer and current company. Depicts 'What do you want to say to the recipient about this order ?'"), + 'struct_communication_type': fields.selection( + _get_struct_communication_types, 'Structured Communication Type'), + } + + _defaults = { + 'priority': 'NORM', + 'struct_communication_type': 'ISO', + } diff --git a/account_banking_pain_base/payment_line_view.xml b/account_banking_pain_base/payment_line_view.xml new file mode 100644 index 000000000..ea0005faf --- /dev/null +++ b/account_banking_pain_base/payment_line_view.xml @@ -0,0 +1,41 @@ + + + + + + + pain.base.payment.line.form + payment.line + + + + + + + + + + + + + + pain.base.payment.line.inside.order.form + payment.order + + + + + + + + + + + + + + diff --git a/account_banking_pain_base/payment_mode.py b/account_banking_pain_base/payment_mode.py new file mode 100644 index 000000000..7113ccc78 --- /dev/null +++ b/account_banking_pain_base/payment_mode.py @@ -0,0 +1,37 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# PAIN Base module for OpenERP +# Copyright (C) 2013 Akretion (http://www.akretion.com) +# @author: Alexis de Lattre +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp.osv import orm, fields + + +class payment_mode(orm.Model): + _inherit = 'payment.mode' + + _columns = { + 'convert_to_ascii': fields.boolean( + 'Convert to ASCII', + help="If active, OpenERP will convert each accented caracter to the corresponding unaccented caracter, so that only ASCII caracters are used in the generated PAIN file."), + } + + _defaults = { + 'convert_to_ascii': True, + } diff --git a/account_banking_pain_base/payment_mode_view.xml b/account_banking_pain_base/payment_mode_view.xml new file mode 100644 index 000000000..2deb24999 --- /dev/null +++ b/account_banking_pain_base/payment_mode_view.xml @@ -0,0 +1,22 @@ + + + + + + + add.convert_to_ascii.in.payment.mode.form + payment.mode + + + + + + + + + + diff --git a/account_banking_sepa_credit_transfer/__openerp__.py b/account_banking_sepa_credit_transfer/__openerp__.py index c5c97dd9a..762ede89e 100644 --- a/account_banking_sepa_credit_transfer/__openerp__.py +++ b/account_banking_sepa_credit_transfer/__openerp__.py @@ -26,7 +26,7 @@ 'author': 'Akretion', 'website': 'http://www.akretion.com', 'category': 'Banking addons', - 'depends': ['account_banking_payment_export'], + 'depends': ['account_banking_pain_base'], 'external_dependencies': { 'python': ['unidecode', 'lxml'], }, diff --git a/account_banking_sepa_credit_transfer/account_banking_sepa.py b/account_banking_sepa_credit_transfer/account_banking_sepa.py index be970a8f8..c2399c37e 100644 --- a/account_banking_sepa_credit_transfer/account_banking_sepa.py +++ b/account_banking_sepa_credit_transfer/account_banking_sepa.py @@ -48,8 +48,6 @@ class banking_export_sepa(orm.Model): 'banking_export_sepa_id', 'account_order_id', 'Payment Orders', readonly=True), - 'prefered_exec_date': fields.date( - 'Prefered Execution Date', readonly=True), 'nb_transactions': fields.integer( 'Number of Transactions', readonly=True), 'total_amount': fields.float('Total Amount', diff --git a/account_banking_sepa_credit_transfer/account_banking_sepa_view.xml b/account_banking_sepa_credit_transfer/account_banking_sepa_view.xml index 8e5421cc4..8bf13cf1d 100644 --- a/account_banking_sepa_credit_transfer/account_banking_sepa_view.xml +++ b/account_banking_sepa_credit_transfer/account_banking_sepa_view.xml @@ -16,7 +16,6 @@ - @@ -47,7 +46,6 @@ - diff --git a/account_banking_sepa_credit_transfer/wizard/export_sepa.py b/account_banking_sepa_credit_transfer/wizard/export_sepa.py index 1f40060c0..79974d9b4 100644 --- a/account_banking_sepa_credit_transfer/wizard/export_sepa.py +++ b/account_banking_sepa_credit_transfer/wizard/export_sepa.py @@ -46,9 +46,6 @@ class banking_export_sepa_wizard(orm.TransientModel): 'batch_booking': fields.boolean( 'Batch Booking', help="If true, the bank statement will display only one debit line for all the wire transfers of the SEPA XML file ; if false, the bank statement will display one debit line per wire transfer of the SEPA XML file."), - 'prefered_exec_date': fields.date( - 'Prefered Execution Date', - help='This is the date on which the file should be processed by the bank. Please keep in mind that banks only execute on working days and typically use a delay of two days between execution date and effective transfer date.'), 'charge_bearer': fields.selection([ ('SLEV', 'Following Service Level'), ('SHAR', 'Shared'), @@ -99,16 +96,18 @@ class banking_export_sepa_wizard(orm.TransientModel): def _prepare_field( self, cr, uid, field_name, field_value, eval_ctx, max_size=0, - context=None): + convert_to_ascii=False, context=None): '''This function is designed to be inherited !''' assert isinstance(eval_ctx, dict), 'eval_ctx must contain a dict' try: + value = safe_eval(field_value, eval_ctx) # SEPA uses XML ; XML = UTF-8 ; UTF-8 = support for all characters # But we are dealing with banks... # and many banks don't want non-ASCCI characters ! # cf section 1.4 "Character set" of the SEPA Credit Transfer # Scheme Customer-to-bank guidelines - value = unidecode(safe_eval(field_value, eval_ctx)) + if convert_to_ascii: + value = unidecode(value) except: line = eval_ctx.get('line') if line: @@ -140,7 +139,6 @@ class banking_export_sepa_wizard(orm.TransientModel): return { 'batch_booking': sepa_export.batch_booking, 'charge_bearer': sepa_export.charge_bearer, - 'prefered_exec_date': sepa_export.prefered_exec_date, 'total_amount': total_amount, 'nb_transactions': transactions_count, 'file': base64.encodestring(xml_string), @@ -174,8 +172,12 @@ class banking_export_sepa_wizard(orm.TransientModel): ''' Creates the SEPA Credit Transfer file. That's the important code ! ''' + if context is None: + context = {} sepa_export = self.browse(cr, uid, ids[0], context=context) pain_flavor = sepa_export.payment_order_ids[0].mode.type.code + convert_to_ascii = \ + sepa_export.payment_order_ids[0].mode.convert_to_ascii if pain_flavor == 'pain.001.001.02': bic_xml_tag = 'BIC' name_maxsize = 70 @@ -206,11 +208,6 @@ class banking_export_sepa_wizard(orm.TransientModel): _('Error:'), _("Payment Type Code '%s' is not supported. The only Payment Type Codes supported for SEPA Credit Transfers are 'pain.001.001.02', 'pain.001.001.03', 'pain.001.001.04' and 'pain.001.001.05'.") % pain_flavor) - if sepa_export.prefered_exec_date: - my_requested_exec_date = sepa_export.prefered_exec_date - else: - my_requested_exec_date = fields.date.context_today( - self, cr, uid, context=context) pain_ns = { 'xsi': 'http://www.w3.org/2001/XMLSchema-instance', @@ -219,11 +216,14 @@ class banking_export_sepa_wizard(orm.TransientModel): root = etree.Element('Document', nsmap=pain_ns) pain_root = etree.SubElement(root, root_xml_tag) + pain_03_to_05 = \ + ['pain.001.001.03', 'pain.001.001.04', 'pain.001.001.05'] my_company_name = self._prepare_field( cr, uid, 'Company Name', 'sepa_export.payment_order_ids[0].mode.bank_id.partner_id.name', - {'sepa_export': sepa_export}, name_maxsize, context=context) + {'sepa_export': sepa_export}, name_maxsize, + convert_to_ascii=convert_to_ascii, context=context) # A. Group header group_header_1_0 = etree.SubElement(pain_root, 'GrpHdr') @@ -232,7 +232,8 @@ class banking_export_sepa_wizard(orm.TransientModel): message_identification_1_1.text = self._prepare_field( cr, uid, 'Message Identification', 'sepa_export.payment_order_ids[0].reference', - {'sepa_export': sepa_export}, 35, context=context) + {'sepa_export': sepa_export}, 35, + convert_to_ascii=convert_to_ascii, context=context) creation_date_time_1_2 = etree.SubElement(group_header_1_0, 'CreDtTm') creation_date_time_1_2.text = datetime.strftime( datetime.today(), '%Y-%m-%dT%H:%M:%S') @@ -251,77 +252,124 @@ class banking_export_sepa_wizard(orm.TransientModel): initiating_party_1_8 = etree.SubElement(group_header_1_0, 'InitgPty') initiating_party_name = etree.SubElement(initiating_party_1_8, 'Nm') initiating_party_name.text = my_company_name + initiating_party_identifier = self.pool['res.company'].\ + _get_initiating_party_identifier( + cr, uid, sepa_export.payment_order_ids[0].company_id.id, + context=context) + initiating_party_issuer = \ + sepa_export.payment_order_ids[0].company_id.initiating_party_issuer + if initiating_party_identifier and initiating_party_issuer: + iniparty_id = etree.SubElement(initiating_party_1_8, 'Id') + iniparty_org_id = etree.SubElement(iniparty_id, 'OrgId') + iniparty_org_other = etree.SubElement(iniparty_org_id, 'Othr') + iniparty_org_other_id = etree.SubElement(iniparty_org_other, 'Id') + iniparty_org_other_id.text = initiating_party_identifier + iniparty_org_other_issuer = etree.SubElement( + iniparty_org_other, 'Issr') + iniparty_org_other_issuer.text = initiating_party_issuer - # B. Payment info - payment_info_2_0 = etree.SubElement(pain_root, 'PmtInf') - payment_info_identification_2_1 = etree.SubElement( - payment_info_2_0, 'PmtInfId') - payment_info_identification_2_1.text = self._prepare_field( - cr, uid, 'Payment Information Identification', - "sepa_export.payment_order_ids[0].reference", - {'sepa_export': sepa_export}, 35, context=context) - payment_method_2_2 = etree.SubElement(payment_info_2_0, 'PmtMtd') - payment_method_2_2.text = 'TRF' - if pain_flavor in [ - 'pain.001.001.03', 'pain.001.001.04', 'pain.001.001.05']: - # batch_booking is in "Group header" with pain.001.001.02 - # and in "Payment info" in pain.001.001.03/04 - batch_booking_2_3 = etree.SubElement(payment_info_2_0, 'BtchBookg') - batch_booking_2_3.text = str(sepa_export.batch_booking).lower() - # It may seem surprising, but the - # "SEPA Credit Transfer Scheme Customer-to-bank Implementation - # guidelines" v6.0 says that control sum and nb_of_transactions - # should be present at both "group header" level and "payment info" - # level. This seems to be confirmed by the tests carried out at - # BNP Paribas in PAIN v001.001.03 - if pain_flavor in [ - 'pain.001.001.03', 'pain.001.001.04', 'pain.001.001.05']: - nb_of_transactions_2_4 = etree.SubElement( - payment_info_2_0, 'NbOfTxs') - control_sum_2_5 = etree.SubElement(payment_info_2_0, 'CtrlSum') - payment_type_info_2_6 = etree.SubElement(payment_info_2_0, 'PmtTpInf') - service_level_2_8 = etree.SubElement(payment_type_info_2_6, 'SvcLvl') - service_level_code_2_9 = etree.SubElement(service_level_2_8, 'Cd') - service_level_code_2_9.text = 'SEPA' - requested_exec_date_2_17 = etree.SubElement( - payment_info_2_0, 'ReqdExctnDt') - requested_exec_date_2_17.text = my_requested_exec_date - debtor_2_19 = etree.SubElement(payment_info_2_0, 'Dbtr') - debtor_name = etree.SubElement(debtor_2_19, 'Nm') - debtor_name.text = my_company_name - debtor_account_2_20 = etree.SubElement(payment_info_2_0, 'DbtrAcct') - debtor_account_id = etree.SubElement(debtor_account_2_20, 'Id') - debtor_account_iban = etree.SubElement(debtor_account_id, 'IBAN') - debtor_account_iban.text = self._validate_iban( - cr, uid, self._prepare_field( - cr, uid, 'Company IBAN', - 'sepa_export.payment_order_ids[0].mode.bank_id.acc_number', - {'sepa_export': sepa_export}, context=context), - context=context) - debtor_agent_2_21 = etree.SubElement(payment_info_2_0, 'DbtrAgt') - debtor_agent_institution = etree.SubElement( - debtor_agent_2_21, 'FinInstnId') - debtor_agent_bic = etree.SubElement( - debtor_agent_institution, bic_xml_tag) - # TODO validate BIC with pattern - # [A-Z]{6,6}[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3,3}){0,1} - # because OpenERP doesn't have a constraint on BIC - debtor_agent_bic.text = self._prepare_field( - cr, uid, 'Company BIC', - 'sepa_export.payment_order_ids[0].mode.bank_id.bank.bic', - {'sepa_export': sepa_export}, context=context) - charge_bearer_2_24 = etree.SubElement(payment_info_2_0, 'ChrgBr') - charge_bearer_2_24.text = sepa_export.charge_bearer - - transactions_count = 0 + transactions_count_1_6 = 0 total_amount = 0.0 - amount_control_sum = 0.0 - # Iterate on payment orders + amount_control_sum_1_7 = 0.0 + lines_per_group = {} + # key = (requested_exec_date, priority) + # values = list of lines as object + today = fields.date.context_today(self, cr, uid, context=context) for payment_order in sepa_export.payment_order_ids: total_amount = total_amount + payment_order.total - # Iterate each payment lines for line in payment_order.line_ids: - transactions_count += 1 + priority = line.priority + if payment_order.date_prefered == 'due': + requested_exec_date = line.ml_maturity_date or today + elif payment_order.date_prefered == 'fixed': + requested_exec_date = payment_order.date_scheduled or today + else: + requested_exec_date = today + if (requested_exec_date, priority) in lines_per_group: + lines_per_group[(requested_exec_date, priority)].append(line) + else: + lines_per_group[(requested_exec_date, priority)] = [line] + # Write requested_exec_date on 'Payment date' of the pay line + if requested_exec_date != line.date: + self.pool['payment.line'].write( + cr, uid, line.id, + {'date': requested_exec_date}, context=context) + + for (requested_exec_date, priority), lines in lines_per_group.items(): + # B. Payment info + payment_info_2_0 = etree.SubElement(pain_root, 'PmtInf') + payment_info_identification_2_1 = etree.SubElement( + payment_info_2_0, 'PmtInfId') + payment_info_identification_2_1.text = self._prepare_field( + cr, uid, 'Payment Information Identification', + "sepa_export.payment_order_ids[0].reference + '-' + requested_exec_date.replace('-', '') + '-' + priority", { + 'sepa_export': sepa_export, + 'priority': priority, + 'requested_exec_date': requested_exec_date + }, 35, convert_to_ascii=convert_to_ascii, context=context) + payment_method_2_2 = etree.SubElement(payment_info_2_0, 'PmtMtd') + payment_method_2_2.text = 'TRF' + if pain_flavor in pain_03_to_05: + # batch_booking is in "Group header" with pain.001.001.02 + # and in "Payment info" in pain.001.001.03/04 + batch_booking_2_3 = etree.SubElement( + payment_info_2_0, 'BtchBookg') + batch_booking_2_3.text = str(sepa_export.batch_booking).lower() + # It may seem surprising, but the + # "SEPA Credit Transfer Scheme Customer-to-bank Implementation + # guidelines" v6.0 says that control sum and nb_of_transactions + # should be present at both "group header" level and "payment info" + # level. This seems to be confirmed by the tests carried out at + # BNP Paribas in PAIN v001.001.03 + if pain_flavor in pain_03_to_05: + nb_of_transactions_2_4 = etree.SubElement( + payment_info_2_0, 'NbOfTxs') + control_sum_2_5 = etree.SubElement(payment_info_2_0, 'CtrlSum') + payment_type_info_2_6 = etree.SubElement(payment_info_2_0, 'PmtTpInf') + if priority: + instruction_priority_2_7 = etree.SubElement( + payment_type_info_2_6, 'InstrPrty') + instruction_priority_2_7.text = priority + service_level_2_8 = etree.SubElement(payment_type_info_2_6, 'SvcLvl') + service_level_code_2_9 = etree.SubElement(service_level_2_8, 'Cd') + service_level_code_2_9.text = 'SEPA' + requested_exec_date_2_17 = etree.SubElement( + payment_info_2_0, 'ReqdExctnDt') + requested_exec_date_2_17.text = requested_exec_date + debtor_2_19 = etree.SubElement(payment_info_2_0, 'Dbtr') + debtor_name = etree.SubElement(debtor_2_19, 'Nm') + debtor_name.text = my_company_name + debtor_account_2_20 = etree.SubElement(payment_info_2_0, 'DbtrAcct') + debtor_account_id = etree.SubElement(debtor_account_2_20, 'Id') + debtor_account_iban = etree.SubElement(debtor_account_id, 'IBAN') + debtor_account_iban.text = self._validate_iban( + cr, uid, self._prepare_field( + cr, uid, 'Company IBAN', + 'sepa_export.payment_order_ids[0].mode.bank_id.acc_number', + {'sepa_export': sepa_export}, + convert_to_ascii=convert_to_ascii, context=context), + context=context) + debtor_agent_2_21 = etree.SubElement(payment_info_2_0, 'DbtrAgt') + debtor_agent_institution = etree.SubElement( + debtor_agent_2_21, 'FinInstnId') + debtor_agent_bic = etree.SubElement( + debtor_agent_institution, bic_xml_tag) + # TODO validate BIC with pattern + # [A-Z]{6,6}[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3,3}){0,1} + # because OpenERP doesn't have a constraint on BIC + debtor_agent_bic.text = self._prepare_field( + cr, uid, 'Company BIC', + 'sepa_export.payment_order_ids[0].mode.bank_id.bank.bic', + {'sepa_export': sepa_export}, + convert_to_ascii=convert_to_ascii, context=context) + charge_bearer_2_24 = etree.SubElement(payment_info_2_0, 'ChrgBr') + charge_bearer_2_24.text = sepa_export.charge_bearer + + transactions_count_2_4 = 0 + amount_control_sum_2_5 = 0.0 + for line in lines: + transactions_count_1_6 += 1 + transactions_count_2_4 += 1 # C. Credit Transfer Transaction Info credit_transfer_transaction_info_2_27 = etree.SubElement( payment_info_2_0, 'CdtTrfTxInf') @@ -331,16 +379,19 @@ class banking_export_sepa_wizard(orm.TransientModel): payment_identification_2_28, 'EndToEndId') end2end_identification_2_30.text = self._prepare_field( cr, uid, 'End to End Identification', 'line.name', - {'line': line}, 35, context=context) + {'line': line}, 35, convert_to_ascii=convert_to_ascii, + context=context) currency_name = self._prepare_field( cr, uid, 'Currency Code', 'line.currency.name', - {'line': line}, 3, context=context) + {'line': line}, 3, convert_to_ascii=convert_to_ascii, + context=context) amount_2_42 = etree.SubElement( credit_transfer_transaction_info_2_27, 'Amt') instructed_amount_2_43 = etree.SubElement( amount_2_42, 'InstdAmt', Ccy=currency_name) instructed_amount_2_43.text = '%.2f' % line.amount_currency - amount_control_sum += line.amount_currency + amount_control_sum_1_7 += line.amount_currency + amount_control_sum_2_5 += line.amount_currency creditor_agent_2_77 = etree.SubElement( credit_transfer_transaction_info_2_27, 'CdtrAgt') creditor_agent_institution = etree.SubElement( @@ -354,13 +405,15 @@ class banking_export_sepa_wizard(orm.TransientModel): creditor_agent_institution, bic_xml_tag) creditor_agent_bic.text = self._prepare_field( cr, uid, 'Customer BIC', 'line.bank_id.bank.bic', - {'line': line}, context=context) + {'line': line}, convert_to_ascii=convert_to_ascii, + context=context) creditor_2_79 = etree.SubElement( credit_transfer_transaction_info_2_27, 'Cdtr') creditor_name = etree.SubElement(creditor_2_79, 'Nm') creditor_name.text = self._prepare_field( cr, uid, 'Customer Name', 'line.partner_id.name', - {'line': line}, name_maxsize, context=context) + {'line': line}, name_maxsize, + convert_to_ascii=convert_to_ascii, context=context) creditor_account_2_80 = etree.SubElement( credit_transfer_transaction_info_2_27, 'CdtrAcct') creditor_account_id = etree.SubElement( @@ -371,28 +424,69 @@ class banking_export_sepa_wizard(orm.TransientModel): cr, uid, self._prepare_field( cr, uid, 'Customer IBAN', 'line.bank_id.acc_number', {'line': line}, - context=context), + convert_to_ascii=convert_to_ascii, context=context), context=context) remittance_info_2_91 = etree.SubElement( credit_transfer_transaction_info_2_27, 'RmtInf') - # switch to Structured (Strdr) ? - # If we do it, beware that the format is not the same - # between pain 02 and pain 03 - remittance_info_unstructured_2_99 = etree.SubElement( - remittance_info_2_91, 'Ustrd') - remittance_info_unstructured_2_99.text = self._prepare_field( - cr, uid, 'Remittance Information', 'line.communication', - {'line': line}, 140, context=context) + if line.state == 'normal': + remittance_info_unstructured_2_99 = etree.SubElement( + remittance_info_2_91, 'Ustrd') + remittance_info_unstructured_2_99.text = \ + self._prepare_field( + cr, uid, 'Remittance Unstructured Information', + 'line.communication', {'line': line}, 140, + convert_to_ascii=convert_to_ascii, + context=context) + else: + if not line.struct_communication_type: + raise orm.except_orm( + _('Error:'), + _("Missing 'Structured Communication Type' on payment line with your reference '%s'.") + % (line.name)) + remittance_info_unstructured_2_100 = etree.SubElement( + remittance_info_2_91, 'Strd') + creditor_ref_information_2_120 = etree.SubElement( + remittance_info_unstructured_2_100, 'CdtrRefInf') + if pain_flavor in pain_03_to_05: + creditor_ref_info_type_2_121 = etree.SubElement( + creditor_ref_information_2_120, 'Tp') + creditor_ref_info_type_or_2_122 = etree.SubElement( + creditor_ref_info_type_2_121, 'CdOrPrtry') + creditor_ref_info_type_code_2_123 = etree.SubElement( + creditor_ref_info_type_or_2_122, 'Cd') + creditor_ref_info_type_issuer_2_125 = etree.SubElement( + creditor_ref_info_type_2_121, 'Issr') + creditor_reference_2_126 = etree.SubElement( + creditor_ref_information_2_120, 'Ref') + else: + creditor_ref_info_type_2_121 = etree.SubElement( + creditor_ref_information_2_120, 'CdtrRefTp') + creditor_ref_info_type_code_2_123 = etree.SubElement( + creditor_ref_info_type_2_121, 'Cd') + creditor_ref_info_type_issuer_2_125 = etree.SubElement( + creditor_ref_info_type_2_121, 'Issr') + creditor_reference_2_126 = etree.SubElement( + creditor_ref_information_2_120, 'CdtrRef') - if pain_flavor in [ - 'pain.001.001.03', 'pain.001.001.04', 'pain.001.001.05']: - nb_of_transactions_1_6.text = nb_of_transactions_2_4.text = \ - str(transactions_count) - control_sum_1_7.text = control_sum_2_5.text = \ - '%.2f' % amount_control_sum + creditor_ref_info_type_code_2_123.text = 'SCOR' + creditor_ref_info_type_issuer_2_125.text = \ + line.struct_communication_type + creditor_reference_2_126.text = \ + self._prepare_field( + cr, uid, 'Creditor Structured Reference', + 'line.communication', {'line': line}, 35, + convert_to_ascii=convert_to_ascii, + context=context) + if pain_flavor in pain_03_to_05: + nb_of_transactions_2_4.text = str(transactions_count_2_4) + control_sum_2_5.text = '%.2f' % amount_control_sum_2_5 + + if pain_flavor in pain_03_to_05: + nb_of_transactions_1_6.text = str(transactions_count_1_6) + control_sum_1_7.text = '%.2f' % amount_control_sum_1_7 else: - nb_of_transactions_1_6.text = str(transactions_count) - control_sum_1_7.text = '%.2f' % amount_control_sum + nb_of_transactions_1_6.text = str(transactions_count_1_6) + control_sum_1_7.text = '%.2f' % amount_control_sum_1_7 xml_string = etree.tostring( root, pretty_print=True, encoding='UTF-8', xml_declaration=True) @@ -405,7 +499,7 @@ class banking_export_sepa_wizard(orm.TransientModel): # CREATE the banking.export.sepa record file_id = self.pool.get('banking.export.sepa').create( cr, uid, self._prepare_export_sepa( - cr, uid, sepa_export, total_amount, transactions_count, + cr, uid, sepa_export, total_amount, transactions_count_1_6, xml_string, context=context), context=context) diff --git a/account_banking_sepa_credit_transfer/wizard/export_sepa_view.xml b/account_banking_sepa_credit_transfer/wizard/export_sepa_view.xml index 5d1d846e9..c85acf454 100644 --- a/account_banking_sepa_credit_transfer/wizard/export_sepa_view.xml +++ b/account_banking_sepa_credit_transfer/wizard/export_sepa_view.xml @@ -15,7 +15,6 @@ - From 87f2fc0af7c042447a181ac596fa983a8ec1b388 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Mon, 25 Nov 2013 22:49:05 +0100 Subject: [PATCH 20/43] FIX label : Customer (which is wrong, it is most of the time a Supplier !)-> Creditor More PEP8 stuff. --- .../wizard/export_sepa.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/account_banking_sepa_credit_transfer/wizard/export_sepa.py b/account_banking_sepa_credit_transfer/wizard/export_sepa.py index 79974d9b4..b21c57a99 100644 --- a/account_banking_sepa_credit_transfer/wizard/export_sepa.py +++ b/account_banking_sepa_credit_transfer/wizard/export_sepa.py @@ -114,7 +114,8 @@ class banking_export_sepa_wizard(orm.TransientModel): raise orm.except_orm( _('Error:'), _("Cannot compute the '%s' of the Payment Line with Invoice Reference '%s'.") - % (field_name, self.pool['account.invoice'].name_get(cr, uid, [line.ml_inv_ref.id], context=context)[0][1])) + % (field_name, self.pool['account.invoice'].name_get( + cr, uid, [line.ml_inv_ref.id], context=context)[0][1])) else: raise orm.except_orm( _('Error:'), @@ -325,12 +326,14 @@ class banking_export_sepa_wizard(orm.TransientModel): nb_of_transactions_2_4 = etree.SubElement( payment_info_2_0, 'NbOfTxs') control_sum_2_5 = etree.SubElement(payment_info_2_0, 'CtrlSum') - payment_type_info_2_6 = etree.SubElement(payment_info_2_0, 'PmtTpInf') + payment_type_info_2_6 = etree.SubElement( + payment_info_2_0, 'PmtTpInf') if priority: instruction_priority_2_7 = etree.SubElement( payment_type_info_2_6, 'InstrPrty') instruction_priority_2_7.text = priority - service_level_2_8 = etree.SubElement(payment_type_info_2_6, 'SvcLvl') + service_level_2_8 = etree.SubElement( + payment_type_info_2_6, 'SvcLvl') service_level_code_2_9 = etree.SubElement(service_level_2_8, 'Cd') service_level_code_2_9.text = 'SEPA' requested_exec_date_2_17 = etree.SubElement( @@ -339,7 +342,8 @@ class banking_export_sepa_wizard(orm.TransientModel): debtor_2_19 = etree.SubElement(payment_info_2_0, 'Dbtr') debtor_name = etree.SubElement(debtor_2_19, 'Nm') debtor_name.text = my_company_name - debtor_account_2_20 = etree.SubElement(payment_info_2_0, 'DbtrAcct') + debtor_account_2_20 = etree.SubElement( + payment_info_2_0, 'DbtrAcct') debtor_account_id = etree.SubElement(debtor_account_2_20, 'Id') debtor_account_iban = etree.SubElement(debtor_account_id, 'IBAN') debtor_account_iban.text = self._validate_iban( @@ -404,14 +408,14 @@ class banking_export_sepa_wizard(orm.TransientModel): creditor_agent_bic = etree.SubElement( creditor_agent_institution, bic_xml_tag) creditor_agent_bic.text = self._prepare_field( - cr, uid, 'Customer BIC', 'line.bank_id.bank.bic', + cr, uid, 'Creditor BIC', 'line.bank_id.bank.bic', {'line': line}, convert_to_ascii=convert_to_ascii, context=context) creditor_2_79 = etree.SubElement( credit_transfer_transaction_info_2_27, 'Cdtr') creditor_name = etree.SubElement(creditor_2_79, 'Nm') creditor_name.text = self._prepare_field( - cr, uid, 'Customer Name', 'line.partner_id.name', + cr, uid, 'Creditor Name', 'line.partner_id.name', {'line': line}, name_maxsize, convert_to_ascii=convert_to_ascii, context=context) creditor_account_2_80 = etree.SubElement( @@ -422,7 +426,7 @@ class banking_export_sepa_wizard(orm.TransientModel): creditor_account_id, 'IBAN') creditor_account_iban.text = self._validate_iban( cr, uid, self._prepare_field( - cr, uid, 'Customer IBAN', + cr, uid, 'Creditor IBAN', 'line.bank_id.acc_number', {'line': line}, convert_to_ascii=convert_to_ascii, context=context), context=context) From db6c581823c628bd5854064a56096fac16b16e90 Mon Sep 17 00:00:00 2001 From: Ruchir Shukla Date: Thu, 5 Dec 2013 14:48:03 +0530 Subject: [PATCH 21/43] make account_payment_shortcut installable so default Invoices will be selected in Wizard --- account_payment_shortcut/__openerp__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/account_payment_shortcut/__openerp__.py b/account_payment_shortcut/__openerp__.py index 8261bdcd2..830e37931 100644 --- a/account_payment_shortcut/__openerp__.py +++ b/account_payment_shortcut/__openerp__.py @@ -29,5 +29,5 @@ 'description': ''' When composing a payment order, select all candidates by default (in the second step of the "Select invoices to pay" wizard). ''', - 'installable': False, + 'installable': True, } From 1f9b56be79ae2bd4cb108d03f2f4bbf691235ff5 Mon Sep 17 00:00:00 2001 From: Ruchir Shukla Date: Thu, 5 Dec 2013 14:48:43 +0530 Subject: [PATCH 22/43] return Form view of Payment Orders so record will be reloaded --- account_banking_payment/model/payment_order_create.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/account_banking_payment/model/payment_order_create.py b/account_banking_payment/model/payment_order_create.py index c7ac88790..a3d1ed9b0 100644 --- a/account_banking_payment/model/payment_order_create.py +++ b/account_banking_payment/model/payment_order_create.py @@ -194,4 +194,11 @@ class payment_order_create(orm.TransientModel): or line.journal_id.currency.id or line.journal_id.company_id.currency_id.id), }, context=context) - return {'type': 'ir.actions.act_window_close'} + return {'name': _('Payment Orders'), + 'context': context, + 'view_type': 'form', + 'view_mode': 'form,tree', + 'res_model': 'payment.order', + 'res_id': context['active_id'], + 'type': 'ir.actions.act_window', + } From f377a391e89d98cf7a3fbcce3efcf037609772f2 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Thu, 12 Dec 2013 14:47:01 +0100 Subject: [PATCH 23/43] Start code factoring between SCT and SDD. --- account_banking_pain_base/__init__.py | 1 + account_banking_pain_base/__openerp__.py | 3 + .../banking_export_pain.py | 186 ++++++++++++++++++ account_banking_pain_base/company.py | 5 +- .../wizard/export_sepa.py | 171 +++------------- .../__openerp__.py | 2 +- .../wizard/export_sdd.py | 174 +++++----------- 7 files changed, 268 insertions(+), 274 deletions(-) create mode 100644 account_banking_pain_base/banking_export_pain.py diff --git a/account_banking_pain_base/__init__.py b/account_banking_pain_base/__init__.py index a54725775..6662843e6 100644 --- a/account_banking_pain_base/__init__.py +++ b/account_banking_pain_base/__init__.py @@ -23,3 +23,4 @@ from . import payment_line from . import payment_mode from . import company +from . import banking_export_pain diff --git a/account_banking_pain_base/__openerp__.py b/account_banking_pain_base/__openerp__.py index 8a66aaafa..5d461865e 100644 --- a/account_banking_pain_base/__openerp__.py +++ b/account_banking_pain_base/__openerp__.py @@ -27,6 +27,9 @@ 'website': 'http://openerp-community-association.org/', 'category': 'Hidden', 'depends': ['account_banking_payment_export'], + 'external_dependencies': { + 'python': ['unidecode', 'lxml'], + }, 'data': [ 'payment_line_view.xml', 'payment_mode_view.xml', diff --git a/account_banking_pain_base/banking_export_pain.py b/account_banking_pain_base/banking_export_pain.py new file mode 100644 index 000000000..6f84033a8 --- /dev/null +++ b/account_banking_pain_base/banking_export_pain.py @@ -0,0 +1,186 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# PAIN Base module for OpenERP +# Copyright (C) 2013 Akretion (http://www.akretion.com) +# @author: Alexis de Lattre +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp.osv import orm +from openerp.tools.translate import _ +from openerp.tools.safe_eval import safe_eval +from unidecode import unidecode +from lxml import etree +from openerp import tools +import logging + +logger = logging.getLogger(__name__) + + +class banking_export_pain(orm.AbstractModel): + _name = 'banking.export.pain' + + def _validate_iban(self, cr, uid, iban, context=None): + '''if IBAN is valid, returns IBAN + if IBAN is NOT valid, raises an error message''' + partner_bank_obj = self.pool.get('res.partner.bank') + if partner_bank_obj.is_iban_valid(cr, uid, iban, context=context): + return iban.replace(' ', '') + else: + raise orm.except_orm( + _('Error:'), _("This IBAN is not valid : %s") % iban) + + def _prepare_field( + self, cr, uid, field_name, field_value, eval_ctx, max_size=0, + convert_to_ascii=False, context=None): + '''This function is designed to be inherited !''' + assert isinstance(eval_ctx, dict), 'eval_ctx must contain a dict' + try: + value = safe_eval(field_value, eval_ctx) + # SEPA uses XML ; XML = UTF-8 ; UTF-8 = support for all characters + # But we are dealing with banks... + # and many banks don't want non-ASCCI characters ! + # cf section 1.4 "Character set" of the SEPA Credit Transfer + # Scheme Customer-to-bank guidelines + if convert_to_ascii: + value = unidecode(value) + except: + line = eval_ctx.get('line') + if line: + raise orm.except_orm( + _('Error:'), + _("Cannot compute the '%s' of the Payment Line with Invoice Reference '%s'.") + % (field_name, self.pool['account.invoice'].name_get( + cr, uid, [line.ml_inv_ref.id], context=context)[0][1])) + else: + raise orm.except_orm( + _('Error:'), + _("Cannot compute the '%s'.") % field_name) + if not isinstance(value, (str, unicode)): + raise orm.except_orm( + _('Field type error:'), + _("The type of the field '%s' is %s. It should be a string or unicode.") + % (field_name, type(value))) + if not value: + raise orm.except_orm( + _('Error:'), + _("The '%s' is empty or 0. It should have a non-null value.") + % field_name) + if max_size and len(value) > max_size: + value = value[0:max_size] + return value + + def _validate_xml(self, cr, uid, xml_string, pain_xsd_file): + xsd_etree_obj = etree.parse( + tools.file_open(pain_xsd_file)) + official_pain_schema = etree.XMLSchema(xsd_etree_obj) + + try: + root_to_validate = etree.fromstring(xml_string) + official_pain_schema.assertValid(root_to_validate) + except Exception, e: + logger.warning( + "The XML file is invalid against the XML Schema Definition") + logger.warning(xml_string) + logger.warning(e) + raise orm.except_orm( + _('Error:'), + _('The generated XML file is not valid against the official XML Schema Definition. The generated XML file and the full error have been written in the server logs. Here is the error, which may give you an idea on the cause of the problem : %s') + % str(e)) + return True + + def generate_initiating_party_block( + self, cr, uid, parent_node, sepa_export, gen_args, + context=None): + my_company_name = self._prepare_field( + cr, uid, 'Company Name', + 'sepa_export.payment_order_ids[0].mode.bank_id.partner_id.name', + {'sepa_export': sepa_export}, gen_args.get('name_maxsize'), + convert_to_ascii=gen_args.get('convert_to_ascii'), context=context) + initiating_party_1_8 = etree.SubElement(parent_node, 'InitgPty') + initiating_party_name = etree.SubElement(initiating_party_1_8, 'Nm') + initiating_party_name.text = my_company_name + initiating_party_identifier = self.pool['res.company'].\ + _get_initiating_party_identifier( + cr, uid, sepa_export.payment_order_ids[0].company_id.id, + context=context) + initiating_party_issuer = \ + sepa_export.payment_order_ids[0].company_id.initiating_party_issuer + if initiating_party_identifier and initiating_party_issuer: + iniparty_id = etree.SubElement(initiating_party_1_8, 'Id') + iniparty_org_id = etree.SubElement(iniparty_id, 'OrgId') + iniparty_org_other = etree.SubElement(iniparty_org_id, 'Othr') + iniparty_org_other_id = etree.SubElement(iniparty_org_other, 'Id') + iniparty_org_other_id.text = initiating_party_identifier + iniparty_org_other_issuer = etree.SubElement( + iniparty_org_other, 'Issr') + iniparty_org_other_issuer.text = initiating_party_issuer + return True + + def generate_party_bic( + self, cr, uid, parent_node, party_type, party_type_label, bic, + eval_ctx, gen_args, context=None): + '''Generate the piece of the XML file corresponding to BIC + This code is mutualized between TRF and DD''' + party_agent = etree.SubElement(parent_node, '%sAgt' % party_type) + party_agent_institution = etree.SubElement( + party_agent, 'FinInstnId') + party_agent_bic = etree.SubElement( + party_agent_institution, gen_args.get('bic_xml_tag')) + party_agent_bic.text = self._prepare_field( + cr, uid, '%s BIC' % party_type_label, bic, eval_ctx, + convert_to_ascii=gen_args.get('convert_to_ascii'), context=context) + return True + + def generate_party_block( + self, cr, uid, parent_node, party_type, order, name, iban, bic, + eval_ctx, gen_args, context=None): + '''Generate the piece of the XML file corresponding to Name+IBAN+BIC + This code is mutualized between TRF and DD''' + assert order in ('B', 'C'), "Order can be 'B' or 'C'" + if party_type == 'Cdtr': + party_type_label = 'Creditor' + elif party_type == 'Dbtr': + party_type_label = 'Debtor' + # At C level, the order is : BIC, Name, IBAN + # At B level, the order is : Name, IBAN, BIC + if order == 'C': + self.generate_party_bic( + cr, uid, parent_node, party_type, party_type_label, bic, + eval_ctx, gen_args, context=context) + party = etree.SubElement(parent_node, party_type) + party_name = etree.SubElement(party, 'Nm') + party_name.text = self._prepare_field( + cr, uid, '%s Name' % party_type_label, name, eval_ctx, + gen_args.get('name_maxsize'), + convert_to_ascii=gen_args.get('convert_to_ascii'), context=context) + party_account = etree.SubElement( + parent_node, '%sAcct' % party_type) + party_account_id = etree.SubElement(party_account, 'Id') + party_account_iban = etree.SubElement( + party_account_id, 'IBAN') + piban = self._prepare_field( + cr, uid, '%s IBAN' % party_type_label, iban, eval_ctx, + convert_to_ascii=gen_args.get('convert_to_ascii'), + context=context) + viban = self._validate_iban(cr, uid, piban, context=context) + party_account_iban.text = viban + if order == 'B': + self.generate_party_bic( + cr, uid, parent_node, party_type, party_type_label, bic, + eval_ctx, gen_args, context=context) + return True diff --git a/account_banking_pain_base/company.py b/account_banking_pain_base/company.py index b40f64440..c11c13d9b 100644 --- a/account_banking_pain_base/company.py +++ b/account_banking_pain_base/company.py @@ -38,7 +38,10 @@ class res_company(orm.Model): self, cr, uid, company_id, context=None): '''This function is designed to be inherited by localization modules''' assert isinstance(company_id, int), 'Only one company ID' - return False + # TODO REMOOOOOOOOOOOOOOOOOOOVE BEFORE COMMIT + + return self.browse(cr, uid, company_id).partner_id.vat + #return False def _initiating_party_issuer_default(self, cr, uid, context=None): '''This function is designed to be inherited by localization modules''' diff --git a/account_banking_sepa_credit_transfer/wizard/export_sepa.py b/account_banking_sepa_credit_transfer/wizard/export_sepa.py index b21c57a99..9948ab594 100644 --- a/account_banking_sepa_credit_transfer/wizard/export_sepa.py +++ b/account_banking_sepa_credit_transfer/wizard/export_sepa.py @@ -36,6 +36,7 @@ _logger = logging.getLogger(__name__) class banking_export_sepa_wizard(orm.TransientModel): _name = 'banking.export.sepa.wizard' + _inherit = ['banking.export.pain'] _description = 'Export SEPA Credit Transfer File' _columns = { @@ -76,16 +77,6 @@ class banking_export_sepa_wizard(orm.TransientModel): 'state': 'create', } - def _validate_iban(self, cr, uid, iban, context=None): - '''if IBAN is valid, returns IBAN - if IBAN is NOT valid, raises an error message''' - partner_bank_obj = self.pool.get('res.partner.bank') - if partner_bank_obj.is_iban_valid(cr, uid, iban, context=context): - return iban.replace(' ', '') - else: - raise orm.except_orm( - _('Error:'), _("This IBAN is not valid : %s") % iban) - def create(self, cr, uid, vals, context=None): payment_order_ids = context.get('active_ids', []) vals.update({ @@ -94,46 +85,6 @@ class banking_export_sepa_wizard(orm.TransientModel): return super(banking_export_sepa_wizard, self).create( cr, uid, vals, context=context) - def _prepare_field( - self, cr, uid, field_name, field_value, eval_ctx, max_size=0, - convert_to_ascii=False, context=None): - '''This function is designed to be inherited !''' - assert isinstance(eval_ctx, dict), 'eval_ctx must contain a dict' - try: - value = safe_eval(field_value, eval_ctx) - # SEPA uses XML ; XML = UTF-8 ; UTF-8 = support for all characters - # But we are dealing with banks... - # and many banks don't want non-ASCCI characters ! - # cf section 1.4 "Character set" of the SEPA Credit Transfer - # Scheme Customer-to-bank guidelines - if convert_to_ascii: - value = unidecode(value) - except: - line = eval_ctx.get('line') - if line: - raise orm.except_orm( - _('Error:'), - _("Cannot compute the '%s' of the Payment Line with Invoice Reference '%s'.") - % (field_name, self.pool['account.invoice'].name_get( - cr, uid, [line.ml_inv_ref.id], context=context)[0][1])) - else: - raise orm.except_orm( - _('Error:'), - _("Cannot compute the '%s'.") % field_name) - if not isinstance(value, (str, unicode)): - raise orm.except_orm( - _('Field type error:'), - _("The type of the field '%s' is %s. It should be a string or unicode.") - % (field_name, type(value))) - if not value: - raise orm.except_orm( - _('Error:'), - _("The '%s' is empty or 0. It should have a non-null value.") - % field_name) - if max_size and len(value) > max_size: - value = value[0:max_size] - return value - def _prepare_export_sepa( self, cr, uid, sepa_export, total_amount, transactions_count, xml_string, context=None): @@ -148,27 +99,6 @@ class banking_export_sepa_wizard(orm.TransientModel): ], } - def _validate_xml(self, cr, uid, xml_string, pain_flavor): - xsd_etree_obj = etree.parse( - tools.file_open( - 'account_banking_sepa_credit_transfer/data/%s.xsd' - % pain_flavor)) - official_pain_schema = etree.XMLSchema(xsd_etree_obj) - - try: - root_to_validate = etree.fromstring(xml_string) - official_pain_schema.assertValid(root_to_validate) - except Exception, e: - _logger.warning( - "The XML file is invalid against the XML Schema Definition") - _logger.warning(xml_string) - _logger.warning(e) - raise orm.except_orm( - _('Error:'), - _('The generated XML file is not valid against the official XML Schema Definition. The generated XML file and the full error have been written in the server logs. Here is the error, which may give you an idea on the cause of the problem : %s') - % str(e)) - return True - def create_sepa(self, cr, uid, ids, context=None): ''' Creates the SEPA Credit Transfer file. That's the important code ! @@ -210,6 +140,12 @@ class banking_export_sepa_wizard(orm.TransientModel): _("Payment Type Code '%s' is not supported. The only Payment Type Codes supported for SEPA Credit Transfers are 'pain.001.001.02', 'pain.001.001.03', 'pain.001.001.04' and 'pain.001.001.05'.") % pain_flavor) + gen_args = { + 'bic_xml_tag': bic_xml_tag, + 'name_maxsize': name_maxsize, + 'convert_to_ascii': convert_to_ascii, + } + pain_ns = { 'xsi': 'http://www.w3.org/2001/XMLSchema-instance', None: 'urn:iso:std:iso:20022:tech:xsd:%s' % pain_flavor, @@ -250,24 +186,9 @@ class banking_export_sepa_wizard(orm.TransientModel): if pain_flavor == 'pain.001.001.02': grouping = etree.SubElement(group_header_1_0, 'Grpg') grouping.text = 'GRPD' - initiating_party_1_8 = etree.SubElement(group_header_1_0, 'InitgPty') - initiating_party_name = etree.SubElement(initiating_party_1_8, 'Nm') - initiating_party_name.text = my_company_name - initiating_party_identifier = self.pool['res.company'].\ - _get_initiating_party_identifier( - cr, uid, sepa_export.payment_order_ids[0].company_id.id, - context=context) - initiating_party_issuer = \ - sepa_export.payment_order_ids[0].company_id.initiating_party_issuer - if initiating_party_identifier and initiating_party_issuer: - iniparty_id = etree.SubElement(initiating_party_1_8, 'Id') - iniparty_org_id = etree.SubElement(iniparty_id, 'OrgId') - iniparty_org_other = etree.SubElement(iniparty_org_id, 'Othr') - iniparty_org_other_id = etree.SubElement(iniparty_org_other, 'Id') - iniparty_org_other_id.text = initiating_party_identifier - iniparty_org_other_issuer = etree.SubElement( - iniparty_org_other, 'Issr') - iniparty_org_other_issuer.text = initiating_party_issuer + self.generate_initiating_party_block( + cr, uid, group_header_1_0, sepa_export, gen_args, + context=context) transactions_count_1_6 = 0 total_amount = 0.0 @@ -339,33 +260,14 @@ class banking_export_sepa_wizard(orm.TransientModel): requested_exec_date_2_17 = etree.SubElement( payment_info_2_0, 'ReqdExctnDt') requested_exec_date_2_17.text = requested_exec_date - debtor_2_19 = etree.SubElement(payment_info_2_0, 'Dbtr') - debtor_name = etree.SubElement(debtor_2_19, 'Nm') - debtor_name.text = my_company_name - debtor_account_2_20 = etree.SubElement( - payment_info_2_0, 'DbtrAcct') - debtor_account_id = etree.SubElement(debtor_account_2_20, 'Id') - debtor_account_iban = etree.SubElement(debtor_account_id, 'IBAN') - debtor_account_iban.text = self._validate_iban( - cr, uid, self._prepare_field( - cr, uid, 'Company IBAN', - 'sepa_export.payment_order_ids[0].mode.bank_id.acc_number', - {'sepa_export': sepa_export}, - convert_to_ascii=convert_to_ascii, context=context), - context=context) - debtor_agent_2_21 = etree.SubElement(payment_info_2_0, 'DbtrAgt') - debtor_agent_institution = etree.SubElement( - debtor_agent_2_21, 'FinInstnId') - debtor_agent_bic = etree.SubElement( - debtor_agent_institution, bic_xml_tag) - # TODO validate BIC with pattern - # [A-Z]{6,6}[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3,3}){0,1} - # because OpenERP doesn't have a constraint on BIC - debtor_agent_bic.text = self._prepare_field( - cr, uid, 'Company BIC', + + self.generate_party_block( + cr, uid, payment_info_2_0, 'Dbtr', 'B', + 'sepa_export.payment_order_ids[0].mode.bank_id.partner_id.name', + 'sepa_export.payment_order_ids[0].mode.bank_id.acc_number', 'sepa_export.payment_order_ids[0].mode.bank_id.bank.bic', {'sepa_export': sepa_export}, - convert_to_ascii=convert_to_ascii, context=context) + gen_args, context=context) charge_bearer_2_24 = etree.SubElement(payment_info_2_0, 'ChrgBr') charge_bearer_2_24.text = sepa_export.charge_bearer @@ -396,40 +298,19 @@ class banking_export_sepa_wizard(orm.TransientModel): instructed_amount_2_43.text = '%.2f' % line.amount_currency amount_control_sum_1_7 += line.amount_currency amount_control_sum_2_5 += line.amount_currency - creditor_agent_2_77 = etree.SubElement( - credit_transfer_transaction_info_2_27, 'CdtrAgt') - creditor_agent_institution = etree.SubElement( - creditor_agent_2_77, 'FinInstnId') + if not line.bank_id: raise orm.except_orm( _('Error:'), _("Missing Bank Account on invoice '%s' (payment order line reference '%s').") % (line.ml_inv_ref.number, line.name)) - creditor_agent_bic = etree.SubElement( - creditor_agent_institution, bic_xml_tag) - creditor_agent_bic.text = self._prepare_field( - cr, uid, 'Creditor BIC', 'line.bank_id.bank.bic', - {'line': line}, convert_to_ascii=convert_to_ascii, - context=context) - creditor_2_79 = etree.SubElement( - credit_transfer_transaction_info_2_27, 'Cdtr') - creditor_name = etree.SubElement(creditor_2_79, 'Nm') - creditor_name.text = self._prepare_field( - cr, uid, 'Creditor Name', 'line.partner_id.name', - {'line': line}, name_maxsize, - convert_to_ascii=convert_to_ascii, context=context) - creditor_account_2_80 = etree.SubElement( - credit_transfer_transaction_info_2_27, 'CdtrAcct') - creditor_account_id = etree.SubElement( - creditor_account_2_80, 'Id') - creditor_account_iban = etree.SubElement( - creditor_account_id, 'IBAN') - creditor_account_iban.text = self._validate_iban( - cr, uid, self._prepare_field( - cr, uid, 'Creditor IBAN', - 'line.bank_id.acc_number', {'line': line}, - convert_to_ascii=convert_to_ascii, context=context), - context=context) + self.generate_party_block( + cr, uid, credit_transfer_transaction_info_2_27, 'Cdtr', 'C', + 'line.partner_id.name', + 'line.bank_id.acc_number', + 'line.bank_id.bank.bic', + {'line': line}, gen_args, context=context) + remittance_info_2_91 = etree.SubElement( credit_transfer_transaction_info_2_27, 'RmtInf') if line.state == 'normal': @@ -498,7 +379,9 @@ class banking_export_sepa_wizard(orm.TransientModel): "Generated SEPA Credit Transfer XML file in format %s below" % pain_flavor) _logger.debug(xml_string) - self._validate_xml(cr, uid, xml_string, pain_flavor) + pain_xsd_file = \ + 'account_banking_sepa_credit_transfer/data/%s.xsd' % pain_flavor + self._validate_xml(cr, uid, xml_string, pain_xsd_file) # CREATE the banking.export.sepa record file_id = self.pool.get('banking.export.sepa').create( diff --git a/account_banking_sepa_direct_debit/__openerp__.py b/account_banking_sepa_direct_debit/__openerp__.py index 44c744a4a..070d965a1 100644 --- a/account_banking_sepa_direct_debit/__openerp__.py +++ b/account_banking_sepa_direct_debit/__openerp__.py @@ -26,7 +26,7 @@ 'author': 'Akretion', 'website': 'http://www.akretion.com', 'category': 'Banking addons', - 'depends': ['account_direct_debit'], + 'depends': ['account_direct_debit', 'account_banking_pain_base'], 'external_dependencies': { 'python': ['unidecode', 'lxml'], }, diff --git a/account_banking_sepa_direct_debit/wizard/export_sdd.py b/account_banking_sepa_direct_debit/wizard/export_sdd.py index 1f68674a7..39422b74c 100644 --- a/account_banking_sepa_direct_debit/wizard/export_sdd.py +++ b/account_banking_sepa_direct_debit/wizard/export_sdd.py @@ -36,6 +36,7 @@ _logger = logging.getLogger(__name__) class banking_export_sdd_wizard(orm.TransientModel): _name = 'banking.export.sdd.wizard' + _inherit = ['banking.export.pain'] _description = 'Export SEPA Direct Debit File' _columns = { 'state': fields.selection([ @@ -78,16 +79,6 @@ class banking_export_sdd_wizard(orm.TransientModel): 'state': 'create', } - def _validate_iban(self, cr, uid, iban, context=None): - '''if IBAN is valid, returns IBAN - if IBAN is NOT valid, raises an error message''' - partner_bank_obj = self.pool.get('res.partner.bank') - if partner_bank_obj.is_iban_valid(cr, uid, iban, context=context): - return iban.replace(' ', '') - else: - raise orm.except_orm( - _('Error:'), _("This IBAN is not valid : %s") % iban) - def create(self, cr, uid, vals, context=None): payment_order_ids = context.get('active_ids', []) vals.update({ @@ -96,44 +87,6 @@ class banking_export_sdd_wizard(orm.TransientModel): return super(banking_export_sdd_wizard, self).create( cr, uid, vals, context=context) - def _prepare_field( - self, cr, uid, field_name, field_value, eval_ctx, max_size=0, - context=None): - '''This function is designed to be inherited !''' - assert isinstance(eval_ctx, dict), 'eval_ctx must contain a dict' - try: - # SEPA uses XML ; XML = UTF-8 ; UTF-8 = support for all characters - # But we are dealing with banks... - # and many banks don't want non-ASCCI characters ! - # cf section 1.4 "Character set" of the SEPA Core Direct Debit - # Customer-to-bank implementation guidelines - value = unidecode(safe_eval(field_value, eval_ctx)) - except: - line = eval_ctx.get('line') - if line: - raise orm.except_orm( - _('Error:'), - _("Cannot compute the '%s' of the Payment Line with Invoice Reference '%s'.") - % (field_name, self.pool['account.invoice'].name_get( - cr, uid, [line.ml_inv_ref.id], context=context)[0][1])) - else: - raise orm.except_orm( - _('Error:'), - _("Cannot compute the '%s'.") % field_name) - if not isinstance(value, (str, unicode)): - raise orm.except_orm( - _('Field type error:'), - _("The type of the field '%s' is %s. It should be a string or unicode.") - % (field_name, type(value))) - if not value: - raise orm.except_orm( - _('Error:'), - _("The '%s' is empty or 0. It should have a non-null value.") - % field_name) - if max_size and len(value) > max_size: - value = value[0:max_size] - return value - def _prepare_export_sepa( self, cr, uid, sepa_export, total_amount, transactions_count, xml_string, context=None): @@ -149,26 +102,6 @@ class banking_export_sdd_wizard(orm.TransientModel): ], } - def _validate_xml(self, cr, uid, xml_string, pain_flavor): - xsd_etree_obj = etree.parse( - tools.file_open( - 'account_banking_sepa_direct_debit/data/%s.xsd' - % pain_flavor)) - official_pain_schema = etree.XMLSchema(xsd_etree_obj) - - try: - root_to_validate = etree.fromstring(xml_string) - official_pain_schema.assertValid(root_to_validate) - except Exception, e: - _logger.warning( - "The XML file is invalid against the XML Schema Definition") - _logger.warning(xml_string) - _logger.warning(e) - raise orm.except_orm( - _('Error:'), - _('The generated XML file is not valid against the official XML Schema Definition. The generated XML file and the full error have been written in the server logs. Here is the error, which may give you an idea on the cause of the problem : %s') - % str(e)) - return True def _get_previous_bank(self, cr, uid, payline, context=None): payline_obj = self.pool['payment.line'] @@ -203,6 +136,8 @@ class banking_export_sdd_wizard(orm.TransientModel): sepa_export = self.browse(cr, uid, ids[0], context=context) pain_flavor = sepa_export.payment_order_ids[0].mode.type.code + convert_to_ascii = \ + sepa_export.payment_order_ids[0].mode.convert_to_ascii if pain_flavor == 'pain.008.001.02': bic_xml_tag = 'BIC' name_maxsize = 70 @@ -217,6 +152,13 @@ class banking_export_sdd_wizard(orm.TransientModel): root_xml_tag = 'CstmrDrctDbtInitn' else: raise orm.except_orm(_('Error:'), _("Payment Type Code '%s' is not supported. The only Payment Type Code supported for SEPA Direct Debit are 'pain.008.001.02', 'pain.008.001.03' and 'pain.008.001.04'.") % pain_flavor) + + gen_args = { + 'bic_xml_tag': bic_xml_tag, + 'name_maxsize': name_maxsize, + 'convert_to_ascii': convert_to_ascii, + } + if sepa_export.requested_collec_date: my_requested_collec_date = sepa_export.requested_collec_date else: @@ -243,15 +185,16 @@ class banking_export_sdd_wizard(orm.TransientModel): message_identification_1_1.text = self._prepare_field( cr, uid, 'Message Identification', 'sepa_export.payment_order_ids[0].reference', - {'sepa_export': sepa_export}, 35, context=context) + {'sepa_export': sepa_export}, 35, + convert_to_ascii=convert_to_ascii, context=context) creation_date_time_1_2 = etree.SubElement(group_header_1_0, 'CreDtTm') creation_date_time_1_2.text = datetime.strftime( datetime.today(), '%Y-%m-%dT%H:%M:%S') nb_of_transactions_1_6 = etree.SubElement(group_header_1_0, 'NbOfTxs') control_sum_1_7 = etree.SubElement(group_header_1_0, 'CtrlSum') - initiating_party_1_8 = etree.SubElement(group_header_1_0, 'InitgPty') - initiating_party_name = etree.SubElement(initiating_party_1_8, 'Nm') - initiating_party_name.text = my_company_name + self.generate_initiating_party_block( + cr, uid, group_header_1_0, sepa_export, gen_args, + context=context) transactions_count_1_6 = 0 total_amount = 0.0 @@ -312,7 +255,7 @@ class banking_export_sdd_wizard(orm.TransientModel): cr, uid, 'Payment Information Identification', "sequence_type + '-' + sepa_export.payment_order_ids[0].reference", {'sepa_export': sepa_export, 'sequence_type': sequence_type}, - 35, context=context) + 35, convert_to_ascii=convert_to_ascii, context=context) payment_method_2_2 = etree.SubElement(payment_info_2_0, 'PmtMtd') payment_method_2_2.text = 'DD' # batch_booking is in "Payment Info" with pain.008.001.02/03 @@ -347,30 +290,14 @@ class banking_export_sdd_wizard(orm.TransientModel): requested_collec_date_2_18 = etree.SubElement( payment_info_2_0, 'ReqdColltnDt') requested_collec_date_2_18.text = my_requested_collec_date - creditor_2_19 = etree.SubElement(payment_info_2_0, 'Cdtr') - creditor_name = etree.SubElement(creditor_2_19, 'Nm') - creditor_name.text = my_company_name - creditor_account_2_20 = etree.SubElement( - payment_info_2_0, 'CdtrAcct') - creditor_account_id = etree.SubElement(creditor_account_2_20, 'Id') - creditor_account_iban = etree.SubElement( - creditor_account_id, 'IBAN') - creditor_account_iban.text = self._validate_iban( - cr, uid, self._prepare_field( - cr, uid, 'Company IBAN', - 'sepa_export.payment_order_ids[0].mode.bank_id.acc_number', - {'sepa_export': sepa_export}, context=context), - context=context) - creditor_agent_2_21 = etree.SubElement(payment_info_2_0, 'CdtrAgt') - creditor_agent_institution = etree.SubElement( - creditor_agent_2_21, 'FinInstnId') - creditor_agent_bic = etree.SubElement( - creditor_agent_institution, bic_xml_tag) - creditor_agent_bic.text = self._prepare_field( - cr, uid, 'Company BIC', + self.generate_party_block( + cr, uid, payment_info_2_0, 'Cdtr', 'B', + 'sepa_export.payment_order_ids[0].mode.bank_id.partner_id.name', + 'sepa_export.payment_order_ids[0].mode.bank_id.acc_number', 'sepa_export.payment_order_ids[0].mode.bank_id.bank.bic', - {'sepa_export': sepa_export}, context=context) + {'sepa_export': sepa_export}, + gen_args, context=context) charge_bearer_2_24 = etree.SubElement(payment_info_2_0, 'ChrgBr') charge_bearer_2_24.text = sepa_export.charge_bearer @@ -385,7 +312,8 @@ class banking_export_sdd_wizard(orm.TransientModel): csi_other_id.text = self._prepare_field( cr, uid, 'SEPA Creditor Identifier', 'sepa_export.payment_order_ids[0].company_id.sepa_creditor_identifier', - {'sepa_export': sepa_export}, context=context) + {'sepa_export': sepa_export}, + convert_to_ascii=convert_to_ascii, context=context) csi_scheme_name = etree.SubElement(csi_other, 'SchmeNm') csi_scheme_name_proprietary = etree.SubElement( csi_scheme_name, 'Prtry') @@ -404,10 +332,12 @@ class banking_export_sdd_wizard(orm.TransientModel): payment_identification_2_29, 'EndToEndId') end2end_identification_2_31.text = self._prepare_field( cr, uid, 'End to End Identification', 'line.name', - {'line': line}, 35, context=context) + {'line': line}, 35, + convert_to_ascii=convert_to_ascii, context=context) currency_name = self._prepare_field( cr, uid, 'Currency Code', 'line.currency.name', - {'line': line}, 3, context=context) + {'line': line}, 3, convert_to_ascii=convert_to_ascii, + context=context) instructed_amount_2_44 = etree.SubElement( dd_transaction_info_2_28, 'InstdAmt', Ccy=currency_name) instructed_amount_2_44.text = '%.2f' % line.amount_currency @@ -422,13 +352,15 @@ class banking_export_sdd_wizard(orm.TransientModel): mandate_identification_2_48.text = self._prepare_field( cr, uid, 'Unique Mandate Reference', 'line.sdd_mandate_id.unique_mandate_reference', - {'line': line}, 35, context=context) + {'line': line}, 35, + convert_to_ascii=convert_to_ascii, context=context) mandate_signature_date_2_49 = etree.SubElement( mandate_related_info_2_47, 'DtOfSgntr') mandate_signature_date_2_49.text = self._prepare_field( cr, uid, 'Mandate Signature Date', 'line.sdd_mandate_id.signature_date', - {'line': line}, 10, context=context) + {'line': line}, 10, + convert_to_ascii=convert_to_ascii, context=context) if (sequence_type == 'FRST' and line.sdd_mandate_id.last_debit_date): previous_bank = self._get_previous_bank( @@ -451,6 +383,7 @@ class banking_export_sdd_wizard(orm.TransientModel): cr, uid, 'Original Debtor Account', 'previous_bank.acc_number', {'previous_bank': previous_bank}, + convert_to_ascii=convert_to_ascii, context=context), context=context) else: @@ -464,6 +397,7 @@ class banking_export_sdd_wizard(orm.TransientModel): cr, uid, 'Original Debtor Agent', 'previous_bank.bank.bic', {'previous_bank': previous_bank}, + convert_to_ascii=convert_to_ascii, context=context) ori_debtor_agent_other = etree.SubElement( ori_debtor_agent_institution, 'Othr') @@ -472,32 +406,13 @@ class banking_export_sdd_wizard(orm.TransientModel): ori_debtor_agent_other_id.text = 'SMNDA' # SMNDA = Same Mandate New Debtor Agent - debtor_agent_2_70 = etree.SubElement( - dd_transaction_info_2_28, 'DbtrAgt') - debtor_agent_institution = etree.SubElement( - debtor_agent_2_70, 'FinInstnId') - debtor_agent_bic = etree.SubElement( - debtor_agent_institution, bic_xml_tag) - debtor_agent_bic.text = self._prepare_field( - cr, uid, 'Customer BIC', 'line.bank_id.bank.bic', - {'line': line}, context=context) - debtor_2_72 = etree.SubElement( - dd_transaction_info_2_28, 'Dbtr') - debtor_name = etree.SubElement(debtor_2_72, 'Nm') - debtor_name.text = self._prepare_field( - cr, uid, 'Customer Name', 'line.partner_id.name', - {'line': line}, name_maxsize, context=context) - debtor_account_2_73 = etree.SubElement( - dd_transaction_info_2_28, 'DbtrAcct') - debtor_account_id = etree.SubElement(debtor_account_2_73, 'Id') - debtor_account_iban = etree.SubElement( - debtor_account_id, 'IBAN') - debtor_account_iban.text = self._validate_iban( - cr, uid, self._prepare_field( - cr, uid, 'Customer IBAN', - 'line.bank_id.acc_number', {'line': line}, - context=context), - context=context) + self.generate_party_block( + cr, uid, dd_transaction_info_2_28, 'Dbtr', 'C', + 'line.partner_id.name', + 'line.bank_id.acc_number', + 'line.bank_id.bank.bic', + {'line': line}, gen_args, context=context) + remittance_info_2_88 = etree.SubElement( dd_transaction_info_2_28, 'RmtInf') # switch to Structured (Strdr) ? If we do it, beware that the format is not the same between pain 02 and pain 03 @@ -505,7 +420,8 @@ class banking_export_sdd_wizard(orm.TransientModel): remittance_info_2_88, 'Ustrd') remittance_info_unstructured_2_89.text = self._prepare_field( cr, uid, 'Remittance Information', 'line.communication', - {'line': line}, 140, context=context) + {'line': line}, 140, convert_to_ascii=convert_to_ascii, + context=context) nb_of_transactions_2_4.text = str(transactions_count_2_4) control_sum_2_5.text = '%.2f' % amount_control_sum_2_5 nb_of_transactions_1_6.text = str(transactions_count_1_6) @@ -516,7 +432,9 @@ class banking_export_sdd_wizard(orm.TransientModel): _logger.debug( "Generated SDD XML file in format %s below" % pain_flavor) _logger.debug(xml_string) - self._validate_xml(cr, uid, xml_string, pain_flavor) + pain_xsd_file = \ + 'account_banking_sepa_direct_debit/data/%s.xsd' % pain_flavor + self._validate_xml(cr, uid, xml_string, pain_xsd_file) # CREATE the banking.export.sepa record file_id = self.pool.get('banking.export.sdd').create( From 2613ec77a760ccfca64c86a101f0ce6d57ee44d5 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Thu, 12 Dec 2013 22:46:16 +0100 Subject: [PATCH 24/43] More code factoring between SCT and SDD As a consequence, we now have support for structured remittance info in SDD. --- .../banking_export_pain.py | 87 ++++++++++++++++++ .../wizard/export_sepa.py | 91 ++----------------- .../account_banking_sdd_view.xml | 2 +- .../wizard/export_sdd.py | 34 ++----- 4 files changed, 103 insertions(+), 111 deletions(-) diff --git a/account_banking_pain_base/banking_export_pain.py b/account_banking_pain_base/banking_export_pain.py index 6f84033a8..334c106c2 100644 --- a/account_banking_pain_base/banking_export_pain.py +++ b/account_banking_pain_base/banking_export_pain.py @@ -23,6 +23,7 @@ from openerp.osv import orm from openerp.tools.translate import _ from openerp.tools.safe_eval import safe_eval +from datetime import datetime from unidecode import unidecode from lxml import etree from openerp import tools @@ -103,6 +104,36 @@ class banking_export_pain(orm.AbstractModel): % str(e)) return True + def generate_group_header_block( + self, cr, uid, parent_node, sepa_export, gen_args, context=None): + group_header_1_0 = etree.SubElement(parent_node, 'GrpHdr') + message_identification_1_1 = etree.SubElement( + group_header_1_0, 'MsgId') + message_identification_1_1.text = self._prepare_field( + cr, uid, 'Message Identification', + 'sepa_export.payment_order_ids[0].reference', + {'sepa_export': sepa_export}, 35, + convert_to_ascii=gen_args.get('convert_to_ascii'), context=context) + creation_date_time_1_2 = etree.SubElement(group_header_1_0, 'CreDtTm') + creation_date_time_1_2.text = datetime.strftime( + datetime.today(), '%Y-%m-%dT%H:%M:%S') + if gen_args.get('pain_flavor') == 'pain.001.001.02': + # batch_booking is in "Group header" with pain.001.001.02 + # and in "Payment info" in pain.001.001.03/04 + batch_booking = etree.SubElement(group_header_1_0, 'BtchBookg') + batch_booking.text = str(sepa_export.batch_booking).lower() + nb_of_transactions_1_6 = etree.SubElement( + group_header_1_0, 'NbOfTxs') + control_sum_1_7 = etree.SubElement(group_header_1_0, 'CtrlSum') + # Grpg removed in pain.001.001.03 + if gen_args.get('pain_flavor') == 'pain.001.001.02': + grouping = etree.SubElement(group_header_1_0, 'Grpg') + grouping.text = 'GRPD' + self.generate_initiating_party_block( + cr, uid, group_header_1_0, sepa_export, gen_args, + context=context) + return group_header_1_0, nb_of_transactions_1_6, control_sum_1_7 + def generate_initiating_party_block( self, cr, uid, parent_node, sepa_export, gen_args, context=None): @@ -184,3 +215,59 @@ class banking_export_pain(orm.AbstractModel): cr, uid, parent_node, party_type, party_type_label, bic, eval_ctx, gen_args, context=context) return True + + def generate_remittance_info_block( + self, cr, uid, parent_node, line, gen_args, context=None): + + remittance_info_2_91 = etree.SubElement( + parent_node, 'RmtInf') + if line.state == 'normal': + remittance_info_unstructured_2_99 = etree.SubElement( + remittance_info_2_91, 'Ustrd') + remittance_info_unstructured_2_99.text = \ + self._prepare_field( + cr, uid, 'Remittance Unstructured Information', + 'line.communication', {'line': line}, 140, + convert_to_ascii=gen_args.get('convert_to_ascii'), + context=context) + else: + if not line.struct_communication_type: + raise orm.except_orm( + _('Error:'), + _("Missing 'Structured Communication Type' on payment line with your reference '%s'.") + % (line.name)) + remittance_info_unstructured_2_100 = etree.SubElement( + remittance_info_2_91, 'Strd') + creditor_ref_information_2_120 = etree.SubElement( + remittance_info_unstructured_2_100, 'CdtrRefInf') + if gen_args.get('pain_flavor') == 'pain.001.001.02': + creditor_ref_info_type_2_121 = etree.SubElement( + creditor_ref_information_2_120, 'CdtrRefTp') + creditor_ref_info_type_code_2_123 = etree.SubElement( + creditor_ref_info_type_2_121, 'Cd') + creditor_ref_info_type_issuer_2_125 = etree.SubElement( + creditor_ref_info_type_2_121, 'Issr') + creditor_reference_2_126 = etree.SubElement( + creditor_ref_information_2_120, 'CdtrRef') + else: + creditor_ref_info_type_2_121 = etree.SubElement( + creditor_ref_information_2_120, 'Tp') + creditor_ref_info_type_or_2_122 = etree.SubElement( + creditor_ref_info_type_2_121, 'CdOrPrtry') + creditor_ref_info_type_code_2_123 = etree.SubElement( + creditor_ref_info_type_or_2_122, 'Cd') + creditor_ref_info_type_issuer_2_125 = etree.SubElement( + creditor_ref_info_type_2_121, 'Issr') + creditor_reference_2_126 = etree.SubElement( + creditor_ref_information_2_120, 'Ref') + + creditor_ref_info_type_code_2_123.text = 'SCOR' + creditor_ref_info_type_issuer_2_125.text = \ + line.struct_communication_type + creditor_reference_2_126.text = \ + self._prepare_field( + cr, uid, 'Creditor Structured Reference', + 'line.communication', {'line': line}, 35, + convert_to_ascii=gen_args.get('convert_to_ascii'), + context=context) + return True diff --git a/account_banking_sepa_credit_transfer/wizard/export_sepa.py b/account_banking_sepa_credit_transfer/wizard/export_sepa.py index 9948ab594..a7042cca7 100644 --- a/account_banking_sepa_credit_transfer/wizard/export_sepa.py +++ b/account_banking_sepa_credit_transfer/wizard/export_sepa.py @@ -23,13 +23,11 @@ from openerp.osv import orm, fields import base64 -from datetime import datetime from openerp.tools.translate import _ from openerp.tools.safe_eval import safe_eval from openerp import tools, netsvc from lxml import etree import logging -from unidecode import unidecode _logger = logging.getLogger(__name__) @@ -144,6 +142,7 @@ class banking_export_sepa_wizard(orm.TransientModel): 'bic_xml_tag': bic_xml_tag, 'name_maxsize': name_maxsize, 'convert_to_ascii': convert_to_ascii, + 'pain_flavor': pain_flavor, } pain_ns = { @@ -156,39 +155,10 @@ class banking_export_sepa_wizard(orm.TransientModel): pain_03_to_05 = \ ['pain.001.001.03', 'pain.001.001.04', 'pain.001.001.05'] - my_company_name = self._prepare_field( - cr, uid, 'Company Name', - 'sepa_export.payment_order_ids[0].mode.bank_id.partner_id.name', - {'sepa_export': sepa_export}, name_maxsize, - convert_to_ascii=convert_to_ascii, context=context) - # A. Group header - group_header_1_0 = etree.SubElement(pain_root, 'GrpHdr') - message_identification_1_1 = etree.SubElement( - group_header_1_0, 'MsgId') - message_identification_1_1.text = self._prepare_field( - cr, uid, 'Message Identification', - 'sepa_export.payment_order_ids[0].reference', - {'sepa_export': sepa_export}, 35, - convert_to_ascii=convert_to_ascii, context=context) - creation_date_time_1_2 = etree.SubElement(group_header_1_0, 'CreDtTm') - creation_date_time_1_2.text = datetime.strftime( - datetime.today(), '%Y-%m-%dT%H:%M:%S') - if pain_flavor == 'pain.001.001.02': - # batch_booking is in "Group header" with pain.001.001.02 - # and in "Payment info" in pain.001.001.03/04 - batch_booking = etree.SubElement(group_header_1_0, 'BtchBookg') - batch_booking.text = str(sepa_export.batch_booking).lower() - nb_of_transactions_1_6 = etree.SubElement( - group_header_1_0, 'NbOfTxs') - control_sum_1_7 = etree.SubElement(group_header_1_0, 'CtrlSum') - # Grpg removed in pain.001.001.03 - if pain_flavor == 'pain.001.001.02': - grouping = etree.SubElement(group_header_1_0, 'Grpg') - grouping.text = 'GRPD' - self.generate_initiating_party_block( - cr, uid, group_header_1_0, sepa_export, gen_args, - context=context) + group_header_1_0, nb_of_transactions_1_6, control_sum_1_7 = \ + self.generate_group_header_block( + cr, uid, pain_root, sepa_export, gen_args, context=context) transactions_count_1_6 = 0 total_amount = 0.0 @@ -311,57 +281,10 @@ class banking_export_sepa_wizard(orm.TransientModel): 'line.bank_id.bank.bic', {'line': line}, gen_args, context=context) - remittance_info_2_91 = etree.SubElement( - credit_transfer_transaction_info_2_27, 'RmtInf') - if line.state == 'normal': - remittance_info_unstructured_2_99 = etree.SubElement( - remittance_info_2_91, 'Ustrd') - remittance_info_unstructured_2_99.text = \ - self._prepare_field( - cr, uid, 'Remittance Unstructured Information', - 'line.communication', {'line': line}, 140, - convert_to_ascii=convert_to_ascii, - context=context) - else: - if not line.struct_communication_type: - raise orm.except_orm( - _('Error:'), - _("Missing 'Structured Communication Type' on payment line with your reference '%s'.") - % (line.name)) - remittance_info_unstructured_2_100 = etree.SubElement( - remittance_info_2_91, 'Strd') - creditor_ref_information_2_120 = etree.SubElement( - remittance_info_unstructured_2_100, 'CdtrRefInf') - if pain_flavor in pain_03_to_05: - creditor_ref_info_type_2_121 = etree.SubElement( - creditor_ref_information_2_120, 'Tp') - creditor_ref_info_type_or_2_122 = etree.SubElement( - creditor_ref_info_type_2_121, 'CdOrPrtry') - creditor_ref_info_type_code_2_123 = etree.SubElement( - creditor_ref_info_type_or_2_122, 'Cd') - creditor_ref_info_type_issuer_2_125 = etree.SubElement( - creditor_ref_info_type_2_121, 'Issr') - creditor_reference_2_126 = etree.SubElement( - creditor_ref_information_2_120, 'Ref') - else: - creditor_ref_info_type_2_121 = etree.SubElement( - creditor_ref_information_2_120, 'CdtrRefTp') - creditor_ref_info_type_code_2_123 = etree.SubElement( - creditor_ref_info_type_2_121, 'Cd') - creditor_ref_info_type_issuer_2_125 = etree.SubElement( - creditor_ref_info_type_2_121, 'Issr') - creditor_reference_2_126 = etree.SubElement( - creditor_ref_information_2_120, 'CdtrRef') + self.generate_remittance_info_block( + cr, uid, credit_transfer_transaction_info_2_27, + line, gen_args, context=context) - creditor_ref_info_type_code_2_123.text = 'SCOR' - creditor_ref_info_type_issuer_2_125.text = \ - line.struct_communication_type - creditor_reference_2_126.text = \ - self._prepare_field( - cr, uid, 'Creditor Structured Reference', - 'line.communication', {'line': line}, 35, - convert_to_ascii=convert_to_ascii, - context=context) if pain_flavor in pain_03_to_05: nb_of_transactions_2_4.text = str(transactions_count_2_4) control_sum_2_5.text = '%.2f' % amount_control_sum_2_5 diff --git a/account_banking_sepa_direct_debit/account_banking_sdd_view.xml b/account_banking_sepa_direct_debit/account_banking_sdd_view.xml index 079e2023b..f3712479a 100644 --- a/account_banking_sepa_direct_debit/account_banking_sdd_view.xml +++ b/account_banking_sepa_direct_debit/account_banking_sdd_view.xml @@ -56,7 +56,7 @@ - Generated SEPA Direct Debit Files + SEPA Direct Debit Files banking.export.sdd form tree,form diff --git a/account_banking_sepa_direct_debit/wizard/export_sdd.py b/account_banking_sepa_direct_debit/wizard/export_sdd.py index 39422b74c..e285a36c7 100644 --- a/account_banking_sepa_direct_debit/wizard/export_sdd.py +++ b/account_banking_sepa_direct_debit/wizard/export_sdd.py @@ -29,7 +29,6 @@ import base64 from datetime import datetime, timedelta from lxml import etree import logging -from unidecode import unidecode _logger = logging.getLogger(__name__) @@ -157,6 +156,7 @@ class banking_export_sdd_wizard(orm.TransientModel): 'bic_xml_tag': bic_xml_tag, 'name_maxsize': name_maxsize, 'convert_to_ascii': convert_to_ascii, + 'pain_flavor': pain_flavor, } if sepa_export.requested_collec_date: @@ -179,22 +179,9 @@ class banking_export_sdd_wizard(orm.TransientModel): {'sepa_export': sepa_export}, name_maxsize, context=context) # A. Group header - group_header_1_0 = etree.SubElement(pain_root, 'GrpHdr') - message_identification_1_1 = etree.SubElement( - group_header_1_0, 'MsgId') - message_identification_1_1.text = self._prepare_field( - cr, uid, 'Message Identification', - 'sepa_export.payment_order_ids[0].reference', - {'sepa_export': sepa_export}, 35, - convert_to_ascii=convert_to_ascii, context=context) - creation_date_time_1_2 = etree.SubElement(group_header_1_0, 'CreDtTm') - creation_date_time_1_2.text = datetime.strftime( - datetime.today(), '%Y-%m-%dT%H:%M:%S') - nb_of_transactions_1_6 = etree.SubElement(group_header_1_0, 'NbOfTxs') - control_sum_1_7 = etree.SubElement(group_header_1_0, 'CtrlSum') - self.generate_initiating_party_block( - cr, uid, group_header_1_0, sepa_export, gen_args, - context=context) + group_header_1_0, nb_of_transactions_1_6, control_sum_1_7 = \ + self.generate_group_header_block( + cr, uid, pain_root, sepa_export, gen_args, context=context) transactions_count_1_6 = 0 total_amount = 0.0 @@ -413,15 +400,10 @@ class banking_export_sdd_wizard(orm.TransientModel): 'line.bank_id.bank.bic', {'line': line}, gen_args, context=context) - remittance_info_2_88 = etree.SubElement( - dd_transaction_info_2_28, 'RmtInf') - # switch to Structured (Strdr) ? If we do it, beware that the format is not the same between pain 02 and pain 03 - remittance_info_unstructured_2_89 = etree.SubElement( - remittance_info_2_88, 'Ustrd') - remittance_info_unstructured_2_89.text = self._prepare_field( - cr, uid, 'Remittance Information', 'line.communication', - {'line': line}, 140, convert_to_ascii=convert_to_ascii, - context=context) + self.generate_remittance_info_block( + cr, uid, dd_transaction_info_2_28, + line, gen_args, context=context) + nb_of_transactions_2_4.text = str(transactions_count_2_4) control_sum_2_5.text = '%.2f' % amount_control_sum_2_5 nb_of_transactions_1_6.text = str(transactions_count_1_6) From 681bad8fbf815f756a26c1e06d008f76dfad5b78 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Thu, 12 Dec 2013 23:19:53 +0100 Subject: [PATCH 25/43] The requested collection date now uses the fields date_prefered and date_scheduled of payment.order, instead of the field in the SDD wizard. --- .../wizard/export_sepa.py | 7 ++- .../account_banking_sdd.py | 2 - .../account_banking_sdd_view.xml | 2 - .../wizard/export_sdd.py | 61 +++++++++++-------- .../wizard/export_sdd_view.xml | 1 - 5 files changed, 40 insertions(+), 33 deletions(-) diff --git a/account_banking_sepa_credit_transfer/wizard/export_sepa.py b/account_banking_sepa_credit_transfer/wizard/export_sepa.py index a7042cca7..5a58299c2 100644 --- a/account_banking_sepa_credit_transfer/wizard/export_sepa.py +++ b/account_banking_sepa_credit_transfer/wizard/export_sepa.py @@ -177,10 +177,11 @@ class banking_export_sepa_wizard(orm.TransientModel): requested_exec_date = payment_order.date_scheduled or today else: requested_exec_date = today - if (requested_exec_date, priority) in lines_per_group: - lines_per_group[(requested_exec_date, priority)].append(line) + key = (requested_exec_date, priority) + if key in lines_per_group: + lines_per_group[key].append(line) else: - lines_per_group[(requested_exec_date, priority)] = [line] + lines_per_group[key] = [line] # Write requested_exec_date on 'Payment date' of the pay line if requested_exec_date != line.date: self.pool['payment.line'].write( diff --git a/account_banking_sepa_direct_debit/account_banking_sdd.py b/account_banking_sepa_direct_debit/account_banking_sdd.py index d65aff415..7b2be778f 100644 --- a/account_banking_sepa_direct_debit/account_banking_sdd.py +++ b/account_banking_sepa_direct_debit/account_banking_sdd.py @@ -56,8 +56,6 @@ class banking_export_sdd(orm.Model): 'banking_export_sepa_id', 'account_order_id', 'Payment Orders', readonly=True), - 'requested_collec_date': fields.date( - 'Requested Collection Date', readonly=True), 'nb_transactions': fields.integer( 'Number of Transactions', readonly=True), 'total_amount': fields.float( diff --git a/account_banking_sepa_direct_debit/account_banking_sdd_view.xml b/account_banking_sepa_direct_debit/account_banking_sdd_view.xml index f3712479a..f89ec7389 100644 --- a/account_banking_sepa_direct_debit/account_banking_sdd_view.xml +++ b/account_banking_sepa_direct_debit/account_banking_sdd_view.xml @@ -16,7 +16,6 @@ - @@ -47,7 +46,6 @@ - diff --git a/account_banking_sepa_direct_debit/wizard/export_sdd.py b/account_banking_sepa_direct_debit/wizard/export_sdd.py index e285a36c7..59d031362 100644 --- a/account_banking_sepa_direct_debit/wizard/export_sdd.py +++ b/account_banking_sepa_direct_debit/wizard/export_sdd.py @@ -45,9 +45,6 @@ class banking_export_sdd_wizard(orm.TransientModel): 'batch_booking': fields.boolean( 'Batch Booking', help="If true, the bank statement will display only one credit line for all the direct debits of the SEPA file ; if false, the bank statement will display one credit line per direct debit of the SEPA file."), - 'requested_collec_date': fields.date( - 'Requested Collection Date', - help='This is the date on which you would like the collection to be made by the bank. Please keep in mind that there are minimum delays for SEPA direct debits that depend on the type of mandate and the type of sequence.'), 'charge_bearer': fields.selection([ ('SLEV', 'Following Service Level'), ('SHAR', 'Shared'), @@ -92,7 +89,6 @@ class banking_export_sdd_wizard(orm.TransientModel): return { 'batch_booking': sepa_export.batch_booking, 'charge_bearer': sepa_export.charge_bearer, - 'requested_collec_date': sepa_export.requested_collec_date, 'total_amount': total_amount, 'nb_transactions': transactions_count, 'file': base64.encodestring(xml_string), @@ -159,12 +155,6 @@ class banking_export_sdd_wizard(orm.TransientModel): 'pain_flavor': pain_flavor, } - if sepa_export.requested_collec_date: - my_requested_collec_date = sepa_export.requested_collec_date - else: - my_requested_collec_date = datetime.strftime( - datetime.today() + timedelta(days=1), '%Y-%m-%d') - pain_ns = { 'xsi': 'http://www.w3.org/2001/XMLSchema-instance', None: 'urn:iso:std:iso:20022:tech:xsd:%s' % pain_flavor, @@ -186,14 +176,23 @@ class banking_export_sdd_wizard(orm.TransientModel): transactions_count_1_6 = 0 total_amount = 0.0 amount_control_sum_1_7 = 0.0 - lines_per_seq_type = {} - # key = sequence type ; value = list of lines as objects + lines_per_group = {} + # key = (requested_collec_date, priority, sequence type) + # value = list of lines as objects # Iterate on payment orders + today = fields.date.context_today(self, cr, uid, context=context) for payment_order in sepa_export.payment_order_ids: total_amount = total_amount + payment_order.total # Iterate each payment lines for line in payment_order.line_ids: transactions_count_1_6 += 1 + priority = line.priority + if payment_order.date_prefered == 'due': + requested_collec_date = line.ml_maturity_date or today + elif payment_order.date_prefered == 'fixed': + requested_collec_date = payment_order.date_scheduled or today + else: + requested_collec_date = today if not line.sdd_mandate_id: raise orm.except_orm( _('Error:'), @@ -208,10 +207,7 @@ class banking_export_sdd_wizard(orm.TransientModel): line.sdd_mandate_id.partner_id.name)) if line.sdd_mandate_id.type == 'oneoff': if not line.sdd_mandate_id.last_debit_date: - if lines_per_seq_type.get('OOFF'): - lines_per_seq_type['OOFF'].append(line) - else: - lines_per_seq_type['OOFF'] = [line] + seq_type = 'OOFF' else: raise orm.except_orm( _('Error:'), @@ -228,21 +224,32 @@ class banking_export_sdd_wizard(orm.TransientModel): seq_type_label = line.sdd_mandate_id.recurrent_sequence_type assert seq_type_label is not False seq_type = seq_type_map[seq_type_label] - if lines_per_seq_type.get(seq_type): - lines_per_seq_type[seq_type].append(line) - else: - lines_per_seq_type[seq_type] = [line] - for sequence_type, lines in lines_per_seq_type.items(): + key = (requested_collec_date, priority, seq_type) + if key in lines_per_group: + lines_per_group[key].append(line) + else: + lines_per_group[key] = [line] + # Write requested_exec_date on 'Payment date' of the pay line + if requested_collec_date != line.date: + self.pool['payment.line'].write( + cr, uid, line.id, + {'date': requested_collec_date}, context=context) + + for (requested_collec_date, priority, sequence_type), lines in lines_per_group.items(): # B. Payment info payment_info_2_0 = etree.SubElement(pain_root, 'PmtInf') payment_info_identification_2_1 = etree.SubElement( payment_info_2_0, 'PmtInfId') payment_info_identification_2_1.text = self._prepare_field( cr, uid, 'Payment Information Identification', - "sequence_type + '-' + sepa_export.payment_order_ids[0].reference", - {'sepa_export': sepa_export, 'sequence_type': sequence_type}, - 35, convert_to_ascii=convert_to_ascii, context=context) + "sepa_export.payment_order_ids[0].reference + '-' + sequence_type + '-' + requested_collec_date.replace('-', '') + '-' + priority", + { + 'sepa_export': sepa_export, + 'sequence_type': sequence_type, + 'priority': priority, + 'requested_collec_date': requested_collec_date, + }, 35, convert_to_ascii=convert_to_ascii, context=context) payment_method_2_2 = etree.SubElement(payment_info_2_0, 'PmtMtd') payment_method_2_2.text = 'DD' # batch_booking is in "Payment Info" with pain.008.001.02/03 @@ -257,6 +264,10 @@ class banking_export_sdd_wizard(orm.TransientModel): control_sum_2_5 = etree.SubElement(payment_info_2_0, 'CtrlSum') payment_type_info_2_6 = etree.SubElement( payment_info_2_0, 'PmtTpInf') + if priority: + instruction_priority_2_7 = etree.SubElement( + payment_type_info_2_6, 'InstrPrty') + instruction_priority_2_7.text = priority service_level_2_8 = etree.SubElement( payment_type_info_2_6, 'SvcLvl') service_level_code_2_9 = etree.SubElement(service_level_2_8, 'Cd') @@ -276,7 +287,7 @@ class banking_export_sdd_wizard(orm.TransientModel): requested_collec_date_2_18 = etree.SubElement( payment_info_2_0, 'ReqdColltnDt') - requested_collec_date_2_18.text = my_requested_collec_date + requested_collec_date_2_18.text = requested_collec_date self.generate_party_block( cr, uid, payment_info_2_0, 'Cdtr', 'B', diff --git a/account_banking_sepa_direct_debit/wizard/export_sdd_view.xml b/account_banking_sepa_direct_debit/wizard/export_sdd_view.xml index c1b8a77c2..3699de91c 100644 --- a/account_banking_sepa_direct_debit/wizard/export_sdd_view.xml +++ b/account_banking_sepa_direct_debit/wizard/export_sdd_view.xml @@ -15,7 +15,6 @@ - From 466a748ca4d7ecd80d5eeb059cc39a366e2c5ea3 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Fri, 13 Dec 2013 00:40:45 +0100 Subject: [PATCH 26/43] Add support for direct debit migration from national format to SEPA Source : Standard-XML-SDD-Initiation-v3-EN by Febelfin --- .../banking_export_pain.py | 17 +++++++ .../account_banking_sdd.py | 7 +++ account_banking_sepa_direct_debit/company.py | 2 + .../company_view.xml | 1 + .../sdd_mandate_view.xml | 2 + .../wizard/export_sdd.py | 49 ++++++++++++------- 6 files changed, 60 insertions(+), 18 deletions(-) diff --git a/account_banking_pain_base/banking_export_pain.py b/account_banking_pain_base/banking_export_pain.py index 334c106c2..ffabe82dc 100644 --- a/account_banking_pain_base/banking_export_pain.py +++ b/account_banking_pain_base/banking_export_pain.py @@ -271,3 +271,20 @@ class banking_export_pain(orm.AbstractModel): convert_to_ascii=gen_args.get('convert_to_ascii'), context=context) return True + + def generate_creditor_scheme_identification( + self, cr, uid, parent_node, identification, identification_label, + eval_ctx, scheme_name_proprietary, gen_args, context=None): + csi_id = etree.SubElement( + parent_node, 'Id') + csi_privateid = csi_id = etree.SubElement(csi_id, 'PrvtId') + csi_other = etree.SubElement(csi_privateid, 'Othr') + csi_other_id = etree.SubElement(csi_other, 'Id') + csi_other_id.text = self._prepare_field( + cr, uid, identification_label, identification, eval_ctx, + convert_to_ascii=gen_args.get('convert_to_ascii'), context=context) + csi_scheme_name = etree.SubElement(csi_other, 'SchmeNm') + csi_scheme_name_proprietary = etree.SubElement( + csi_scheme_name, 'Prtry') + csi_scheme_name_proprietary.text = scheme_name_proprietary + return True diff --git a/account_banking_sepa_direct_debit/account_banking_sdd.py b/account_banking_sepa_direct_debit/account_banking_sdd.py index 7b2be778f..b54f3002c 100644 --- a/account_banking_sepa_direct_debit/account_banking_sdd.py +++ b/account_banking_sepa_direct_debit/account_banking_sdd.py @@ -148,6 +148,12 @@ class sdd_mandate(orm.Model): help="Only valid mandates can be used in a payment line. A cancelled mandate is a mandate that has been cancelled by the customer. A one-off mandate expires after its first use. A recurrent mandate expires after it's final use or if it hasn't been used for 36 months."), 'payment_line_ids': fields.one2many( 'payment.line', 'sdd_mandate_id', "Related Payment Lines"), + 'sepa_migrated': fields.boolean( + 'Migrated to SEPA', + help="If this field is not active, the mandate section of the direct debit file will contain the Original Mandate Identification and the Original Creditor Scheme Identification."), + 'original_mandate_identification': fields.char( + 'Original Mandate Identification', size=35, + help="When the field 'Migrated to SEPA' is not active, this field will be used as the Original Mandate Identification in the the Direct Debit file."), } _defaults = { @@ -157,6 +163,7 @@ class sdd_mandate(orm.Model): 'unique_mandate_reference': lambda self, cr, uid, ctx: self.pool['ir.sequence'].get(cr, uid, 'sdd.mandate.reference'), 'state': 'draft', + 'sepa_migrated': True, } _sql_constraints = [( diff --git a/account_banking_sepa_direct_debit/company.py b/account_banking_sepa_direct_debit/company.py index eb3730d57..ba4c7b7c8 100644 --- a/account_banking_sepa_direct_debit/company.py +++ b/account_banking_sepa_direct_debit/company.py @@ -32,6 +32,8 @@ class res_company(orm.Model): 'sepa_creditor_identifier': fields.char( 'SEPA Creditor Identifier', size=35, help="Enter the Creditor Identifier that has been attributed to your company to make SEPA Direct Debits. This identifier is composed of :\n- your country ISO code (2 letters)\n- a 2-digits checkum\n- a 3-letters business code\n- a country-specific identifier"), + 'original_creditor_identifier': fields.char( + 'Original Creditor Identifier', size=70), } def is_sepa_creditor_identifier_valid( diff --git a/account_banking_sepa_direct_debit/company_view.xml b/account_banking_sepa_direct_debit/company_view.xml index 7691844c1..4599454f5 100644 --- a/account_banking_sepa_direct_debit/company_view.xml +++ b/account_banking_sepa_direct_debit/company_view.xml @@ -14,6 +14,7 @@ + diff --git a/account_banking_sepa_direct_debit/sdd_mandate_view.xml b/account_banking_sepa_direct_debit/sdd_mandate_view.xml index ad11d8804..15ec3a675 100644 --- a/account_banking_sepa_direct_debit/sdd_mandate_view.xml +++ b/account_banking_sepa_direct_debit/sdd_mandate_view.xml @@ -35,6 +35,8 @@ + + diff --git a/account_banking_sepa_direct_debit/wizard/export_sdd.py b/account_banking_sepa_direct_debit/wizard/export_sdd.py index 59d031362..babec1260 100644 --- a/account_banking_sepa_direct_debit/wizard/export_sdd.py +++ b/account_banking_sepa_direct_debit/wizard/export_sdd.py @@ -302,20 +302,11 @@ class banking_export_sdd_wizard(orm.TransientModel): creditor_scheme_identification_2_27 = etree.SubElement( payment_info_2_0, 'CdtrSchmeId') - csi_id = etree.SubElement( - creditor_scheme_identification_2_27, 'Id') - csi_privateid = csi_id = etree.SubElement(csi_id, 'PrvtId') - csi_other = etree.SubElement(csi_privateid, 'Othr') - csi_other_id = etree.SubElement(csi_other, 'Id') - csi_other_id.text = self._prepare_field( - cr, uid, 'SEPA Creditor Identifier', + self.generate_creditor_scheme_identification( + cr, uid, creditor_scheme_identification_2_27, 'sepa_export.payment_order_ids[0].company_id.sepa_creditor_identifier', - {'sepa_export': sepa_export}, - convert_to_ascii=convert_to_ascii, context=context) - csi_scheme_name = etree.SubElement(csi_other, 'SchmeNm') - csi_scheme_name_proprietary = etree.SubElement( - csi_scheme_name, 'Prtry') - csi_scheme_name_proprietary.text = 'SEPA' + 'SEPA Creditor Identifier', {'sepa_export': sepa_export}, + 'SEPA', gen_args, context=context) transactions_count_2_4 = 0 amount_control_sum_2_5 = 0.0 @@ -359,16 +350,18 @@ class banking_export_sdd_wizard(orm.TransientModel): 'line.sdd_mandate_id.signature_date', {'line': line}, 10, convert_to_ascii=convert_to_ascii, context=context) - if (sequence_type == 'FRST' - and line.sdd_mandate_id.last_debit_date): + if sequence_type == 'FRST' and ( + line.sdd_mandate_id.last_debit_date or + not line.sdd_mandate_id.sepa_migrated): previous_bank = self._get_previous_bank( cr, uid, line, context=context) - if previous_bank: + if previous_bank or not line.sdd_mandate_id.sepa_migrated: amendment_indicator_2_50 = etree.SubElement( mandate_related_info_2_47, 'AmdmntInd') amendment_indicator_2_50.text = 'true' amendment_info_details_2_51 = etree.SubElement( mandate_related_info_2_47, 'AmdmntInfDtls') + if previous_bank: if previous_bank.bank.bic == line.bank_id.bank.bic: ori_debtor_account_2_57 = etree.SubElement( amendment_info_details_2_51, 'OrgnlDbtrAcct') @@ -403,6 +396,24 @@ class banking_export_sdd_wizard(orm.TransientModel): ori_debtor_agent_other, 'Id') ori_debtor_agent_other_id.text = 'SMNDA' # SMNDA = Same Mandate New Debtor Agent + elif not line.sdd_mandate_id.sepa_migrated: + ori_mandate_identification_2_52 = etree.SubElement( + amendment_info_details_2_51, 'OrgnlMndtId') + ori_mandate_identification_2_52.text = \ + self._prepare_field( + cr, uid, 'Original Mandate Identification', + 'line.sdd_mandate_id.original_mandate_identification', + {'line': line}, + convert_to_ascii=convert_to_ascii, + context=context) + ori_creditor_scheme_id_2_53 = etree.SubElement( + amendment_info_details_2_51, 'OrgnlCdtrSchmeId') + self.generate_creditor_scheme_identification( + cr, uid, ori_creditor_scheme_id_2_53, + 'sepa_export.payment_order_ids[0].company_id.original_creditor_identifier', + 'Original Creditor Identifier', + {'sepa_export': sepa_export}, + 'SEPA', gen_args, context=context) self.generate_party_block( cr, uid, dd_transaction_info_2_28, 'Dbtr', 'C', @@ -494,6 +505,8 @@ class banking_export_sdd_wizard(orm.TransientModel): self.pool['sdd.mandate'].write( cr, uid, to_expire_ids, {'state': 'expired'}, context=context) self.pool['sdd.mandate'].write( - cr, uid, first_mandate_ids, - {'recurrent_sequence_type': 'recurring'}, context=context) + cr, uid, first_mandate_ids, { + 'recurrent_sequence_type': 'recurring', + 'sepa_migrated': True, + }, context=context) return {'type': 'ir.actions.act_window_close'} From a39b2e2038c84310d5d362d1bde83b4a61784cc9 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Mon, 16 Dec 2013 00:46:50 +0100 Subject: [PATCH 27/43] Add group in order to mask the fields for "Original Mandate Indentification" for user s in countries that don't required it. Add tracking on important fields of the mandate. Better form view on company. Update constraint on mandate following my devs on "Original Mandate Identification". --- account_banking_pain_base/company.py | 5 +- .../__openerp__.py | 1 + .../account_banking_sdd.py | 67 +++++++++++-------- .../company_view.xml | 8 +-- .../sdd_mandate_view.xml | 4 +- .../original_mandate_required_security.xml | 17 +++++ 6 files changed, 65 insertions(+), 37 deletions(-) create mode 100644 account_banking_sepa_direct_debit/security/original_mandate_required_security.xml diff --git a/account_banking_pain_base/company.py b/account_banking_pain_base/company.py index c11c13d9b..b40f64440 100644 --- a/account_banking_pain_base/company.py +++ b/account_banking_pain_base/company.py @@ -38,10 +38,7 @@ class res_company(orm.Model): self, cr, uid, company_id, context=None): '''This function is designed to be inherited by localization modules''' assert isinstance(company_id, int), 'Only one company ID' - # TODO REMOOOOOOOOOOOOOOOOOOOVE BEFORE COMMIT - - return self.browse(cr, uid, company_id).partner_id.vat - #return False + return False def _initiating_party_issuer_default(self, cr, uid, context=None): '''This function is designed to be inherited by localization modules''' diff --git a/account_banking_sepa_direct_debit/__openerp__.py b/account_banking_sepa_direct_debit/__openerp__.py index 070d965a1..95ac05413 100644 --- a/account_banking_sepa_direct_debit/__openerp__.py +++ b/account_banking_sepa_direct_debit/__openerp__.py @@ -31,6 +31,7 @@ 'python': ['unidecode', 'lxml'], }, 'data': [ + 'security/original_mandate_required_security.xml', 'account_banking_sdd_view.xml', 'sdd_mandate_view.xml', 'res_partner_bank_view.xml', diff --git a/account_banking_sepa_direct_debit/account_banking_sdd.py b/account_banking_sepa_direct_debit/account_banking_sdd.py index b54f3002c..28759ef64 100644 --- a/account_banking_sepa_direct_debit/account_banking_sdd.py +++ b/account_banking_sepa_direct_debit/account_banking_sdd.py @@ -118,24 +118,27 @@ class sdd_mandate(orm.Model): } _columns = { - 'partner_bank_id': fields.many2one('res.partner.bank', 'Bank Account'), + 'partner_bank_id': fields.many2one( + 'res.partner.bank', 'Bank Account', track_visibility='onchange'), 'partner_id': fields.related( 'partner_bank_id', 'partner_id', type='many2one', relation='res.partner', string='Partner', readonly=True), 'company_id': fields.many2one('res.company', 'Company', required=True), 'unique_mandate_reference': fields.char( - 'Unique Mandate Reference', size=35, readonly=True), + 'Unique Mandate Reference', size=35, readonly=True, + track_visibility='always'), 'type': fields.selection([ ('recurrent', 'Recurrent'), ('oneoff', 'One-Off'), - ], 'Type of Mandate', required=True), + ], 'Type of Mandate', required=True, track_visibility='always'), 'recurrent_sequence_type': fields.selection([ ('first', 'First'), ('recurring', 'Recurring'), ('final', 'Final'), - ], 'Sequence Type for Next Debit', + ], 'Sequence Type for Next Debit', track_visibility='onchange', help="This field is only used for Recurrent mandates, not for One-Off mandates."), - 'signature_date': fields.date('Date of Signature of the Mandate'), + 'signature_date': fields.date( + 'Date of Signature of the Mandate', track_visibility='onchange'), 'scan': fields.binary('Scan of the Mandate'), 'last_debit_date': fields.date( 'Date of the Last Debit', readonly=True), @@ -149,10 +152,11 @@ class sdd_mandate(orm.Model): 'payment_line_ids': fields.one2many( 'payment.line', 'sdd_mandate_id', "Related Payment Lines"), 'sepa_migrated': fields.boolean( - 'Migrated to SEPA', - help="If this field is not active, the mandate section of the direct debit file will contain the Original Mandate Identification and the Original Creditor Scheme Identification."), + 'Migrated to SEPA', track_visibility='onchange', + help="If this field is not active, the mandate section of the next direct debit file that include this mandate will contain the 'Original Mandate Identification' and the 'Original Creditor Scheme Identification'. This is required in a few countries (Belgium for instance), but not in all countries. If this is not required in your country, you should keep this field always active."), 'original_mandate_identification': fields.char( 'Original Mandate Identification', size=35, + track_visibility='onchange', help="When the field 'Migrated to SEPA' is not active, this field will be used as the Original Mandate Identification in the the Direct Debit file."), } @@ -172,48 +176,57 @@ class sdd_mandate(orm.Model): 'A Mandate with the same reference already exists for this company !' )] - def _check_sdd_mandate(self, cr, uid, ids, context=None): - for mandate in self.read(cr, uid, ids, [ - 'last_debit_date', 'signature_date', - 'unique_mandate_reference', 'state', 'partner_bank_id', - 'type', 'recurrent_sequence_type', - ], context=context): - if (mandate['signature_date'] and - mandate['signature_date'] > + def _check_sdd_mandate(self, cr, uid, ids): + for mandate in self.browse(cr, uid, ids): + if (mandate.signature_date and + mandate.signature_date > datetime.today().strftime('%Y-%m-%d')): raise orm.except_orm( _('Error:'), _("The date of signature of mandate '%s' is in the future!") - % mandate['unique_mandate_reference']) - if mandate['state'] == 'valid' and not mandate['signature_date']: + % mandate.unique_mandate_reference) + if mandate.state == 'valid' and not mandate.signature_date: raise orm.except_orm( _('Error:'), _("Cannot validate the mandate '%s' without a date of signature.") - % mandate['unique_mandate_reference']) - if mandate['state'] == 'valid' and not mandate['partner_bank_id']: + % mandate.unique_mandate_reference) + if mandate.state == 'valid' and not mandate.partner_bank_id: raise orm.except_orm( _('Error:'), _("Cannot validate the mandate '%s' because it is not attached to a bank account.") - % mandate['unique_mandate_reference']) + % mandate.unique_mandate_reference) - if (mandate['signature_date'] and mandate['last_debit_date'] and - mandate['signature_date'] > mandate['last_debit_date']): + if (mandate.signature_date and mandate.last_debit_date and + mandate.signature_date > mandate.last_debit_date): raise orm.except_orm( _('Error:'), _("The mandate '%s' can't have a date of last debit before the date of signature.") - % mandate['unique_mandate_reference']) - if (mandate['type'] == 'recurrent' - and not mandate['recurrent_sequence_type']): + % mandate.unique_mandate_reference) + if (mandate.type == 'recurrent' + and not mandate.recurrent_sequence_type): raise orm.except_orm( _('Error:'), _("The recurrent mandate '%s' must have a sequence type.") - % mandate['unique_mandate_reference']) + % mandate.unique_mandate_reference) + if (mandate.type == 'recurrent' and not mandate.sepa_migrated + and mandate.recurrent_sequence_type != 'first'): + raise orm.except_orm( + _('Error:'), + _("The recurrent mandate '%s' which is not marked as 'Migrated to SEPA' must have its recurrent sequence type set to 'First'.") + % mandate.unique_mandate_reference) + if (mandate.type == 'recurrent' and not mandate.sepa_migrated + and not mandate.original_mandate_identification): + raise orm.except_orm( + _('Error:'), + _("You must set the 'Original Mandate Identification' on the recurrent mandate '%s' which is not marked as 'Migrated to SEPA'.") + % mandate.unique_mandate_reference) return True _constraints = [ (_check_sdd_mandate, "Error msg in raise", [ 'last_debit_date', 'signature_date', 'state', 'partner_bank_id', - 'type', 'recurrent_sequence_type', + 'type', 'recurrent_sequence_type', 'sepa_migrated', + 'original_mandate_identification', ]), ] diff --git a/account_banking_sepa_direct_debit/company_view.xml b/account_banking_sepa_direct_debit/company_view.xml index 4599454f5..e4c9e0b93 100644 --- a/account_banking_sepa_direct_debit/company_view.xml +++ b/account_banking_sepa_direct_debit/company_view.xml @@ -10,12 +10,12 @@ sepa_direct_debit.res.company.form res.company - + - + - - + + diff --git a/account_banking_sepa_direct_debit/sdd_mandate_view.xml b/account_banking_sepa_direct_debit/sdd_mandate_view.xml index 15ec3a675..d86f74f5b 100644 --- a/account_banking_sepa_direct_debit/sdd_mandate_view.xml +++ b/account_banking_sepa_direct_debit/sdd_mandate_view.xml @@ -35,8 +35,8 @@ - - + + diff --git a/account_banking_sepa_direct_debit/security/original_mandate_required_security.xml b/account_banking_sepa_direct_debit/security/original_mandate_required_security.xml new file mode 100644 index 000000000..e6a8570cf --- /dev/null +++ b/account_banking_sepa_direct_debit/security/original_mandate_required_security.xml @@ -0,0 +1,17 @@ + + + + + + + + Original Mandate Required (SEPA) + + + + + From a9c7a67825c690b6b0682c20c10016105163dd17 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Mon, 16 Dec 2013 15:36:42 +0100 Subject: [PATCH 28/43] Add support for Party Identifier for Belgium. Can be easily extended for other countries. --- account_banking_pain_base/company.py | 32 ++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/account_banking_pain_base/company.py b/account_banking_pain_base/company.py index b40f64440..31c709fb5 100644 --- a/account_banking_pain_base/company.py +++ b/account_banking_pain_base/company.py @@ -36,13 +36,37 @@ class res_company(orm.Model): def _get_initiating_party_identifier( self, cr, uid, company_id, context=None): - '''This function is designed to be inherited by localization modules''' + '''The code here may be different from one country to another. + If you need to add support for an additionnal country, you can + contribute your code here or inherit this function in the + localization modules for your country''' assert isinstance(company_id, int), 'Only one company ID' - return False + company = self.browse(cr, uid, company_id, context=context) + company_vat = company.vat + party_identifier = False + if company_vat and company_vat[0:2].upper() in ['BE']: + party_identifier = company_vat[2:].replace(' ', '') + return party_identifier def _initiating_party_issuer_default(self, cr, uid, context=None): - '''This function is designed to be inherited by localization modules''' - return '' + '''If you need to add support for an additionnal country, you can + add an entry in the dict "party_issuer_per_country" here + or inherit this function in the localization modules for + your country''' + initiating_party_issuer = '' + # If your country require the 'Initiating Party Issuer', you should + # contribute the entry for your country in the dict below + party_issuer_per_country = { + 'BE': 'KBO-BCE', # KBO-BCE = the registry of companies in Belgium + } + company_id = self._company_default_get( + cr, uid, 'res.company', context=context) + if company_id: + company = self.browse(cr, uid, company_id, context=context) + country_code = company.country_id.code + initiating_party_issuer = party_issuer_per_country.get( + country_code, '') + return initiating_party_issuer def _initiating_party_issuer_def(self, cr, uid, context=None): return self._initiating_party_issuer_default( From 58fefbf94585f202a4c57132df1771e1e67654b3 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Fri, 20 Dec 2013 14:13:20 +0100 Subject: [PATCH 29/43] Mutualize more code between SCT and SDD. --- .../banking_export_pain.py | 92 ++++++++++++-- .../wizard/export_sepa.py | 90 ++++---------- .../wizard/export_sdd.py | 112 ++++-------------- 3 files changed, 128 insertions(+), 166 deletions(-) diff --git a/account_banking_pain_base/banking_export_pain.py b/account_banking_pain_base/banking_export_pain.py index ffabe82dc..28edd97a0 100644 --- a/account_banking_pain_base/banking_export_pain.py +++ b/account_banking_pain_base/banking_export_pain.py @@ -28,6 +28,7 @@ from unidecode import unidecode from lxml import etree from openerp import tools import logging +import base64 logger = logging.getLogger(__name__) @@ -47,8 +48,10 @@ class banking_export_pain(orm.AbstractModel): def _prepare_field( self, cr, uid, field_name, field_value, eval_ctx, max_size=0, - convert_to_ascii=False, context=None): + gen_args=None, context=None): '''This function is designed to be inherited !''' + if gen_args is None: + gen_args = {} assert isinstance(eval_ctx, dict), 'eval_ctx must contain a dict' try: value = safe_eval(field_value, eval_ctx) @@ -57,7 +60,7 @@ class banking_export_pain(orm.AbstractModel): # and many banks don't want non-ASCCI characters ! # cf section 1.4 "Character set" of the SEPA Credit Transfer # Scheme Customer-to-bank guidelines - if convert_to_ascii: + if gen_args.get('convert_to_ascii'): value = unidecode(value) except: line = eval_ctx.get('line') @@ -85,6 +88,20 @@ class banking_export_pain(orm.AbstractModel): value = value[0:max_size] return value + def _prepare_export_sepa( + self, cr, uid, sepa_export, total_amount, transactions_count, + xml_string, gen_args, context=None): + return { + 'batch_booking': sepa_export.batch_booking, + 'charge_bearer': sepa_export.charge_bearer, + 'total_amount': total_amount, + 'nb_transactions': transactions_count, + 'file': base64.encodestring(xml_string), + 'payment_order_ids': [ + (6, 0, [x.id for x in sepa_export.payment_order_ids]) + ], + } + def _validate_xml(self, cr, uid, xml_string, pain_xsd_file): xsd_etree_obj = etree.parse( tools.file_open(pain_xsd_file)) @@ -113,7 +130,7 @@ class banking_export_pain(orm.AbstractModel): cr, uid, 'Message Identification', 'sepa_export.payment_order_ids[0].reference', {'sepa_export': sepa_export}, 35, - convert_to_ascii=gen_args.get('convert_to_ascii'), context=context) + gen_args=gen_args, context=context) creation_date_time_1_2 = etree.SubElement(group_header_1_0, 'CreDtTm') creation_date_time_1_2.text = datetime.strftime( datetime.today(), '%Y-%m-%dT%H:%M:%S') @@ -134,6 +151,61 @@ class banking_export_pain(orm.AbstractModel): context=context) return group_header_1_0, nb_of_transactions_1_6, control_sum_1_7 + def generate_start_payment_info_block( + self, cr, uid, parent_node, sepa_export, payment_info_ident, + priority, local_instrument, sequence_type, requested_date, + eval_ctx, gen_args, context=None): + payment_info_2_0 = etree.SubElement(parent_node, 'PmtInf') + payment_info_identification_2_1 = etree.SubElement( + payment_info_2_0, 'PmtInfId') + payment_info_identification_2_1.text = self._prepare_field( + cr, uid, 'Payment Information Identification', + payment_info_ident, eval_ctx, 35, + gen_args=gen_args, context=context) + payment_method_2_2 = etree.SubElement(payment_info_2_0, 'PmtMtd') + if gen_args.get('pain_flavor').startswith('pain.008.'): + payment_method_2_2.text = 'DD' + request_date_tag = 'ReqdColltnDt' + else: + payment_method_2_2.text = 'TRF' + request_date_tag = 'ReqdExctnDt' + if gen_args.get('pain_flavor') != 'pain.001.001.02': + batch_booking_2_3 = etree.SubElement(payment_info_2_0, 'BtchBookg') + batch_booking_2_3.text = str(sepa_export.batch_booking).lower() + # The "SEPA Customer-to-bank + # Implementation guidelines" for SCT and SDD says that control sum + # and nb_of_transactions should be present + # at both "group header" level and "payment info" level + nb_of_transactions_2_4 = etree.SubElement( + payment_info_2_0, 'NbOfTxs') + control_sum_2_5 = etree.SubElement(payment_info_2_0, 'CtrlSum') + payment_type_info_2_6 = etree.SubElement( + payment_info_2_0, 'PmtTpInf') + if priority: + instruction_priority_2_7 = etree.SubElement( + payment_type_info_2_6, 'InstrPrty') + instruction_priority_2_7.text = priority + service_level_2_8 = etree.SubElement( + payment_type_info_2_6, 'SvcLvl') + service_level_code_2_9 = etree.SubElement(service_level_2_8, 'Cd') + service_level_code_2_9.text = 'SEPA' + if local_instrument: + local_instrument_2_11 = etree.SubElement( + payment_type_info_2_6, 'LclInstrm') + local_instr_code_2_12 = etree.SubElement( + local_instrument_2_11, 'Cd') + local_instr_code_2_12.text = local_instrument + if sequence_type: + sequence_type_2_14 = etree.SubElement( + payment_type_info_2_6, 'SeqTp') + sequence_type_2_14.text = sequence_type + + requested_date_2_17 = etree.SubElement( + payment_info_2_0, request_date_tag) + requested_date_2_17.text = requested_date + return payment_info_2_0, nb_of_transactions_2_4, control_sum_2_5 + + def generate_initiating_party_block( self, cr, uid, parent_node, sepa_export, gen_args, context=None): @@ -141,7 +213,7 @@ class banking_export_pain(orm.AbstractModel): cr, uid, 'Company Name', 'sepa_export.payment_order_ids[0].mode.bank_id.partner_id.name', {'sepa_export': sepa_export}, gen_args.get('name_maxsize'), - convert_to_ascii=gen_args.get('convert_to_ascii'), context=context) + gen_args=gen_args, context=context) initiating_party_1_8 = etree.SubElement(parent_node, 'InitgPty') initiating_party_name = etree.SubElement(initiating_party_1_8, 'Nm') initiating_party_name.text = my_company_name @@ -174,7 +246,7 @@ class banking_export_pain(orm.AbstractModel): party_agent_institution, gen_args.get('bic_xml_tag')) party_agent_bic.text = self._prepare_field( cr, uid, '%s BIC' % party_type_label, bic, eval_ctx, - convert_to_ascii=gen_args.get('convert_to_ascii'), context=context) + gen_args=gen_args, context=context) return True def generate_party_block( @@ -198,7 +270,7 @@ class banking_export_pain(orm.AbstractModel): party_name.text = self._prepare_field( cr, uid, '%s Name' % party_type_label, name, eval_ctx, gen_args.get('name_maxsize'), - convert_to_ascii=gen_args.get('convert_to_ascii'), context=context) + gen_args=gen_args, context=context) party_account = etree.SubElement( parent_node, '%sAcct' % party_type) party_account_id = etree.SubElement(party_account, 'Id') @@ -206,7 +278,7 @@ class banking_export_pain(orm.AbstractModel): party_account_id, 'IBAN') piban = self._prepare_field( cr, uid, '%s IBAN' % party_type_label, iban, eval_ctx, - convert_to_ascii=gen_args.get('convert_to_ascii'), + gen_args=gen_args, context=context) viban = self._validate_iban(cr, uid, piban, context=context) party_account_iban.text = viban @@ -228,7 +300,7 @@ class banking_export_pain(orm.AbstractModel): self._prepare_field( cr, uid, 'Remittance Unstructured Information', 'line.communication', {'line': line}, 140, - convert_to_ascii=gen_args.get('convert_to_ascii'), + gen_args=gen_args, context=context) else: if not line.struct_communication_type: @@ -268,7 +340,7 @@ class banking_export_pain(orm.AbstractModel): self._prepare_field( cr, uid, 'Creditor Structured Reference', 'line.communication', {'line': line}, 35, - convert_to_ascii=gen_args.get('convert_to_ascii'), + gen_args=gen_args, context=context) return True @@ -282,7 +354,7 @@ class banking_export_pain(orm.AbstractModel): csi_other_id = etree.SubElement(csi_other, 'Id') csi_other_id.text = self._prepare_field( cr, uid, identification_label, identification, eval_ctx, - convert_to_ascii=gen_args.get('convert_to_ascii'), context=context) + gen_args=gen_args, context=context) csi_scheme_name = etree.SubElement(csi_other, 'SchmeNm') csi_scheme_name_proprietary = etree.SubElement( csi_scheme_name, 'Prtry') diff --git a/account_banking_sepa_credit_transfer/wizard/export_sepa.py b/account_banking_sepa_credit_transfer/wizard/export_sepa.py index 5a58299c2..b1e8ff047 100644 --- a/account_banking_sepa_credit_transfer/wizard/export_sepa.py +++ b/account_banking_sepa_credit_transfer/wizard/export_sepa.py @@ -22,9 +22,7 @@ from openerp.osv import orm, fields -import base64 from openerp.tools.translate import _ -from openerp.tools.safe_eval import safe_eval from openerp import tools, netsvc from lxml import etree import logging @@ -83,20 +81,6 @@ class banking_export_sepa_wizard(orm.TransientModel): return super(banking_export_sepa_wizard, self).create( cr, uid, vals, context=context) - def _prepare_export_sepa( - self, cr, uid, sepa_export, total_amount, transactions_count, - xml_string, context=None): - return { - 'batch_booking': sepa_export.batch_booking, - 'charge_bearer': sepa_export.charge_bearer, - 'total_amount': total_amount, - 'nb_transactions': transactions_count, - 'file': base64.encodestring(xml_string), - 'payment_order_ids': [ - (6, 0, [x.id for x in sepa_export.payment_order_ids]) - ], - } - def create_sepa(self, cr, uid, ids, context=None): ''' Creates the SEPA Credit Transfer file. That's the important code ! @@ -164,7 +148,7 @@ class banking_export_sepa_wizard(orm.TransientModel): total_amount = 0.0 amount_control_sum_1_7 = 0.0 lines_per_group = {} - # key = (requested_exec_date, priority) + # key = (requested_date, priority) # values = list of lines as object today = fields.date.context_today(self, cr, uid, context=context) for payment_order in sepa_export.payment_order_ids: @@ -172,65 +156,33 @@ class banking_export_sepa_wizard(orm.TransientModel): for line in payment_order.line_ids: priority = line.priority if payment_order.date_prefered == 'due': - requested_exec_date = line.ml_maturity_date or today + requested_date = line.ml_maturity_date or today elif payment_order.date_prefered == 'fixed': - requested_exec_date = payment_order.date_scheduled or today + requested_date = payment_order.date_scheduled or today else: - requested_exec_date = today - key = (requested_exec_date, priority) + requested_date = today + key = (requested_date, priority) if key in lines_per_group: lines_per_group[key].append(line) else: lines_per_group[key] = [line] - # Write requested_exec_date on 'Payment date' of the pay line - if requested_exec_date != line.date: + # Write requested_date on 'Payment date' of the pay line + if requested_date != line.date: self.pool['payment.line'].write( cr, uid, line.id, - {'date': requested_exec_date}, context=context) + {'date': requested_date}, context=context) - for (requested_exec_date, priority), lines in lines_per_group.items(): + for (requested_date, priority), lines in lines_per_group.items(): # B. Payment info - payment_info_2_0 = etree.SubElement(pain_root, 'PmtInf') - payment_info_identification_2_1 = etree.SubElement( - payment_info_2_0, 'PmtInfId') - payment_info_identification_2_1.text = self._prepare_field( - cr, uid, 'Payment Information Identification', - "sepa_export.payment_order_ids[0].reference + '-' + requested_exec_date.replace('-', '') + '-' + priority", { + payment_info_2_0, nb_of_transactions_2_4, control_sum_2_5 = \ + self.generate_start_payment_info_block( + cr, uid, pain_root, sepa_export, + "sepa_export.payment_order_ids[0].reference + '-' + requested_date.replace('-', '') + '-' + priority", + priority, False, False, requested_date, { 'sepa_export': sepa_export, 'priority': priority, - 'requested_exec_date': requested_exec_date - }, 35, convert_to_ascii=convert_to_ascii, context=context) - payment_method_2_2 = etree.SubElement(payment_info_2_0, 'PmtMtd') - payment_method_2_2.text = 'TRF' - if pain_flavor in pain_03_to_05: - # batch_booking is in "Group header" with pain.001.001.02 - # and in "Payment info" in pain.001.001.03/04 - batch_booking_2_3 = etree.SubElement( - payment_info_2_0, 'BtchBookg') - batch_booking_2_3.text = str(sepa_export.batch_booking).lower() - # It may seem surprising, but the - # "SEPA Credit Transfer Scheme Customer-to-bank Implementation - # guidelines" v6.0 says that control sum and nb_of_transactions - # should be present at both "group header" level and "payment info" - # level. This seems to be confirmed by the tests carried out at - # BNP Paribas in PAIN v001.001.03 - if pain_flavor in pain_03_to_05: - nb_of_transactions_2_4 = etree.SubElement( - payment_info_2_0, 'NbOfTxs') - control_sum_2_5 = etree.SubElement(payment_info_2_0, 'CtrlSum') - payment_type_info_2_6 = etree.SubElement( - payment_info_2_0, 'PmtTpInf') - if priority: - instruction_priority_2_7 = etree.SubElement( - payment_type_info_2_6, 'InstrPrty') - instruction_priority_2_7.text = priority - service_level_2_8 = etree.SubElement( - payment_type_info_2_6, 'SvcLvl') - service_level_code_2_9 = etree.SubElement(service_level_2_8, 'Cd') - service_level_code_2_9.text = 'SEPA' - requested_exec_date_2_17 = etree.SubElement( - payment_info_2_0, 'ReqdExctnDt') - requested_exec_date_2_17.text = requested_exec_date + 'requested_date': requested_date, + }, gen_args, context=context) self.generate_party_block( cr, uid, payment_info_2_0, 'Dbtr', 'B', @@ -256,11 +208,11 @@ class banking_export_sepa_wizard(orm.TransientModel): payment_identification_2_28, 'EndToEndId') end2end_identification_2_30.text = self._prepare_field( cr, uid, 'End to End Identification', 'line.name', - {'line': line}, 35, convert_to_ascii=convert_to_ascii, + {'line': line}, 35, gen_args=gen_args, context=context) currency_name = self._prepare_field( cr, uid, 'Currency Code', 'line.currency.name', - {'line': line}, 3, convert_to_ascii=convert_to_ascii, + {'line': line}, 3, gen_args=gen_args, context=context) amount_2_42 = etree.SubElement( credit_transfer_transaction_info_2_27, 'Amt') @@ -311,7 +263,7 @@ class banking_export_sepa_wizard(orm.TransientModel): file_id = self.pool.get('banking.export.sepa').create( cr, uid, self._prepare_export_sepa( cr, uid, sepa_export, total_amount, transactions_count_1_6, - xml_string, context=context), + xml_string, gen_args, context=context), context=context) self.write( @@ -333,7 +285,7 @@ class banking_export_sepa_wizard(orm.TransientModel): def cancel_sepa(self, cr, uid, ids, context=None): ''' - Cancel the SEPA PAIN: just drop the file + Cancel the SEPA file: just drop the file ''' sepa_export = self.browse(cr, uid, ids[0], context=context) self.pool.get('banking.export.sepa').unlink( @@ -342,7 +294,7 @@ class banking_export_sepa_wizard(orm.TransientModel): def save_sepa(self, cr, uid, ids, context=None): ''' - Save the SEPA PAIN: send the done signal to all payment + Save the SEPA file: send the done signal to all payment orders in the file. With the default workflow, they will transition to 'done', while with the advanced workflow in account_banking_payment they will transition to 'sent' waiting diff --git a/account_banking_sepa_direct_debit/wizard/export_sdd.py b/account_banking_sepa_direct_debit/wizard/export_sdd.py index babec1260..5e4134f73 100644 --- a/account_banking_sepa_direct_debit/wizard/export_sdd.py +++ b/account_banking_sepa_direct_debit/wizard/export_sdd.py @@ -23,10 +23,8 @@ from openerp.osv import orm, fields from openerp.tools.translate import _ -from openerp.tools.safe_eval import safe_eval from openerp import tools, netsvc -import base64 -from datetime import datetime, timedelta +from datetime import datetime from lxml import etree import logging @@ -83,21 +81,6 @@ class banking_export_sdd_wizard(orm.TransientModel): return super(banking_export_sdd_wizard, self).create( cr, uid, vals, context=context) - def _prepare_export_sepa( - self, cr, uid, sepa_export, total_amount, transactions_count, - xml_string, context=None): - return { - 'batch_booking': sepa_export.batch_booking, - 'charge_bearer': sepa_export.charge_bearer, - 'total_amount': total_amount, - 'nb_transactions': transactions_count, - 'file': base64.encodestring(xml_string), - 'payment_order_ids': [ - (6, 0, [x.id for x in sepa_export.payment_order_ids]) - ], - } - - def _get_previous_bank(self, cr, uid, payline, context=None): payline_obj = self.pool['payment.line'] previous_bank = False @@ -163,11 +146,6 @@ class banking_export_sdd_wizard(orm.TransientModel): root = etree.Element('Document', nsmap=pain_ns) pain_root = etree.SubElement(root, root_xml_tag) - my_company_name = self._prepare_field( - cr, uid, 'Company Name', - 'sepa_export.payment_order_ids[0].company_id.partner_id.name', - {'sepa_export': sepa_export}, name_maxsize, context=context) - # A. Group header group_header_1_0, nb_of_transactions_1_6, control_sum_1_7 = \ self.generate_group_header_block( @@ -177,7 +155,7 @@ class banking_export_sdd_wizard(orm.TransientModel): total_amount = 0.0 amount_control_sum_1_7 = 0.0 lines_per_group = {} - # key = (requested_collec_date, priority, sequence type) + # key = (requested_date, priority, sequence type) # value = list of lines as objects # Iterate on payment orders today = fields.date.context_today(self, cr, uid, context=context) @@ -188,11 +166,11 @@ class banking_export_sdd_wizard(orm.TransientModel): transactions_count_1_6 += 1 priority = line.priority if payment_order.date_prefered == 'due': - requested_collec_date = line.ml_maturity_date or today + requested_date = line.ml_maturity_date or today elif payment_order.date_prefered == 'fixed': - requested_collec_date = payment_order.date_scheduled or today + requested_date = payment_order.date_scheduled or today else: - requested_collec_date = today + requested_date = today if not line.sdd_mandate_id: raise orm.except_orm( _('Error:'), @@ -225,69 +203,29 @@ class banking_export_sdd_wizard(orm.TransientModel): assert seq_type_label is not False seq_type = seq_type_map[seq_type_label] - key = (requested_collec_date, priority, seq_type) + key = (requested_date, priority, seq_type) if key in lines_per_group: lines_per_group[key].append(line) else: lines_per_group[key] = [line] # Write requested_exec_date on 'Payment date' of the pay line - if requested_collec_date != line.date: + if requested_date != line.date: self.pool['payment.line'].write( cr, uid, line.id, - {'date': requested_collec_date}, context=context) + {'date': requested_date}, context=context) - for (requested_collec_date, priority, sequence_type), lines in lines_per_group.items(): + for (requested_date, priority, sequence_type), lines in lines_per_group.items(): # B. Payment info - payment_info_2_0 = etree.SubElement(pain_root, 'PmtInf') - payment_info_identification_2_1 = etree.SubElement( - payment_info_2_0, 'PmtInfId') - payment_info_identification_2_1.text = self._prepare_field( - cr, uid, 'Payment Information Identification', - "sepa_export.payment_order_ids[0].reference + '-' + sequence_type + '-' + requested_collec_date.replace('-', '') + '-' + priority", - { + payment_info_2_0, nb_of_transactions_2_4, control_sum_2_5 = \ + self.generate_start_payment_info_block( + cr, uid, pain_root, sepa_export, + "sepa_export.payment_order_ids[0].reference + '-' + sequence_type + '-' + requested_date.replace('-', '') + '-' + priority", + priority, 'CORE', sequence_type, requested_date, { 'sepa_export': sepa_export, 'sequence_type': sequence_type, 'priority': priority, - 'requested_collec_date': requested_collec_date, - }, 35, convert_to_ascii=convert_to_ascii, context=context) - payment_method_2_2 = etree.SubElement(payment_info_2_0, 'PmtMtd') - payment_method_2_2.text = 'DD' - # batch_booking is in "Payment Info" with pain.008.001.02/03 - batch_booking_2_3 = etree.SubElement(payment_info_2_0, 'BtchBookg') - batch_booking_2_3.text = str(sepa_export.batch_booking).lower() - # The "SEPA Core Direct Debit Scheme Customer-to-bank - # Implementation guidelines" v6.0 says that control sum - # and nb_of_transactions should be present - # at both "group header" level and "payment info" level - nb_of_transactions_2_4 = etree.SubElement( - payment_info_2_0, 'NbOfTxs') - control_sum_2_5 = etree.SubElement(payment_info_2_0, 'CtrlSum') - payment_type_info_2_6 = etree.SubElement( - payment_info_2_0, 'PmtTpInf') - if priority: - instruction_priority_2_7 = etree.SubElement( - payment_type_info_2_6, 'InstrPrty') - instruction_priority_2_7.text = priority - service_level_2_8 = etree.SubElement( - payment_type_info_2_6, 'SvcLvl') - service_level_code_2_9 = etree.SubElement(service_level_2_8, 'Cd') - service_level_code_2_9.text = 'SEPA' - local_instrument_2_11 = etree.SubElement( - payment_type_info_2_6, 'LclInstrm') - local_instr_code_2_12 = etree.SubElement( - local_instrument_2_11, 'Cd') - local_instr_code_2_12.text = 'CORE' - # 2.14 Sequence Type MANDATORY - # this message element must indicate ‘FRST - # 'FRST' = First ; 'OOFF' = One Off ; 'RCUR' : Recurring - # 'FNAL' = Final - sequence_type_2_14 = etree.SubElement( - payment_type_info_2_6, 'SeqTp') - sequence_type_2_14.text = sequence_type - - requested_collec_date_2_18 = etree.SubElement( - payment_info_2_0, 'ReqdColltnDt') - requested_collec_date_2_18.text = requested_collec_date + 'requested_date': requested_date, + }, gen_args, context=context) self.generate_party_block( cr, uid, payment_info_2_0, 'Cdtr', 'B', @@ -322,10 +260,10 @@ class banking_export_sdd_wizard(orm.TransientModel): end2end_identification_2_31.text = self._prepare_field( cr, uid, 'End to End Identification', 'line.name', {'line': line}, 35, - convert_to_ascii=convert_to_ascii, context=context) + gen_args=gen_args, context=context) currency_name = self._prepare_field( cr, uid, 'Currency Code', 'line.currency.name', - {'line': line}, 3, convert_to_ascii=convert_to_ascii, + {'line': line}, 3, gen_args=gen_args, context=context) instructed_amount_2_44 = etree.SubElement( dd_transaction_info_2_28, 'InstdAmt', Ccy=currency_name) @@ -342,14 +280,14 @@ class banking_export_sdd_wizard(orm.TransientModel): cr, uid, 'Unique Mandate Reference', 'line.sdd_mandate_id.unique_mandate_reference', {'line': line}, 35, - convert_to_ascii=convert_to_ascii, context=context) + gen_args=gen_args, context=context) mandate_signature_date_2_49 = etree.SubElement( mandate_related_info_2_47, 'DtOfSgntr') mandate_signature_date_2_49.text = self._prepare_field( cr, uid, 'Mandate Signature Date', 'line.sdd_mandate_id.signature_date', {'line': line}, 10, - convert_to_ascii=convert_to_ascii, context=context) + gen_args=gen_args, context=context) if sequence_type == 'FRST' and ( line.sdd_mandate_id.last_debit_date or not line.sdd_mandate_id.sepa_migrated): @@ -374,7 +312,7 @@ class banking_export_sdd_wizard(orm.TransientModel): cr, uid, 'Original Debtor Account', 'previous_bank.acc_number', {'previous_bank': previous_bank}, - convert_to_ascii=convert_to_ascii, + gen_args=gen_args, context=context), context=context) else: @@ -388,7 +326,7 @@ class banking_export_sdd_wizard(orm.TransientModel): cr, uid, 'Original Debtor Agent', 'previous_bank.bank.bic', {'previous_bank': previous_bank}, - convert_to_ascii=convert_to_ascii, + gen_args=gen_args, context=context) ori_debtor_agent_other = etree.SubElement( ori_debtor_agent_institution, 'Othr') @@ -404,7 +342,7 @@ class banking_export_sdd_wizard(orm.TransientModel): cr, uid, 'Original Mandate Identification', 'line.sdd_mandate_id.original_mandate_identification', {'line': line}, - convert_to_ascii=convert_to_ascii, + gen_args=gen_args, context=context) ori_creditor_scheme_id_2_53 = etree.SubElement( amendment_info_details_2_51, 'OrgnlCdtrSchmeId') @@ -444,7 +382,7 @@ class banking_export_sdd_wizard(orm.TransientModel): file_id = self.pool.get('banking.export.sdd').create( cr, uid, self._prepare_export_sepa( cr, uid, sepa_export, total_amount, transactions_count_1_6, - xml_string, context=context), + xml_string, gen_args, context=context), context=context) self.write( @@ -466,7 +404,7 @@ class banking_export_sdd_wizard(orm.TransientModel): def cancel_sepa(self, cr, uid, ids, context=None): ''' - Cancel the SEPA Direct Debit file: just drop the file + Cancel the SEPA file: just drop the file ''' sepa_export = self.browse(cr, uid, ids[0], context=context) self.pool.get('banking.export.sdd').unlink( From cf20fa4882eb98ca5e54ff4de90941108cb25af4 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Tue, 24 Dec 2013 01:01:04 +0100 Subject: [PATCH 30/43] Replace unallowed ascii caracters by '-' Update some error messages Update translation files and FR translation Include sepa_export in gen_args Factorize more code between SDD and SCT Fix view of payment lines The modules account_banking_pain_base and account_banking_sepa_* are now fully PEP8 compliant --- .../banking_export_pain.py | 105 +++++-- account_banking_pain_base/company.py | 3 +- .../i18n/account_banking_pain_base.pot | 146 ++++++++++ account_banking_pain_base/i18n/fr.po | 146 ++++++++++ account_banking_pain_base/payment_line.py | 7 +- .../payment_line_view.xml | 6 +- account_banking_pain_base/payment_mode.py | 4 +- .../account_banking_sepa.py | 19 +- .../account_banking_sepa_credit_transfer.pot | 82 +----- .../i18n/fr.po | 258 ++---------------- .../wizard/export_sepa.py | 106 ++++--- .../account_banking_sdd.py | 113 +++++--- account_banking_sepa_direct_debit/company.py | 6 +- .../account_banking_sepa_direct_debit.pot | 194 +++++++------ account_banking_sepa_direct_debit/i18n/fr.po | 224 ++++++++------- .../wizard/export_sdd.py | 122 ++++----- 16 files changed, 824 insertions(+), 717 deletions(-) create mode 100644 account_banking_pain_base/i18n/account_banking_pain_base.pot create mode 100644 account_banking_pain_base/i18n/fr.po diff --git a/account_banking_pain_base/banking_export_pain.py b/account_banking_pain_base/banking_export_pain.py index 28edd97a0..30a1d5474 100644 --- a/account_banking_pain_base/banking_export_pain.py +++ b/account_banking_pain_base/banking_export_pain.py @@ -62,14 +62,19 @@ class banking_export_pain(orm.AbstractModel): # Scheme Customer-to-bank guidelines if gen_args.get('convert_to_ascii'): value = unidecode(value) + unallowed_ascii_chars = [ + '"', '#', '$', '%', '&', '*', ';', '<', '>', '=', '@', + '[', ']', '^', '_', '`', '{', '}', '|', '~', '\\', '!'] + for unallowed_ascii_char in unallowed_ascii_chars: + value = value.replace(unallowed_ascii_char, '-') except: line = eval_ctx.get('line') if line: raise orm.except_orm( _('Error:'), - _("Cannot compute the '%s' of the Payment Line with Invoice Reference '%s'.") - % (field_name, self.pool['account.invoice'].name_get( - cr, uid, [line.ml_inv_ref.id], context=context)[0][1])) + _("Cannot compute the '%s' of the Payment Line with " + "reference '%s'.") + % (field_name, line.name)) else: raise orm.except_orm( _('Error:'), @@ -77,7 +82,8 @@ class banking_export_pain(orm.AbstractModel): if not isinstance(value, (str, unicode)): raise orm.except_orm( _('Field type error:'), - _("The type of the field '%s' is %s. It should be a string or unicode.") + _("The type of the field '%s' is %s. It should be a string " + "or unicode.") % (field_name, type(value))) if not value: raise orm.except_orm( @@ -89,22 +95,22 @@ class banking_export_pain(orm.AbstractModel): return value def _prepare_export_sepa( - self, cr, uid, sepa_export, total_amount, transactions_count, - xml_string, gen_args, context=None): + self, cr, uid, total_amount, transactions_count, xml_string, + gen_args, context=None): return { - 'batch_booking': sepa_export.batch_booking, - 'charge_bearer': sepa_export.charge_bearer, + 'batch_booking': gen_args['sepa_export'].batch_booking, + 'charge_bearer': gen_args['sepa_export'].charge_bearer, 'total_amount': total_amount, 'nb_transactions': transactions_count, 'file': base64.encodestring(xml_string), - 'payment_order_ids': [ - (6, 0, [x.id for x in sepa_export.payment_order_ids]) - ], + 'payment_order_ids': [( + 6, 0, [x.id for x in gen_args['sepa_export'].payment_order_ids] + )], } - def _validate_xml(self, cr, uid, xml_string, pain_xsd_file): + def _validate_xml(self, cr, uid, xml_string, gen_args, context=None): xsd_etree_obj = etree.parse( - tools.file_open(pain_xsd_file)) + tools.file_open(gen_args['pain_xsd_file'])) official_pain_schema = etree.XMLSchema(xsd_etree_obj) try: @@ -117,19 +123,58 @@ class banking_export_pain(orm.AbstractModel): logger.warning(e) raise orm.except_orm( _('Error:'), - _('The generated XML file is not valid against the official XML Schema Definition. The generated XML file and the full error have been written in the server logs. Here is the error, which may give you an idea on the cause of the problem : %s') + _("The generated XML file is not valid against the official " + "XML Schema Definition. The generated XML file and the " + "full error have been written in the server logs. Here " + "is the error, which may give you an idea on the cause " + "of the problem : %s") % str(e)) return True + def finalize_sepa_file_creation( + self, cr, uid, ids, xml_root, total_amount, transactions_count, + gen_args, context=None): + xml_string = etree.tostring( + xml_root, pretty_print=True, encoding='UTF-8', + xml_declaration=True) + logger.debug( + "Generated SEPA XML file in format %s below" + % gen_args['pain_flavor']) + logger.debug(xml_string) + self._validate_xml(cr, uid, xml_string, gen_args, context=context) + + file_id = gen_args['file_obj'].create( + cr, uid, self._prepare_export_sepa( + cr, uid, total_amount, transactions_count, + xml_string, gen_args, context=context), + context=context) + + self.write( + cr, uid, ids, { + 'file_id': file_id, + 'state': 'finish', + }, context=context) + + action = { + 'name': 'SEPA File', + 'type': 'ir.actions.act_window', + 'view_type': 'form', + 'view_mode': 'form,tree', + 'res_model': self._name, + 'res_id': ids[0], + 'target': 'new', + } + return action + def generate_group_header_block( - self, cr, uid, parent_node, sepa_export, gen_args, context=None): + self, cr, uid, parent_node, gen_args, context=None): group_header_1_0 = etree.SubElement(parent_node, 'GrpHdr') message_identification_1_1 = etree.SubElement( group_header_1_0, 'MsgId') message_identification_1_1.text = self._prepare_field( cr, uid, 'Message Identification', 'sepa_export.payment_order_ids[0].reference', - {'sepa_export': sepa_export}, 35, + {'sepa_export': gen_args['sepa_export']}, 35, gen_args=gen_args, context=context) creation_date_time_1_2 = etree.SubElement(group_header_1_0, 'CreDtTm') creation_date_time_1_2.text = datetime.strftime( @@ -138,7 +183,8 @@ class banking_export_pain(orm.AbstractModel): # batch_booking is in "Group header" with pain.001.001.02 # and in "Payment info" in pain.001.001.03/04 batch_booking = etree.SubElement(group_header_1_0, 'BtchBookg') - batch_booking.text = str(sepa_export.batch_booking).lower() + batch_booking.text = \ + str(gen_args['sepa_export'].batch_booking).lower() nb_of_transactions_1_6 = etree.SubElement( group_header_1_0, 'NbOfTxs') control_sum_1_7 = etree.SubElement(group_header_1_0, 'CtrlSum') @@ -147,12 +193,12 @@ class banking_export_pain(orm.AbstractModel): grouping = etree.SubElement(group_header_1_0, 'Grpg') grouping.text = 'GRPD' self.generate_initiating_party_block( - cr, uid, group_header_1_0, sepa_export, gen_args, + cr, uid, group_header_1_0, gen_args, context=context) return group_header_1_0, nb_of_transactions_1_6, control_sum_1_7 def generate_start_payment_info_block( - self, cr, uid, parent_node, sepa_export, payment_info_ident, + self, cr, uid, parent_node, payment_info_ident, priority, local_instrument, sequence_type, requested_date, eval_ctx, gen_args, context=None): payment_info_2_0 = etree.SubElement(parent_node, 'PmtInf') @@ -171,7 +217,8 @@ class banking_export_pain(orm.AbstractModel): request_date_tag = 'ReqdExctnDt' if gen_args.get('pain_flavor') != 'pain.001.001.02': batch_booking_2_3 = etree.SubElement(payment_info_2_0, 'BtchBookg') - batch_booking_2_3.text = str(sepa_export.batch_booking).lower() + batch_booking_2_3.text = \ + str(gen_args['sepa_export'].batch_booking).lower() # The "SEPA Customer-to-bank # Implementation guidelines" for SCT and SDD says that control sum # and nb_of_transactions should be present @@ -205,24 +252,23 @@ class banking_export_pain(orm.AbstractModel): requested_date_2_17.text = requested_date return payment_info_2_0, nb_of_transactions_2_4, control_sum_2_5 - def generate_initiating_party_block( - self, cr, uid, parent_node, sepa_export, gen_args, - context=None): + self, cr, uid, parent_node, gen_args, context=None): my_company_name = self._prepare_field( cr, uid, 'Company Name', 'sepa_export.payment_order_ids[0].mode.bank_id.partner_id.name', - {'sepa_export': sepa_export}, gen_args.get('name_maxsize'), - gen_args=gen_args, context=context) + {'sepa_export': gen_args['sepa_export']}, + gen_args.get('name_maxsize'), gen_args=gen_args, context=context) initiating_party_1_8 = etree.SubElement(parent_node, 'InitgPty') initiating_party_name = etree.SubElement(initiating_party_1_8, 'Nm') initiating_party_name.text = my_company_name initiating_party_identifier = self.pool['res.company'].\ _get_initiating_party_identifier( - cr, uid, sepa_export.payment_order_ids[0].company_id.id, + cr, uid, + gen_args['sepa_export'].payment_order_ids[0].company_id.id, context=context) - initiating_party_issuer = \ - sepa_export.payment_order_ids[0].company_id.initiating_party_issuer + initiating_party_issuer = gen_args['sepa_export'].\ + payment_order_ids[0].company_id.initiating_party_issuer if initiating_party_identifier and initiating_party_issuer: iniparty_id = etree.SubElement(initiating_party_1_8, 'Id') iniparty_org_id = etree.SubElement(iniparty_id, 'OrgId') @@ -306,7 +352,8 @@ class banking_export_pain(orm.AbstractModel): if not line.struct_communication_type: raise orm.except_orm( _('Error:'), - _("Missing 'Structured Communication Type' on payment line with your reference '%s'.") + _("Missing 'Structured Communication Type' on payment " + "line with reference '%s'.") % (line.name)) remittance_info_unstructured_2_100 = etree.SubElement( remittance_info_2_91, 'Strd') diff --git a/account_banking_pain_base/company.py b/account_banking_pain_base/company.py index 31c709fb5..2c238cc6a 100644 --- a/account_banking_pain_base/company.py +++ b/account_banking_pain_base/company.py @@ -31,7 +31,8 @@ class res_company(orm.Model): _columns = { 'initiating_party_issuer': fields.char( 'Initiating Party Issuer', size=35, - help="This will be used as the 'Initiating Party Issuer' in the PAIN files generated by OpenERP."), + help="This will be used as the 'Initiating Party Issuer' in the " + "PAIN files generated by OpenERP."), } def _get_initiating_party_identifier( diff --git a/account_banking_pain_base/i18n/account_banking_pain_base.pot b/account_banking_pain_base/i18n/account_banking_pain_base.pot new file mode 100644 index 000000000..d4a7dbac5 --- /dev/null +++ b/account_banking_pain_base/i18n/account_banking_pain_base.pot @@ -0,0 +1,146 @@ +# Translation of OpenERP Server. +# This file contains the translation of the following modules: +# * account_banking_pain_base +# +msgid "" +msgstr "" +"Project-Id-Version: OpenERP Server 7.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-12-23 21:26+0000\n" +"PO-Revision-Date: 2013-12-23 21:26+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: account_banking_pain_base +#: field:res.company,initiating_party_issuer:0 +msgid "Initiating Party Issuer" +msgstr "" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:122 +#, python-format +msgid "The generated XML file is not valid against the official XML Schema Definition. The generated XML file and the full error have been written in the server logs. Here is the error, which may give you an idea on the cause of the problem : %s" +msgstr "" + +#. module: account_banking_pain_base +#: field:payment.line,priority:0 +msgid "Priority" +msgstr "" + +#. module: account_banking_pain_base +#: model:ir.model,name:account_banking_pain_base.model_payment_line +msgid "Payment Line" +msgstr "" + +#. module: account_banking_pain_base +#: model:ir.model,name:account_banking_pain_base.model_payment_mode +msgid "Payment Mode" +msgstr "" + +#. module: account_banking_pain_base +#: help:res.company,initiating_party_issuer:0 +msgid "This will be used as the 'Initiating Party Issuer' in the PAIN files generated by OpenERP." +msgstr "" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:351 +#, python-format +msgid "Missing 'Structured Communication Type' on payment line with reference '%s'." +msgstr "" + +#. module: account_banking_pain_base +#: selection:payment.line,priority:0 +msgid "Normal" +msgstr "" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:70 +#, python-format +msgid "Cannot compute the '%s' of the Payment Line with reference '%s'." +msgstr "" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:77 +#, python-format +msgid "Cannot compute the '%s'." +msgstr "" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:81 +#, python-format +msgid "The type of the field '%s' is %s. It should be a string or unicode." +msgstr "" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:47 +#: code:addons/account_banking_pain_base/banking_export_pain.py:69 +#: code:addons/account_banking_pain_base/banking_export_pain.py:76 +#: code:addons/account_banking_pain_base/banking_export_pain.py:86 +#: code:addons/account_banking_pain_base/banking_export_pain.py:121 +#: code:addons/account_banking_pain_base/banking_export_pain.py:350 +#, python-format +msgid "Error:" +msgstr "" + +#. module: account_banking_pain_base +#: model:ir.model,name:account_banking_pain_base.model_res_company +msgid "Companies" +msgstr "" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:47 +#, python-format +msgid "This IBAN is not valid : %s" +msgstr "" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:80 +#, python-format +msgid "Field type error:" +msgstr "" + +#. module: account_banking_pain_base +#: field:payment.line,struct_communication_type:0 +msgid "Structured Communication Type" +msgstr "" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:87 +#, python-format +msgid "The '%s' is empty or 0. It should have a non-null value." +msgstr "" + +#. module: account_banking_pain_base +#: model:ir.model,name:account_banking_pain_base.model_banking_export_pain +msgid "banking.export.pain" +msgstr "" + +#. module: account_banking_pain_base +#: help:payment.mode,convert_to_ascii:0 +msgid "If active, OpenERP will convert each accented caracter to the corresponding unaccented caracter, so that only ASCII caracters are used in the generated PAIN file." +msgstr "" + +#. module: account_banking_pain_base +#: help:payment.line,priority:0 +msgid "This field will be used as the 'Instruction Priority' in the generated PAIN file." +msgstr "" + +#. module: account_banking_pain_base +#: view:res.company:0 +msgid "Payment Initiation" +msgstr "" + +#. module: account_banking_pain_base +#: selection:payment.line,priority:0 +msgid "High" +msgstr "" + +#. module: account_banking_pain_base +#: field:payment.mode,convert_to_ascii:0 +msgid "Convert to ASCII" +msgstr "" + diff --git a/account_banking_pain_base/i18n/fr.po b/account_banking_pain_base/i18n/fr.po new file mode 100644 index 000000000..22a9c9232 --- /dev/null +++ b/account_banking_pain_base/i18n/fr.po @@ -0,0 +1,146 @@ +# Translation of OpenERP Server. +# This file contains the translation of the following modules: +# * account_banking_pain_base +# +msgid "" +msgstr "" +"Project-Id-Version: OpenERP Server 7.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-12-23 21:27+0000\n" +"PO-Revision-Date: 2013-12-23 21:27+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: account_banking_pain_base +#: field:res.company,initiating_party_issuer:0 +msgid "Initiating Party Issuer" +msgstr "Initiating Party Issuer" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:122 +#, python-format +msgid "The generated XML file is not valid against the official XML Schema Definition. The generated XML file and the full error have been written in the server logs. Here is the error, which may give you an idea on the cause of the problem : %s" +msgstr "Le fichier XML généré n'est pas valide par rapport à la Définition du Schéma XML officiel. Le fichier XML généré et le message d'erreur complet ont été écrits dans les logs du serveur. Voici l'erreur, qui vous donnera peut-être une idée sur la cause du problème : %s" + +#. module: account_banking_pain_base +#: field:payment.line,priority:0 +msgid "Priority" +msgstr "Priorité" + +#. module: account_banking_pain_base +#: model:ir.model,name:account_banking_pain_base.model_payment_line +msgid "Payment Line" +msgstr "Ligne de paiement" + +#. module: account_banking_pain_base +#: model:ir.model,name:account_banking_pain_base.model_payment_mode +msgid "Payment Mode" +msgstr "Mode de paiement" + +#. module: account_banking_pain_base +#: help:res.company,initiating_party_issuer:0 +msgid "This will be used as the 'Initiating Party Issuer' in the PAIN files generated by OpenERP." +msgstr "Ce champ sera le 'Initiating Party Issuer' dans les fichiers PAIN générés par OpenERP." + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:351 +#, python-format +msgid "Missing 'Structured Communication Type' on payment line with reference '%s'." +msgstr "Le 'Type de communication structuré' n'est pas renseigné sur la ligne de paiement ayant la référence '%s'." + +#. module: account_banking_pain_base +#: selection:payment.line,priority:0 +msgid "Normal" +msgstr "Normal" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:70 +#, python-format +msgid "Cannot compute the '%s' of the Payment Line with reference '%s'." +msgstr "Impossible de calculer le '%s' de la ligne de paiement ayant la référence '%s'." + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:77 +#, python-format +msgid "Cannot compute the '%s'." +msgstr "Impossible de calculer le '%s'." + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:81 +#, python-format +msgid "The type of the field '%s' is %s. It should be a string or unicode." +msgstr "Le type du champ '%s' est %s. Il devrait être de type string ou unicode." + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:47 +#: code:addons/account_banking_pain_base/banking_export_pain.py:69 +#: code:addons/account_banking_pain_base/banking_export_pain.py:76 +#: code:addons/account_banking_pain_base/banking_export_pain.py:86 +#: code:addons/account_banking_pain_base/banking_export_pain.py:121 +#: code:addons/account_banking_pain_base/banking_export_pain.py:350 +#, python-format +msgid "Error:" +msgstr "Erreur :" + +#. module: account_banking_pain_base +#: model:ir.model,name:account_banking_pain_base.model_res_company +msgid "Companies" +msgstr "Sociétés" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:47 +#, python-format +msgid "This IBAN is not valid : %s" +msgstr "Cet IBAN n'est pas valide : %s" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:80 +#, python-format +msgid "Field type error:" +msgstr "Erreur dans le type de champ :" + +#. module: account_banking_pain_base +#: field:payment.line,struct_communication_type:0 +msgid "Structured Communication Type" +msgstr "Type de communication structurée" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:87 +#, python-format +msgid "The '%s' is empty or 0. It should have a non-null value." +msgstr "Le '%s' est vide ou égal à 0. Il devrait avoir une valeur non-nulle." + +#. module: account_banking_pain_base +#: model:ir.model,name:account_banking_pain_base.model_banking_export_pain +msgid "banking.export.pain" +msgstr "banking.export.pain" + +#. module: account_banking_pain_base +#: help:payment.mode,convert_to_ascii:0 +msgid "If active, OpenERP will convert each accented caracter to the corresponding unaccented caracter, so that only ASCII caracters are used in the generated PAIN file." +msgstr "Si actif, OpenERP convertira chaque caractère accentué en son équivalent non accentué, de telle façon que seuls des caractères ASCII soient utilisés dans le fichier PAIN généré." + +#. module: account_banking_pain_base +#: help:payment.line,priority:0 +msgid "This field will be used as the 'Instruction Priority' in the generated PAIN file." +msgstr "Ce champ sera le 'Instruction Priority' dans le fichier PAIN généré." + +#. module: account_banking_pain_base +#: view:res.company:0 +msgid "Payment Initiation" +msgstr "Payment Initiation" + +#. module: account_banking_pain_base +#: selection:payment.line,priority:0 +msgid "High" +msgstr "Élevé" + +#. module: account_banking_pain_base +#: field:payment.mode,convert_to_ascii:0 +msgid "Convert to ASCII" +msgstr "Convertir en ASCII" + diff --git a/account_banking_pain_base/payment_line.py b/account_banking_pain_base/payment_line.py index 11d597e4d..0dffbcf42 100644 --- a/account_banking_pain_base/payment_line.py +++ b/account_banking_pain_base/payment_line.py @@ -34,11 +34,14 @@ class payment_line(orm.Model): ('NORM', 'Normal'), ('HIGH', 'High'), ], 'Priority', - help="This field will be used as the 'Instruction Priority' in the generated PAIN files."), + help="This field will be used as the 'Instruction Priority' in " + "the generated PAIN file."), # Update size from 64 to 140, because PAIN allows 140 caracters 'communication': fields.char( 'Communication', size=140, required=True, - help="Used as the message between ordering customer and current company. Depicts 'What do you want to say to the recipient about this order ?'"), + help="Used as the message between ordering customer and current " + "company. Depicts 'What do you want to say to the recipient " + "about this order ?'"), 'struct_communication_type': fields.selection( _get_struct_communication_types, 'Structured Communication Type'), } diff --git a/account_banking_pain_base/payment_line_view.xml b/account_banking_pain_base/payment_line_view.xml index ea0005faf..40087836c 100644 --- a/account_banking_pain_base/payment_line_view.xml +++ b/account_banking_pain_base/payment_line_view.xml @@ -14,11 +14,12 @@ + + - @@ -29,11 +30,12 @@ + + - diff --git a/account_banking_pain_base/payment_mode.py b/account_banking_pain_base/payment_mode.py index 7113ccc78..540d01b67 100644 --- a/account_banking_pain_base/payment_mode.py +++ b/account_banking_pain_base/payment_mode.py @@ -29,7 +29,9 @@ class payment_mode(orm.Model): _columns = { 'convert_to_ascii': fields.boolean( 'Convert to ASCII', - help="If active, OpenERP will convert each accented caracter to the corresponding unaccented caracter, so that only ASCII caracters are used in the generated PAIN file."), + help="If active, OpenERP will convert each accented caracter to " + "the corresponding unaccented caracter, so that only ASCII " + "caracters are used in the generated PAIN file."), } _defaults = { diff --git a/account_banking_sepa_credit_transfer/account_banking_sepa.py b/account_banking_sepa_credit_transfer/account_banking_sepa.py index c2399c37e..a54888bb9 100644 --- a/account_banking_sepa_credit_transfer/account_banking_sepa.py +++ b/account_banking_sepa_credit_transfer/account_banking_sepa.py @@ -50,18 +50,29 @@ class banking_export_sepa(orm.Model): readonly=True), 'nb_transactions': fields.integer( 'Number of Transactions', readonly=True), - 'total_amount': fields.float('Total Amount', - digits_compute=dp.get_precision('Account'), readonly=True), + 'total_amount': fields.float( + 'Total Amount', digits_compute=dp.get_precision('Account'), + readonly=True), 'batch_booking': fields.boolean( 'Batch Booking', readonly=True, - help="If true, the bank statement will display only one debit line for all the wire transfers of the SEPA XML file ; if false, the bank statement will display one debit line per wire transfer of the SEPA XML file."), + help="If true, the bank statement will display only one debit " + "line for all the wire transfers of the SEPA XML file ; " + "if false, the bank statement will display one debit line " + "per wire transfer of the SEPA XML file."), 'charge_bearer': fields.selection([ ('SLEV', 'Following Service Level'), ('SHAR', 'Shared'), ('CRED', 'Borne by Creditor'), ('DEBT', 'Borne by Debtor'), ], 'Charge Bearer', readonly=True, - help='Following service level : transaction charges are to be applied following the rules agreed in the service level and/or scheme (SEPA Core messages must use this). Shared : transaction charges on the creditor side are to be borne by the creditor, transaction charges on the debtor side are to be borne by the debtor. Borne by creditor : all transaction charges are to be borne by the creditor. Borne by debtor : all transaction charges are to be borne by the debtor.'), + help="Following service level : transaction charges are to be " + "applied following the rules agreed in the service level and/or " + "scheme (SEPA Core messages must use this). Shared : " + "transaction charges on the creditor side are to be borne by " + "the creditor, transaction charges on the debtor side are to " + "be borne by the debtor. Borne by creditor : all transaction " + "charges are to be borne by the creditor. Borne by debtor : " + "all transaction charges are to be borne by the debtor."), 'create_date': fields.datetime('Generation Date', readonly=True), 'file': fields.binary('SEPA XML File', readonly=True), 'filename': fields.function( diff --git a/account_banking_sepa_credit_transfer/i18n/account_banking_sepa_credit_transfer.pot b/account_banking_sepa_credit_transfer/i18n/account_banking_sepa_credit_transfer.pot index ba9f9fb70..38feaadd4 100644 --- a/account_banking_sepa_credit_transfer/i18n/account_banking_sepa_credit_transfer.pot +++ b/account_banking_sepa_credit_transfer/i18n/account_banking_sepa_credit_transfer.pot @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: OpenERP Server 7.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-11-13 09:13+0000\n" -"PO-Revision-Date: 2013-11-13 09:13+0000\n" +"POT-Creation-Date: 2013-12-23 22:49+0000\n" +"PO-Revision-Date: 2013-12-23 22:49+0000\n" "Last-Translator: <>\n" "Language-Team: \n" "MIME-Version: 1.0\n" @@ -15,12 +15,6 @@ msgstr "" "Content-Transfer-Encoding: \n" "Plural-Forms: \n" -#. module: account_banking_sepa_credit_transfer -#: field:banking.export.sepa,prefered_exec_date:0 -#: field:banking.export.sepa.wizard,prefered_exec_date:0 -msgid "Prefered Execution Date" -msgstr "" - #. module: account_banking_sepa_credit_transfer #: selection:banking.export.sepa.wizard,state:0 msgid "Create" @@ -54,12 +48,6 @@ msgstr "" msgid "Following service level : transaction charges are to be applied following the rules agreed in the service level and/or scheme (SEPA Core messages must use this). Shared : transaction charges on the debtor side are to be borne by the debtor, transaction charges on the creditor side are to be borne by the creditor. Borne by creditor : all transaction charges are to be borne by the creditor. Borne by debtor : all transaction charges are to be borne by the debtor." msgstr "" -#. module: account_banking_sepa_credit_transfer -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:117 -#, python-format -msgid "Cannot compute the '%s' of the Payment Line with Invoice Reference '%s'." -msgstr "" - #. module: account_banking_sepa_credit_transfer #: selection:banking.export.sepa,charge_bearer:0 #: selection:banking.export.sepa.wizard,charge_bearer:0 @@ -72,9 +60,14 @@ msgstr "" msgid "Batch Booking" msgstr "" +#. module: account_banking_sepa_credit_transfer +#: selection:banking.export.sepa,state:0 +msgid "Sent" +msgstr "" + #. module: account_banking_sepa_credit_transfer #: model:ir.model,name:account_banking_sepa_credit_transfer.model_banking_export_sepa_wizard -msgid "Export SEPA Credit Transfer XML file" +msgid "Export SEPA Credit Transfer File" msgstr "" #. module: account_banking_sepa_credit_transfer @@ -104,23 +97,6 @@ msgstr "" msgid "Borne by Creditor" msgstr "" -#. module: account_banking_sepa_credit_transfer -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:122 -#, python-format -msgid "Cannot compute the '%s'." -msgstr "" - -#. module: account_banking_sepa_credit_transfer -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:126 -#, python-format -msgid "The type of the field '%s' is %s. It should be a string or unicode." -msgstr "" - -#. module: account_banking_sepa_credit_transfer -#: selection:banking.export.sepa,state:0 -msgid "Sent" -msgstr "" - #. module: account_banking_sepa_credit_transfer #: view:banking.export.sepa.wizard:0 msgid "Validate" @@ -131,12 +107,6 @@ msgstr "" msgid "Generate" msgstr "" -#. module: account_banking_sepa_credit_transfer -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:169 -#, python-format -msgid "The generated XML file is not valid against the official XML Schema Definition. The generated XML file and the full error have been written in the server logs. Here is the error, which may give you an idea on the cause of the problem : %s" -msgstr "" - #. module: account_banking_sepa_credit_transfer #: selection:banking.export.sepa,charge_bearer:0 #: selection:banking.export.sepa.wizard,charge_bearer:0 @@ -144,13 +114,8 @@ msgid "Borne by Debtor" msgstr "" #. module: account_banking_sepa_credit_transfer -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:90 -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:116 -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:121 -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:130 -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:168 -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:206 -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:350 +#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:128 +#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:245 #, python-format msgid "Error:" msgstr "" @@ -172,19 +137,13 @@ msgstr "" msgid "SEPA File Generation" msgstr "" -#. module: account_banking_sepa_credit_transfer -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:125 -#, python-format -msgid "Field type error:" -msgstr "" - #. module: account_banking_sepa_credit_transfer #: model:ir.model,name:account_banking_sepa_credit_transfer.model_banking_export_sepa msgid "SEPA export" msgstr "" #. module: account_banking_sepa_credit_transfer -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:351 +#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:246 #, python-format msgid "Missing Bank Account on invoice '%s' (payment order line reference '%s')." msgstr "" @@ -195,29 +154,17 @@ msgstr "" msgid "SEPA XML File" msgstr "" -#. module: account_banking_sepa_credit_transfer -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:131 -#, python-format -msgid "The '%s' is empty or 0. It should have a non-null value." -msgstr "" - #. module: account_banking_sepa_credit_transfer #: help:banking.export.sepa,charge_bearer:0 msgid "Following service level : transaction charges are to be applied following the rules agreed in the service level and/or scheme (SEPA Core messages must use this). Shared : transaction charges on the creditor side are to be borne by the creditor, transaction charges on the debtor side are to be borne by the debtor. Borne by creditor : all transaction charges are to be borne by the creditor. Borne by debtor : all transaction charges are to be borne by the debtor." msgstr "" #. module: account_banking_sepa_credit_transfer -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:207 +#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:129 #, python-format msgid "Payment Type Code '%s' is not supported. The only Payment Type Codes supported for SEPA Credit Transfers are 'pain.001.001.02', 'pain.001.001.03', 'pain.001.001.04' and 'pain.001.001.05'." msgstr "" -#. module: account_banking_sepa_credit_transfer -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:90 -#, python-format -msgid "This IBAN is not valid : %s" -msgstr "" - #. module: account_banking_sepa_credit_transfer #: view:banking.export.sepa:0 #: field:banking.export.sepa,payment_order_ids:0 @@ -243,11 +190,6 @@ msgstr "" msgid "If true, the bank statement will display only one debit line for all the wire transfers of the SEPA XML file ; if false, the bank statement will display one debit line per wire transfer of the SEPA XML file." msgstr "" -#. module: account_banking_sepa_credit_transfer -#: help:banking.export.sepa.wizard,prefered_exec_date:0 -msgid "This is the date on which the file should be processed by the bank. Please keep in mind that banks only execute on working days and typically use a delay of two days between execution date and effective transfer date." -msgstr "" - #. module: account_banking_sepa_credit_transfer #: field:banking.export.sepa.wizard,file:0 msgid "File" diff --git a/account_banking_sepa_credit_transfer/i18n/fr.po b/account_banking_sepa_credit_transfer/i18n/fr.po index 6b415fc5b..098e87ea3 100644 --- a/account_banking_sepa_credit_transfer/i18n/fr.po +++ b/account_banking_sepa_credit_transfer/i18n/fr.po @@ -6,21 +6,14 @@ msgid "" msgstr "" "Project-Id-Version: OpenERP Server 7.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-11-13 09:13+0000\n" -"PO-Revision-Date: 2013-12-02 16:36+0000\n" -"Last-Translator: Alexis de Lattre \n" +"POT-Creation-Date: 2013-12-23 22:52+0000\n" +"PO-Revision-Date: 2013-12-23 22:52+0000\n" +"Last-Translator: <>\n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-12-03 06:20+0000\n" -"X-Generator: Launchpad (build 16856)\n" - -#. module: account_banking_sepa_credit_transfer -#: field:banking.export.sepa,prefered_exec_date:0 -#: field:banking.export.sepa.wizard,prefered_exec_date:0 -msgid "Prefered Execution Date" -msgstr "Date d'exécution demandée" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" #. module: account_banking_sepa_credit_transfer #: selection:banking.export.sepa.wizard,state:0 @@ -52,31 +45,8 @@ msgstr "Brouillon" #. module: account_banking_sepa_credit_transfer #: help:banking.export.sepa.wizard,charge_bearer:0 -msgid "" -"Following service level : transaction charges are to be applied following " -"the rules agreed in the service level and/or scheme (SEPA Core messages must " -"use this). Shared : transaction charges on the debtor side are to be borne " -"by the debtor, transaction charges on the creditor side are to be borne by " -"the creditor. Borne by creditor : all transaction charges are to be borne by " -"the creditor. Borne by debtor : all transaction charges are to be borne by " -"the debtor." -msgstr "" -"Suivant le niveau de service : la répartition des frais bancaires suit les " -"règles pré-établies dans le schema ou dans le contrat avec la banque (les " -"messages SEPA Core doivent utiliser ce paramètre). Partagés : les frais " -"bancaires côté débiteur sont à la charge du débiteur, les frais bancaires " -"côté créancier sont à la charge du créancier. Supportés par le créancier : " -"tous les frais bancaires sont à la charge du créancier. Supportés par le " -"débiteur : tous les frais bancaires sont à la charge du débiteur." - -#. module: account_banking_sepa_credit_transfer -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:117 -#, python-format -msgid "" -"Cannot compute the '%s' of the Payment Line with Invoice Reference '%s'." -msgstr "" -"Impossible de générer le '%s' de la ligne de paiement ayant la référence de " -"facture '%s'." +msgid "Following service level : transaction charges are to be applied following the rules agreed in the service level and/or scheme (SEPA Core messages must use this). Shared : transaction charges on the debtor side are to be borne by the debtor, transaction charges on the creditor side are to be borne by the creditor. Borne by creditor : all transaction charges are to be borne by the creditor. Borne by debtor : all transaction charges are to be borne by the debtor." +msgstr "Suivant le niveau de service : la répartition des frais bancaires suit les règles pré-établies dans le schema ou dans le contrat avec la banque (les messages SEPA Core doivent utiliser ce paramètre). Partagés : les frais bancaires côté débiteur sont à la charge du débiteur, les frais bancaires côté créancier sont à la charge du créancier. Supportés par le créancier : tous les frais bancaires sont à la charge du créancier. Supportés par le débiteur : tous les frais bancaires sont à la charge du débiteur." #. module: account_banking_sepa_credit_transfer #: selection:banking.export.sepa,charge_bearer:0 @@ -90,10 +60,15 @@ msgstr "Partagé" msgid "Batch Booking" msgstr "Débit groupé" +#. module: account_banking_sepa_credit_transfer +#: selection:banking.export.sepa,state:0 +msgid "Sent" +msgstr "Envoyé" + #. module: account_banking_sepa_credit_transfer #: model:ir.model,name:account_banking_sepa_credit_transfer.model_banking_export_sepa_wizard -msgid "Export SEPA Credit Transfer XML file" -msgstr "Exporte the fichier de virement SEPA XML" +msgid "Export SEPA Credit Transfer File" +msgstr "Exporte le fichier de virement SEPA" #. module: account_banking_sepa_credit_transfer #: view:banking.export.sepa:0 @@ -122,24 +97,6 @@ msgstr "Suivant le niveau de service" msgid "Borne by Creditor" msgstr "Supportés par le destinataire" -#. module: account_banking_sepa_credit_transfer -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:122 -#, python-format -msgid "Cannot compute the '%s'." -msgstr "Impossible de générer le '%s'." - -#. module: account_banking_sepa_credit_transfer -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:126 -#, python-format -msgid "The type of the field '%s' is %s. It should be a string or unicode." -msgstr "" -"Le champ '%s' est de type %s. Le type devrait être string ou unicode." - -#. module: account_banking_sepa_credit_transfer -#: selection:banking.export.sepa,state:0 -msgid "Sent" -msgstr "Envoyé" - #. module: account_banking_sepa_credit_transfer #: view:banking.export.sepa.wizard:0 msgid "Validate" @@ -150,20 +107,6 @@ msgstr "Valider" msgid "Generate" msgstr "Générer" -#. module: account_banking_sepa_credit_transfer -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:169 -#, python-format -msgid "" -"The generated XML file is not valid against the official XML Schema " -"Definition. The generated XML file and the full error have been written in " -"the server logs. Here is the error, which may give you an idea on the cause " -"of the problem : %s" -msgstr "" -"Le fichier XML généré n'est pas valide par rapport à la Définition du Schéma " -"XML officiel. Le fichier XML généré et le message d'erreur complet ont été " -"écrits dans les logs du serveur. Voici l'erreur, qui vous donnera peut-être " -"une idée sur la cause du problème : %s" - #. module: account_banking_sepa_credit_transfer #: selection:banking.export.sepa,charge_bearer:0 #: selection:banking.export.sepa.wizard,charge_bearer:0 @@ -171,13 +114,8 @@ msgid "Borne by Debtor" msgstr "Supportés par l'émetteur" #. module: account_banking_sepa_credit_transfer -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:90 -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:116 -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:121 -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:130 -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:168 -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:206 -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:350 +#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:128 +#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:245 #, python-format msgid "Error:" msgstr "Erreur :" @@ -199,25 +137,16 @@ msgstr "Répartition des frais" msgid "SEPA File Generation" msgstr "Génération du fichier SEPA" -#. module: account_banking_sepa_credit_transfer -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:125 -#, python-format -msgid "Field type error:" -msgstr "Erreur dans le type de champ:" - #. module: account_banking_sepa_credit_transfer #: model:ir.model,name:account_banking_sepa_credit_transfer.model_banking_export_sepa msgid "SEPA export" msgstr "Export SEPA" #. module: account_banking_sepa_credit_transfer -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:351 +#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:246 #, python-format -msgid "" -"Missing Bank Account on invoice '%s' (payment order line reference '%s')." -msgstr "" -"Compte bancaire manquant sur la facture '%s' (référence de la ligne de " -"paiement : '%s')." +msgid "Missing Bank Account on invoice '%s' (payment order line reference '%s')." +msgstr "Compte bancaire manquant sur la facture '%s' (référence de la ligne de paiement : '%s')." #. module: account_banking_sepa_credit_transfer #: field:banking.export.sepa,file:0 @@ -225,48 +154,16 @@ msgstr "" msgid "SEPA XML File" msgstr "Fichier SEPA XML" -#. module: account_banking_sepa_credit_transfer -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:131 -#, python-format -msgid "The '%s' is empty or 0. It should have a non-null value." -msgstr "Le '%s' est vide ou égal à 0. La valeur devrait être non nulle." - #. module: account_banking_sepa_credit_transfer #: help:banking.export.sepa,charge_bearer:0 -msgid "" -"Following service level : transaction charges are to be applied following " -"the rules agreed in the service level and/or scheme (SEPA Core messages must " -"use this). Shared : transaction charges on the creditor side are to be borne " -"by the creditor, transaction charges on the debtor side are to be borne by " -"the debtor. Borne by creditor : all transaction charges are to be borne by " -"the creditor. Borne by debtor : all transaction charges are to be borne by " -"the debtor." -msgstr "" -"Suivant le niveau de service : la répartition des frais bancaires suit les " -"règles pré-établies dans le schema ou dans le contrat avec la banque (les " -"messages SEPA Core doivent utiliser ce paramètre). Partagés : les frais " -"bancaires côté débiteur sont à la charge du débiteur, les frais bancaires " -"côté créancier sont à la charge du créancier. Supportés par le créancier : " -"tous les frais bancaires sont à la charge du créancier. Supportés par le " -"débiteur : tous les frais bancaires sont à la charge du débiteur." +msgid "Following service level : transaction charges are to be applied following the rules agreed in the service level and/or scheme (SEPA Core messages must use this). Shared : transaction charges on the creditor side are to be borne by the creditor, transaction charges on the debtor side are to be borne by the debtor. Borne by creditor : all transaction charges are to be borne by the creditor. Borne by debtor : all transaction charges are to be borne by the debtor." +msgstr "Suivant le niveau de service : la répartition des frais bancaires suit les règles pré-établies dans le schema ou dans le contrat avec la banque (les messages SEPA Core doivent utiliser ce paramètre). Partagés : les frais bancaires côté débiteur sont à la charge du débiteur, les frais bancaires côté créancier sont à la charge du créancier. Supportés par le créancier : tous les frais bancaires sont à la charge du créancier. Supportés par le débiteur : tous les frais bancaires sont à la charge du débiteur." #. module: account_banking_sepa_credit_transfer -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:207 +#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:129 #, python-format -msgid "" -"Payment Type Code '%s' is not supported. The only Payment Type Codes " -"supported for SEPA Credit Transfers are 'pain.001.001.02', " -"'pain.001.001.03', 'pain.001.001.04' and 'pain.001.001.05'." -msgstr "" -"Le code du Type de paiement '%s' n'est pas supporté. Les seuls codes de Type " -"de paiement supportés pour les virements SEPA sont 'pain.001.001.02', " -"'pain.001.001.03', 'pain.001.001.04' et 'pain.001.001.05'." - -#. module: account_banking_sepa_credit_transfer -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:90 -#, python-format -msgid "This IBAN is not valid : %s" -msgstr "Cet IBAN n'est pas valide : %s" +msgid "Payment Type Code '%s' is not supported. The only Payment Type Codes supported for SEPA Credit Transfers are 'pain.001.001.02', 'pain.001.001.03', 'pain.001.001.04' and 'pain.001.001.05'." +msgstr "Le code du Type de paiement '%s' n'est pas supporté. Les seuls codes de Type de paiement supportés pour les virements SEPA sont 'pain.001.001.02', 'pain.001.001.03', 'pain.001.001.04' et 'pain.001.001.05'." #. module: account_banking_sepa_credit_transfer #: view:banking.export.sepa:0 @@ -290,26 +187,8 @@ msgstr "Fichiers de virement SEPA" #. module: account_banking_sepa_credit_transfer #: help:banking.export.sepa,batch_booking:0 #: help:banking.export.sepa.wizard,batch_booking:0 -msgid "" -"If true, the bank statement will display only one debit line for all the " -"wire transfers of the SEPA XML file ; if false, the bank statement will " -"display one debit line per wire transfer of the SEPA XML file." -msgstr "" -"Si coché, le relevé de compte ne comportera qu'une ligne de débit pour tous " -"les virements du fichier SEPA XML ; si non coché, le relevé de compte " -"comportera une ligne de débit pour chaque virement du fichier SEPA XML." - -#. module: account_banking_sepa_credit_transfer -#: help:banking.export.sepa.wizard,prefered_exec_date:0 -msgid "" -"This is the date on which the file should be processed by the bank. Please " -"keep in mind that banks only execute on working days and typically use a " -"delay of two days between execution date and effective transfer date." -msgstr "" -"C'est la date à laquelle le fichier doit être traité par la banque. Gardez " -"en tête que les banques réalisent des traitements seulement les jours ouvrés " -"et ont habituellement un délai de 2 jours entre la date de traitement et la " -"date du transfert effectif." +msgid "If true, the bank statement will display only one debit line for all the wire transfers of the SEPA XML file ; if false, the bank statement will display one debit line per wire transfer of the SEPA XML file." +msgstr "Si coché, le relevé de compte ne comportera qu'une ligne de débit pour tous les virements du fichier SEPA XML ; si non coché, le relevé de compte comportera une ligne de débit pour chaque virement du fichier SEPA XML." #. module: account_banking_sepa_credit_transfer #: field:banking.export.sepa.wizard,file:0 @@ -326,88 +205,3 @@ msgstr "Annuler" msgid "Generation Date" msgstr "Date de génération" -#~ msgid "SEPA XML file" -#~ msgstr "Fichier SEPA XML" - -#~ msgid "Payment order" -#~ msgstr "Ordre de paiement" - -#~ msgid "" -#~ "This is the message identification of the entire SEPA XML file. 35 " -#~ "characters max." -#~ msgstr "" -#~ "Ceci est le libellé d'identification du fichier SEPA XML. 35 caractères " -#~ "maximum." - -#~ msgid "Prefered execution date" -#~ msgstr "Date d'exécution demandée" - -#~ msgid "Generation date" -#~ msgstr "Date de génération" - -#~ msgid "Message identification" -#~ msgstr "Libellé d'identification" - -#~ msgid "Total amount" -#~ msgstr "Montant total" - -#~ msgid "" -#~ "Shared : transaction charges on the sender side are to be borne by the " -#~ "debtor, transaction charges on the receiver side are to be borne by the " -#~ "creditor (most transfers use this). Borne by creditor : all transaction " -#~ "charges are to be borne by the creditor. Borne by debtor : all transaction " -#~ "charges are to be borne by the debtor. Following service level : transaction " -#~ "charges are to be applied following the rules agreed in the service level " -#~ "and/or scheme." -#~ msgstr "" -#~ "Partagés : les frais bancaires côté émetteur sont à la charge de l'émetteur " -#~ "et les frais bancaires côté destinataire sont à la charge du destinataire " -#~ "(la plupart des virements utilisent cette répartition). Supportés par le " -#~ "destinataire : tous les frais bancaires sont à la charge du destinataire. " -#~ "Supportés par l'émetteur : tous les frais bancaires sont à la charge de " -#~ "l'émetteur. Suivant le niveau de service : la répartition des frais " -#~ "bancaires suit les règles pré-établies dans le contrat avec la banque." - -#~ msgid "Borne by creditor" -#~ msgstr "Supportés par le destinataire" - -#~ msgid "Payment orders" -#~ msgstr "Ordres de paiement" - -#~ msgid "SEPA XML file generation" -#~ msgstr "Génération du fichier SEPA XML" - -#~ msgid "Reference for further communication" -#~ msgstr "Référence pour communication ultérieure" - -#~ msgid "Processing details" -#~ msgstr "Paramètres" - -#~ msgid "Borne by debtor" -#~ msgstr "Supportés par l'émetteur" - -#~ msgid "Number of transactions" -#~ msgstr "Nombre de transactions" - -#~ msgid "Following service level" -#~ msgstr "Suivant le niveau de service" - -#~ msgid "Charge bearer" -#~ msgstr "Répartition des frais" - -#, python-format -#~ msgid "" -#~ "Payment Type Code '%s' is not supported. The only Payment Type Codes " -#~ "supported for SEPA Credit Transfers are 'pain.001.001.02', 'pain.001.001.03' " -#~ "and 'pain.001.001.04'." -#~ msgstr "" -#~ "Le code '%s' pour le Type de Paiment n'est pas supporté. Les seuls codes de " -#~ "Types de Paiement supportés pour les virements SEPA sont 'pain.001.001.02', " -#~ "'pain.001.001.03' et 'pain.001.001.04'." - -#, python-format -#~ msgid "Error :" -#~ msgstr "Erreur :" - -#~ msgid "Batch booking" -#~ msgstr "Débit groupé" diff --git a/account_banking_sepa_credit_transfer/wizard/export_sepa.py b/account_banking_sepa_credit_transfer/wizard/export_sepa.py index b1e8ff047..3b7aa0460 100644 --- a/account_banking_sepa_credit_transfer/wizard/export_sepa.py +++ b/account_banking_sepa_credit_transfer/wizard/export_sepa.py @@ -23,11 +23,8 @@ from openerp.osv import orm, fields from openerp.tools.translate import _ -from openerp import tools, netsvc +from openerp import netsvc from lxml import etree -import logging - -_logger = logging.getLogger(__name__) class banking_export_sepa_wizard(orm.TransientModel): @@ -42,14 +39,24 @@ class banking_export_sepa_wizard(orm.TransientModel): ], 'State', readonly=True), 'batch_booking': fields.boolean( 'Batch Booking', - help="If true, the bank statement will display only one debit line for all the wire transfers of the SEPA XML file ; if false, the bank statement will display one debit line per wire transfer of the SEPA XML file."), + help="If true, the bank statement will display only one debit " + "line for all the wire transfers of the SEPA XML file ; if " + "false, the bank statement will display one debit line per wire " + "transfer of the SEPA XML file."), 'charge_bearer': fields.selection([ ('SLEV', 'Following Service Level'), ('SHAR', 'Shared'), ('CRED', 'Borne by Creditor'), ('DEBT', 'Borne by Debtor'), ], 'Charge Bearer', required=True, - help='Following service level : transaction charges are to be applied following the rules agreed in the service level and/or scheme (SEPA Core messages must use this). Shared : transaction charges on the debtor side are to be borne by the debtor, transaction charges on the creditor side are to be borne by the creditor. Borne by creditor : all transaction charges are to be borne by the creditor. Borne by debtor : all transaction charges are to be borne by the debtor.'), + help="Following service level : transaction charges are to be " + "applied following the rules agreed in the service level and/or " + "scheme (SEPA Core messages must use this). Shared : transaction " + "charges on the debtor side are to be borne by the debtor, " + "transaction charges on the creditor side are to be borne by " + "the creditor. Borne by creditor : all transaction charges are " + "to be borne by the creditor. Borne by debtor : all transaction " + "charges are to be borne by the debtor."), 'nb_transactions': fields.related( 'file_id', 'nb_transactions', type='integer', string='Number of Transactions', readonly=True), @@ -119,7 +126,10 @@ class banking_export_sepa_wizard(orm.TransientModel): else: raise orm.except_orm( _('Error:'), - _("Payment Type Code '%s' is not supported. The only Payment Type Codes supported for SEPA Credit Transfers are 'pain.001.001.02', 'pain.001.001.03', 'pain.001.001.04' and 'pain.001.001.05'.") + _("Payment Type Code '%s' is not supported. The only " + "Payment Type Codes supported for SEPA Credit Transfers " + "are 'pain.001.001.02', 'pain.001.001.03', " + "'pain.001.001.04' and 'pain.001.001.05'.") % pain_flavor) gen_args = { @@ -127,6 +137,11 @@ class banking_export_sepa_wizard(orm.TransientModel): 'name_maxsize': name_maxsize, 'convert_to_ascii': convert_to_ascii, 'pain_flavor': pain_flavor, + 'sepa_export': sepa_export, + 'file_obj': self.pool['banking.export.sepa'], + 'pain_xsd_file': + 'account_banking_sepa_credit_transfer/data/%s.xsd' + % pain_flavor, } pain_ns = { @@ -134,15 +149,15 @@ class banking_export_sepa_wizard(orm.TransientModel): None: 'urn:iso:std:iso:20022:tech:xsd:%s' % pain_flavor, } - root = etree.Element('Document', nsmap=pain_ns) - pain_root = etree.SubElement(root, root_xml_tag) + xml_root = etree.Element('Document', nsmap=pain_ns) + pain_root = etree.SubElement(xml_root, root_xml_tag) pain_03_to_05 = \ ['pain.001.001.03', 'pain.001.001.04', 'pain.001.001.05'] # A. Group header group_header_1_0, nb_of_transactions_1_6, control_sum_1_7 = \ - self.generate_group_header_block( - cr, uid, pain_root, sepa_export, gen_args, context=context) + self.generate_group_header_block( + cr, uid, pain_root, gen_args, context=context) transactions_count_1_6 = 0 total_amount = 0.0 @@ -175,22 +190,25 @@ class banking_export_sepa_wizard(orm.TransientModel): for (requested_date, priority), lines in lines_per_group.items(): # B. Payment info payment_info_2_0, nb_of_transactions_2_4, control_sum_2_5 = \ - self.generate_start_payment_info_block( - cr, uid, pain_root, sepa_export, - "sepa_export.payment_order_ids[0].reference + '-' + requested_date.replace('-', '') + '-' + priority", - priority, False, False, requested_date, { - 'sepa_export': sepa_export, - 'priority': priority, - 'requested_date': requested_date, - }, gen_args, context=context) + self.generate_start_payment_info_block( + cr, uid, pain_root, + "sepa_export.payment_order_ids[0].reference + '-' " + "+ requested_date.replace('-', '') + '-' + priority", + priority, False, False, requested_date, { + 'sepa_export': sepa_export, + 'priority': priority, + 'requested_date': requested_date, + }, gen_args, context=context) self.generate_party_block( cr, uid, payment_info_2_0, 'Dbtr', 'B', - 'sepa_export.payment_order_ids[0].mode.bank_id.partner_id.name', + 'sepa_export.payment_order_ids[0].mode.bank_id.partner_id.' + 'name', 'sepa_export.payment_order_ids[0].mode.bank_id.acc_number', 'sepa_export.payment_order_ids[0].mode.bank_id.bank.bic', {'sepa_export': sepa_export}, gen_args, context=context) + charge_bearer_2_24 = etree.SubElement(payment_info_2_0, 'ChrgBr') charge_bearer_2_24.text = sepa_export.charge_bearer @@ -225,14 +243,14 @@ class banking_export_sepa_wizard(orm.TransientModel): if not line.bank_id: raise orm.except_orm( _('Error:'), - _("Missing Bank Account on invoice '%s' (payment order line reference '%s').") + _("Missing Bank Account on invoice '%s' (payment " + "order line reference '%s').") % (line.ml_inv_ref.number, line.name)) self.generate_party_block( - cr, uid, credit_transfer_transaction_info_2_27, 'Cdtr', 'C', - 'line.partner_id.name', - 'line.bank_id.acc_number', - 'line.bank_id.bank.bic', - {'line': line}, gen_args, context=context) + cr, uid, credit_transfer_transaction_info_2_27, 'Cdtr', + 'C', 'line.partner_id.name', 'line.bank_id.acc_number', + 'line.bank_id.bank.bic', {'line': line}, gen_args, + context=context) self.generate_remittance_info_block( cr, uid, credit_transfer_transaction_info_2_27, @@ -249,39 +267,9 @@ class banking_export_sepa_wizard(orm.TransientModel): nb_of_transactions_1_6.text = str(transactions_count_1_6) control_sum_1_7.text = '%.2f' % amount_control_sum_1_7 - xml_string = etree.tostring( - root, pretty_print=True, encoding='UTF-8', xml_declaration=True) - _logger.debug( - "Generated SEPA Credit Transfer XML file in format %s below" - % pain_flavor) - _logger.debug(xml_string) - pain_xsd_file = \ - 'account_banking_sepa_credit_transfer/data/%s.xsd' % pain_flavor - self._validate_xml(cr, uid, xml_string, pain_xsd_file) - - # CREATE the banking.export.sepa record - file_id = self.pool.get('banking.export.sepa').create( - cr, uid, self._prepare_export_sepa( - cr, uid, sepa_export, total_amount, transactions_count_1_6, - xml_string, gen_args, context=context), - context=context) - - self.write( - cr, uid, ids, { - 'file_id': file_id, - 'state': 'finish', - }, context=context) - - action = { - 'name': 'SEPA Credit Transfer File', - 'type': 'ir.actions.act_window', - 'view_type': 'form', - 'view_mode': 'form,tree', - 'res_model': self._name, - 'res_id': ids[0], - 'target': 'new', - } - return action + return self.finalize_sepa_file_creation( + cr, uid, ids, xml_root, total_amount, transactions_count_1_6, + gen_args, context=context) def cancel_sepa(self, cr, uid, ids, context=None): ''' diff --git a/account_banking_sepa_direct_debit/account_banking_sdd.py b/account_banking_sepa_direct_debit/account_banking_sdd.py index 28759ef64..d0edb5e90 100644 --- a/account_banking_sepa_direct_debit/account_banking_sdd.py +++ b/account_banking_sepa_direct_debit/account_banking_sdd.py @@ -63,14 +63,24 @@ class banking_export_sdd(orm.Model): readonly=True), 'batch_booking': fields.boolean( 'Batch Booking', readonly=True, - help="If true, the bank statement will display only one credit line for all the direct debits of the SEPA file ; if false, the bank statement will display one credit line per direct debit of the SEPA file."), + help="If true, the bank statement will display only one credit " + "line for all the direct debits of the SEPA file ; if false, " + "the bank statement will display one credit line per direct " + "debit of the SEPA file."), 'charge_bearer': fields.selection([ ('SLEV', 'Following Service Level'), ('SHAR', 'Shared'), ('CRED', 'Borne by Creditor'), ('DEBT', 'Borne by Debtor'), ], 'Charge Bearer', readonly=True, - help='Following service level : transaction charges are to be applied following the rules agreed in the service level and/or scheme (SEPA Core messages must use this). Shared : transaction charges on the creditor side are to be borne by the creditor, transaction charges on the debtor side are to be borne by the debtor. Borne by creditor : all transaction charges are to be borne by the creditor. Borne by debtor : all transaction charges are to be borne by the debtor.'), + help="Following service level : transaction charges are to be " + "applied following the rules agreed in the service level and/or " + "scheme (SEPA Core messages must use this). Shared : " + "transaction charges on the creditor side are to be borne by " + "the creditor, transaction charges on the debtor side are to be " + "borne by the debtor. Borne by creditor : all transaction " + "charges are to be borne by the creditor. Borne by debtor : " + "all transaction charges are to be borne by the debtor."), 'create_date': fields.datetime('Generation Date', readonly=True), 'file': fields.binary('SEPA File', readonly=True), 'filename': fields.function( @@ -98,22 +108,26 @@ class sdd_mandate(orm.Model): _track = { 'state': { 'account_banking_sepa_direct_debit.mandate_valid': - lambda self, cr, uid, obj, ctx=None: obj['state'] == 'valid', + lambda self, cr, uid, obj, ctx=None: + obj['state'] == 'valid', 'account_banking_sepa_direct_debit.mandate_expired': - lambda self, cr, uid, obj, ctx=None: obj['state'] == 'expired', + lambda self, cr, uid, obj, ctx=None: + obj['state'] == 'expired', 'account_banking_sepa_direct_debit.mandate_cancel': - lambda self, cr, uid, obj, ctx=None: obj['state'] == 'cancel', + lambda self, cr, uid, obj, ctx=None: + obj['state'] == 'cancel', }, 'recurrent_sequence_type': { 'account_banking_sepa_direct_debit.recurrent_sequence_type_first': - lambda self, cr, uid, obj, ctx=None: - obj['recurrent_sequence_type'] == 'first', - 'account_banking_sepa_direct_debit.recurrent_sequence_type_recurring': - lambda self, cr, uid, obj, ctx=None: - obj['recurrent_sequence_type'] == 'recurring', + lambda self, cr, uid, obj, ctx=None: + obj['recurrent_sequence_type'] == 'first', + 'account_banking_sepa_direct_debit.' + 'recurrent_sequence_type_recurring': + lambda self, cr, uid, obj, ctx=None: + obj['recurrent_sequence_type'] == 'recurring', 'account_banking_sepa_direct_debit.recurrent_sequence_type_final': - lambda self, cr, uid, obj, ctx=None: - obj['recurrent_sequence_type'] == 'final', + lambda self, cr, uid, obj, ctx=None: + obj['recurrent_sequence_type'] == 'final', } } @@ -136,7 +150,8 @@ class sdd_mandate(orm.Model): ('recurring', 'Recurring'), ('final', 'Final'), ], 'Sequence Type for Next Debit', track_visibility='onchange', - help="This field is only used for Recurrent mandates, not for One-Off mandates."), + help="This field is only used for Recurrent mandates, not for " + "One-Off mandates."), 'signature_date': fields.date( 'Date of Signature of the Mandate', track_visibility='onchange'), 'scan': fields.binary('Scan of the Mandate'), @@ -148,24 +163,36 @@ class sdd_mandate(orm.Model): ('expired', 'Expired'), ('cancel', 'Cancelled'), ], 'Status', - help="Only valid mandates can be used in a payment line. A cancelled mandate is a mandate that has been cancelled by the customer. A one-off mandate expires after its first use. A recurrent mandate expires after it's final use or if it hasn't been used for 36 months."), + help="Only valid mandates can be used in a payment line. A " + "cancelled mandate is a mandate that has been cancelled by " + "the customer. A one-off mandate expires after its first use. " + "A recurrent mandate expires after it's final use or if it " + "hasn't been used for 36 months."), 'payment_line_ids': fields.one2many( 'payment.line', 'sdd_mandate_id', "Related Payment Lines"), 'sepa_migrated': fields.boolean( 'Migrated to SEPA', track_visibility='onchange', - help="If this field is not active, the mandate section of the next direct debit file that include this mandate will contain the 'Original Mandate Identification' and the 'Original Creditor Scheme Identification'. This is required in a few countries (Belgium for instance), but not in all countries. If this is not required in your country, you should keep this field always active."), + help="If this field is not active, the mandate section of the " + "next direct debit file that include this mandate will contain " + "the 'Original Mandate Identification' and the 'Original " + "Creditor Scheme Identification'. This is required in a few " + "countries (Belgium for instance), but not in all countries. " + "If this is not required in your country, you should keep this " + "field always active."), 'original_mandate_identification': fields.char( 'Original Mandate Identification', size=35, track_visibility='onchange', - help="When the field 'Migrated to SEPA' is not active, this field will be used as the Original Mandate Identification in the the Direct Debit file."), + help="When the field 'Migrated to SEPA' is not active, this " + "field will be used as the Original Mandate Identification in " + "the Direct Debit file."), } _defaults = { 'company_id': lambda self, cr, uid, context: - self.pool['res.company'].\ - _company_default_get(cr, uid, 'sdd.mandate', context=context), + self.pool['res.company']._company_default_get( + cr, uid, 'sdd.mandate', context=context), 'unique_mandate_reference': lambda self, cr, uid, ctx: - self.pool['ir.sequence'].get(cr, uid, 'sdd.mandate.reference'), + self.pool['ir.sequence'].get(cr, uid, 'sdd.mandate.reference'), 'state': 'draft', 'sepa_migrated': True, } @@ -183,24 +210,28 @@ class sdd_mandate(orm.Model): datetime.today().strftime('%Y-%m-%d')): raise orm.except_orm( _('Error:'), - _("The date of signature of mandate '%s' is in the future!") + _("The date of signature of mandate '%s' is in the " + "future !") % mandate.unique_mandate_reference) if mandate.state == 'valid' and not mandate.signature_date: raise orm.except_orm( _('Error:'), - _("Cannot validate the mandate '%s' without a date of signature.") + _("Cannot validate the mandate '%s' without a date of " + "signature.") % mandate.unique_mandate_reference) if mandate.state == 'valid' and not mandate.partner_bank_id: raise orm.except_orm( _('Error:'), - _("Cannot validate the mandate '%s' because it is not attached to a bank account.") + _("Cannot validate the mandate '%s' because it is not " + "attached to a bank account.") % mandate.unique_mandate_reference) if (mandate.signature_date and mandate.last_debit_date and mandate.signature_date > mandate.last_debit_date): raise orm.except_orm( _('Error:'), - _("The mandate '%s' can't have a date of last debit before the date of signature.") + _("The mandate '%s' can't have a date of last debit " + "before the date of signature.") % mandate.unique_mandate_reference) if (mandate.type == 'recurrent' and not mandate.recurrent_sequence_type): @@ -212,13 +243,17 @@ class sdd_mandate(orm.Model): and mandate.recurrent_sequence_type != 'first'): raise orm.except_orm( _('Error:'), - _("The recurrent mandate '%s' which is not marked as 'Migrated to SEPA' must have its recurrent sequence type set to 'First'.") + _("The recurrent mandate '%s' which is not marked as " + "'Migrated to SEPA' must have its recurrent sequence " + "type set to 'First'.") % mandate.unique_mandate_reference) if (mandate.type == 'recurrent' and not mandate.sepa_migrated and not mandate.original_mandate_identification): raise orm.except_orm( _('Error:'), - _("You must set the 'Original Mandate Identification' on the recurrent mandate '%s' which is not marked as 'Migrated to SEPA'.") + _("You must set the 'Original Mandate Identification' " + "on the recurrent mandate '%s' which is not marked " + "as 'Migrated to SEPA'.") % mandate.unique_mandate_reference) return True @@ -252,8 +287,11 @@ class sdd_mandate(orm.Model): and recurrent_sequence_type != 'first'): res['value']['recurrent_sequence_type'] = 'first' res['warning'] = { - 'title': _('Mandate update'), - 'message': _("As you changed the bank account attached to this mandate, the 'Sequence Type' has been set back to 'First'."), + 'title': _('Mandate update'), + 'message': _( + "As you changed the bank account attached to this " + "mandate, the 'Sequence Type' has been set back to " + "'First'."), } return res @@ -337,7 +375,7 @@ class payment_line(orm.Model): vals.update({ 'sdd_mandate_id': line.invoice.sdd_mandate_id.id, 'bank_id': - line.invoice.sdd_mandate_id.partner_bank_id.id, + line.invoice.sdd_mandate_id.partner_bank_id.id, }) if partner_bank_id and 'sdd_mandate_id' not in vals: mandate_ids = self.pool['sdd.mandate'].search(cr, uid, [ @@ -355,14 +393,17 @@ class payment_line(orm.Model): payline.bank_id.id): raise orm.except_orm( _('Error:'), - _("The payment line with reference '%s' has the bank account '%s' which is not attached to the mandate '%s' (this mandate is attached to the bank account '%s').") - % (payline.name, - self.pool['res.partner.bank'].name_get( - cr, uid, [payline.bank_id.id])[0][1], - payline.sdd_mandate_id.unique_mandate_reference, - self.pool['res.partner.bank'].name_get( - cr, uid, - [payline.sdd_mandate_id.partner_bank_id.id])[0][1], + _("The payment line with reference '%s' has the bank " + "account '%s' which is not attached to the mandate " + "'%s' (this mandate is attached to the bank account " + "'%s').") % ( + payline.name, + self.pool['res.partner.bank'].name_get( + cr, uid, [payline.bank_id.id])[0][1], + payline.sdd_mandate_id.unique_mandate_reference, + self.pool['res.partner.bank'].name_get( + cr, uid, + [payline.sdd_mandate_id.partner_bank_id.id])[0][1], )) return True diff --git a/account_banking_sepa_direct_debit/company.py b/account_banking_sepa_direct_debit/company.py index ba4c7b7c8..5dd960224 100644 --- a/account_banking_sepa_direct_debit/company.py +++ b/account_banking_sepa_direct_debit/company.py @@ -31,7 +31,11 @@ class res_company(orm.Model): _columns = { 'sepa_creditor_identifier': fields.char( 'SEPA Creditor Identifier', size=35, - help="Enter the Creditor Identifier that has been attributed to your company to make SEPA Direct Debits. This identifier is composed of :\n- your country ISO code (2 letters)\n- a 2-digits checkum\n- a 3-letters business code\n- a country-specific identifier"), + help="Enter the Creditor Identifier that has been attributed " + "to your company to make SEPA Direct Debits. This identifier " + "is composed of :\n- your country ISO code (2 letters)\n- a " + "2-digits checkum\n- a 3-letters business code\n- a " + "country-specific identifier"), 'original_creditor_identifier': fields.char( 'Original Creditor Identifier', size=70), } diff --git a/account_banking_sepa_direct_debit/i18n/account_banking_sepa_direct_debit.pot b/account_banking_sepa_direct_debit/i18n/account_banking_sepa_direct_debit.pot index c33a775b4..0db576726 100644 --- a/account_banking_sepa_direct_debit/i18n/account_banking_sepa_direct_debit.pot +++ b/account_banking_sepa_direct_debit/i18n/account_banking_sepa_direct_debit.pot @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: OpenERP Server 7.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-11-11 14:28+0000\n" -"PO-Revision-Date: 2013-11-11 14:28+0000\n" +"POT-Creation-Date: 2013-12-23 22:24+0000\n" +"PO-Revision-Date: 2013-12-23 22:24+0000\n" "Last-Translator: <>\n" "Language-Team: \n" "MIME-Version: 1.0\n" @@ -27,19 +27,13 @@ msgid "Filename" msgstr "" #. module: account_banking_sepa_direct_debit -#: field:banking.export.sdd,requested_collec_date:0 -#: field:banking.export.sdd.wizard,requested_collec_date:0 -msgid "Requested Collection Date" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:276 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:200 #, python-format msgid "The SEPA Direct Debit mandate with reference '%s' for partner '%s' has expired." msgstr "" #. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:186 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:219 #, python-format msgid "Cannot validate the mandate '%s' without a date of signature." msgstr "" @@ -67,8 +61,8 @@ msgid "Error msg in raise" msgstr "" #. module: account_banking_sepa_direct_debit -#: field:sdd.mandate,company_id:0 -msgid "Company" +#: selection:banking.export.sdd,state:0 +msgid "Reconciled" msgstr "" #. module: account_banking_sepa_direct_debit @@ -119,21 +113,18 @@ msgid "Borne by Debtor" msgstr "" #. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:180 -#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:185 -#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:190 -#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:197 -#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:203 -#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:336 -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:89 -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:115 -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:121 -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:130 -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:168 -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:219 -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:269 -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:275 -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:287 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:212 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:218 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:224 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:232 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:239 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:245 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:253 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:395 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:140 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:192 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:199 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:209 #, python-format msgid "Error:" msgstr "" @@ -144,20 +135,8 @@ msgid "Messages" msgstr "" #. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:131 -#, python-format -msgid "The '%s' is empty or 0. It should have a non-null value." -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:89 -#, python-format -msgid "This IBAN is not valid : %s" -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: model:ir.model,name:account_banking_sepa_direct_debit.model_banking_export_sdd_wizard -msgid "Export SEPA Direct Debit XML file" +#: field:sdd.mandate,unique_mandate_reference:0 +msgid "Unique Mandate Reference" msgstr "" #. module: account_banking_sepa_direct_debit @@ -167,7 +146,7 @@ msgid "Cancelled" msgstr "" #. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:219 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:141 #, python-format msgid "Payment Type Code '%s' is not supported. The only Payment Type Code supported for SEPA Direct Debit are 'pain.008.001.02', 'pain.008.001.03' and 'pain.008.001.04'." msgstr "" @@ -187,6 +166,12 @@ msgstr "" msgid "SEPA Direct Debit Mandate has Expired" msgstr "" +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:246 +#, python-format +msgid "The recurrent mandate '%s' which is not marked as 'Migrated to SEPA' must have its recurrent sequence type set to 'First'." +msgstr "" + #. module: account_banking_sepa_direct_debit #: help:banking.export.sdd,charge_bearer:0 #: help:banking.export.sdd.wizard,charge_bearer:0 @@ -213,11 +198,6 @@ msgstr "" msgid "Holds the Chatter summary (number of messages, ...). This summary is directly in html format in order to be inserted in kanban views." msgstr "" -#. module: account_banking_sepa_direct_debit -#: help:banking.export.sdd.wizard,requested_collec_date:0 -msgid "This is the date on which you would like the collection to be made by the bank. Please keep in mind that there are minimum delays for SEPA direct debits that depend on the type of mandate and the type of sequence." -msgstr "" - #. module: account_banking_sepa_direct_debit #: model:ir.model,name:account_banking_sepa_direct_debit.model_payment_line msgid "Payment Line" @@ -229,7 +209,7 @@ msgid "Generation Date" msgstr "" #. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:337 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:396 #, python-format msgid "The payment line with reference '%s' has the bank account '%s' which is not attached to the mandate '%s' (this mandate is attached to the bank account '%s')." msgstr "" @@ -258,7 +238,7 @@ msgid "State" msgstr "" #. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:204 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:240 #, python-format msgid "The recurrent mandate '%s' must have a sequence type." msgstr "" @@ -291,14 +271,13 @@ msgid "Sent" msgstr "" #. module: account_banking_sepa_direct_debit -#: selection:sdd.mandate,recurrent_sequence_type:0 -msgid "Recurring" +#: field:res.company,original_creditor_identifier:0 +msgid "Original Creditor Identifier" msgstr "" #. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:181 -#, python-format -msgid "The date of signature of mandate '%s' is in the future!" +#: selection:sdd.mandate,recurrent_sequence_type:0 +msgid "Recurring" msgstr "" #. module: account_banking_sepa_direct_debit @@ -325,6 +304,12 @@ msgstr "" msgid "This field is only used for Recurrent mandates, not for One-Off mandates." msgstr "" +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:213 +#, python-format +msgid "The date of signature of mandate '%s' is in the future !" +msgstr "" + #. module: account_banking_sepa_direct_debit #: view:sdd.mandate:0 msgid "Signature Date" @@ -341,12 +326,6 @@ msgstr "" msgid "Partner" msgstr "" -#. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:125 -#, python-format -msgid "Field type error:" -msgstr "" - #. module: account_banking_sepa_direct_debit #: selection:sdd.mandate,recurrent_sequence_type:0 msgid "First" @@ -364,18 +343,32 @@ msgstr "" #. module: account_banking_sepa_direct_debit #: model:ir.actions.act_window,name:account_banking_sepa_direct_debit.act_banking_export_sdd_payment_order -#: model:ir.actions.act_window,name:account_banking_sepa_direct_debit.action_account_banking_sdd -#: model:ir.ui.menu,name:account_banking_sepa_direct_debit.menu_account_banking_sdd msgid "Generated SEPA Direct Debit Files" msgstr "" #. module: account_banking_sepa_direct_debit -#: selection:banking.export.sdd,state:0 -msgid "Reconciled" +#: help:sdd.mandate,sepa_migrated:0 +msgid "If this field is not active, the mandate section of the next direct debit file that include this mandate will contain the 'Original Mandate Identification' and the 'Original Creditor Scheme Identification'. This is required in a few countries (Belgium for instance), but not in all countries. If this is not required in your country, you should keep this field always active." msgstr "" #. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:191 +#: field:sdd.mandate,company_id:0 +msgid "Company" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: model:ir.model,name:account_banking_sepa_direct_debit.model_banking_export_sdd_wizard +msgid "Export SEPA Direct Debit File" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: help:banking.export.sdd,batch_booking:0 +#: help:banking.export.sdd.wizard,batch_booking:0 +msgid "If true, the bank statement will display only one credit line for all the direct debits of the SEPA file ; if false, the bank statement will display one credit line per direct debit of the SEPA file." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:225 #, python-format msgid "Cannot validate the mandate '%s' because it is not attached to a bank account." msgstr "" @@ -388,17 +381,11 @@ msgid "Draft" msgstr "" #. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:232 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:290 #, python-format msgid "Mandate update" msgstr "" -#. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:116 -#, python-format -msgid "Cannot compute the '%s' of the Payment Line with Invoice Reference '%s'." -msgstr "" - #. module: account_banking_sepa_direct_debit #: selection:banking.export.sdd,charge_bearer:0 #: selection:banking.export.sdd.wizard,charge_bearer:0 @@ -411,6 +398,11 @@ msgstr "" msgid "Batch Booking" msgstr "" +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,sepa_migrated:0 +msgid "Migrated to SEPA" +msgstr "" + #. module: account_banking_sepa_direct_debit #: field:sdd.mandate,state:0 msgid "Status" @@ -423,9 +415,9 @@ msgid "Total Amount" msgstr "" #. module: account_banking_sepa_direct_debit -#: help:banking.export.sdd,batch_booking:0 -#: help:banking.export.sdd.wizard,batch_booking:0 -msgid "If true, the bank statement will display only one credit line for all the direct debits of the SEPA file ; if false, the bank statement will display one credit line per direct debit of the SEPA file." +#: model:ir.actions.act_window,name:account_banking_sepa_direct_debit.action_account_banking_sdd +#: model:ir.ui.menu,name:account_banking_sepa_direct_debit.menu_account_banking_sdd +msgid "SEPA Direct Debit Files" msgstr "" #. module: account_banking_sepa_direct_debit @@ -435,7 +427,7 @@ msgid "Following Service Level" msgstr "" #. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:198 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:233 #, python-format msgid "The mandate '%s' can't have a date of last debit before the date of signature." msgstr "" @@ -451,11 +443,21 @@ msgstr "" msgid "Is a Follower" msgstr "" +#. module: account_banking_sepa_direct_debit +#: help:sdd.mandate,original_mandate_identification:0 +msgid "When the field 'Migrated to SEPA' is not active, this field will be used as the Original Mandate Identification in the Direct Debit file." +msgstr "" + #. module: account_banking_sepa_direct_debit #: view:payment.order:0 msgid "SDD Mandate" msgstr "" +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,original_mandate_identification:0 +msgid "Original Mandate Identification" +msgstr "" + #. module: account_banking_sepa_direct_debit #: model:ir.model,name:account_banking_sepa_direct_debit.model_res_company msgid "Companies" @@ -466,6 +468,11 @@ msgstr "" msgid "Summary" msgstr "" +#. module: account_banking_sepa_direct_debit +#: model:res.groups,name:account_banking_sepa_direct_debit.group_original_mandate_required +msgid "Original Mandate Required (SEPA)" +msgstr "" + #. module: account_banking_sepa_direct_debit #: field:account.invoice,sdd_mandate_id:0 #: model:ir.model,name:account_banking_sepa_direct_debit.model_sdd_mandate @@ -475,13 +482,13 @@ msgid "SEPA Direct Debit Mandate" msgstr "" #. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:270 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:193 #, python-format msgid "Missing SEPA Direct Debit mandate on the payment line with partner '%s' and Invoice ref '%s'." msgstr "" #. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:288 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:210 #, python-format msgid "The mandate with reference '%s' for partner '%s' has type set to 'One-Off' and it has a last debit date set to '%s', so we can't use it." msgstr "" @@ -549,12 +556,6 @@ msgstr "" msgid "Related Payment Lines" msgstr "" -#. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:169 -#, python-format -msgid "The generated XML file is not valid against the official XML Schema Definition. The generated XML file and the full error have been written in the server logs. Here is the error, which may give you an idea on the cause of the problem : %s" -msgstr "" - #. module: account_banking_sepa_direct_debit #: view:sdd.mandate:0 #: selection:sdd.mandate,type:0 @@ -581,18 +582,6 @@ msgstr "" msgid "SEPA Creditor Identifier" msgstr "" -#. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:122 -#, python-format -msgid "Cannot compute the '%s'." -msgstr "" - -#. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:126 -#, python-format -msgid "The type of the field '%s' is %s. It should be a string or unicode." -msgstr "" - #. module: account_banking_sepa_direct_debit #: model:ir.model,name:account_banking_sepa_direct_debit.model_banking_export_sdd msgid "SEPA Direct Debit export" @@ -609,6 +598,12 @@ msgstr "" msgid "Bank Account" msgstr "" +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:254 +#, python-format +msgid "You must set the 'Original Mandate Identification' on the recurrent mandate '%s' which is not marked as 'Migrated to SEPA'." +msgstr "" + #. module: account_banking_sepa_direct_debit #: model:mail.message.subtype,description:account_banking_sepa_direct_debit.recurrent_sequence_type_first #: model:mail.message.subtype,name:account_banking_sepa_direct_debit.recurrent_sequence_type_first @@ -616,7 +611,7 @@ msgid "Sequence Type set to First" msgstr "" #. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:233 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:291 #, python-format msgid "As you changed the bank account attached to this mandate, the 'Sequence Type' has been set back to 'First'." msgstr "" @@ -631,11 +626,6 @@ msgstr "" msgid "Search SEPA Direct Debit Mandates" msgstr "" -#. module: account_banking_sepa_direct_debit -#: field:sdd.mandate,unique_mandate_reference:0 -msgid "Unique Mandate Reference" -msgstr "" - #. module: account_banking_sepa_direct_debit #: field:banking.export.sdd.wizard,file:0 msgid "File" diff --git a/account_banking_sepa_direct_debit/i18n/fr.po b/account_banking_sepa_direct_debit/i18n/fr.po index 25b2df96f..9d30343dd 100644 --- a/account_banking_sepa_direct_debit/i18n/fr.po +++ b/account_banking_sepa_direct_debit/i18n/fr.po @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: OpenERP Server 7.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-11-11 14:04+0000\n" -"PO-Revision-Date: 2013-11-11 14:04+0000\n" +"POT-Creation-Date: 2013-12-23 22:25+0000\n" +"PO-Revision-Date: 2013-12-23 22:25+0000\n" "Last-Translator: <>\n" "Language-Team: \n" "MIME-Version: 1.0\n" @@ -27,19 +27,13 @@ msgid "Filename" msgstr "Nom du fichier" #. module: account_banking_sepa_direct_debit -#: field:banking.export.sdd,requested_collec_date:0 -#: field:banking.export.sdd.wizard,requested_collec_date:0 -msgid "Requested Collection Date" -msgstr "Date de collecte demandée" - -#. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:276 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:200 #, python-format msgid "The SEPA Direct Debit mandate with reference '%s' for partner '%s' has expired." msgstr "Le mandat de prélèvement SEPA portant la référence '%s' pour le partenaire '%s' a expiré." #. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:186 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:219 #, python-format msgid "Cannot validate the mandate '%s' without a date of signature." msgstr "Impossible de valider le mandat '%s' sans date de signature." @@ -119,21 +113,18 @@ msgid "Borne by Debtor" msgstr "Supportés par le débiteur" #. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:180 -#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:185 -#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:190 -#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:197 -#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:203 -#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:336 -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:89 -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:115 -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:121 -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:130 -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:168 -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:219 -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:269 -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:275 -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:287 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:212 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:218 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:224 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:232 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:239 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:245 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:253 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:395 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:140 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:192 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:199 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:209 #, python-format msgid "Error:" msgstr "Erreur :" @@ -144,21 +135,9 @@ msgid "Messages" msgstr "Messages" #. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:131 -#, python-format -msgid "The '%s' is empty or 0. It should have a non-null value." -msgstr "Le champ '%s' est vide ou nul. Il doit avoir une valeur non nulle." - -#. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:89 -#, python-format -msgid "This IBAN is not valid : %s" -msgstr "Cet IBAN n'est pas valide : %s" - -#. module: account_banking_sepa_direct_debit -#: model:ir.model,name:account_banking_sepa_direct_debit.model_banking_export_sdd_wizard -msgid "Export SEPA Direct Debit XML file" -msgstr "Export des fichiers de prélèvement SEPA" +#: field:sdd.mandate,unique_mandate_reference:0 +msgid "Unique Mandate Reference" +msgstr "Référence unique de mandat" #. module: account_banking_sepa_direct_debit #: view:sdd.mandate:0 @@ -167,7 +146,7 @@ msgid "Cancelled" msgstr "Annulé" #. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:219 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:141 #, python-format msgid "Payment Type Code '%s' is not supported. The only Payment Type Code supported for SEPA Direct Debit are 'pain.008.001.02', 'pain.008.001.03' and 'pain.008.001.04'." msgstr "Le code du Type de paiement '%s' n'est pas supporté. Les seuls codes de Type de paiement supportés pour les prélèvements SEPA sont 'pain.008.001.02', 'pain.008.001.03' et 'pain.008.001.04'." @@ -187,6 +166,12 @@ msgstr "Fichier de prélèvement SEPA" msgid "SEPA Direct Debit Mandate has Expired" msgstr "Le mandat de prélèvement SEPA a expiré" +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:246 +#, python-format +msgid "The recurrent mandate '%s' which is not marked as 'Migrated to SEPA' must have its recurrent sequence type set to 'First'." +msgstr "Le mandat récurrent '%s' dont l'option 'Migré à SEPA' n'est pas activée doit avec sa séquence mise à 'First'." + #. module: account_banking_sepa_direct_debit #: help:banking.export.sdd,charge_bearer:0 #: help:banking.export.sdd.wizard,charge_bearer:0 @@ -224,7 +209,7 @@ msgid "Generation Date" msgstr "Date de génération" #. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:337 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:396 #, python-format msgid "The payment line with reference '%s' has the bank account '%s' which is not attached to the mandate '%s' (this mandate is attached to the bank account '%s')." msgstr "La ligne de paiement portant la référence '%s' est configurée avec le compte bancaire '%s' qui n'est pas rattaché au mandat '%s' (ce mandat est rattaché au compte bancaire '%s')." @@ -253,7 +238,7 @@ msgid "State" msgstr "État" #. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:204 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:240 #, python-format msgid "The recurrent mandate '%s' must have a sequence type." msgstr "Le mandat récurrent '%s' doit avoir un type de séquence." @@ -285,17 +270,16 @@ msgstr "Type" msgid "Sent" msgstr "Envoyé" +#. module: account_banking_sepa_direct_debit +#: field:res.company,original_creditor_identifier:0 +msgid "Original Creditor Identifier" +msgstr "Ancien Identifiant Créancier" + #. module: account_banking_sepa_direct_debit #: selection:sdd.mandate,recurrent_sequence_type:0 msgid "Recurring" msgstr "Recurring" -#. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:181 -#, python-format -msgid "The date of signature of mandate '%s' is in the future!" -msgstr "La date de signature du mandat '%s' est dans le futur !" - #. module: account_banking_sepa_direct_debit #: help:res.company,sepa_creditor_identifier:0 msgid "Enter the Creditor Identifier that has been attributed to your company to make SEPA Direct Debits. This identifier is composed of :\n" @@ -324,6 +308,12 @@ msgstr "Seuls des mandats valides peuvent être utilisés dans une ligne de paie msgid "This field is only used for Recurrent mandates, not for One-Off mandates." msgstr "Ce champ n'est utilisé que pour les mandats récurrents, pas pour les mandats One-Off." +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:213 +#, python-format +msgid "The date of signature of mandate '%s' is in the future !" +msgstr "La date de signature du mandat '%s' est dans le futur !" + #. module: account_banking_sepa_direct_debit #: view:sdd.mandate:0 msgid "Signature Date" @@ -340,12 +330,6 @@ msgstr "Répartition des frais" msgid "Partner" msgstr "Partenaire" -#. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:125 -#, python-format -msgid "Field type error:" -msgstr "Erreur de type de champ :" - #. module: account_banking_sepa_direct_debit #: selection:sdd.mandate,recurrent_sequence_type:0 msgid "First" @@ -363,18 +347,32 @@ msgstr "Mandat annulé" #. module: account_banking_sepa_direct_debit #: model:ir.actions.act_window,name:account_banking_sepa_direct_debit.act_banking_export_sdd_payment_order -#: model:ir.actions.act_window,name:account_banking_sepa_direct_debit.action_account_banking_sdd -#: model:ir.ui.menu,name:account_banking_sepa_direct_debit.menu_account_banking_sdd msgid "Generated SEPA Direct Debit Files" msgstr "Fichiers de prélèvement SEPA générés" +#. module: account_banking_sepa_direct_debit +#: help:sdd.mandate,sepa_migrated:0 +msgid "If this field is not active, the mandate section of the next direct debit file that include this mandate will contain the 'Original Mandate Identification' and the 'Original Creditor Scheme Identification'. This is required in a few countries (Belgium for instance), but not in all countries. If this is not required in your country, you should keep this field always active." +msgstr "Si cette option n'est pas activée, la section qui concerne le mandat dans le prochain fichier de prélèvement qui incluera ce mandat contiendra les champs 'Original Mandate Identification' et 'Original Creditor Scheme Identification'. Ces champs sont requis dans certains pays (en Belgique notamment), mais pas dans tous les pays. Si ces champs ne sont pas requis dans votre pays, vous devriez garder ce champ toujours actif." + #. module: account_banking_sepa_direct_debit #: field:sdd.mandate,company_id:0 msgid "Company" msgstr "Société" #. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:191 +#: model:ir.model,name:account_banking_sepa_direct_debit.model_banking_export_sdd_wizard +msgid "Export SEPA Direct Debit File" +msgstr "Export du fichier de prélèvement SEPA" + +#. module: account_banking_sepa_direct_debit +#: help:banking.export.sdd,batch_booking:0 +#: help:banking.export.sdd.wizard,batch_booking:0 +msgid "If true, the bank statement will display only one credit line for all the direct debits of the SEPA file ; if false, the bank statement will display one credit line per direct debit of the SEPA file." +msgstr "Si activé, le relevé de compte ne fera apparaître qu'une ligne de crédit pour tous les prélèvements du fichier SEPA ; si désactivé, le relevé de banque fera apparaître une ligne de crédit pour chaque prélèvement du fichier SEPA." + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:225 #, python-format msgid "Cannot validate the mandate '%s' because it is not attached to a bank account." msgstr "Impossible de valider le mandat '%s' car il n'est pas rattaché à un compte bancaire." @@ -387,17 +385,11 @@ msgid "Draft" msgstr "Brouillon" #. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:232 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:290 #, python-format msgid "Mandate update" msgstr "Mise-à-jour du mandat" -#. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:116 -#, python-format -msgid "Cannot compute the '%s' of the Payment Line with Invoice Reference '%s'." -msgstr "Impossible de générer le '%s' de la ligne de paiement ayant la référence de facture '%s'." - #. module: account_banking_sepa_direct_debit #: selection:banking.export.sdd,charge_bearer:0 #: selection:banking.export.sdd.wizard,charge_bearer:0 @@ -410,6 +402,11 @@ msgstr "Partagée" msgid "Batch Booking" msgstr "Crédit groupé" +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,sepa_migrated:0 +msgid "Migrated to SEPA" +msgstr "Migré à SEPA" + #. module: account_banking_sepa_direct_debit #: field:sdd.mandate,state:0 msgid "Status" @@ -422,10 +419,10 @@ msgid "Total Amount" msgstr "Montant total" #. module: account_banking_sepa_direct_debit -#: help:banking.export.sdd,batch_booking:0 -#: help:banking.export.sdd.wizard,batch_booking:0 -msgid "If true, the bank statement will display only one credit line for all the direct debits of the SEPA file ; if false, the bank statement will display one credit line per direct debit of the SEPA file." -msgstr "Si activé, le relevé de compte ne fera apparaître qu'une ligne de crédit pour tous les prélèvements du fichier SEPA ; si désactivé, le relevé de banque fera apparaître une ligne de crédit pour chaque prélèvement du fichier SEPA." +#: model:ir.actions.act_window,name:account_banking_sepa_direct_debit.action_account_banking_sdd +#: model:ir.ui.menu,name:account_banking_sepa_direct_debit.menu_account_banking_sdd +msgid "SEPA Direct Debit Files" +msgstr "Fichiers de prélèvement SEPA" #. module: account_banking_sepa_direct_debit #: selection:banking.export.sdd,charge_bearer:0 @@ -434,7 +431,7 @@ msgid "Following Service Level" msgstr "Suivant le niveau de service" #. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:198 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:233 #, python-format msgid "The mandate '%s' can't have a date of last debit before the date of signature." msgstr "Le mandat '%s' ne peut pas avoir une date de dernier débit antérieure à la date de signature." @@ -450,11 +447,21 @@ msgstr "Type de Séquence mis à Final" msgid "Is a Follower" msgstr "Is a Follower" +#. module: account_banking_sepa_direct_debit +#: help:sdd.mandate,original_mandate_identification:0 +msgid "When the field 'Migrated to SEPA' is not active, this field will be used as the Original Mandate Identification in the Direct Debit file." +msgstr "Quand le champ 'Migré à SEPA' n'est pas activé, ce champ sera le 'Original Mandate Identification' dans le fichier de prélèvement." + #. module: account_banking_sepa_direct_debit #: view:payment.order:0 msgid "SDD Mandate" msgstr "Mandat de prélèvement" +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,original_mandate_identification:0 +msgid "Original Mandate Identification" +msgstr "Ancien Identifiant du Mandat" + #. module: account_banking_sepa_direct_debit #: model:ir.model,name:account_banking_sepa_direct_debit.model_res_company msgid "Companies" @@ -465,6 +472,11 @@ msgstr "Sociétés" msgid "Summary" msgstr "Résumé" +#. module: account_banking_sepa_direct_debit +#: model:res.groups,name:account_banking_sepa_direct_debit.group_original_mandate_required +msgid "Original Mandate Required (SEPA)" +msgstr "Ancien mandat requis (SEPA)" + #. module: account_banking_sepa_direct_debit #: field:account.invoice,sdd_mandate_id:0 #: model:ir.model,name:account_banking_sepa_direct_debit.model_sdd_mandate @@ -474,13 +486,13 @@ msgid "SEPA Direct Debit Mandate" msgstr "Mandat de prélèvement SEPA" #. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:270 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:193 #, python-format msgid "Missing SEPA Direct Debit mandate on the payment line with partner '%s' and Invoice ref '%s'." msgstr "Mandat de prélèvement SEPA manquant sur la ligne de paiement ayant pour partenaire '%s' et pour référence de facture '%s'." #. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:288 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:210 #, python-format msgid "The mandate with reference '%s' for partner '%s' has type set to 'One-Off' and it has a last debit date set to '%s', so we can't use it." msgstr "Le mandat portant la référence '%s' pour le partenaire '%s' est de type 'One-Off' et il a une date de dernier débit au '%s', donc il n'est pas utilisable." @@ -510,6 +522,21 @@ msgstr "Identifiant créancier SEPA invalide." msgid "Bank Accounts" msgstr "Comptes bancaires" +#. module: account_banking_sepa_direct_debit +#: model:ir.actions.act_window,help:account_banking_sepa_direct_debit.sdd_mandate_action +msgid "

\n" +" Click to create a new SEPA Direct Debit Mandate.\n" +"

\n" +" A SEPA Direct Debit Mandate is a document signed by your customer that gives you the autorization to do one or several direct debits on his bank account.\n" +"

\n" +" " +msgstr "

\n" +" Cliquez pour créer un mandat de prélèvement SEPA.\n" +"

\n" +" Un mandat de prélèvement SEPA est un document signé par votre client qui vous donne l'autorisation de réaliser un ou plusieurs prélèvements sur son compte bancaire.\n" +"

\n" +" " + #. module: account_banking_sepa_direct_debit #: view:banking.export.sdd:0 msgid "General Information" @@ -538,12 +565,6 @@ msgstr "Annuler" msgid "Related Payment Lines" msgstr "Lignes de paiement associées" -#. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:169 -#, python-format -msgid "The generated XML file is not valid against the official XML Schema Definition. The generated XML file and the full error have been written in the server logs. Here is the error, which may give you an idea on the cause of the problem : %s" -msgstr "Le fichier XML généré n'est pas valide par rapport à la Définition du Schéma XML officiel. Le fichier XML généré et le message d'erreur complet ont été écrits dans les logs du serveur. Voici l'erreur, qui vous donnera peut-être une idée sur la cause du problème : %s" - #. module: account_banking_sepa_direct_debit #: view:sdd.mandate:0 #: selection:sdd.mandate,type:0 @@ -563,25 +584,13 @@ msgstr "Mandat validé" #. module: account_banking_sepa_direct_debit #: field:banking.export.sdd,file:0 msgid "SEPA File" -msgstr "SEPA File" +msgstr "Fichier SEPA" #. module: account_banking_sepa_direct_debit #: field:res.company,sepa_creditor_identifier:0 msgid "SEPA Creditor Identifier" msgstr "Identifiant créancier SEPA" -#. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:122 -#, python-format -msgid "Cannot compute the '%s'." -msgstr "Impossible de calculer le '%s'." - -#. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:126 -#, python-format -msgid "The type of the field '%s' is %s. It should be a string or unicode." -msgstr "Le champ '%s' est de type %s. Il devrait être de type string ou unicode." - #. module: account_banking_sepa_direct_debit #: model:ir.model,name:account_banking_sepa_direct_debit.model_banking_export_sdd msgid "SEPA Direct Debit export" @@ -598,6 +607,12 @@ msgstr "Expiré" msgid "Bank Account" msgstr "Compte bancaire" +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:254 +#, python-format +msgid "You must set the 'Original Mandate Identification' on the recurrent mandate '%s' which is not marked as 'Migrated to SEPA'." +msgstr "Vous devez renseigner le champ 'Ancien identifiant du mandat' sur le mandat récurrent '%s' qui n'est pas marqué comme étant 'Migré à SEPA'." + #. module: account_banking_sepa_direct_debit #: model:mail.message.subtype,description:account_banking_sepa_direct_debit.recurrent_sequence_type_first #: model:mail.message.subtype,name:account_banking_sepa_direct_debit.recurrent_sequence_type_first @@ -605,22 +620,7 @@ msgid "Sequence Type set to First" msgstr "Type de Séquence mis à First" #. module: account_banking_sepa_direct_debit -#: model:ir.actions.act_window,help:account_banking_sepa_direct_debit.sdd_mandate_action -msgid "

\n" -" Click to create a new SEPA Direct Debit Mandate.\n" -"

\n" -" A SEPA Direct Debit Mandate is a document signed by your customer that gives you the autorization to do one or several direct debits on his bank account.\n" -"

\n" -" " -msgstr "

\n" -" Cliquez pour créer un mandat de prélèvement SEPA.\n" -"

\n" -" Un mandat de prélèvement SEPA est un document signé par votre client qui vous donne l'autorisation de réaliser un ou plusieurs prélèvements sur son compte bancaire.\n" -"

\n" -" " - -#. module: account_banking_sepa_direct_debit -#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:233 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:291 #, python-format msgid "As you changed the bank account attached to this mandate, the 'Sequence Type' has been set back to 'First'." msgstr "Etant donné que vous avez changé le compte bancaire associé à ce mandat, le 'Type de séquence' a été remis à 'First'." @@ -635,16 +635,6 @@ msgstr "Messages and communication history" msgid "Search SEPA Direct Debit Mandates" msgstr "Recherche dans les mandats de prélèvement SEPA" -#. module: account_banking_sepa_direct_debit -#: help:banking.export.sdd.wizard,requested_collec_date:0 -msgid "This is the date on which you would like the collection to be made by the bank. Please keep in mind that there are minimum delays for SEPA direct debits that depend on the type of mandate and the type of sequence." -msgstr "Entrez la date à laquelle vous voudriez que le prélèvement soit effectué par la banque. Gardez en mémoire qu'il y a un délai minimum pour les prélèvements SEPA qui dépend du type de mandat et du type de séquence." - -#. module: account_banking_sepa_direct_debit -#: field:sdd.mandate,unique_mandate_reference:0 -msgid "Unique Mandate Reference" -msgstr "Référence unique de mandat" - #. module: account_banking_sepa_direct_debit #: field:banking.export.sdd.wizard,file:0 msgid "File" diff --git a/account_banking_sepa_direct_debit/wizard/export_sdd.py b/account_banking_sepa_direct_debit/wizard/export_sdd.py index 5e4134f73..9657d0484 100644 --- a/account_banking_sepa_direct_debit/wizard/export_sdd.py +++ b/account_banking_sepa_direct_debit/wizard/export_sdd.py @@ -23,12 +23,9 @@ from openerp.osv import orm, fields from openerp.tools.translate import _ -from openerp import tools, netsvc +from openerp import netsvc from datetime import datetime from lxml import etree -import logging - -_logger = logging.getLogger(__name__) class banking_export_sdd_wizard(orm.TransientModel): @@ -42,14 +39,24 @@ class banking_export_sdd_wizard(orm.TransientModel): ], 'State', readonly=True), 'batch_booking': fields.boolean( 'Batch Booking', - help="If true, the bank statement will display only one credit line for all the direct debits of the SEPA file ; if false, the bank statement will display one credit line per direct debit of the SEPA file."), + help="If true, the bank statement will display only one credit " + "line for all the direct debits of the SEPA file ; if false, " + "the bank statement will display one credit line per direct " + "debit of the SEPA file."), 'charge_bearer': fields.selection([ ('SLEV', 'Following Service Level'), ('SHAR', 'Shared'), ('CRED', 'Borne by Creditor'), ('DEBT', 'Borne by Debtor'), ], 'Charge Bearer', required=True, - help='Following service level : transaction charges are to be applied following the rules agreed in the service level and/or scheme (SEPA Core messages must use this). Shared : transaction charges on the creditor side are to be borne by the creditor, transaction charges on the debtor side are to be borne by the debtor. Borne by creditor : all transaction charges are to be borne by the creditor. Borne by debtor : all transaction charges are to be borne by the debtor.'), + help="Following service level : transaction charges are to be " + "applied following the rules agreed in the service level and/or " + "scheme (SEPA Core messages must use this). Shared : transaction " + "charges on the creditor side are to be borne by the creditor, " + "transaction charges on the debtor side are to be borne by the " + "debtor. Borne by creditor : all transaction charges are to be " + "borne by the creditor. Borne by debtor : all transaction " + "charges are to be borne by the debtor."), 'nb_transactions': fields.related( 'file_id', 'nb_transactions', type='integer', string='Number of Transactions', readonly=True), @@ -129,13 +136,22 @@ class banking_export_sdd_wizard(orm.TransientModel): name_maxsize = 140 root_xml_tag = 'CstmrDrctDbtInitn' else: - raise orm.except_orm(_('Error:'), _("Payment Type Code '%s' is not supported. The only Payment Type Code supported for SEPA Direct Debit are 'pain.008.001.02', 'pain.008.001.03' and 'pain.008.001.04'.") % pain_flavor) + raise orm.except_orm( + _('Error:'), + _("Payment Type Code '%s' is not supported. The only " + "Payment Type Code supported for SEPA Direct Debit " + "are 'pain.008.001.02', 'pain.008.001.03' and " + "'pain.008.001.04'.") % pain_flavor) gen_args = { 'bic_xml_tag': bic_xml_tag, 'name_maxsize': name_maxsize, 'convert_to_ascii': convert_to_ascii, 'pain_flavor': pain_flavor, + 'sepa_export': sepa_export, + 'file_obj': self.pool['banking.export.sdd'], + 'pain_xsd_file': + 'account_banking_sepa_direct_debit/data/%s.xsd' % pain_flavor, } pain_ns = { @@ -143,13 +159,13 @@ class banking_export_sdd_wizard(orm.TransientModel): None: 'urn:iso:std:iso:20022:tech:xsd:%s' % pain_flavor, } - root = etree.Element('Document', nsmap=pain_ns) - pain_root = etree.SubElement(root, root_xml_tag) + xml_root = etree.Element('Document', nsmap=pain_ns) + pain_root = etree.SubElement(xml_root, root_xml_tag) # A. Group header group_header_1_0, nb_of_transactions_1_6, control_sum_1_7 = \ - self.generate_group_header_block( - cr, uid, pain_root, sepa_export, gen_args, context=context) + self.generate_group_header_block( + cr, uid, pain_root, gen_args, context=context) transactions_count_1_6 = 0 total_amount = 0.0 @@ -174,13 +190,15 @@ class banking_export_sdd_wizard(orm.TransientModel): if not line.sdd_mandate_id: raise orm.except_orm( _('Error:'), - _("Missing SEPA Direct Debit mandate on the payment line with partner '%s' and Invoice ref '%s'.") + _("Missing SEPA Direct Debit mandate on the payment " + "line with partner '%s' and Invoice ref '%s'.") % (line.partner_id.name, line.ml_inv_ref.number)) if line.sdd_mandate_id.state != 'valid': raise orm.except_orm( _('Error:'), - _("The SEPA Direct Debit mandate with reference '%s' for partner '%s' has expired.") + _("The SEPA Direct Debit mandate with reference '%s' " + "for partner '%s' has expired.") % (line.sdd_mandate_id.unique_mandate_reference, line.sdd_mandate_id.partner_id.name)) if line.sdd_mandate_id.type == 'oneoff': @@ -189,7 +207,10 @@ class banking_export_sdd_wizard(orm.TransientModel): else: raise orm.except_orm( _('Error:'), - _("The mandate with reference '%s' for partner '%s' has type set to 'One-Off' and it has a last debit date set to '%s', so we can't use it.") + _("The mandate with reference '%s' for partner " + "'%s' has type set to 'One-Off' and it has a " + "last debit date set to '%s', so we can't use " + "it.") % (line.sdd_mandate_id.unique_mandate_reference, line.sdd_mandate_id.partner_id.name, line.sdd_mandate_id.last_debit_date)) @@ -199,7 +220,8 @@ class banking_export_sdd_wizard(orm.TransientModel): 'first': 'FRST', 'final': 'FNAL', } - seq_type_label = line.sdd_mandate_id.recurrent_sequence_type + seq_type_label = \ + line.sdd_mandate_id.recurrent_sequence_type assert seq_type_label is not False seq_type = seq_type_map[seq_type_label] @@ -214,22 +236,26 @@ class banking_export_sdd_wizard(orm.TransientModel): cr, uid, line.id, {'date': requested_date}, context=context) - for (requested_date, priority, sequence_type), lines in lines_per_group.items(): + for (requested_date, priority, sequence_type), lines in \ + lines_per_group.items(): # B. Payment info payment_info_2_0, nb_of_transactions_2_4, control_sum_2_5 = \ - self.generate_start_payment_info_block( - cr, uid, pain_root, sepa_export, - "sepa_export.payment_order_ids[0].reference + '-' + sequence_type + '-' + requested_date.replace('-', '') + '-' + priority", - priority, 'CORE', sequence_type, requested_date, { - 'sepa_export': sepa_export, - 'sequence_type': sequence_type, - 'priority': priority, - 'requested_date': requested_date, - }, gen_args, context=context) + self.generate_start_payment_info_block( + cr, uid, pain_root, + "sepa_export.payment_order_ids[0].reference + '-' + " + "sequence_type + '-' + requested_date.replace('-', '') " + "+ '-' + priority", + priority, 'CORE', sequence_type, requested_date, { + 'sepa_export': sepa_export, + 'sequence_type': sequence_type, + 'priority': priority, + 'requested_date': requested_date, + }, gen_args, context=context) self.generate_party_block( cr, uid, payment_info_2_0, 'Cdtr', 'B', - 'sepa_export.payment_order_ids[0].mode.bank_id.partner_id.name', + 'sepa_export.payment_order_ids[0].mode.bank_id.partner_id.' + 'name', 'sepa_export.payment_order_ids[0].mode.bank_id.acc_number', 'sepa_export.payment_order_ids[0].mode.bank_id.bank.bic', {'sepa_export': sepa_export}, @@ -242,7 +268,8 @@ class banking_export_sdd_wizard(orm.TransientModel): payment_info_2_0, 'CdtrSchmeId') self.generate_creditor_scheme_identification( cr, uid, creditor_scheme_identification_2_27, - 'sepa_export.payment_order_ids[0].company_id.sepa_creditor_identifier', + 'sepa_export.payment_order_ids[0].company_id.' + 'sepa_creditor_identifier', 'SEPA Creditor Identifier', {'sepa_export': sepa_export}, 'SEPA', gen_args, context=context) @@ -340,7 +367,8 @@ class banking_export_sdd_wizard(orm.TransientModel): ori_mandate_identification_2_52.text = \ self._prepare_field( cr, uid, 'Original Mandate Identification', - 'line.sdd_mandate_id.original_mandate_identification', + 'line.sdd_mandate_id.' + 'original_mandate_identification', {'line': line}, gen_args=gen_args, context=context) @@ -348,7 +376,8 @@ class banking_export_sdd_wizard(orm.TransientModel): amendment_info_details_2_51, 'OrgnlCdtrSchmeId') self.generate_creditor_scheme_identification( cr, uid, ori_creditor_scheme_id_2_53, - 'sepa_export.payment_order_ids[0].company_id.original_creditor_identifier', + 'sepa_export.payment_order_ids[0].company_id.' + 'original_creditor_identifier', 'Original Creditor Identifier', {'sepa_export': sepa_export}, 'SEPA', gen_args, context=context) @@ -369,38 +398,9 @@ class banking_export_sdd_wizard(orm.TransientModel): nb_of_transactions_1_6.text = str(transactions_count_1_6) control_sum_1_7.text = '%.2f' % amount_control_sum_1_7 - xml_string = etree.tostring( - root, pretty_print=True, encoding='UTF-8', xml_declaration=True) - _logger.debug( - "Generated SDD XML file in format %s below" % pain_flavor) - _logger.debug(xml_string) - pain_xsd_file = \ - 'account_banking_sepa_direct_debit/data/%s.xsd' % pain_flavor - self._validate_xml(cr, uid, xml_string, pain_xsd_file) - - # CREATE the banking.export.sepa record - file_id = self.pool.get('banking.export.sdd').create( - cr, uid, self._prepare_export_sepa( - cr, uid, sepa_export, total_amount, transactions_count_1_6, - xml_string, gen_args, context=context), - context=context) - - self.write( - cr, uid, ids, { - 'file_id': file_id, - 'state': 'finish', - }, context=context) - - action = { - 'name': 'SEPA Direct Debit File', - 'type': 'ir.actions.act_window', - 'view_type': 'form', - 'view_mode': 'form,tree', - 'res_model': self._name, - 'res_id': ids[0], - 'target': 'new', - } - return action + return self.finalize_sepa_file_creation( + cr, uid, ids, xml_root, total_amount, transactions_count_1_6, + gen_args, context=context) def cancel_sepa(self, cr, uid, ids, context=None): ''' From 74e937b6e61c30b5081fc8be6ed67dfdb5f40e39 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Tue, 24 Dec 2013 14:06:44 +0100 Subject: [PATCH 31/43] Remove 'For debit type modes only' in the help message of the field transfer_account_id, because it is now used for both debits and payments. --- account_banking_payment/model/payment_mode.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/account_banking_payment/model/payment_mode.py b/account_banking_payment/model/payment_mode.py index 0ce7d2837..31e1cb65b 100644 --- a/account_banking_payment/model/payment_mode.py +++ b/account_banking_payment/model/payment_mode.py @@ -34,10 +34,9 @@ class payment_mode(orm.Model): 'account.account', 'Transfer account', domain=[('type', '=', 'other'), ('reconcile', '=', True)], - help=('Pay off lines in sent orders with a ' - 'move on this account. For debit type modes only. ' - 'You can only select accounts of type regular that ' - 'are marked for reconciliation'), + help=('Pay off lines in sent orders with a move on this ' + 'account. You can only select accounts of type regular ' + 'that are marked for reconciliation'), ), 'transfer_journal_id': fields.many2one( 'account.journal', 'Transfer journal', From 08566e18711bc9de84e234865a4dada174fa9271 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Tue, 24 Dec 2013 15:30:37 +0100 Subject: [PATCH 32/43] Update module description. --- account_banking_pain_base/__openerp__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/account_banking_pain_base/__openerp__.py b/account_banking_pain_base/__openerp__.py index 5d461865e..9803980d5 100644 --- a/account_banking_pain_base/__openerp__.py +++ b/account_banking_pain_base/__openerp__.py @@ -43,7 +43,7 @@ This module contains fields and functions that are used by the module for SEPA C This module is part of the banking addons: https://launchpad.net/banking-addons -This module was developped during the Akretion-Noviat code sprint of November 21st 2013 in Epiais les Louvres (France). +This module was started during the Akretion-Noviat code sprint of November 21st 2013 in Epiais les Louvres (France). ''', 'active': False, 'installable': True, From 523469fe2628af2cf2416d3b5c8728a3801bad41 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Sat, 4 Jan 2014 14:14:54 +0100 Subject: [PATCH 33/43] Put the field communication2 back in the view of payment lines. Rename a badly named variable (thanks to Stefan Rijnhart for spotting this) --- account_banking_pain_base/banking_export_pain.py | 4 ++-- account_banking_pain_base/payment_line_view.xml | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/account_banking_pain_base/banking_export_pain.py b/account_banking_pain_base/banking_export_pain.py index 30a1d5474..1db13aa83 100644 --- a/account_banking_pain_base/banking_export_pain.py +++ b/account_banking_pain_base/banking_export_pain.py @@ -355,10 +355,10 @@ class banking_export_pain(orm.AbstractModel): _("Missing 'Structured Communication Type' on payment " "line with reference '%s'.") % (line.name)) - remittance_info_unstructured_2_100 = etree.SubElement( + remittance_info_structured_2_100 = etree.SubElement( remittance_info_2_91, 'Strd') creditor_ref_information_2_120 = etree.SubElement( - remittance_info_unstructured_2_100, 'CdtrRefInf') + remittance_info_structured_2_100, 'CdtrRefInf') if gen_args.get('pain_flavor') == 'pain.001.001.02': creditor_ref_info_type_2_121 = etree.SubElement( creditor_ref_information_2_120, 'CdtrRefTp') diff --git a/account_banking_pain_base/payment_line_view.xml b/account_banking_pain_base/payment_line_view.xml index 40087836c..f92b1bbf5 100644 --- a/account_banking_pain_base/payment_line_view.xml +++ b/account_banking_pain_base/payment_line_view.xml @@ -16,7 +16,6 @@ - @@ -32,7 +31,6 @@ - From 6ca609e664afb2ff68532cedbac1cc6583639e71 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Sun, 5 Jan 2014 00:24:47 +0100 Subject: [PATCH 34/43] If it's a national payment, we now support "BIC not provided". --- .../banking_export_pain.py | 70 ++++++++++++------- 1 file changed, 46 insertions(+), 24 deletions(-) diff --git a/account_banking_pain_base/banking_export_pain.py b/account_banking_pain_base/banking_export_pain.py index 1db13aa83..64cd3ed6e 100644 --- a/account_banking_pain_base/banking_export_pain.py +++ b/account_banking_pain_base/banking_export_pain.py @@ -280,19 +280,36 @@ class banking_export_pain(orm.AbstractModel): iniparty_org_other_issuer.text = initiating_party_issuer return True - def generate_party_bic( - self, cr, uid, parent_node, party_type, party_type_label, bic, - eval_ctx, gen_args, context=None): + def generate_party_agent( + self, cr, uid, parent_node, party_type, party_type_label, + order, party_name, iban, bic, eval_ctx, gen_args, context=None): '''Generate the piece of the XML file corresponding to BIC This code is mutualized between TRF and DD''' + assert order in ('B', 'C'), "Order can be 'B' or 'C'" party_agent = etree.SubElement(parent_node, '%sAgt' % party_type) party_agent_institution = etree.SubElement( party_agent, 'FinInstnId') - party_agent_bic = etree.SubElement( - party_agent_institution, gen_args.get('bic_xml_tag')) - party_agent_bic.text = self._prepare_field( - cr, uid, '%s BIC' % party_type_label, bic, eval_ctx, - gen_args=gen_args, context=context) + try: + bic = self._prepare_field( + cr, uid, '%s BIC' % party_type_label, bic, eval_ctx, + gen_args=gen_args, context=context) + party_agent_bic = etree.SubElement( + party_agent_institution, gen_args.get('bic_xml_tag')) + party_agent_bic.text = bic + except: + if order == 'C': + if iban[0:2] != gen_args['initiating_party_country_code']: + raise orm.except_orm( + _('Error:'), + _("The bank account with IBAN '%s' of partner '%s' " + "must have an associated BIC because it is a " + "cross-border SEPA operation.") + % (iban, party_name)) + party_agent_other = etree.SubElement( + party_agent_institution, 'Othr') + party_agent_other_identification = etree.SubElement( + party_agent_other, 'Id') + party_agent_other_identification.text = 'NOTPROVIDED' return True def generate_party_block( @@ -305,32 +322,37 @@ class banking_export_pain(orm.AbstractModel): party_type_label = 'Creditor' elif party_type == 'Dbtr': party_type_label = 'Debtor' - # At C level, the order is : BIC, Name, IBAN - # At B level, the order is : Name, IBAN, BIC - if order == 'C': - self.generate_party_bic( - cr, uid, parent_node, party_type, party_type_label, bic, - eval_ctx, gen_args, context=context) - party = etree.SubElement(parent_node, party_type) - party_name = etree.SubElement(party, 'Nm') - party_name.text = self._prepare_field( + party_name = self._prepare_field( cr, uid, '%s Name' % party_type_label, name, eval_ctx, gen_args.get('name_maxsize'), gen_args=gen_args, context=context) - party_account = etree.SubElement( - parent_node, '%sAcct' % party_type) - party_account_id = etree.SubElement(party_account, 'Id') - party_account_iban = etree.SubElement( - party_account_id, 'IBAN') piban = self._prepare_field( cr, uid, '%s IBAN' % party_type_label, iban, eval_ctx, gen_args=gen_args, context=context) viban = self._validate_iban(cr, uid, piban, context=context) + # At C level, the order is : BIC, Name, IBAN + # At B level, the order is : Name, IBAN, BIC + if order == 'B': + gen_args['initiating_party_country_code'] = viban[0:2] + elif order == 'C': + self.generate_party_agent( + cr, uid, parent_node, party_type, party_type_label, + order, party_name, viban, bic, + eval_ctx, gen_args, context=context) + party = etree.SubElement(parent_node, party_type) + party_nm = etree.SubElement(party, 'Nm') + party_nm.text = party_name + party_account = etree.SubElement( + parent_node, '%sAcct' % party_type) + party_account_id = etree.SubElement(party_account, 'Id') + party_account_iban = etree.SubElement( + party_account_id, 'IBAN') party_account_iban.text = viban if order == 'B': - self.generate_party_bic( - cr, uid, parent_node, party_type, party_type_label, bic, + self.generate_party_agent( + cr, uid, parent_node, party_type, party_type_label, + order, party_name, viban, bic, eval_ctx, gen_args, context=context) return True From 0f7bf84f7c770423fe9f310e9656e9b982305a9f Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Mon, 6 Jan 2014 00:51:22 +0100 Subject: [PATCH 35/43] For SCT, if BIC is not provided, we should not put the 'Creditor Agent' block at all, according to EPC guidelines (on this point, it is different from the Direct Debit !) --- .../banking_export_pain.py | 36 +++++++++++-------- .../wizard/export_sepa.py | 1 + .../wizard/export_sdd.py | 1 + 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/account_banking_pain_base/banking_export_pain.py b/account_banking_pain_base/banking_export_pain.py index 64cd3ed6e..8e2ac7d8f 100644 --- a/account_banking_pain_base/banking_export_pain.py +++ b/account_banking_pain_base/banking_export_pain.py @@ -209,12 +209,7 @@ class banking_export_pain(orm.AbstractModel): payment_info_ident, eval_ctx, 35, gen_args=gen_args, context=context) payment_method_2_2 = etree.SubElement(payment_info_2_0, 'PmtMtd') - if gen_args.get('pain_flavor').startswith('pain.008.'): - payment_method_2_2.text = 'DD' - request_date_tag = 'ReqdColltnDt' - else: - payment_method_2_2.text = 'TRF' - request_date_tag = 'ReqdExctnDt' + payment_method_2_2.text = gen_args['payment_method'] if gen_args.get('pain_flavor') != 'pain.001.001.02': batch_booking_2_3 = etree.SubElement(payment_info_2_0, 'BtchBookg') batch_booking_2_3.text = \ @@ -247,6 +242,10 @@ class banking_export_pain(orm.AbstractModel): payment_type_info_2_6, 'SeqTp') sequence_type_2_14.text = sequence_type + if gen_args['payment_method'] == 'DD': + request_date_tag = 'ReqdColltnDt' + else: + request_date_tag = 'ReqdExctnDt' requested_date_2_17 = etree.SubElement( payment_info_2_0, request_date_tag) requested_date_2_17.text = requested_date @@ -286,13 +285,13 @@ class banking_export_pain(orm.AbstractModel): '''Generate the piece of the XML file corresponding to BIC This code is mutualized between TRF and DD''' assert order in ('B', 'C'), "Order can be 'B' or 'C'" - party_agent = etree.SubElement(parent_node, '%sAgt' % party_type) - party_agent_institution = etree.SubElement( - party_agent, 'FinInstnId') try: bic = self._prepare_field( cr, uid, '%s BIC' % party_type_label, bic, eval_ctx, gen_args=gen_args, context=context) + party_agent = etree.SubElement(parent_node, '%sAgt' % party_type) + party_agent_institution = etree.SubElement( + party_agent, 'FinInstnId') party_agent_bic = etree.SubElement( party_agent_institution, gen_args.get('bic_xml_tag')) party_agent_bic.text = bic @@ -305,11 +304,20 @@ class banking_export_pain(orm.AbstractModel): "must have an associated BIC because it is a " "cross-border SEPA operation.") % (iban, party_name)) - party_agent_other = etree.SubElement( - party_agent_institution, 'Othr') - party_agent_other_identification = etree.SubElement( - party_agent_other, 'Id') - party_agent_other_identification.text = 'NOTPROVIDED' + if order == 'B' or ( + order == 'C' and gen_args['payment_method'] == 'DD'): + party_agent = etree.SubElement( + parent_node, '%sAgt' % party_type) + party_agent_institution = etree.SubElement( + party_agent, 'FinInstnId') + party_agent_other = etree.SubElement( + party_agent_institution, 'Othr') + party_agent_other_identification = etree.SubElement( + party_agent_other, 'Id') + party_agent_other_identification.text = 'NOTPROVIDED' + # for Credit Transfers, in the 'C' block, if BIC is not provided, + # we should not put the 'Creditor Agent' block at all, + # as per the guidelines of the EPC return True def generate_party_block( diff --git a/account_banking_sepa_credit_transfer/wizard/export_sepa.py b/account_banking_sepa_credit_transfer/wizard/export_sepa.py index 3b7aa0460..eb2461ad8 100644 --- a/account_banking_sepa_credit_transfer/wizard/export_sepa.py +++ b/account_banking_sepa_credit_transfer/wizard/export_sepa.py @@ -136,6 +136,7 @@ class banking_export_sepa_wizard(orm.TransientModel): 'bic_xml_tag': bic_xml_tag, 'name_maxsize': name_maxsize, 'convert_to_ascii': convert_to_ascii, + 'payment_method': 'TRF', 'pain_flavor': pain_flavor, 'sepa_export': sepa_export, 'file_obj': self.pool['banking.export.sepa'], diff --git a/account_banking_sepa_direct_debit/wizard/export_sdd.py b/account_banking_sepa_direct_debit/wizard/export_sdd.py index 9657d0484..19520d318 100644 --- a/account_banking_sepa_direct_debit/wizard/export_sdd.py +++ b/account_banking_sepa_direct_debit/wizard/export_sdd.py @@ -147,6 +147,7 @@ class banking_export_sdd_wizard(orm.TransientModel): 'bic_xml_tag': bic_xml_tag, 'name_maxsize': name_maxsize, 'convert_to_ascii': convert_to_ascii, + 'payment_method': 'DD', 'pain_flavor': pain_flavor, 'sepa_export': sepa_export, 'file_obj': self.pool['banking.export.sdd'], From 0eda2e7c09954922380397858ce41d0663dc1159 Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Sat, 11 Jan 2014 17:06:19 +0100 Subject: [PATCH 36/43] [FIX] Undefined variables msg, ref --- account_banking/banking_import_transaction.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/account_banking/banking_import_transaction.py b/account_banking/banking_import_transaction.py index f3224dd12..e2b6e2c87 100644 --- a/account_banking/banking_import_transaction.py +++ b/account_banking/banking_import_transaction.py @@ -255,9 +255,9 @@ class banking_import_transaction(orm.Model): # creation. This also enables us to search for the invoice number in the # reference instead of the other way around, as most human interventions # *add* text. + ref = trans.reference.upper() + msg = trans.message.upper() if len(candidates) > 1 or not candidates: - ref = trans.reference.upper() - msg = trans.message.upper() # The manual usage of the sales journal creates moves that # are not tied to invoices. Thanks to Stefan Rijnhart for # reporting this. From d686ca22acb4d2053e95a304591b4fcb725f15e8 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Mon, 13 Jan 2014 13:41:25 +0100 Subject: [PATCH 37/43] Only catch the openerp exception in generate_party_agent(), as suggested by Stefan on the MP. --- account_banking_pain_base/banking_export_pain.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/account_banking_pain_base/banking_export_pain.py b/account_banking_pain_base/banking_export_pain.py index 8e2ac7d8f..5a063c5ee 100644 --- a/account_banking_pain_base/banking_export_pain.py +++ b/account_banking_pain_base/banking_export_pain.py @@ -295,7 +295,7 @@ class banking_export_pain(orm.AbstractModel): party_agent_bic = etree.SubElement( party_agent_institution, gen_args.get('bic_xml_tag')) party_agent_bic.text = bic - except: + except except_orm: if order == 'C': if iban[0:2] != gen_args['initiating_party_country_code']: raise orm.except_orm( From 9583855a6557bd404a91335dd542ed77722c4995 Mon Sep 17 00:00:00 2001 From: Ruchir Shukla Date: Tue, 21 Jan 2014 13:25:55 +0530 Subject: [PATCH 38/43] link partner funtionality without remote owner --- account_banking/banking_import_transaction.py | 1 - account_banking/wizard/link_partner.py | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/account_banking/banking_import_transaction.py b/account_banking/banking_import_transaction.py index e2b6e2c87..a9b9ac132 100644 --- a/account_banking/banking_import_transaction.py +++ b/account_banking/banking_import_transaction.py @@ -1409,7 +1409,6 @@ class account_bank_statement_line(orm.Model): line.state == 'draft' and not line.partner_id and line.import_transaction_id - and line.import_transaction_id.remote_owner and line.import_transaction_id.remote_account) return res diff --git a/account_banking/wizard/link_partner.py b/account_banking/wizard/link_partner.py index 719843a77..3a74bd6c2 100644 --- a/account_banking/wizard/link_partner.py +++ b/account_banking/wizard/link_partner.py @@ -87,7 +87,7 @@ class link_partner(orm.TransientModel): _('Error'), _('Statement line is already linked to a bank account ')) - if not(transaction and transaction.remote_owner + if not(transaction and transaction.remote_account): raise orm.except_orm( _('Error'), @@ -117,6 +117,8 @@ class link_partner(orm.TransientModel): self.pool, cr, uid, transaction, context=context) if not vals.get('name'): vals['name'] = transaction.remote_owner + if not vals['name']: + vals['name'] = '/' if not vals.get('remote_account'): vals['remote_account'] = transaction.remote_account From 6e8bac9bc2aa9a7613423b87e7df75c8d3d4d626 Mon Sep 17 00:00:00 2001 From: Launchpad Translations on behalf of banking-addons-team Date: Mon, 27 Jan 2014 05:50:20 +0000 Subject: [PATCH 39/43] Launchpad automatic translations update. --- account_banking/i18n/hu.po | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/account_banking/i18n/hu.po b/account_banking/i18n/hu.po index 3c3db4cca..c0ff7bf72 100644 --- a/account_banking/i18n/hu.po +++ b/account_banking/i18n/hu.po @@ -8,14 +8,14 @@ msgstr "" "Project-Id-Version: banking-addons\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2013-10-25 15:52+0000\n" -"PO-Revision-Date: 2014-01-13 19:15+0000\n" +"PO-Revision-Date: 2014-01-26 14:44+0000\n" "Last-Translator: krnkris \n" "Language-Team: Hungarian \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-01-14 06:52+0000\n" -"X-Generator: Launchpad (build 16890)\n" +"X-Launchpad-Export-Date: 2014-01-27 05:50+0000\n" +"X-Generator: Launchpad (build 16914)\n" #. module: account_banking #: field:account.bank.statement.line,reconcile_id:0 @@ -547,7 +547,7 @@ msgstr "remote_owner" #. module: account_banking #: view:account.banking.account.settings:0 msgid "Default Accounts for Unknown Movements" -msgstr "Issmeretlen mozgások alapértelmezett számlája" +msgstr "Ismeretlen mozgások alapértelmezett számlája" #. module: account_banking #: view:account.banking.bank.import:0 From 61fe92445b3bb84e8a510f2a390e293cb0b3616f Mon Sep 17 00:00:00 2001 From: Launchpad Translations on behalf of banking-addons-team Date: Sat, 1 Feb 2014 06:56:49 +0000 Subject: [PATCH 40/43] Launchpad automatic translations update. --- account_banking_pain_base/i18n/fr.po | 60 ++++-- .../i18n/fr.po | 188 +++++++++++++++-- .../i18n/nl.po | 135 ++++-------- account_banking_sepa_direct_debit/i18n/fr.po | 199 ++++++++++++++---- 4 files changed, 412 insertions(+), 170 deletions(-) diff --git a/account_banking_pain_base/i18n/fr.po b/account_banking_pain_base/i18n/fr.po index 22a9c9232..5ca1a72c2 100644 --- a/account_banking_pain_base/i18n/fr.po +++ b/account_banking_pain_base/i18n/fr.po @@ -6,14 +6,15 @@ msgid "" msgstr "" "Project-Id-Version: OpenERP Server 7.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-12-23 21:27+0000\n" -"PO-Revision-Date: 2013-12-23 21:27+0000\n" -"Last-Translator: <>\n" +"POT-Creation-Date: 2013-12-23 21:26+0000\n" +"PO-Revision-Date: 2014-02-01 04:48+0000\n" +"Last-Translator: Alexis de Lattre \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: \n" -"Plural-Forms: \n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2014-02-01 06:56+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_banking_pain_base #: field:res.company,initiating_party_issuer:0 @@ -23,8 +24,16 @@ msgstr "Initiating Party Issuer" #. module: account_banking_pain_base #: code:addons/account_banking_pain_base/banking_export_pain.py:122 #, python-format -msgid "The generated XML file is not valid against the official XML Schema Definition. The generated XML file and the full error have been written in the server logs. Here is the error, which may give you an idea on the cause of the problem : %s" -msgstr "Le fichier XML généré n'est pas valide par rapport à la Définition du Schéma XML officiel. Le fichier XML généré et le message d'erreur complet ont été écrits dans les logs du serveur. Voici l'erreur, qui vous donnera peut-être une idée sur la cause du problème : %s" +msgid "" +"The generated XML file is not valid against the official XML Schema " +"Definition. The generated XML file and the full error have been written in " +"the server logs. Here is the error, which may give you an idea on the cause " +"of the problem : %s" +msgstr "" +"Le fichier XML généré n'est pas valide par rapport à la Définition du Schéma " +"XML officiel. Le fichier XML généré et le message d'erreur complet ont été " +"écrits dans les logs du serveur. Voici l'erreur, qui vous donnera peut-être " +"une idée sur la cause du problème : %s" #. module: account_banking_pain_base #: field:payment.line,priority:0 @@ -43,14 +52,21 @@ msgstr "Mode de paiement" #. module: account_banking_pain_base #: help:res.company,initiating_party_issuer:0 -msgid "This will be used as the 'Initiating Party Issuer' in the PAIN files generated by OpenERP." -msgstr "Ce champ sera le 'Initiating Party Issuer' dans les fichiers PAIN générés par OpenERP." +msgid "" +"This will be used as the 'Initiating Party Issuer' in the PAIN files " +"generated by OpenERP." +msgstr "" +"Ce champ sera le 'Initiating Party Issuer' dans les fichiers PAIN générés " +"par OpenERP." #. module: account_banking_pain_base #: code:addons/account_banking_pain_base/banking_export_pain.py:351 #, python-format -msgid "Missing 'Structured Communication Type' on payment line with reference '%s'." -msgstr "Le 'Type de communication structuré' n'est pas renseigné sur la ligne de paiement ayant la référence '%s'." +msgid "" +"Missing 'Structured Communication Type' on payment line with reference '%s'." +msgstr "" +"Le 'Type de communication structuré' n'est pas renseigné sur la ligne de " +"paiement ayant la référence '%s'." #. module: account_banking_pain_base #: selection:payment.line,priority:0 @@ -61,7 +77,9 @@ msgstr "Normal" #: code:addons/account_banking_pain_base/banking_export_pain.py:70 #, python-format msgid "Cannot compute the '%s' of the Payment Line with reference '%s'." -msgstr "Impossible de calculer le '%s' de la ligne de paiement ayant la référence '%s'." +msgstr "" +"Impossible de calculer le '%s' de la ligne de paiement ayant la référence " +"'%s'." #. module: account_banking_pain_base #: code:addons/account_banking_pain_base/banking_export_pain.py:77 @@ -73,7 +91,8 @@ msgstr "Impossible de calculer le '%s'." #: code:addons/account_banking_pain_base/banking_export_pain.py:81 #, python-format msgid "The type of the field '%s' is %s. It should be a string or unicode." -msgstr "Le type du champ '%s' est %s. Il devrait être de type string ou unicode." +msgstr "" +"Le type du champ '%s' est %s. Il devrait être de type string ou unicode." #. module: account_banking_pain_base #: code:addons/account_banking_pain_base/banking_export_pain.py:47 @@ -121,12 +140,20 @@ msgstr "banking.export.pain" #. module: account_banking_pain_base #: help:payment.mode,convert_to_ascii:0 -msgid "If active, OpenERP will convert each accented caracter to the corresponding unaccented caracter, so that only ASCII caracters are used in the generated PAIN file." -msgstr "Si actif, OpenERP convertira chaque caractère accentué en son équivalent non accentué, de telle façon que seuls des caractères ASCII soient utilisés dans le fichier PAIN généré." +msgid "" +"If active, OpenERP will convert each accented caracter to the corresponding " +"unaccented caracter, so that only ASCII caracters are used in the generated " +"PAIN file." +msgstr "" +"Si actif, OpenERP convertira chaque caractère accentué en son équivalent non " +"accentué, de telle façon que seuls des caractères ASCII soient utilisés dans " +"le fichier PAIN généré." #. module: account_banking_pain_base #: help:payment.line,priority:0 -msgid "This field will be used as the 'Instruction Priority' in the generated PAIN file." +msgid "" +"This field will be used as the 'Instruction Priority' in the generated PAIN " +"file." msgstr "Ce champ sera le 'Instruction Priority' dans le fichier PAIN généré." #. module: account_banking_pain_base @@ -143,4 +170,3 @@ msgstr "Élevé" #: field:payment.mode,convert_to_ascii:0 msgid "Convert to ASCII" msgstr "Convertir en ASCII" - diff --git a/account_banking_sepa_credit_transfer/i18n/fr.po b/account_banking_sepa_credit_transfer/i18n/fr.po index 098e87ea3..72cd4b560 100644 --- a/account_banking_sepa_credit_transfer/i18n/fr.po +++ b/account_banking_sepa_credit_transfer/i18n/fr.po @@ -6,14 +6,15 @@ msgid "" msgstr "" "Project-Id-Version: OpenERP Server 7.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-12-23 22:52+0000\n" -"PO-Revision-Date: 2013-12-23 22:52+0000\n" -"Last-Translator: <>\n" +"POT-Creation-Date: 2013-12-23 22:49+0000\n" +"PO-Revision-Date: 2014-02-01 04:49+0000\n" +"Last-Translator: Alexis de Lattre \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: \n" -"Plural-Forms: \n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2014-02-01 06:56+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_banking_sepa_credit_transfer #: selection:banking.export.sepa.wizard,state:0 @@ -45,8 +46,22 @@ msgstr "Brouillon" #. module: account_banking_sepa_credit_transfer #: help:banking.export.sepa.wizard,charge_bearer:0 -msgid "Following service level : transaction charges are to be applied following the rules agreed in the service level and/or scheme (SEPA Core messages must use this). Shared : transaction charges on the debtor side are to be borne by the debtor, transaction charges on the creditor side are to be borne by the creditor. Borne by creditor : all transaction charges are to be borne by the creditor. Borne by debtor : all transaction charges are to be borne by the debtor." -msgstr "Suivant le niveau de service : la répartition des frais bancaires suit les règles pré-établies dans le schema ou dans le contrat avec la banque (les messages SEPA Core doivent utiliser ce paramètre). Partagés : les frais bancaires côté débiteur sont à la charge du débiteur, les frais bancaires côté créancier sont à la charge du créancier. Supportés par le créancier : tous les frais bancaires sont à la charge du créancier. Supportés par le débiteur : tous les frais bancaires sont à la charge du débiteur." +msgid "" +"Following service level : transaction charges are to be applied following " +"the rules agreed in the service level and/or scheme (SEPA Core messages must " +"use this). Shared : transaction charges on the debtor side are to be borne " +"by the debtor, transaction charges on the creditor side are to be borne by " +"the creditor. Borne by creditor : all transaction charges are to be borne by " +"the creditor. Borne by debtor : all transaction charges are to be borne by " +"the debtor." +msgstr "" +"Suivant le niveau de service : la répartition des frais bancaires suit les " +"règles pré-établies dans le schema ou dans le contrat avec la banque (les " +"messages SEPA Core doivent utiliser ce paramètre). Partagés : les frais " +"bancaires côté débiteur sont à la charge du débiteur, les frais bancaires " +"côté créancier sont à la charge du créancier. Supportés par le créancier : " +"tous les frais bancaires sont à la charge du créancier. Supportés par le " +"débiteur : tous les frais bancaires sont à la charge du débiteur." #. module: account_banking_sepa_credit_transfer #: selection:banking.export.sepa,charge_bearer:0 @@ -145,8 +160,11 @@ msgstr "Export SEPA" #. module: account_banking_sepa_credit_transfer #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:246 #, python-format -msgid "Missing Bank Account on invoice '%s' (payment order line reference '%s')." -msgstr "Compte bancaire manquant sur la facture '%s' (référence de la ligne de paiement : '%s')." +msgid "" +"Missing Bank Account on invoice '%s' (payment order line reference '%s')." +msgstr "" +"Compte bancaire manquant sur la facture '%s' (référence de la ligne de " +"paiement : '%s')." #. module: account_banking_sepa_credit_transfer #: field:banking.export.sepa,file:0 @@ -156,14 +174,34 @@ msgstr "Fichier SEPA XML" #. module: account_banking_sepa_credit_transfer #: help:banking.export.sepa,charge_bearer:0 -msgid "Following service level : transaction charges are to be applied following the rules agreed in the service level and/or scheme (SEPA Core messages must use this). Shared : transaction charges on the creditor side are to be borne by the creditor, transaction charges on the debtor side are to be borne by the debtor. Borne by creditor : all transaction charges are to be borne by the creditor. Borne by debtor : all transaction charges are to be borne by the debtor." -msgstr "Suivant le niveau de service : la répartition des frais bancaires suit les règles pré-établies dans le schema ou dans le contrat avec la banque (les messages SEPA Core doivent utiliser ce paramètre). Partagés : les frais bancaires côté débiteur sont à la charge du débiteur, les frais bancaires côté créancier sont à la charge du créancier. Supportés par le créancier : tous les frais bancaires sont à la charge du créancier. Supportés par le débiteur : tous les frais bancaires sont à la charge du débiteur." +msgid "" +"Following service level : transaction charges are to be applied following " +"the rules agreed in the service level and/or scheme (SEPA Core messages must " +"use this). Shared : transaction charges on the creditor side are to be borne " +"by the creditor, transaction charges on the debtor side are to be borne by " +"the debtor. Borne by creditor : all transaction charges are to be borne by " +"the creditor. Borne by debtor : all transaction charges are to be borne by " +"the debtor." +msgstr "" +"Suivant le niveau de service : la répartition des frais bancaires suit les " +"règles pré-établies dans le schema ou dans le contrat avec la banque (les " +"messages SEPA Core doivent utiliser ce paramètre). Partagés : les frais " +"bancaires côté débiteur sont à la charge du débiteur, les frais bancaires " +"côté créancier sont à la charge du créancier. Supportés par le créancier : " +"tous les frais bancaires sont à la charge du créancier. Supportés par le " +"débiteur : tous les frais bancaires sont à la charge du débiteur." #. module: account_banking_sepa_credit_transfer #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:129 #, python-format -msgid "Payment Type Code '%s' is not supported. The only Payment Type Codes supported for SEPA Credit Transfers are 'pain.001.001.02', 'pain.001.001.03', 'pain.001.001.04' and 'pain.001.001.05'." -msgstr "Le code du Type de paiement '%s' n'est pas supporté. Les seuls codes de Type de paiement supportés pour les virements SEPA sont 'pain.001.001.02', 'pain.001.001.03', 'pain.001.001.04' et 'pain.001.001.05'." +msgid "" +"Payment Type Code '%s' is not supported. The only Payment Type Codes " +"supported for SEPA Credit Transfers are 'pain.001.001.02', " +"'pain.001.001.03', 'pain.001.001.04' and 'pain.001.001.05'." +msgstr "" +"Le code du Type de paiement '%s' n'est pas supporté. Les seuls codes de Type " +"de paiement supportés pour les virements SEPA sont 'pain.001.001.02', " +"'pain.001.001.03', 'pain.001.001.04' et 'pain.001.001.05'." #. module: account_banking_sepa_credit_transfer #: view:banking.export.sepa:0 @@ -187,8 +225,14 @@ msgstr "Fichiers de virement SEPA" #. module: account_banking_sepa_credit_transfer #: help:banking.export.sepa,batch_booking:0 #: help:banking.export.sepa.wizard,batch_booking:0 -msgid "If true, the bank statement will display only one debit line for all the wire transfers of the SEPA XML file ; if false, the bank statement will display one debit line per wire transfer of the SEPA XML file." -msgstr "Si coché, le relevé de compte ne comportera qu'une ligne de débit pour tous les virements du fichier SEPA XML ; si non coché, le relevé de compte comportera une ligne de débit pour chaque virement du fichier SEPA XML." +msgid "" +"If true, the bank statement will display only one debit line for all the " +"wire transfers of the SEPA XML file ; if false, the bank statement will " +"display one debit line per wire transfer of the SEPA XML file." +msgstr "" +"Si coché, le relevé de compte ne comportera qu'une ligne de débit pour tous " +"les virements du fichier SEPA XML ; si non coché, le relevé de compte " +"comportera une ligne de débit pour chaque virement du fichier SEPA XML." #. module: account_banking_sepa_credit_transfer #: field:banking.export.sepa.wizard,file:0 @@ -205,3 +249,117 @@ msgstr "Annuler" msgid "Generation Date" msgstr "Date de génération" +#~ msgid "SEPA XML file" +#~ msgstr "Fichier SEPA XML" + +#~ msgid "Payment order" +#~ msgstr "Ordre de paiement" + +#~ msgid "" +#~ "This is the message identification of the entire SEPA XML file. 35 " +#~ "characters max." +#~ msgstr "" +#~ "Ceci est le libellé d'identification du fichier SEPA XML. 35 caractères " +#~ "maximum." + +#~ msgid "Prefered execution date" +#~ msgstr "Date d'exécution demandée" + +#~ msgid "Generation date" +#~ msgstr "Date de génération" + +#~ msgid "Export SEPA Credit Transfer XML file" +#~ msgstr "Exporte the fichier de virement SEPA XML" + +#~ msgid "Message identification" +#~ msgstr "Libellé d'identification" + +#, python-format +#~ msgid "" +#~ "The generated XML file is not valid against the official XML Schema " +#~ "Definition. The generated XML file and the full error have been written in " +#~ "the server logs. Here is the error, which may give you an idea on the cause " +#~ "of the problem : %s" +#~ msgstr "" +#~ "Le fichier XML généré n'est pas valide par rapport à la Définition du Schéma " +#~ "XML officiel. Le fichier XML généré et le message d'erreur complet ont été " +#~ "écrits dans les logs du serveur. Voici l'erreur, qui vous donnera peut-être " +#~ "une idée sur la cause du problème : %s" + +#~ msgid "Total amount" +#~ msgstr "Montant total" + +#~ msgid "" +#~ "Shared : transaction charges on the sender side are to be borne by the " +#~ "debtor, transaction charges on the receiver side are to be borne by the " +#~ "creditor (most transfers use this). Borne by creditor : all transaction " +#~ "charges are to be borne by the creditor. Borne by debtor : all transaction " +#~ "charges are to be borne by the debtor. Following service level : transaction " +#~ "charges are to be applied following the rules agreed in the service level " +#~ "and/or scheme." +#~ msgstr "" +#~ "Partagés : les frais bancaires côté émetteur sont à la charge de l'émetteur " +#~ "et les frais bancaires côté destinataire sont à la charge du destinataire " +#~ "(la plupart des virements utilisent cette répartition). Supportés par le " +#~ "destinataire : tous les frais bancaires sont à la charge du destinataire. " +#~ "Supportés par l'émetteur : tous les frais bancaires sont à la charge de " +#~ "l'émetteur. Suivant le niveau de service : la répartition des frais " +#~ "bancaires suit les règles pré-établies dans le contrat avec la banque." + +#~ msgid "Borne by creditor" +#~ msgstr "Supportés par le destinataire" + +#~ msgid "Payment orders" +#~ msgstr "Ordres de paiement" + +#, python-format +#~ msgid "This IBAN is not valid : %s" +#~ msgstr "Cet IBAN n'est pas valide : %s" + +#~ msgid "SEPA XML file generation" +#~ msgstr "Génération du fichier SEPA XML" + +#~ msgid "Reference for further communication" +#~ msgstr "Référence pour communication ultérieure" + +#~ msgid "Processing details" +#~ msgstr "Paramètres" + +#~ msgid "Borne by debtor" +#~ msgstr "Supportés par l'émetteur" + +#~ msgid "Number of transactions" +#~ msgstr "Nombre de transactions" + +#~ msgid "Following service level" +#~ msgstr "Suivant le niveau de service" + +#~ msgid "Charge bearer" +#~ msgstr "Répartition des frais" + +#~ msgid "" +#~ "This is the date on which the file should be processed by the bank. Please " +#~ "keep in mind that banks only execute on working days and typically use a " +#~ "delay of two days between execution date and effective transfer date." +#~ msgstr "" +#~ "C'est la date à laquelle le fichier doit être traité par la banque. Gardez " +#~ "en tête que les banques réalisent des traitements seulement les jours ouvrés " +#~ "et ont habituellement un délai de 2 jours entre la date de traitement et la " +#~ "date du transfert effectif." + +#, python-format +#~ msgid "" +#~ "Payment Type Code '%s' is not supported. The only Payment Type Codes " +#~ "supported for SEPA Credit Transfers are 'pain.001.001.02', 'pain.001.001.03' " +#~ "and 'pain.001.001.04'." +#~ msgstr "" +#~ "Le code '%s' pour le Type de Paiment n'est pas supporté. Les seuls codes de " +#~ "Types de Paiement supportés pour les virements SEPA sont 'pain.001.001.02', " +#~ "'pain.001.001.03' et 'pain.001.001.04'." + +#, python-format +#~ msgid "Error :" +#~ msgstr "Erreur :" + +#~ msgid "Batch booking" +#~ msgstr "Débit groupé" diff --git a/account_banking_sepa_credit_transfer/i18n/nl.po b/account_banking_sepa_credit_transfer/i18n/nl.po index 4a22dce97..53f9263cf 100644 --- a/account_banking_sepa_credit_transfer/i18n/nl.po +++ b/account_banking_sepa_credit_transfer/i18n/nl.po @@ -6,21 +6,15 @@ msgid "" msgstr "" "Project-Id-Version: OpenERP Server 7.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-11-13 09:13+0000\n" +"POT-Creation-Date: 2013-12-23 22:49+0000\n" "PO-Revision-Date: 2013-12-03 11:49+0000\n" "Last-Translator: Jan Jurkus (GCE CAD-Service) \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-12-04 05:59+0000\n" -"X-Generator: Launchpad (build 16861)\n" - -#. module: account_banking_sepa_credit_transfer -#: field:banking.export.sepa,prefered_exec_date:0 -#: field:banking.export.sepa.wizard,prefered_exec_date:0 -msgid "Prefered Execution Date" -msgstr "Voorkeurs uitvoerdatum" +"X-Launchpad-Export-Date: 2014-02-01 06:56+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_banking_sepa_credit_transfer #: selection:banking.export.sepa.wizard,state:0 @@ -69,15 +63,6 @@ msgstr "" "rekening van de schuldenaar. Rekening van de schuldeiser: Alle transactie " "kosten zijn voor rekening van de schuldeiser." -#. module: account_banking_sepa_credit_transfer -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:117 -#, python-format -msgid "" -"Cannot compute the '%s' of the Payment Line with Invoice Reference '%s'." -msgstr "" -"Niet mogelijk de '%s' van de betaalregel te berekenen met factuurreferentie " -"'%s'." - #. module: account_banking_sepa_credit_transfer #: selection:banking.export.sepa,charge_bearer:0 #: selection:banking.export.sepa.wizard,charge_bearer:0 @@ -90,10 +75,15 @@ msgstr "Gedeeld" msgid "Batch Booking" msgstr "Bach verwerking" +#. module: account_banking_sepa_credit_transfer +#: selection:banking.export.sepa,state:0 +msgid "Sent" +msgstr "Verzonden" + #. module: account_banking_sepa_credit_transfer #: model:ir.model,name:account_banking_sepa_credit_transfer.model_banking_export_sepa_wizard -msgid "Export SEPA Credit Transfer XML file" -msgstr "Exporteer SEPA XML overschrijvingsbestand" +msgid "Export SEPA Credit Transfer File" +msgstr "" #. module: account_banking_sepa_credit_transfer #: view:banking.export.sepa:0 @@ -122,25 +112,6 @@ msgstr "Volg service level" msgid "Borne by Creditor" msgstr "Rekening van schuldeiser" -#. module: account_banking_sepa_credit_transfer -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:122 -#, python-format -msgid "Cannot compute the '%s'." -msgstr "Niet mogelijk de '%s' te berekenen." - -#. module: account_banking_sepa_credit_transfer -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:126 -#, python-format -msgid "The type of the field '%s' is %s. It should be a string or unicode." -msgstr "" -"Het veldsoort van het veld '%s' is %s. Het moet een string of unicode soort " -"zijn." - -#. module: account_banking_sepa_credit_transfer -#: selection:banking.export.sepa,state:0 -msgid "Sent" -msgstr "Verzonden" - #. module: account_banking_sepa_credit_transfer #: view:banking.export.sepa.wizard:0 msgid "Validate" @@ -151,20 +122,6 @@ msgstr "Bevestig" msgid "Generate" msgstr "Genereer" -#. module: account_banking_sepa_credit_transfer -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:169 -#, python-format -msgid "" -"The generated XML file is not valid against the official XML Schema " -"Definition. The generated XML file and the full error have been written in " -"the server logs. Here is the error, which may give you an idea on the cause " -"of the problem : %s" -msgstr "" -"Het gegenereerde XML bestand is niet geldig volgens de officiële XML schema " -"definities. Het gegenereerde XML bestand en de volledige fout zijn " -"weggeschreven in de server log bestanden. Hier is de fout, wat u een idee " -"kunt geven over de oorzaak van het probleem: %s\"" - #. module: account_banking_sepa_credit_transfer #: selection:banking.export.sepa,charge_bearer:0 #: selection:banking.export.sepa.wizard,charge_bearer:0 @@ -172,13 +129,8 @@ msgid "Borne by Debtor" msgstr "Rekening van schuldenaar" #. module: account_banking_sepa_credit_transfer -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:90 -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:116 -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:121 -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:130 -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:168 -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:206 -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:350 +#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:128 +#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:245 #, python-format msgid "Error:" msgstr "Fout:" @@ -200,19 +152,13 @@ msgstr "Kostenverdeling" msgid "SEPA File Generation" msgstr "SEPA bestand genereren" -#. module: account_banking_sepa_credit_transfer -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:125 -#, python-format -msgid "Field type error:" -msgstr "Veldsoort fout:" - #. module: account_banking_sepa_credit_transfer #: model:ir.model,name:account_banking_sepa_credit_transfer.model_banking_export_sepa msgid "SEPA export" msgstr "SEPA export" #. module: account_banking_sepa_credit_transfer -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:351 +#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:246 #, python-format msgid "" "Missing Bank Account on invoice '%s' (payment order line reference '%s')." @@ -225,12 +171,6 @@ msgstr "" msgid "SEPA XML File" msgstr "SEPA XML bestand" -#. module: account_banking_sepa_credit_transfer -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:131 -#, python-format -msgid "The '%s' is empty or 0. It should have a non-null value." -msgstr "De '%s' is leeg of 0. Het mag geen lege of nul waarde hebben." - #. module: account_banking_sepa_credit_transfer #: help:banking.export.sepa,charge_bearer:0 msgid "" @@ -251,7 +191,7 @@ msgstr "" "kosten zijn voor rekening van de schuldeiser." #. module: account_banking_sepa_credit_transfer -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:207 +#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:129 #, python-format msgid "" "Payment Type Code '%s' is not supported. The only Payment Type Codes " @@ -262,12 +202,6 @@ msgstr "" "voor SEPA credit boekingen zijn 'pain.001.001.02', 'pain.001.001.03' en " "'pain.001.001.04'." -#. module: account_banking_sepa_credit_transfer -#: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:90 -#, python-format -msgid "This IBAN is not valid : %s" -msgstr "Deze IBAN is niet geldig : %s" - #. module: account_banking_sepa_credit_transfer #: view:banking.export.sepa:0 #: field:banking.export.sepa,payment_order_ids:0 @@ -299,18 +233,6 @@ msgstr "" "alle overschrijvingen van het SEPA XML bestand. Indien uitgevinkt, zal het " "bankafschrift een debet regel weergeven per SEPA XML bestand." -#. module: account_banking_sepa_credit_transfer -#: help:banking.export.sepa.wizard,prefered_exec_date:0 -msgid "" -"This is the date on which the file should be processed by the bank. Please " -"keep in mind that banks only execute on working days and typically use a " -"delay of two days between execution date and effective transfer date." -msgstr "" -"Dit is de datum waarop het bestand zou moeten worden verwerkt door de bank. " -"Houdt u er rekening mee dat banken alleen op werkdagen de bestanden " -"verwerken en veelal een vertraging hebben van twee dagen tussen de " -"verwerkingsdatum en de effectieve overschrijfdatum." - #. module: account_banking_sepa_credit_transfer #: field:banking.export.sepa.wizard,file:0 msgid "File" @@ -345,6 +267,9 @@ msgstr "Aangemaakt op" #~ msgid "Generation date" #~ msgstr "Aanmaakdatum" +#~ msgid "Export SEPA Credit Transfer XML file" +#~ msgstr "Exporteer SEPA XML overschrijvingsbestand" + #~ msgid "Message identification" #~ msgstr "Bericht identificatie" @@ -403,3 +328,29 @@ msgstr "Aangemaakt op" #~ msgid "Generated SEPA Credit Transfer XML files" #~ msgstr "Gengenereerde SEPA XML overschrijf bestanden" + +#, python-format +#~ msgid "This IBAN is not valid : %s" +#~ msgstr "Deze IBAN is niet geldig : %s" + +#~ msgid "" +#~ "This is the date on which the file should be processed by the bank. Please " +#~ "keep in mind that banks only execute on working days and typically use a " +#~ "delay of two days between execution date and effective transfer date." +#~ msgstr "" +#~ "Dit is de datum waarop het bestand zou moeten worden verwerkt door de bank. " +#~ "Houdt u er rekening mee dat banken alleen op werkdagen de bestanden " +#~ "verwerken en veelal een vertraging hebben van twee dagen tussen de " +#~ "verwerkingsdatum en de effectieve overschrijfdatum." + +#, python-format +#~ msgid "" +#~ "The generated XML file is not valid against the official XML Schema " +#~ "Definition. The generated XML file and the full error have been written in " +#~ "the server logs. Here is the error, which may give you an idea on the cause " +#~ "of the problem : %s" +#~ msgstr "" +#~ "Het gegenereerde XML bestand is niet geldig volgens de officiële XML schema " +#~ "definities. Het gegenereerde XML bestand en de volledige fout zijn " +#~ "weggeschreven in de server log bestanden. Hier is de fout, wat u een idee " +#~ "kunt geven over de oorzaak van het probleem: %s\"" diff --git a/account_banking_sepa_direct_debit/i18n/fr.po b/account_banking_sepa_direct_debit/i18n/fr.po index 9d30343dd..35b708779 100644 --- a/account_banking_sepa_direct_debit/i18n/fr.po +++ b/account_banking_sepa_direct_debit/i18n/fr.po @@ -6,14 +6,15 @@ msgid "" msgstr "" "Project-Id-Version: OpenERP Server 7.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-12-23 22:25+0000\n" -"PO-Revision-Date: 2013-12-23 22:25+0000\n" -"Last-Translator: <>\n" +"POT-Creation-Date: 2013-12-23 22:24+0000\n" +"PO-Revision-Date: 2014-02-01 04:49+0000\n" +"Last-Translator: Alexis de Lattre \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: \n" -"Plural-Forms: \n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2014-02-01 06:56+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_banking_sepa_direct_debit #: model:mail.message.subtype,description:account_banking_sepa_direct_debit.mandate_valid @@ -29,8 +30,12 @@ msgstr "Nom du fichier" #. module: account_banking_sepa_direct_debit #: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:200 #, python-format -msgid "The SEPA Direct Debit mandate with reference '%s' for partner '%s' has expired." -msgstr "Le mandat de prélèvement SEPA portant la référence '%s' pour le partenaire '%s' a expiré." +msgid "" +"The SEPA Direct Debit mandate with reference '%s' for partner '%s' has " +"expired." +msgstr "" +"Le mandat de prélèvement SEPA portant la référence '%s' pour le partenaire " +"'%s' a expiré." #. module: account_banking_sepa_direct_debit #: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:219 @@ -148,8 +153,14 @@ msgstr "Annulé" #. module: account_banking_sepa_direct_debit #: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:141 #, python-format -msgid "Payment Type Code '%s' is not supported. The only Payment Type Code supported for SEPA Direct Debit are 'pain.008.001.02', 'pain.008.001.03' and 'pain.008.001.04'." -msgstr "Le code du Type de paiement '%s' n'est pas supporté. Les seuls codes de Type de paiement supportés pour les prélèvements SEPA sont 'pain.008.001.02', 'pain.008.001.03' et 'pain.008.001.04'." +msgid "" +"Payment Type Code '%s' is not supported. The only Payment Type Code " +"supported for SEPA Direct Debit are 'pain.008.001.02', 'pain.008.001.03' and " +"'pain.008.001.04'." +msgstr "" +"Le code du Type de paiement '%s' n'est pas supporté. Les seuls codes de Type " +"de paiement supportés pour les prélèvements SEPA sont 'pain.008.001.02', " +"'pain.008.001.03' et 'pain.008.001.04'." #. module: account_banking_sepa_direct_debit #: help:sdd.mandate,message_unread:0 @@ -169,14 +180,32 @@ msgstr "Le mandat de prélèvement SEPA a expiré" #. module: account_banking_sepa_direct_debit #: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:246 #, python-format -msgid "The recurrent mandate '%s' which is not marked as 'Migrated to SEPA' must have its recurrent sequence type set to 'First'." -msgstr "Le mandat récurrent '%s' dont l'option 'Migré à SEPA' n'est pas activée doit avec sa séquence mise à 'First'." +msgid "" +"The recurrent mandate '%s' which is not marked as 'Migrated to SEPA' must " +"have its recurrent sequence type set to 'First'." +msgstr "" +"Le mandat récurrent '%s' dont l'option 'Migré à SEPA' n'est pas activée doit " +"avec sa séquence mise à 'First'." #. module: account_banking_sepa_direct_debit #: help:banking.export.sdd,charge_bearer:0 #: help:banking.export.sdd.wizard,charge_bearer:0 -msgid "Following service level : transaction charges are to be applied following the rules agreed in the service level and/or scheme (SEPA Core messages must use this). Shared : transaction charges on the creditor side are to be borne by the creditor, transaction charges on the debtor side are to be borne by the debtor. Borne by creditor : all transaction charges are to be borne by the creditor. Borne by debtor : all transaction charges are to be borne by the debtor." -msgstr "Suivant le niveau de service : la répartition des frais bancaires suit les règles pré-établies dans le schema ou dans le contrat avec la banque (les messages SEPA Core doivent utiliser ce paramètre). Partagés : les frais bancaires côté débiteur sont à la charge du débiteur, les frais bancaires côté créancier sont à la charge du créancier. Supportés par le créancier : tous les frais bancaires sont à la charge du créancier. Supportés par le débiteur : tous les frais bancaires sont à la charge du débiteur." +msgid "" +"Following service level : transaction charges are to be applied following " +"the rules agreed in the service level and/or scheme (SEPA Core messages must " +"use this). Shared : transaction charges on the creditor side are to be borne " +"by the creditor, transaction charges on the debtor side are to be borne by " +"the debtor. Borne by creditor : all transaction charges are to be borne by " +"the creditor. Borne by debtor : all transaction charges are to be borne by " +"the debtor." +msgstr "" +"Suivant le niveau de service : la répartition des frais bancaires suit les " +"règles pré-établies dans le schema ou dans le contrat avec la banque (les " +"messages SEPA Core doivent utiliser ce paramètre). Partagés : les frais " +"bancaires côté débiteur sont à la charge du débiteur, les frais bancaires " +"côté créancier sont à la charge du créancier. Supportés par le créancier : " +"tous les frais bancaires sont à la charge du créancier. Supportés par le " +"débiteur : tous les frais bancaires sont à la charge du débiteur." #. module: account_banking_sepa_direct_debit #: view:sdd.mandate:0 @@ -195,8 +224,12 @@ msgstr "Génération de fichiers de prélèvement SEPA XML" #. module: account_banking_sepa_direct_debit #: help:sdd.mandate,message_summary:0 -msgid "Holds the Chatter summary (number of messages, ...). This summary is directly in html format in order to be inserted in kanban views." -msgstr "Holds the Chatter summary (number of messages, ...). This summary is directly in html format in order to be inserted in kanban views." +msgid "" +"Holds the Chatter summary (number of messages, ...). This summary is " +"directly in html format in order to be inserted in kanban views." +msgstr "" +"Holds the Chatter summary (number of messages, ...). This summary is " +"directly in html format in order to be inserted in kanban views." #. module: account_banking_sepa_direct_debit #: model:ir.model,name:account_banking_sepa_direct_debit.model_payment_line @@ -211,8 +244,14 @@ msgstr "Date de génération" #. module: account_banking_sepa_direct_debit #: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:396 #, python-format -msgid "The payment line with reference '%s' has the bank account '%s' which is not attached to the mandate '%s' (this mandate is attached to the bank account '%s')." -msgstr "La ligne de paiement portant la référence '%s' est configurée avec le compte bancaire '%s' qui n'est pas rattaché au mandat '%s' (ce mandat est rattaché au compte bancaire '%s')." +msgid "" +"The payment line with reference '%s' has the bank account '%s' which is not " +"attached to the mandate '%s' (this mandate is attached to the bank account " +"'%s')." +msgstr "" +"La ligne de paiement portant la référence '%s' est configurée avec le compte " +"bancaire '%s' qui n'est pas rattaché au mandat '%s' (ce mandat est rattaché " +"au compte bancaire '%s')." #. module: account_banking_sepa_direct_debit #: selection:banking.export.sdd.wizard,state:0 @@ -282,12 +321,16 @@ msgstr "Recurring" #. module: account_banking_sepa_direct_debit #: help:res.company,sepa_creditor_identifier:0 -msgid "Enter the Creditor Identifier that has been attributed to your company to make SEPA Direct Debits. This identifier is composed of :\n" +msgid "" +"Enter the Creditor Identifier that has been attributed to your company to " +"make SEPA Direct Debits. This identifier is composed of :\n" "- your country ISO code (2 letters)\n" "- a 2-digits checkum\n" "- a 3-letters business code\n" "- a country-specific identifier" -msgstr "Entrez l'Identifiant créancier qui a été attribué à votre société pour réaliser des prélèvements SEPA. Cet identifiant est composé de :\n" +msgstr "" +"Entrez l'Identifiant créancier qui a été attribué à votre société pour " +"réaliser des prélèvements SEPA. Cet identifiant est composé de :\n" "- du code ISO de votre pays (2 lettres)\n" "- un code de contrôle à 2 chiffres\n" "- un code d'activité à 3 lettres\n" @@ -300,13 +343,25 @@ msgstr "Un mandat avec la même référence existe déjà pour cette société ! #. module: account_banking_sepa_direct_debit #: help:sdd.mandate,state:0 -msgid "Only valid mandates can be used in a payment line. A cancelled mandate is a mandate that has been cancelled by the customer. A one-off mandate expires after its first use. A recurrent mandate expires after it's final use or if it hasn't been used for 36 months." -msgstr "Seuls des mandats valides peuvent être utilisés dans une ligne de paiement. Un mandate annulé est un mandat qui a été annulé par le client. Un mandat One-Off expire à l'issue de sa première utilisation. Un mandate récurrent expire après sa dernière utilisation ou si il n'a pas été utilisé pendant 36 mois." +msgid "" +"Only valid mandates can be used in a payment line. A cancelled mandate is a " +"mandate that has been cancelled by the customer. A one-off mandate expires " +"after its first use. A recurrent mandate expires after it's final use or if " +"it hasn't been used for 36 months." +msgstr "" +"Seuls des mandats valides peuvent être utilisés dans une ligne de paiement. " +"Un mandate annulé est un mandat qui a été annulé par le client. Un mandat " +"One-Off expire à l'issue de sa première utilisation. Un mandate récurrent " +"expire après sa dernière utilisation ou si il n'a pas été utilisé pendant 36 " +"mois." #. module: account_banking_sepa_direct_debit #: help:sdd.mandate,recurrent_sequence_type:0 -msgid "This field is only used for Recurrent mandates, not for One-Off mandates." -msgstr "Ce champ n'est utilisé que pour les mandats récurrents, pas pour les mandats One-Off." +msgid "" +"This field is only used for Recurrent mandates, not for One-Off mandates." +msgstr "" +"Ce champ n'est utilisé que pour les mandats récurrents, pas pour les mandats " +"One-Off." #. module: account_banking_sepa_direct_debit #: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:213 @@ -352,8 +407,20 @@ msgstr "Fichiers de prélèvement SEPA générés" #. module: account_banking_sepa_direct_debit #: help:sdd.mandate,sepa_migrated:0 -msgid "If this field is not active, the mandate section of the next direct debit file that include this mandate will contain the 'Original Mandate Identification' and the 'Original Creditor Scheme Identification'. This is required in a few countries (Belgium for instance), but not in all countries. If this is not required in your country, you should keep this field always active." -msgstr "Si cette option n'est pas activée, la section qui concerne le mandat dans le prochain fichier de prélèvement qui incluera ce mandat contiendra les champs 'Original Mandate Identification' et 'Original Creditor Scheme Identification'. Ces champs sont requis dans certains pays (en Belgique notamment), mais pas dans tous les pays. Si ces champs ne sont pas requis dans votre pays, vous devriez garder ce champ toujours actif." +msgid "" +"If this field is not active, the mandate section of the next direct debit " +"file that include this mandate will contain the 'Original Mandate " +"Identification' and the 'Original Creditor Scheme Identification'. This is " +"required in a few countries (Belgium for instance), but not in all " +"countries. If this is not required in your country, you should keep this " +"field always active." +msgstr "" +"Si cette option n'est pas activée, la section qui concerne le mandat dans le " +"prochain fichier de prélèvement qui incluera ce mandat contiendra les champs " +"'Original Mandate Identification' et 'Original Creditor Scheme " +"Identification'. Ces champs sont requis dans certains pays (en Belgique " +"notamment), mais pas dans tous les pays. Si ces champs ne sont pas requis " +"dans votre pays, vous devriez garder ce champ toujours actif." #. module: account_banking_sepa_direct_debit #: field:sdd.mandate,company_id:0 @@ -368,14 +435,25 @@ msgstr "Export du fichier de prélèvement SEPA" #. module: account_banking_sepa_direct_debit #: help:banking.export.sdd,batch_booking:0 #: help:banking.export.sdd.wizard,batch_booking:0 -msgid "If true, the bank statement will display only one credit line for all the direct debits of the SEPA file ; if false, the bank statement will display one credit line per direct debit of the SEPA file." -msgstr "Si activé, le relevé de compte ne fera apparaître qu'une ligne de crédit pour tous les prélèvements du fichier SEPA ; si désactivé, le relevé de banque fera apparaître une ligne de crédit pour chaque prélèvement du fichier SEPA." +msgid "" +"If true, the bank statement will display only one credit line for all the " +"direct debits of the SEPA file ; if false, the bank statement will display " +"one credit line per direct debit of the SEPA file." +msgstr "" +"Si activé, le relevé de compte ne fera apparaître qu'une ligne de crédit " +"pour tous les prélèvements du fichier SEPA ; si désactivé, le relevé de " +"banque fera apparaître une ligne de crédit pour chaque prélèvement du " +"fichier SEPA." #. module: account_banking_sepa_direct_debit #: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:225 #, python-format -msgid "Cannot validate the mandate '%s' because it is not attached to a bank account." -msgstr "Impossible de valider le mandat '%s' car il n'est pas rattaché à un compte bancaire." +msgid "" +"Cannot validate the mandate '%s' because it is not attached to a bank " +"account." +msgstr "" +"Impossible de valider le mandat '%s' car il n'est pas rattaché à un compte " +"bancaire." #. module: account_banking_sepa_direct_debit #: selection:banking.export.sdd,state:0 @@ -433,8 +511,12 @@ msgstr "Suivant le niveau de service" #. module: account_banking_sepa_direct_debit #: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:233 #, python-format -msgid "The mandate '%s' can't have a date of last debit before the date of signature." -msgstr "Le mandat '%s' ne peut pas avoir une date de dernier débit antérieure à la date de signature." +msgid "" +"The mandate '%s' can't have a date of last debit before the date of " +"signature." +msgstr "" +"Le mandat '%s' ne peut pas avoir une date de dernier débit antérieure à la " +"date de signature." #. module: account_banking_sepa_direct_debit #: model:mail.message.subtype,description:account_banking_sepa_direct_debit.recurrent_sequence_type_final @@ -449,8 +531,12 @@ msgstr "Is a Follower" #. module: account_banking_sepa_direct_debit #: help:sdd.mandate,original_mandate_identification:0 -msgid "When the field 'Migrated to SEPA' is not active, this field will be used as the Original Mandate Identification in the Direct Debit file." -msgstr "Quand le champ 'Migré à SEPA' n'est pas activé, ce champ sera le 'Original Mandate Identification' dans le fichier de prélèvement." +msgid "" +"When the field 'Migrated to SEPA' is not active, this field will be used as " +"the Original Mandate Identification in the Direct Debit file." +msgstr "" +"Quand le champ 'Migré à SEPA' n'est pas activé, ce champ sera le 'Original " +"Mandate Identification' dans le fichier de prélèvement." #. module: account_banking_sepa_direct_debit #: view:payment.order:0 @@ -488,14 +574,22 @@ msgstr "Mandat de prélèvement SEPA" #. module: account_banking_sepa_direct_debit #: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:193 #, python-format -msgid "Missing SEPA Direct Debit mandate on the payment line with partner '%s' and Invoice ref '%s'." -msgstr "Mandat de prélèvement SEPA manquant sur la ligne de paiement ayant pour partenaire '%s' et pour référence de facture '%s'." +msgid "" +"Missing SEPA Direct Debit mandate on the payment line with partner '%s' and " +"Invoice ref '%s'." +msgstr "" +"Mandat de prélèvement SEPA manquant sur la ligne de paiement ayant pour " +"partenaire '%s' et pour référence de facture '%s'." #. module: account_banking_sepa_direct_debit #: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:210 #, python-format -msgid "The mandate with reference '%s' for partner '%s' has type set to 'One-Off' and it has a last debit date set to '%s', so we can't use it." -msgstr "Le mandat portant la référence '%s' pour le partenaire '%s' est de type 'One-Off' et il a une date de dernier débit au '%s', donc il n'est pas utilisable." +msgid "" +"The mandate with reference '%s' for partner '%s' has type set to 'One-Off' " +"and it has a last debit date set to '%s', so we can't use it." +msgstr "" +"Le mandat portant la référence '%s' pour le partenaire '%s' est de type 'One-" +"Off' et il a une date de dernier débit au '%s', donc il n'est pas utilisable." #. module: account_banking_sepa_direct_debit #: field:sdd.mandate,scan:0 @@ -524,16 +618,22 @@ msgstr "Comptes bancaires" #. module: account_banking_sepa_direct_debit #: model:ir.actions.act_window,help:account_banking_sepa_direct_debit.sdd_mandate_action -msgid "

\n" +msgid "" +"

\n" " Click to create a new SEPA Direct Debit Mandate.\n" "

\n" -" A SEPA Direct Debit Mandate is a document signed by your customer that gives you the autorization to do one or several direct debits on his bank account.\n" +" A SEPA Direct Debit Mandate is a document signed by your customer " +"that gives you the autorization to do one or several direct debits on his " +"bank account.\n" "

\n" " " -msgstr "

\n" +msgstr "" +"

\n" " Cliquez pour créer un mandat de prélèvement SEPA.\n" "

\n" -" Un mandat de prélèvement SEPA est un document signé par votre client qui vous donne l'autorisation de réaliser un ou plusieurs prélèvements sur son compte bancaire.\n" +" Un mandat de prélèvement SEPA est un document signé par votre client " +"qui vous donne l'autorisation de réaliser un ou plusieurs prélèvements sur " +"son compte bancaire.\n" "

\n" " " @@ -610,8 +710,12 @@ msgstr "Compte bancaire" #. module: account_banking_sepa_direct_debit #: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:254 #, python-format -msgid "You must set the 'Original Mandate Identification' on the recurrent mandate '%s' which is not marked as 'Migrated to SEPA'." -msgstr "Vous devez renseigner le champ 'Ancien identifiant du mandat' sur le mandat récurrent '%s' qui n'est pas marqué comme étant 'Migré à SEPA'." +msgid "" +"You must set the 'Original Mandate Identification' on the recurrent mandate " +"'%s' which is not marked as 'Migrated to SEPA'." +msgstr "" +"Vous devez renseigner le champ 'Ancien identifiant du mandat' sur le mandat " +"récurrent '%s' qui n'est pas marqué comme étant 'Migré à SEPA'." #. module: account_banking_sepa_direct_debit #: model:mail.message.subtype,description:account_banking_sepa_direct_debit.recurrent_sequence_type_first @@ -622,8 +726,12 @@ msgstr "Type de Séquence mis à First" #. module: account_banking_sepa_direct_debit #: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:291 #, python-format -msgid "As you changed the bank account attached to this mandate, the 'Sequence Type' has been set back to 'First'." -msgstr "Etant donné que vous avez changé le compte bancaire associé à ce mandat, le 'Type de séquence' a été remis à 'First'." +msgid "" +"As you changed the bank account attached to this mandate, the 'Sequence " +"Type' has been set back to 'First'." +msgstr "" +"Etant donné que vous avez changé le compte bancaire associé à ce mandat, le " +"'Type de séquence' a été remis à 'First'." #. module: account_banking_sepa_direct_debit #: help:sdd.mandate,message_ids:0 @@ -639,4 +747,3 @@ msgstr "Recherche dans les mandats de prélèvement SEPA" #: field:banking.export.sdd.wizard,file:0 msgid "File" msgstr "Fichier" - From fbbfafbeb1f37c43b82007d7323ea8171bb1b0d3 Mon Sep 17 00:00:00 2001 From: Launchpad Translations on behalf of banking-addons-team Date: Sun, 2 Feb 2014 06:05:02 +0000 Subject: [PATCH 41/43] Launchpad automatic translations update. --- account_banking_pain_base/i18n/fr.po | 2 +- account_banking_pain_base/i18n/nl.po | 163 ++++ .../i18n/fr.po | 2 +- .../i18n/nl.po | 8 +- account_banking_sepa_direct_debit/i18n/fr.po | 2 +- account_banking_sepa_direct_debit/i18n/nl.po | 696 ++++++++++++++++++ 6 files changed, 866 insertions(+), 7 deletions(-) create mode 100644 account_banking_pain_base/i18n/nl.po create mode 100644 account_banking_sepa_direct_debit/i18n/nl.po diff --git a/account_banking_pain_base/i18n/fr.po b/account_banking_pain_base/i18n/fr.po index 5ca1a72c2..472d9b59e 100644 --- a/account_banking_pain_base/i18n/fr.po +++ b/account_banking_pain_base/i18n/fr.po @@ -13,7 +13,7 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-02-01 06:56+0000\n" +"X-Launchpad-Export-Date: 2014-02-02 06:05+0000\n" "X-Generator: Launchpad (build 16916)\n" #. module: account_banking_pain_base diff --git a/account_banking_pain_base/i18n/nl.po b/account_banking_pain_base/i18n/nl.po new file mode 100644 index 000000000..9d295b72c --- /dev/null +++ b/account_banking_pain_base/i18n/nl.po @@ -0,0 +1,163 @@ +# Dutch translation for banking-addons +# Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 +# This file is distributed under the same license as the banking-addons package. +# FIRST AUTHOR , 2014. +# +msgid "" +msgstr "" +"Project-Id-Version: banking-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-12-23 21:26+0000\n" +"PO-Revision-Date: 2014-02-01 07:45+0000\n" +"Last-Translator: Erwin van der Ploeg (BAS Solutions) \n" +"Language-Team: Dutch \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2014-02-02 06:05+0000\n" +"X-Generator: Launchpad (build 16916)\n" + +#. module: account_banking_pain_base +#: field:res.company,initiating_party_issuer:0 +msgid "Initiating Party Issuer" +msgstr "" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:122 +#, python-format +msgid "" +"The generated XML file is not valid against the official XML Schema " +"Definition. The generated XML file and the full error have been written in " +"the server logs. Here is the error, which may give you an idea on the cause " +"of the problem : %s" +msgstr "" +"Het gegenereerde XML bestand is niet geldig volgens de officiële XML schema " +"definities. Het gegenereerde XML bestand en de volledige fout zijn " +"weggeschreven in de server log bestanden. Hier is de fout, wat u een idee " +"kunt geven over de oorzaak van het probleem: %s\"" + +#. module: account_banking_pain_base +#: field:payment.line,priority:0 +msgid "Priority" +msgstr "Prioriteit" + +#. module: account_banking_pain_base +#: model:ir.model,name:account_banking_pain_base.model_payment_line +msgid "Payment Line" +msgstr "Betaalregel" + +#. module: account_banking_pain_base +#: model:ir.model,name:account_banking_pain_base.model_payment_mode +msgid "Payment Mode" +msgstr "Betaalwijze" + +#. module: account_banking_pain_base +#: help:res.company,initiating_party_issuer:0 +msgid "" +"This will be used as the 'Initiating Party Issuer' in the PAIN files " +"generated by OpenERP." +msgstr "" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:351 +#, python-format +msgid "" +"Missing 'Structured Communication Type' on payment line with reference '%s'." +msgstr "" + +#. module: account_banking_pain_base +#: selection:payment.line,priority:0 +msgid "Normal" +msgstr "Normaal" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:70 +#, python-format +msgid "Cannot compute the '%s' of the Payment Line with reference '%s'." +msgstr "" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:77 +#, python-format +msgid "Cannot compute the '%s'." +msgstr "Kan de '%s' niet berekenen." + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:81 +#, python-format +msgid "The type of the field '%s' is %s. It should be a string or unicode." +msgstr "" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:47 +#: code:addons/account_banking_pain_base/banking_export_pain.py:69 +#: code:addons/account_banking_pain_base/banking_export_pain.py:76 +#: code:addons/account_banking_pain_base/banking_export_pain.py:86 +#: code:addons/account_banking_pain_base/banking_export_pain.py:121 +#: code:addons/account_banking_pain_base/banking_export_pain.py:350 +#, python-format +msgid "Error:" +msgstr "Fout:" + +#. module: account_banking_pain_base +#: model:ir.model,name:account_banking_pain_base.model_res_company +msgid "Companies" +msgstr "Bedrijven" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:47 +#, python-format +msgid "This IBAN is not valid : %s" +msgstr "Deze IBAN is niet geldig : %s" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:80 +#, python-format +msgid "Field type error:" +msgstr "Veld type fout:" + +#. module: account_banking_pain_base +#: field:payment.line,struct_communication_type:0 +msgid "Structured Communication Type" +msgstr "" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:87 +#, python-format +msgid "The '%s' is empty or 0. It should have a non-null value." +msgstr "" + +#. module: account_banking_pain_base +#: model:ir.model,name:account_banking_pain_base.model_banking_export_pain +msgid "banking.export.pain" +msgstr "banking.export.pain" + +#. module: account_banking_pain_base +#: help:payment.mode,convert_to_ascii:0 +msgid "" +"If active, OpenERP will convert each accented caracter to the corresponding " +"unaccented caracter, so that only ASCII caracters are used in the generated " +"PAIN file." +msgstr "" + +#. module: account_banking_pain_base +#: help:payment.line,priority:0 +msgid "" +"This field will be used as the 'Instruction Priority' in the generated PAIN " +"file." +msgstr "" + +#. module: account_banking_pain_base +#: view:res.company:0 +msgid "Payment Initiation" +msgstr "" + +#. module: account_banking_pain_base +#: selection:payment.line,priority:0 +msgid "High" +msgstr "" + +#. module: account_banking_pain_base +#: field:payment.mode,convert_to_ascii:0 +msgid "Convert to ASCII" +msgstr "" diff --git a/account_banking_sepa_credit_transfer/i18n/fr.po b/account_banking_sepa_credit_transfer/i18n/fr.po index 72cd4b560..52a299b2e 100644 --- a/account_banking_sepa_credit_transfer/i18n/fr.po +++ b/account_banking_sepa_credit_transfer/i18n/fr.po @@ -13,7 +13,7 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-02-01 06:56+0000\n" +"X-Launchpad-Export-Date: 2014-02-02 06:05+0000\n" "X-Generator: Launchpad (build 16916)\n" #. module: account_banking_sepa_credit_transfer diff --git a/account_banking_sepa_credit_transfer/i18n/nl.po b/account_banking_sepa_credit_transfer/i18n/nl.po index 53f9263cf..7e53025fa 100644 --- a/account_banking_sepa_credit_transfer/i18n/nl.po +++ b/account_banking_sepa_credit_transfer/i18n/nl.po @@ -7,13 +7,13 @@ msgstr "" "Project-Id-Version: OpenERP Server 7.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-12-23 22:49+0000\n" -"PO-Revision-Date: 2013-12-03 11:49+0000\n" -"Last-Translator: Jan Jurkus (GCE CAD-Service) \n" +"PO-Revision-Date: 2014-02-01 07:47+0000\n" +"Last-Translator: Erwin van der Ploeg (BAS Solutions) \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-02-01 06:56+0000\n" +"X-Launchpad-Export-Date: 2014-02-02 06:04+0000\n" "X-Generator: Launchpad (build 16916)\n" #. module: account_banking_sepa_credit_transfer @@ -83,7 +83,7 @@ msgstr "Verzonden" #. module: account_banking_sepa_credit_transfer #: model:ir.model,name:account_banking_sepa_credit_transfer.model_banking_export_sepa_wizard msgid "Export SEPA Credit Transfer File" -msgstr "" +msgstr "Exporteer SEPA Credit Transfer bestand" #. module: account_banking_sepa_credit_transfer #: view:banking.export.sepa:0 diff --git a/account_banking_sepa_direct_debit/i18n/fr.po b/account_banking_sepa_direct_debit/i18n/fr.po index 35b708779..76fb55d08 100644 --- a/account_banking_sepa_direct_debit/i18n/fr.po +++ b/account_banking_sepa_direct_debit/i18n/fr.po @@ -13,7 +13,7 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-02-01 06:56+0000\n" +"X-Launchpad-Export-Date: 2014-02-02 06:05+0000\n" "X-Generator: Launchpad (build 16916)\n" #. module: account_banking_sepa_direct_debit diff --git a/account_banking_sepa_direct_debit/i18n/nl.po b/account_banking_sepa_direct_debit/i18n/nl.po new file mode 100644 index 000000000..0666c4754 --- /dev/null +++ b/account_banking_sepa_direct_debit/i18n/nl.po @@ -0,0 +1,696 @@ +# Dutch translation for banking-addons +# Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 +# This file is distributed under the same license as the banking-addons package. +# FIRST AUTHOR , 2014. +# +msgid "" +msgstr "" +"Project-Id-Version: banking-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-12-23 22:24+0000\n" +"PO-Revision-Date: 2014-02-01 07:52+0000\n" +"Last-Translator: Erwin van der Ploeg (BAS Solutions) \n" +"Language-Team: Dutch \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2014-02-02 06:05+0000\n" +"X-Generator: Launchpad (build 16916)\n" + +#. module: account_banking_sepa_direct_debit +#: model:mail.message.subtype,description:account_banking_sepa_direct_debit.mandate_valid +msgid "SEPA Direct Debit Mandate Validated" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd,filename:0 +#: field:banking.export.sdd.wizard,filename:0 +msgid "Filename" +msgstr "Bestandsnaam" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:200 +#, python-format +msgid "" +"The SEPA Direct Debit mandate with reference '%s' for partner '%s' has " +"expired." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:219 +#, python-format +msgid "Cannot validate the mandate '%s' without a date of signature." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: selection:sdd.mandate,recurrent_sequence_type:0 +msgid "Final" +msgstr "Definitief" + +#. module: account_banking_sepa_direct_debit +#: selection:banking.export.sdd.wizard,state:0 +msgid "Finish" +msgstr "Gereed" + +#. module: account_banking_sepa_direct_debit +#: view:res.partner:0 +#: view:res.partner.bank:0 +msgid "SDD Mandates" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: constraint:payment.line:0 +#: constraint:sdd.mandate:0 +msgid "Error msg in raise" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: selection:banking.export.sdd,state:0 +msgid "Reconciled" +msgstr "Afgeletterd" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,recurrent_sequence_type:0 +msgid "Sequence Type for Next Debit" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: selection:banking.export.sdd,charge_bearer:0 +#: selection:banking.export.sdd.wizard,charge_bearer:0 +msgid "Borne by Creditor" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: model:ir.actions.act_window,name:account_banking_sepa_direct_debit.sdd_mandate_action +#: model:ir.ui.menu,name:account_banking_sepa_direct_debit.sdd_mandate_menu +#: view:res.partner.bank:0 +#: field:res.partner.bank,sdd_mandate_ids:0 +msgid "SEPA Direct Debit Mandates" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: view:banking.export.sdd.wizard:0 +#: view:sdd.mandate:0 +msgid "Validate" +msgstr "Bevestigen" + +#. module: account_banking_sepa_direct_debit +#: model:mail.message.subtype,description:account_banking_sepa_direct_debit.recurrent_sequence_type_recurring +#: model:mail.message.subtype,name:account_banking_sepa_direct_debit.recurrent_sequence_type_recurring +msgid "Sequence Type set to Recurring" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: view:banking.export.sdd.wizard:0 +msgid "Generate" +msgstr "Genereer" + +#. module: account_banking_sepa_direct_debit +#: model:mail.message.subtype,description:account_banking_sepa_direct_debit.mandate_cancel +msgid "SEPA Direct Debit Mandate Cancelled" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: selection:banking.export.sdd,charge_bearer:0 +#: selection:banking.export.sdd.wizard,charge_bearer:0 +msgid "Borne by Debtor" +msgstr "Rekening van schuldenaar" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:212 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:218 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:224 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:232 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:239 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:245 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:253 +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:395 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:140 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:192 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:199 +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:209 +#, python-format +msgid "Error:" +msgstr "Fout:" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,message_ids:0 +msgid "Messages" +msgstr "Berichten" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,unique_mandate_reference:0 +msgid "Unique Mandate Reference" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: view:sdd.mandate:0 +#: selection:sdd.mandate,state:0 +msgid "Cancelled" +msgstr "Geannuleerd" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:141 +#, python-format +msgid "" +"Payment Type Code '%s' is not supported. The only Payment Type Code " +"supported for SEPA Direct Debit are 'pain.008.001.02', 'pain.008.001.03' and " +"'pain.008.001.04'." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: help:sdd.mandate,message_unread:0 +msgid "If checked new messages require your attention." +msgstr "Indien aangevinkt zullen nieuwe berichten uw aandacht vragen." + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd.wizard,file_id:0 +msgid "SDD File" +msgstr "SDD bestand" + +#. module: account_banking_sepa_direct_debit +#: model:mail.message.subtype,description:account_banking_sepa_direct_debit.mandate_expired +msgid "SEPA Direct Debit Mandate has Expired" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:246 +#, python-format +msgid "" +"The recurrent mandate '%s' which is not marked as 'Migrated to SEPA' must " +"have its recurrent sequence type set to 'First'." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: help:banking.export.sdd,charge_bearer:0 +#: help:banking.export.sdd.wizard,charge_bearer:0 +msgid "" +"Following service level : transaction charges are to be applied following " +"the rules agreed in the service level and/or scheme (SEPA Core messages must " +"use this). Shared : transaction charges on the creditor side are to be borne " +"by the creditor, transaction charges on the debtor side are to be borne by " +"the debtor. Borne by creditor : all transaction charges are to be borne by " +"the creditor. Borne by debtor : all transaction charges are to be borne by " +"the debtor." +msgstr "" +"Volg service level: Transactie kosten worden toegepast volgens de " +"afgesproken regels in het service level en/of schema (Voor SEPA berichten " +"deze gebruiken). Gedeeld : De transactiekosten aan de crediteur zijde zijn " +"voor de schuldenaar, transactiekosten aan de debiteur kant zijn voor de " +"schuldeiser. Rekening van de schuldenaar: Alle transactie kosten zijn voor " +"rekening van de schuldenaar. Rekening van de schuldeiser: Alle transactie " +"kosten zijn voor rekening van de schuldeiser." + +#. module: account_banking_sepa_direct_debit +#: view:sdd.mandate:0 +msgid "Reference" +msgstr "Referentie" + +#. module: account_banking_sepa_direct_debit +#: view:banking.export.sdd:0 +msgid "SEPA Direct Debit" +msgstr "SEPA Incasso (Direct Debit)" + +#. module: account_banking_sepa_direct_debit +#: view:banking.export.sdd.wizard:0 +msgid "SEPA Direct Debit XML file generation" +msgstr "SEPA Incasso XML bestand aanmaken" + +#. module: account_banking_sepa_direct_debit +#: help:sdd.mandate,message_summary:0 +msgid "" +"Holds the Chatter summary (number of messages, ...). This summary is " +"directly in html format in order to be inserted in kanban views." +msgstr "" +"Bevat de samenvatting van de chatter (aantal berichten,...). Deze " +"samenvatting is direct in html formaat om zo in de kanban weergave te worden " +"ingevoegd." + +#. module: account_banking_sepa_direct_debit +#: model:ir.model,name:account_banking_sepa_direct_debit.model_payment_line +msgid "Payment Line" +msgstr "Betaalregel" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd,create_date:0 +msgid "Generation Date" +msgstr "Aangemaakt op" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:396 +#, python-format +msgid "" +"The payment line with reference '%s' has the bank account '%s' which is not " +"attached to the mandate '%s' (this mandate is attached to the bank account " +"'%s')." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: selection:banking.export.sdd.wizard,state:0 +msgid "Create" +msgstr "Aanmaken" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd,nb_transactions:0 +#: field:banking.export.sdd.wizard,nb_transactions:0 +msgid "Number of Transactions" +msgstr "Aantal transacties" + +#. module: account_banking_sepa_direct_debit +#: view:sdd.mandate:0 +#: selection:sdd.mandate,type:0 +msgid "One-Off" +msgstr "Eenmalig" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd,state:0 +#: field:banking.export.sdd.wizard,state:0 +msgid "State" +msgstr "Status" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:240 +#, python-format +msgid "The recurrent mandate '%s' must have a sequence type." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,message_follower_ids:0 +msgid "Followers" +msgstr "Volgers" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,message_unread:0 +msgid "Unread Messages" +msgstr "Ongelezen berichten" + +#. module: account_banking_sepa_direct_debit +#: view:banking.export.sdd:0 +#: field:banking.export.sdd,payment_order_ids:0 +#: field:banking.export.sdd.wizard,payment_order_ids:0 +msgid "Payment Orders" +msgstr "Betaalopdrachten" + +#. module: account_banking_sepa_direct_debit +#: view:sdd.mandate:0 +msgid "Type" +msgstr "Soort" + +#. module: account_banking_sepa_direct_debit +#: selection:banking.export.sdd,state:0 +msgid "Sent" +msgstr "Verstuurd" + +#. module: account_banking_sepa_direct_debit +#: field:res.company,original_creditor_identifier:0 +msgid "Original Creditor Identifier" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: selection:sdd.mandate,recurrent_sequence_type:0 +msgid "Recurring" +msgstr "Terugkerend" + +#. module: account_banking_sepa_direct_debit +#: help:res.company,sepa_creditor_identifier:0 +msgid "" +"Enter the Creditor Identifier that has been attributed to your company to " +"make SEPA Direct Debits. This identifier is composed of :\n" +"- your country ISO code (2 letters)\n" +"- a 2-digits checkum\n" +"- a 3-letters business code\n" +"- a country-specific identifier" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: sql_constraint:sdd.mandate:0 +msgid "A Mandate with the same reference already exists for this company !" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: help:sdd.mandate,state:0 +msgid "" +"Only valid mandates can be used in a payment line. A cancelled mandate is a " +"mandate that has been cancelled by the customer. A one-off mandate expires " +"after its first use. A recurrent mandate expires after it's final use or if " +"it hasn't been used for 36 months." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: help:sdd.mandate,recurrent_sequence_type:0 +msgid "" +"This field is only used for Recurrent mandates, not for One-Off mandates." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:213 +#, python-format +msgid "The date of signature of mandate '%s' is in the future !" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: view:sdd.mandate:0 +msgid "Signature Date" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd,charge_bearer:0 +#: field:banking.export.sdd.wizard,charge_bearer:0 +msgid "Charge Bearer" +msgstr "Kostenverdeling" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,partner_id:0 +msgid "Partner" +msgstr "Relatie" + +#. module: account_banking_sepa_direct_debit +#: selection:sdd.mandate,recurrent_sequence_type:0 +msgid "First" +msgstr "Eerste" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,signature_date:0 +msgid "Date of Signature of the Mandate" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: model:mail.message.subtype,name:account_banking_sepa_direct_debit.mandate_cancel +msgid "Mandate Cancelled" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: model:ir.actions.act_window,name:account_banking_sepa_direct_debit.act_banking_export_sdd_payment_order +msgid "Generated SEPA Direct Debit Files" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: help:sdd.mandate,sepa_migrated:0 +msgid "" +"If this field is not active, the mandate section of the next direct debit " +"file that include this mandate will contain the 'Original Mandate " +"Identification' and the 'Original Creditor Scheme Identification'. This is " +"required in a few countries (Belgium for instance), but not in all " +"countries. If this is not required in your country, you should keep this " +"field always active." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,company_id:0 +msgid "Company" +msgstr "Bedijf" + +#. module: account_banking_sepa_direct_debit +#: model:ir.model,name:account_banking_sepa_direct_debit.model_banking_export_sdd_wizard +msgid "Export SEPA Direct Debit File" +msgstr "Exporteer SEPA incasso bestand" + +#. module: account_banking_sepa_direct_debit +#: help:banking.export.sdd,batch_booking:0 +#: help:banking.export.sdd.wizard,batch_booking:0 +msgid "" +"If true, the bank statement will display only one credit line for all the " +"direct debits of the SEPA file ; if false, the bank statement will display " +"one credit line per direct debit of the SEPA file." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:225 +#, python-format +msgid "" +"Cannot validate the mandate '%s' because it is not attached to a bank " +"account." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: selection:banking.export.sdd,state:0 +#: view:sdd.mandate:0 +#: selection:sdd.mandate,state:0 +msgid "Draft" +msgstr "Concept" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:290 +#, python-format +msgid "Mandate update" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: selection:banking.export.sdd,charge_bearer:0 +#: selection:banking.export.sdd.wizard,charge_bearer:0 +msgid "Shared" +msgstr "Gedeeld" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd,batch_booking:0 +#: field:banking.export.sdd.wizard,batch_booking:0 +msgid "Batch Booking" +msgstr "Bach verwerking" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,sepa_migrated:0 +msgid "Migrated to SEPA" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,state:0 +msgid "Status" +msgstr "Status" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd,total_amount:0 +#: field:banking.export.sdd.wizard,total_amount:0 +msgid "Total Amount" +msgstr "Totaalbedrag" + +#. module: account_banking_sepa_direct_debit +#: model:ir.actions.act_window,name:account_banking_sepa_direct_debit.action_account_banking_sdd +#: model:ir.ui.menu,name:account_banking_sepa_direct_debit.menu_account_banking_sdd +msgid "SEPA Direct Debit Files" +msgstr "SEPA incasso bestanden" + +#. module: account_banking_sepa_direct_debit +#: selection:banking.export.sdd,charge_bearer:0 +#: selection:banking.export.sdd.wizard,charge_bearer:0 +msgid "Following Service Level" +msgstr "Volg service level" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:233 +#, python-format +msgid "" +"The mandate '%s' can't have a date of last debit before the date of " +"signature." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: model:mail.message.subtype,description:account_banking_sepa_direct_debit.recurrent_sequence_type_final +#: model:mail.message.subtype,name:account_banking_sepa_direct_debit.recurrent_sequence_type_final +msgid "Sequence Type set to Final" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,message_is_follower:0 +msgid "Is a Follower" +msgstr "Is een volger" + +#. module: account_banking_sepa_direct_debit +#: help:sdd.mandate,original_mandate_identification:0 +msgid "" +"When the field 'Migrated to SEPA' is not active, this field will be used as " +"the Original Mandate Identification in the Direct Debit file." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: view:payment.order:0 +msgid "SDD Mandate" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,original_mandate_identification:0 +msgid "Original Mandate Identification" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: model:ir.model,name:account_banking_sepa_direct_debit.model_res_company +msgid "Companies" +msgstr "Bedrijven" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,message_summary:0 +msgid "Summary" +msgstr "Samenvatting" + +#. module: account_banking_sepa_direct_debit +#: model:res.groups,name:account_banking_sepa_direct_debit.group_original_mandate_required +msgid "Original Mandate Required (SEPA)" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:account.invoice,sdd_mandate_id:0 +#: model:ir.model,name:account_banking_sepa_direct_debit.model_sdd_mandate +#: field:payment.line,sdd_mandate_id:0 +#: view:sdd.mandate:0 +msgid "SEPA Direct Debit Mandate" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:193 +#, python-format +msgid "" +"Missing SEPA Direct Debit mandate on the payment line with partner '%s' and " +"Invoice ref '%s'." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:210 +#, python-format +msgid "" +"The mandate with reference '%s' for partner '%s' has type set to 'One-Off' " +"and it has a last debit date set to '%s', so we can't use it." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,scan:0 +msgid "Scan of the Mandate" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,last_debit_date:0 +msgid "Date of the Last Debit" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: model:mail.message.subtype,name:account_banking_sepa_direct_debit.mandate_expired +msgid "Mandate Expired" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: constraint:res.company:0 +msgid "Invalid SEPA Creditor Identifier." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: model:ir.model,name:account_banking_sepa_direct_debit.model_res_partner_bank +msgid "Bank Accounts" +msgstr "Bankrekeningen" + +#. module: account_banking_sepa_direct_debit +#: model:ir.actions.act_window,help:account_banking_sepa_direct_debit.sdd_mandate_action +msgid "" +"

\n" +" Click to create a new SEPA Direct Debit Mandate.\n" +"

\n" +" A SEPA Direct Debit Mandate is a document signed by your customer " +"that gives you the autorization to do one or several direct debits on his " +"bank account.\n" +"

\n" +" " +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: view:banking.export.sdd:0 +msgid "General Information" +msgstr "Algemene informatie" + +#. module: account_banking_sepa_direct_debit +#: view:sdd.mandate:0 +#: selection:sdd.mandate,state:0 +msgid "Valid" +msgstr "Geldig" + +#. module: account_banking_sepa_direct_debit +#: model:ir.model,name:account_banking_sepa_direct_debit.model_account_invoice +msgid "Invoice" +msgstr "Factuur" + +#. module: account_banking_sepa_direct_debit +#: view:banking.export.sdd.wizard:0 +#: view:sdd.mandate:0 +msgid "Cancel" +msgstr "Annuleer" + +#. module: account_banking_sepa_direct_debit +#: view:sdd.mandate:0 +#: field:sdd.mandate,payment_line_ids:0 +msgid "Related Payment Lines" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: view:sdd.mandate:0 +#: selection:sdd.mandate,type:0 +msgid "Recurrent" +msgstr "Terugkerend" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,type:0 +msgid "Type of Mandate" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: model:mail.message.subtype,name:account_banking_sepa_direct_debit.mandate_valid +msgid "Mandate Validated" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd,file:0 +msgid "SEPA File" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:res.company,sepa_creditor_identifier:0 +msgid "SEPA Creditor Identifier" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: model:ir.model,name:account_banking_sepa_direct_debit.model_banking_export_sdd +msgid "SEPA Direct Debit export" +msgstr "SEPA incasso export" + +#. module: account_banking_sepa_direct_debit +#: view:sdd.mandate:0 +#: selection:sdd.mandate,state:0 +msgid "Expired" +msgstr "Verlopen" + +#. module: account_banking_sepa_direct_debit +#: field:sdd.mandate,partner_bank_id:0 +msgid "Bank Account" +msgstr "Bankrekening" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:254 +#, python-format +msgid "" +"You must set the 'Original Mandate Identification' on the recurrent mandate " +"'%s' which is not marked as 'Migrated to SEPA'." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: model:mail.message.subtype,description:account_banking_sepa_direct_debit.recurrent_sequence_type_first +#: model:mail.message.subtype,name:account_banking_sepa_direct_debit.recurrent_sequence_type_first +msgid "Sequence Type set to First" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:291 +#, python-format +msgid "" +"As you changed the bank account attached to this mandate, the 'Sequence " +"Type' has been set back to 'First'." +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: help:sdd.mandate,message_ids:0 +msgid "Messages and communication history" +msgstr "Berichten en communicatie historie" + +#. module: account_banking_sepa_direct_debit +#: view:sdd.mandate:0 +msgid "Search SEPA Direct Debit Mandates" +msgstr "" + +#. module: account_banking_sepa_direct_debit +#: field:banking.export.sdd.wizard,file:0 +msgid "File" +msgstr "Bestand" From 5154e3488f05433355c0b68b428f0c63167738dd Mon Sep 17 00:00:00 2001 From: Launchpad Translations on behalf of banking-addons-team Date: Tue, 11 Feb 2014 06:47:45 +0000 Subject: [PATCH 42/43] Launchpad automatic translations update. --- account_bank_statement_tax/i18n/hu.po | 4 ++-- account_bank_statement_tax/i18n/nl.po | 4 ++-- account_bank_statement_tax/i18n/pt_BR.po | 4 ++-- account_banking/i18n/da.po | 4 ++-- account_banking/i18n/en.po | 4 ++-- account_banking/i18n/es_ES.po | 4 ++-- account_banking/i18n/hr.po | 4 ++-- account_banking/i18n/hu.po | 4 ++-- account_banking/i18n/nb.po | 4 ++-- account_banking/i18n/nl.po | 4 ++-- account_banking/i18n/pt_BR.po | 4 ++-- account_banking/i18n/ro.po | 4 ++-- account_banking/i18n/tr.po | 4 ++-- account_banking_fi_patu/i18n/nl.po | 4 ++-- account_banking_fi_patu/i18n/pt_BR.po | 4 ++-- account_banking_nl_abnamro/i18n/en.po | 4 ++-- account_banking_nl_abnamro/i18n/nl.po | 4 ++-- account_banking_nl_clieop/i18n/da.po | 4 ++-- account_banking_nl_clieop/i18n/en.po | 4 ++-- account_banking_nl_clieop/i18n/nl.po | 4 ++-- account_banking_nl_clieop/i18n/tr.po | 4 ++-- account_banking_nl_girotel/i18n/en.po | 4 ++-- account_banking_nl_girotel/i18n/nl.po | 4 ++-- account_banking_nl_girotel/i18n/pt_BR.po | 4 ++-- account_banking_nl_ing/i18n/nl.po | 4 ++-- account_banking_nl_ing/i18n/pt_BR.po | 4 ++-- account_banking_nl_multibank/i18n/en.po | 4 ++-- account_banking_nl_multibank/i18n/nl.po | 4 ++-- account_banking_nl_multibank/i18n/pt_BR.po | 4 ++-- account_banking_nl_triodos/i18n/en.po | 4 ++-- account_banking_nl_triodos/i18n/nl.po | 4 ++-- account_banking_nl_triodos/i18n/pt_BR.po | 4 ++-- account_banking_pain_base/i18n/fr.po | 2 +- account_banking_pain_base/i18n/nl.po | 2 +- account_banking_partner_journal_account/i18n/nl.po | 4 ++-- account_banking_payment/i18n/nl.po | 4 ++-- account_banking_payment_export/i18n/nl.po | 4 ++-- account_banking_sepa_credit_transfer/i18n/fr.po | 2 +- account_banking_sepa_credit_transfer/i18n/nl.po | 2 +- account_banking_sepa_direct_debit/i18n/fr.po | 2 +- account_banking_sepa_direct_debit/i18n/nl.po | 2 +- account_direct_debit/i18n/nl.po | 4 ++-- account_iban_preserve_domestic/i18n/nl.po | 4 ++-- account_iban_preserve_domestic/i18n/pt_BR.po | 4 ++-- base_iban_bic_not_required/i18n/nl.po | 4 ++-- base_iban_bic_not_required/i18n/pt_BR.po | 4 ++-- 46 files changed, 86 insertions(+), 86 deletions(-) diff --git a/account_bank_statement_tax/i18n/hu.po b/account_bank_statement_tax/i18n/hu.po index 86bdf7e2e..1527497e1 100644 --- a/account_bank_statement_tax/i18n/hu.po +++ b/account_bank_statement_tax/i18n/hu.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-01-14 06:52+0000\n" -"X-Generator: Launchpad (build 16890)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_bank_statement_tax #: model:ir.model,name:account_bank_statement_tax.model_account_bank_statement_line diff --git a/account_bank_statement_tax/i18n/nl.po b/account_bank_statement_tax/i18n/nl.po index c0a570951..1709dae7a 100644 --- a/account_bank_statement_tax/i18n/nl.po +++ b/account_bank_statement_tax/i18n/nl.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-11-12 06:38+0000\n" -"X-Generator: Launchpad (build 16820)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_bank_statement_tax #: model:ir.model,name:account_bank_statement_tax.model_account_bank_statement_line diff --git a/account_bank_statement_tax/i18n/pt_BR.po b/account_bank_statement_tax/i18n/pt_BR.po index 6e586bbbc..13ca3865b 100644 --- a/account_bank_statement_tax/i18n/pt_BR.po +++ b/account_bank_statement_tax/i18n/pt_BR.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-12-26 06:28+0000\n" -"X-Generator: Launchpad (build 16877)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_bank_statement_tax #: model:ir.model,name:account_bank_statement_tax.model_account_bank_statement_line diff --git a/account_banking/i18n/da.po b/account_banking/i18n/da.po index 7048f3df1..bb8b10922 100644 --- a/account_banking/i18n/da.po +++ b/account_banking/i18n/da.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-11-12 06:38+0000\n" -"X-Generator: Launchpad (build 16820)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_banking #: field:account.bank.statement.line,reconcile_id:0 diff --git a/account_banking/i18n/en.po b/account_banking/i18n/en.po index 8d37203da..baddfde14 100644 --- a/account_banking/i18n/en.po +++ b/account_banking/i18n/en.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-11-12 06:38+0000\n" -"X-Generator: Launchpad (build 16820)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_banking #: field:account.bank.statement.line,reconcile_id:0 diff --git a/account_banking/i18n/es_ES.po b/account_banking/i18n/es_ES.po index 42fcb9d6d..6407110c9 100644 --- a/account_banking/i18n/es_ES.po +++ b/account_banking/i18n/es_ES.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-11-12 06:38+0000\n" -"X-Generator: Launchpad (build 16820)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_banking #: field:account.bank.statement.line,reconcile_id:0 diff --git a/account_banking/i18n/hr.po b/account_banking/i18n/hr.po index 2e54757af..79c8ddf76 100644 --- a/account_banking/i18n/hr.po +++ b/account_banking/i18n/hr.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-11-12 06:38+0000\n" -"X-Generator: Launchpad (build 16820)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_banking #: field:account.bank.statement.line,reconcile_id:0 diff --git a/account_banking/i18n/hu.po b/account_banking/i18n/hu.po index c0ff7bf72..53947252d 100644 --- a/account_banking/i18n/hu.po +++ b/account_banking/i18n/hu.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-01-27 05:50+0000\n" -"X-Generator: Launchpad (build 16914)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_banking #: field:account.bank.statement.line,reconcile_id:0 diff --git a/account_banking/i18n/nb.po b/account_banking/i18n/nb.po index e0bdcb2a3..880140043 100644 --- a/account_banking/i18n/nb.po +++ b/account_banking/i18n/nb.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-11-12 06:38+0000\n" -"X-Generator: Launchpad (build 16820)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_banking #: field:account.bank.statement.line,reconcile_id:0 diff --git a/account_banking/i18n/nl.po b/account_banking/i18n/nl.po index b7045906e..5c6d4c205 100644 --- a/account_banking/i18n/nl.po +++ b/account_banking/i18n/nl.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-12-04 05:59+0000\n" -"X-Generator: Launchpad (build 16861)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_banking #: field:account.bank.statement.line,reconcile_id:0 diff --git a/account_banking/i18n/pt_BR.po b/account_banking/i18n/pt_BR.po index f71eb0650..f0c1d32e2 100644 --- a/account_banking/i18n/pt_BR.po +++ b/account_banking/i18n/pt_BR.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-12-26 06:28+0000\n" -"X-Generator: Launchpad (build 16877)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_banking #: field:account.bank.statement.line,reconcile_id:0 diff --git a/account_banking/i18n/ro.po b/account_banking/i18n/ro.po index 32b66557f..2be8848a4 100644 --- a/account_banking/i18n/ro.po +++ b/account_banking/i18n/ro.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-11-12 06:38+0000\n" -"X-Generator: Launchpad (build 16820)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_banking #: field:account.bank.statement.line,reconcile_id:0 diff --git a/account_banking/i18n/tr.po b/account_banking/i18n/tr.po index e91c3654a..9c9325beb 100644 --- a/account_banking/i18n/tr.po +++ b/account_banking/i18n/tr.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-11-12 06:38+0000\n" -"X-Generator: Launchpad (build 16820)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_banking #: field:account.bank.statement.line,reconcile_id:0 diff --git a/account_banking_fi_patu/i18n/nl.po b/account_banking_fi_patu/i18n/nl.po index defb36a99..7a909b75e 100644 --- a/account_banking_fi_patu/i18n/nl.po +++ b/account_banking_fi_patu/i18n/nl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-12-04 05:59+0000\n" -"X-Generator: Launchpad (build 16861)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_banking_fi_patu #: code:addons/account_banking_fi_patu/patu.py:115 diff --git a/account_banking_fi_patu/i18n/pt_BR.po b/account_banking_fi_patu/i18n/pt_BR.po index af5f6848e..2a393d638 100644 --- a/account_banking_fi_patu/i18n/pt_BR.po +++ b/account_banking_fi_patu/i18n/pt_BR.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-12-26 06:28+0000\n" -"X-Generator: Launchpad (build 16877)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_banking_fi_patu #: code:addons/account_banking_fi_patu/patu.py:115 diff --git a/account_banking_nl_abnamro/i18n/en.po b/account_banking_nl_abnamro/i18n/en.po index 4fcb1e3c8..69da64ad0 100644 --- a/account_banking_nl_abnamro/i18n/en.po +++ b/account_banking_nl_abnamro/i18n/en.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-11-12 06:38+0000\n" -"X-Generator: Launchpad (build 16820)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_banking_nl_abnamro #: code:addons/account_banking_nl_abnamro/abnamro.py:122 diff --git a/account_banking_nl_abnamro/i18n/nl.po b/account_banking_nl_abnamro/i18n/nl.po index 85384510b..381942861 100644 --- a/account_banking_nl_abnamro/i18n/nl.po +++ b/account_banking_nl_abnamro/i18n/nl.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-12-04 05:59+0000\n" -"X-Generator: Launchpad (build 16861)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_banking_nl_abnamro #: code:addons/account_banking_nl_abnamro/abnamro.py:122 diff --git a/account_banking_nl_clieop/i18n/da.po b/account_banking_nl_clieop/i18n/da.po index 35952c016..7f37a8c4a 100644 --- a/account_banking_nl_clieop/i18n/da.po +++ b/account_banking_nl_clieop/i18n/da.po @@ -14,7 +14,7 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-11-12 06:38+0000\n" -"X-Generator: Launchpad (build 16820)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" diff --git a/account_banking_nl_clieop/i18n/en.po b/account_banking_nl_clieop/i18n/en.po index ce2258ac7..9872230d7 100644 --- a/account_banking_nl_clieop/i18n/en.po +++ b/account_banking_nl_clieop/i18n/en.po @@ -13,7 +13,7 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-11-12 06:38+0000\n" -"X-Generator: Launchpad (build 16820)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" diff --git a/account_banking_nl_clieop/i18n/nl.po b/account_banking_nl_clieop/i18n/nl.po index ab1760470..8cc5c4d2d 100644 --- a/account_banking_nl_clieop/i18n/nl.po +++ b/account_banking_nl_clieop/i18n/nl.po @@ -13,7 +13,7 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-11-12 06:38+0000\n" -"X-Generator: Launchpad (build 16820)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" diff --git a/account_banking_nl_clieop/i18n/tr.po b/account_banking_nl_clieop/i18n/tr.po index eb9addddc..de3d61ca4 100644 --- a/account_banking_nl_clieop/i18n/tr.po +++ b/account_banking_nl_clieop/i18n/tr.po @@ -14,7 +14,7 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-11-12 06:38+0000\n" -"X-Generator: Launchpad (build 16820)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" diff --git a/account_banking_nl_girotel/i18n/en.po b/account_banking_nl_girotel/i18n/en.po index 7081fa9f3..1af16775b 100644 --- a/account_banking_nl_girotel/i18n/en.po +++ b/account_banking_nl_girotel/i18n/en.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-11-12 06:38+0000\n" -"X-Generator: Launchpad (build 16820)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_banking_nl_girotel #: code:addons/account_banking_nl_girotel/girotel.py:325 diff --git a/account_banking_nl_girotel/i18n/nl.po b/account_banking_nl_girotel/i18n/nl.po index b5dd129da..5cd9e3067 100644 --- a/account_banking_nl_girotel/i18n/nl.po +++ b/account_banking_nl_girotel/i18n/nl.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-12-03 06:20+0000\n" -"X-Generator: Launchpad (build 16856)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_banking_nl_girotel #: code:addons/account_banking_nl_girotel/girotel.py:325 diff --git a/account_banking_nl_girotel/i18n/pt_BR.po b/account_banking_nl_girotel/i18n/pt_BR.po index 3967bc9db..2faa21a20 100644 --- a/account_banking_nl_girotel/i18n/pt_BR.po +++ b/account_banking_nl_girotel/i18n/pt_BR.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-12-26 06:28+0000\n" -"X-Generator: Launchpad (build 16877)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_banking_nl_girotel #: code:addons/account_banking_nl_girotel/girotel.py:325 diff --git a/account_banking_nl_ing/i18n/nl.po b/account_banking_nl_ing/i18n/nl.po index 9de589d62..6f5b2f1b9 100644 --- a/account_banking_nl_ing/i18n/nl.po +++ b/account_banking_nl_ing/i18n/nl.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-12-04 05:59+0000\n" -"X-Generator: Launchpad (build 16861)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_banking_nl_ing #: code:addons/account_banking_nl_ing/ing.py:257 diff --git a/account_banking_nl_ing/i18n/pt_BR.po b/account_banking_nl_ing/i18n/pt_BR.po index 38e21d261..3c8780e1f 100644 --- a/account_banking_nl_ing/i18n/pt_BR.po +++ b/account_banking_nl_ing/i18n/pt_BR.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-12-26 06:28+0000\n" -"X-Generator: Launchpad (build 16877)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_banking_nl_ing #: code:addons/account_banking_nl_ing/ing.py:257 diff --git a/account_banking_nl_multibank/i18n/en.po b/account_banking_nl_multibank/i18n/en.po index 742760baa..79630c748 100644 --- a/account_banking_nl_multibank/i18n/en.po +++ b/account_banking_nl_multibank/i18n/en.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-11-12 06:38+0000\n" -"X-Generator: Launchpad (build 16820)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_banking_nl_multibank #: code:addons/account_banking_nl_multibank/multibank.py:292 diff --git a/account_banking_nl_multibank/i18n/nl.po b/account_banking_nl_multibank/i18n/nl.po index 67244e7df..1667ba56f 100644 --- a/account_banking_nl_multibank/i18n/nl.po +++ b/account_banking_nl_multibank/i18n/nl.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-12-04 05:59+0000\n" -"X-Generator: Launchpad (build 16861)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_banking_nl_multibank #: code:addons/account_banking_nl_multibank/multibank.py:292 diff --git a/account_banking_nl_multibank/i18n/pt_BR.po b/account_banking_nl_multibank/i18n/pt_BR.po index aedc13084..3e9bb535e 100644 --- a/account_banking_nl_multibank/i18n/pt_BR.po +++ b/account_banking_nl_multibank/i18n/pt_BR.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-12-26 06:28+0000\n" -"X-Generator: Launchpad (build 16877)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_banking_nl_multibank #: code:addons/account_banking_nl_multibank/multibank.py:292 diff --git a/account_banking_nl_triodos/i18n/en.po b/account_banking_nl_triodos/i18n/en.po index 4f25a95a8..1352bea75 100644 --- a/account_banking_nl_triodos/i18n/en.po +++ b/account_banking_nl_triodos/i18n/en.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-11-12 06:38+0000\n" -"X-Generator: Launchpad (build 16820)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_banking_nl_triodos #: code:addons/account_banking_nl_triodos/triodos.py:183 diff --git a/account_banking_nl_triodos/i18n/nl.po b/account_banking_nl_triodos/i18n/nl.po index f8671ba52..822d181f4 100644 --- a/account_banking_nl_triodos/i18n/nl.po +++ b/account_banking_nl_triodos/i18n/nl.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-12-04 05:59+0000\n" -"X-Generator: Launchpad (build 16861)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_banking_nl_triodos #: code:addons/account_banking_nl_triodos/triodos.py:183 diff --git a/account_banking_nl_triodos/i18n/pt_BR.po b/account_banking_nl_triodos/i18n/pt_BR.po index 8b0a8b80b..121b958ff 100644 --- a/account_banking_nl_triodos/i18n/pt_BR.po +++ b/account_banking_nl_triodos/i18n/pt_BR.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-12-26 06:28+0000\n" -"X-Generator: Launchpad (build 16877)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_banking_nl_triodos #: code:addons/account_banking_nl_triodos/triodos.py:183 diff --git a/account_banking_pain_base/i18n/fr.po b/account_banking_pain_base/i18n/fr.po index 472d9b59e..360bff594 100644 --- a/account_banking_pain_base/i18n/fr.po +++ b/account_banking_pain_base/i18n/fr.po @@ -13,7 +13,7 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-02-02 06:05+0000\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" "X-Generator: Launchpad (build 16916)\n" #. module: account_banking_pain_base diff --git a/account_banking_pain_base/i18n/nl.po b/account_banking_pain_base/i18n/nl.po index 9d295b72c..f62c839e3 100644 --- a/account_banking_pain_base/i18n/nl.po +++ b/account_banking_pain_base/i18n/nl.po @@ -14,7 +14,7 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-02-02 06:05+0000\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" "X-Generator: Launchpad (build 16916)\n" #. module: account_banking_pain_base diff --git a/account_banking_partner_journal_account/i18n/nl.po b/account_banking_partner_journal_account/i18n/nl.po index 4ce17dba1..d00d02222 100644 --- a/account_banking_partner_journal_account/i18n/nl.po +++ b/account_banking_partner_journal_account/i18n/nl.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-01-08 05:43+0000\n" -"X-Generator: Launchpad (build 16877)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_banking_partner_journal_account #: model:ir.model,name:account_banking_partner_journal_account.model_res_partner diff --git a/account_banking_payment/i18n/nl.po b/account_banking_payment/i18n/nl.po index 60fbc1f9d..862d66b0f 100644 --- a/account_banking_payment/i18n/nl.po +++ b/account_banking_payment/i18n/nl.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-12-04 05:59+0000\n" -"X-Generator: Launchpad (build 16861)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_banking_payment #: model:ir.model,name:account_banking_payment.model_payment_order_create diff --git a/account_banking_payment_export/i18n/nl.po b/account_banking_payment_export/i18n/nl.po index b9f763e5d..615d1938b 100644 --- a/account_banking_payment_export/i18n/nl.po +++ b/account_banking_payment_export/i18n/nl.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-12-04 05:59+0000\n" -"X-Generator: Launchpad (build 16861)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_banking_payment_export #: help:payment.mode.type,name:0 diff --git a/account_banking_sepa_credit_transfer/i18n/fr.po b/account_banking_sepa_credit_transfer/i18n/fr.po index 52a299b2e..7c3e39b02 100644 --- a/account_banking_sepa_credit_transfer/i18n/fr.po +++ b/account_banking_sepa_credit_transfer/i18n/fr.po @@ -13,7 +13,7 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-02-02 06:05+0000\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" "X-Generator: Launchpad (build 16916)\n" #. module: account_banking_sepa_credit_transfer diff --git a/account_banking_sepa_credit_transfer/i18n/nl.po b/account_banking_sepa_credit_transfer/i18n/nl.po index 7e53025fa..f20a91a56 100644 --- a/account_banking_sepa_credit_transfer/i18n/nl.po +++ b/account_banking_sepa_credit_transfer/i18n/nl.po @@ -13,7 +13,7 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-02-02 06:04+0000\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" "X-Generator: Launchpad (build 16916)\n" #. module: account_banking_sepa_credit_transfer diff --git a/account_banking_sepa_direct_debit/i18n/fr.po b/account_banking_sepa_direct_debit/i18n/fr.po index 76fb55d08..6620d99b0 100644 --- a/account_banking_sepa_direct_debit/i18n/fr.po +++ b/account_banking_sepa_direct_debit/i18n/fr.po @@ -13,7 +13,7 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-02-02 06:05+0000\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" "X-Generator: Launchpad (build 16916)\n" #. module: account_banking_sepa_direct_debit diff --git a/account_banking_sepa_direct_debit/i18n/nl.po b/account_banking_sepa_direct_debit/i18n/nl.po index 0666c4754..bbeea4847 100644 --- a/account_banking_sepa_direct_debit/i18n/nl.po +++ b/account_banking_sepa_direct_debit/i18n/nl.po @@ -14,7 +14,7 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-02-02 06:05+0000\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" "X-Generator: Launchpad (build 16916)\n" #. module: account_banking_sepa_direct_debit diff --git a/account_direct_debit/i18n/nl.po b/account_direct_debit/i18n/nl.po index 3fa63efc9..77e7b0b2d 100644 --- a/account_direct_debit/i18n/nl.po +++ b/account_direct_debit/i18n/nl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-12-04 05:59+0000\n" -"X-Generator: Launchpad (build 16861)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_direct_debit #: model:account.payment.term,note:account_direct_debit.payment_term_direct_debit diff --git a/account_iban_preserve_domestic/i18n/nl.po b/account_iban_preserve_domestic/i18n/nl.po index 655cc21f1..7ecd6b88e 100644 --- a/account_iban_preserve_domestic/i18n/nl.po +++ b/account_iban_preserve_domestic/i18n/nl.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-11-12 06:38+0000\n" -"X-Generator: Launchpad (build 16820)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_iban_preserve_domestic #: field:res.partner.bank,acc_number_domestic:0 diff --git a/account_iban_preserve_domestic/i18n/pt_BR.po b/account_iban_preserve_domestic/i18n/pt_BR.po index 29c8a8892..c925a3bff 100644 --- a/account_iban_preserve_domestic/i18n/pt_BR.po +++ b/account_iban_preserve_domestic/i18n/pt_BR.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-12-26 06:28+0000\n" -"X-Generator: Launchpad (build 16877)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: account_iban_preserve_domestic #: field:res.partner.bank,acc_number_domestic:0 diff --git a/base_iban_bic_not_required/i18n/nl.po b/base_iban_bic_not_required/i18n/nl.po index b0f8d77de..952a8fc47 100644 --- a/base_iban_bic_not_required/i18n/nl.po +++ b/base_iban_bic_not_required/i18n/nl.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-12-03 06:20+0000\n" -"X-Generator: Launchpad (build 16856)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: base_iban_bic_not_required #: constraint:res.partner.bank:0 diff --git a/base_iban_bic_not_required/i18n/pt_BR.po b/base_iban_bic_not_required/i18n/pt_BR.po index 0bc2c64cf..1f54e846c 100644 --- a/base_iban_bic_not_required/i18n/pt_BR.po +++ b/base_iban_bic_not_required/i18n/pt_BR.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-12-26 06:28+0000\n" -"X-Generator: Launchpad (build 16877)\n" +"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Generator: Launchpad (build 16916)\n" #. module: base_iban_bic_not_required #: constraint:res.partner.bank:0 From c3556c96f600a371d7afa91a8337ac4526490edb Mon Sep 17 00:00:00 2001 From: Launchpad Translations on behalf of banking-addons-team Date: Wed, 12 Feb 2014 06:27:48 +0000 Subject: [PATCH 43/43] Launchpad automatic translations update. --- account_banking_pain_base/i18n/nl.po | 29 ++-- account_banking_sepa_direct_debit/i18n/nl.po | 132 +++++++++++++------ 2 files changed, 114 insertions(+), 47 deletions(-) diff --git a/account_banking_pain_base/i18n/nl.po b/account_banking_pain_base/i18n/nl.po index f62c839e3..36e33db82 100644 --- a/account_banking_pain_base/i18n/nl.po +++ b/account_banking_pain_base/i18n/nl.po @@ -8,19 +8,19 @@ msgstr "" "Project-Id-Version: banking-addons\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2013-12-23 21:26+0000\n" -"PO-Revision-Date: 2014-02-01 07:45+0000\n" +"PO-Revision-Date: 2014-02-11 08:32+0000\n" "Last-Translator: Erwin van der Ploeg (BAS Solutions) \n" "Language-Team: Dutch \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Launchpad-Export-Date: 2014-02-12 06:27+0000\n" "X-Generator: Launchpad (build 16916)\n" #. module: account_banking_pain_base #: field:res.company,initiating_party_issuer:0 msgid "Initiating Party Issuer" -msgstr "" +msgstr "Initiating Party Issuer" #. module: account_banking_pain_base #: code:addons/account_banking_pain_base/banking_export_pain.py:122 @@ -57,6 +57,8 @@ msgid "" "This will be used as the 'Initiating Party Issuer' in the PAIN files " "generated by OpenERP." msgstr "" +"Dit wordt gebruikt als de 'Initiating Party Issuer' in de PAIN bestanden " +"gegenereerd door OpenERP." #. module: account_banking_pain_base #: code:addons/account_banking_pain_base/banking_export_pain.py:351 @@ -64,6 +66,8 @@ msgstr "" msgid "" "Missing 'Structured Communication Type' on payment line with reference '%s'." msgstr "" +"Ontbrekende 'Structured Communication Type' op betaalregel met referentie " +"'%s'." #. module: account_banking_pain_base #: selection:payment.line,priority:0 @@ -74,7 +78,7 @@ msgstr "Normaal" #: code:addons/account_banking_pain_base/banking_export_pain.py:70 #, python-format msgid "Cannot compute the '%s' of the Payment Line with reference '%s'." -msgstr "" +msgstr "Kan de '%s' niet berekenen van de betaalregel met referentie '%s'." #. module: account_banking_pain_base #: code:addons/account_banking_pain_base/banking_export_pain.py:77 @@ -86,7 +90,7 @@ msgstr "Kan de '%s' niet berekenen." #: code:addons/account_banking_pain_base/banking_export_pain.py:81 #, python-format msgid "The type of the field '%s' is %s. It should be a string or unicode." -msgstr "" +msgstr "Het type van veld '%s' is %s. Dit moet een string of unicode zijn." #. module: account_banking_pain_base #: code:addons/account_banking_pain_base/banking_export_pain.py:47 @@ -119,13 +123,13 @@ msgstr "Veld type fout:" #. module: account_banking_pain_base #: field:payment.line,struct_communication_type:0 msgid "Structured Communication Type" -msgstr "" +msgstr "Structured Communication Type" #. module: account_banking_pain_base #: code:addons/account_banking_pain_base/banking_export_pain.py:87 #, python-format msgid "The '%s' is empty or 0. It should have a non-null value." -msgstr "" +msgstr "De '%s' is leeg of 0. Deze waarde zou niet nul moeten zijn." #. module: account_banking_pain_base #: model:ir.model,name:account_banking_pain_base.model_banking_export_pain @@ -139,6 +143,9 @@ msgid "" "unaccented caracter, so that only ASCII caracters are used in the generated " "PAIN file." msgstr "" +"Indien aangevinkt, zal OpenERP elk geaccentueerde karakter omzetten in een " +"overeenkomstige ongeaccentueerde karakter, zodat alleen ASCII karakters " +"worden gebruikt in het gegenereerde PAIN bestand." #. module: account_banking_pain_base #: help:payment.line,priority:0 @@ -146,18 +153,20 @@ msgid "" "This field will be used as the 'Instruction Priority' in the generated PAIN " "file." msgstr "" +"Dit veld wordt gebruikt als de 'Instruction Priority' in het gegenereerde " +"PAIN bestand." #. module: account_banking_pain_base #: view:res.company:0 msgid "Payment Initiation" -msgstr "" +msgstr "Payment Initiation" #. module: account_banking_pain_base #: selection:payment.line,priority:0 msgid "High" -msgstr "" +msgstr "Hoog" #. module: account_banking_pain_base #: field:payment.mode,convert_to_ascii:0 msgid "Convert to ASCII" -msgstr "" +msgstr "Converteer naar ASCII" diff --git a/account_banking_sepa_direct_debit/i18n/nl.po b/account_banking_sepa_direct_debit/i18n/nl.po index bbeea4847..350697926 100644 --- a/account_banking_sepa_direct_debit/i18n/nl.po +++ b/account_banking_sepa_direct_debit/i18n/nl.po @@ -8,19 +8,19 @@ msgstr "" "Project-Id-Version: banking-addons\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2013-12-23 22:24+0000\n" -"PO-Revision-Date: 2014-02-01 07:52+0000\n" +"PO-Revision-Date: 2014-02-11 09:47+0000\n" "Last-Translator: Erwin van der Ploeg (BAS Solutions) \n" "Language-Team: Dutch \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n" +"X-Launchpad-Export-Date: 2014-02-12 06:27+0000\n" "X-Generator: Launchpad (build 16916)\n" #. module: account_banking_sepa_direct_debit #: model:mail.message.subtype,description:account_banking_sepa_direct_debit.mandate_valid msgid "SEPA Direct Debit Mandate Validated" -msgstr "" +msgstr "SEPA incasso machtiging bevestigd." #. module: account_banking_sepa_direct_debit #: field:banking.export.sdd,filename:0 @@ -35,12 +35,15 @@ msgid "" "The SEPA Direct Debit mandate with reference '%s' for partner '%s' has " "expired." msgstr "" +"De SEPA incasso machtiging met referentie '%s' voor relatie '%s' is verlopen." #. module: account_banking_sepa_direct_debit #: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:219 #, python-format msgid "Cannot validate the mandate '%s' without a date of signature." msgstr "" +"Het is niet mogelijk de machtiging '%s' te bevestigen zonder een datum van " +"ondertekenen." #. module: account_banking_sepa_direct_debit #: selection:sdd.mandate,recurrent_sequence_type:0 @@ -56,13 +59,13 @@ msgstr "Gereed" #: view:res.partner:0 #: view:res.partner.bank:0 msgid "SDD Mandates" -msgstr "" +msgstr "SDD machteging" #. module: account_banking_sepa_direct_debit #: constraint:payment.line:0 #: constraint:sdd.mandate:0 msgid "Error msg in raise" -msgstr "" +msgstr "Fout bericht" #. module: account_banking_sepa_direct_debit #: selection:banking.export.sdd,state:0 @@ -72,13 +75,13 @@ msgstr "Afgeletterd" #. module: account_banking_sepa_direct_debit #: field:sdd.mandate,recurrent_sequence_type:0 msgid "Sequence Type for Next Debit" -msgstr "" +msgstr "Reeks soort voor volgende incasso" #. module: account_banking_sepa_direct_debit #: selection:banking.export.sdd,charge_bearer:0 #: selection:banking.export.sdd.wizard,charge_bearer:0 msgid "Borne by Creditor" -msgstr "" +msgstr "Rekening van schuldeiser" #. module: account_banking_sepa_direct_debit #: model:ir.actions.act_window,name:account_banking_sepa_direct_debit.sdd_mandate_action @@ -86,7 +89,7 @@ msgstr "" #: view:res.partner.bank:0 #: field:res.partner.bank,sdd_mandate_ids:0 msgid "SEPA Direct Debit Mandates" -msgstr "" +msgstr "SEPA incasso machtegingen" #. module: account_banking_sepa_direct_debit #: view:banking.export.sdd.wizard:0 @@ -98,7 +101,7 @@ msgstr "Bevestigen" #: model:mail.message.subtype,description:account_banking_sepa_direct_debit.recurrent_sequence_type_recurring #: model:mail.message.subtype,name:account_banking_sepa_direct_debit.recurrent_sequence_type_recurring msgid "Sequence Type set to Recurring" -msgstr "" +msgstr "Reeks soort ingesteld op herhalend" #. module: account_banking_sepa_direct_debit #: view:banking.export.sdd.wizard:0 @@ -108,7 +111,7 @@ msgstr "Genereer" #. module: account_banking_sepa_direct_debit #: model:mail.message.subtype,description:account_banking_sepa_direct_debit.mandate_cancel msgid "SEPA Direct Debit Mandate Cancelled" -msgstr "" +msgstr "SEPA incasso machtegingen geannuleerd" #. module: account_banking_sepa_direct_debit #: selection:banking.export.sdd,charge_bearer:0 @@ -141,7 +144,7 @@ msgstr "Berichten" #. module: account_banking_sepa_direct_debit #: field:sdd.mandate,unique_mandate_reference:0 msgid "Unique Mandate Reference" -msgstr "" +msgstr "Unieke machtiging referentie" #. module: account_banking_sepa_direct_debit #: view:sdd.mandate:0 @@ -157,6 +160,9 @@ msgid "" "supported for SEPA Direct Debit are 'pain.008.001.02', 'pain.008.001.03' and " "'pain.008.001.04'." msgstr "" +"Betaal soort code '%s' wordt niet ondersteund. De enige betaalsoort code " +"ondersteund voor SEPA incasso's zijn 'pain.008.001.02', 'pain.008.001.03' en " +"'pain.008.001.04'." #. module: account_banking_sepa_direct_debit #: help:sdd.mandate,message_unread:0 @@ -171,7 +177,7 @@ msgstr "SDD bestand" #. module: account_banking_sepa_direct_debit #: model:mail.message.subtype,description:account_banking_sepa_direct_debit.mandate_expired msgid "SEPA Direct Debit Mandate has Expired" -msgstr "" +msgstr "SEPA Direct incasso machtiging is verlopen" #. module: account_banking_sepa_direct_debit #: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:246 @@ -180,6 +186,8 @@ msgid "" "The recurrent mandate '%s' which is not marked as 'Migrated to SEPA' must " "have its recurrent sequence type set to 'First'." msgstr "" +"Bij de herhalende machtiging '%s' welke niet is gemarkeerd als 'gemigreerd " +"naar SEPA' dient de reeks soort te worden ingesteld op 'Eerste'." #. module: account_banking_sepa_direct_debit #: help:banking.export.sdd,charge_bearer:0 @@ -244,6 +252,9 @@ msgid "" "attached to the mandate '%s' (this mandate is attached to the bank account " "'%s')." msgstr "" +"De betaalregel met referentie '%s' heeft het bankrekeningnummer '%s' welke " +"niet is gekoppeld aan de machtiging '%s' (deze machtiging is gekoppeld aan " +"bankrekening '%s')." #. module: account_banking_sepa_direct_debit #: selection:banking.export.sdd.wizard,state:0 @@ -272,7 +283,7 @@ msgstr "Status" #: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:240 #, python-format msgid "The recurrent mandate '%s' must have a sequence type." -msgstr "" +msgstr "De herhalende machtiging '%s' dient een reeks soort te hebben." #. module: account_banking_sepa_direct_debit #: field:sdd.mandate,message_follower_ids:0 @@ -304,7 +315,7 @@ msgstr "Verstuurd" #. module: account_banking_sepa_direct_debit #: field:res.company,original_creditor_identifier:0 msgid "Original Creditor Identifier" -msgstr "" +msgstr "Originele Incassant-ID" #. module: account_banking_sepa_direct_debit #: selection:sdd.mandate,recurrent_sequence_type:0 @@ -321,11 +332,17 @@ msgid "" "- a 3-letters business code\n" "- a country-specific identifier" msgstr "" +"Geef de Incassant-ID in, welke is toegewezen aan uw bedrijf om incasso's uit " +"te voeren. De Incassant-ID is samengesteld uit:\n" +"- uw ISO landcode (2 letters)\n" +"- een 2 cijferig controlegetal\n" +"- een 3 cijferig business code\n" +"- een landspecifieke identifier" #. module: account_banking_sepa_direct_debit #: sql_constraint:sdd.mandate:0 msgid "A Mandate with the same reference already exists for this company !" -msgstr "" +msgstr "Een machtiging met dezelfde referentie bestaat al vooR dit bedrijf!" #. module: account_banking_sepa_direct_debit #: help:sdd.mandate,state:0 @@ -335,23 +352,31 @@ msgid "" "after its first use. A recurrent mandate expires after it's final use or if " "it hasn't been used for 36 months." msgstr "" +"Alleen geldige machtigingen kunnen worden gebruikt op betaalregels. Een " +"geannuleerde machtiging is een machtiging welke is geannuleerd door de " +"klant. Een eenmalige machtiging verloopt na eenmalig gebruik. Een herhalende " +"machtiging verloopt na zijn laatste gebruik of als deze niet is gebruikt " +"voor 36 maanden." #. module: account_banking_sepa_direct_debit #: help:sdd.mandate,recurrent_sequence_type:0 msgid "" "This field is only used for Recurrent mandates, not for One-Off mandates." msgstr "" +"Dit veld wordt alleen gebruikt voor herhalende machtigingen, niet voor een " +"eenmalige machtiging." #. module: account_banking_sepa_direct_debit #: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:213 #, python-format msgid "The date of signature of mandate '%s' is in the future !" msgstr "" +"De datum van de handtekening van de machtiging '%s' is in de toekomst!" #. module: account_banking_sepa_direct_debit #: view:sdd.mandate:0 msgid "Signature Date" -msgstr "" +msgstr "Handtekening datum" #. module: account_banking_sepa_direct_debit #: field:banking.export.sdd,charge_bearer:0 @@ -372,17 +397,17 @@ msgstr "Eerste" #. module: account_banking_sepa_direct_debit #: field:sdd.mandate,signature_date:0 msgid "Date of Signature of the Mandate" -msgstr "" +msgstr "Datum avn de handtekening van de machtiging" #. module: account_banking_sepa_direct_debit #: model:mail.message.subtype,name:account_banking_sepa_direct_debit.mandate_cancel msgid "Mandate Cancelled" -msgstr "" +msgstr "Machtiging geannuleerd" #. module: account_banking_sepa_direct_debit #: model:ir.actions.act_window,name:account_banking_sepa_direct_debit.act_banking_export_sdd_payment_order msgid "Generated SEPA Direct Debit Files" -msgstr "" +msgstr "Genereerde SEPA incasso bestanden" #. module: account_banking_sepa_direct_debit #: help:sdd.mandate,sepa_migrated:0 @@ -394,6 +419,12 @@ msgid "" "countries. If this is not required in your country, you should keep this " "field always active." msgstr "" +"Indien niet aangevinkt, zal het machtiging gedeelte van het volgende incasso " +"bestand, dat deze machtiging bevat, de 'Originele machtiging identificatie' " +"en de 'Origineel schuldeiser identificatie' bevatten. Dit is verplicht in " +"een aantal landen (zoals bijvoorbeeld België), maar niet in alle landen. " +"Indien dit niet verplicht is in uw land, dient u dit veld altijd aangevinkt " +"te houden." #. module: account_banking_sepa_direct_debit #: field:sdd.mandate,company_id:0 @@ -413,6 +444,9 @@ msgid "" "direct debits of the SEPA file ; if false, the bank statement will display " "one credit line per direct debit of the SEPA file." msgstr "" +"Indien aangevinkt, zal het bankafschrift maar één credit regel weergeven " +"voor alle incasso's van het SEPA bestand. Indien niet aangevinkt wordt voor " +"iedere incasso een credit regel weergegeven op het bankafschrift." #. module: account_banking_sepa_direct_debit #: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:225 @@ -421,6 +455,8 @@ msgid "" "Cannot validate the mandate '%s' because it is not attached to a bank " "account." msgstr "" +"Kan de machtiging '%s' niet bevestigen omdat deze niet is gekoppeld aan een " +"bankrekening." #. module: account_banking_sepa_direct_debit #: selection:banking.export.sdd,state:0 @@ -433,7 +469,7 @@ msgstr "Concept" #: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:290 #, python-format msgid "Mandate update" -msgstr "" +msgstr "Machtiging bijwerken" #. module: account_banking_sepa_direct_debit #: selection:banking.export.sdd,charge_bearer:0 @@ -450,7 +486,7 @@ msgstr "Bach verwerking" #. module: account_banking_sepa_direct_debit #: field:sdd.mandate,sepa_migrated:0 msgid "Migrated to SEPA" -msgstr "" +msgstr "Gemigreerd naar SEPa" #. module: account_banking_sepa_direct_debit #: field:sdd.mandate,state:0 @@ -482,12 +518,14 @@ msgid "" "The mandate '%s' can't have a date of last debit before the date of " "signature." msgstr "" +"De machtiging '%s' kan geen datum van laatste incasso hebben die eerder is " +"dan de datum van ondertekening." #. module: account_banking_sepa_direct_debit #: model:mail.message.subtype,description:account_banking_sepa_direct_debit.recurrent_sequence_type_final #: model:mail.message.subtype,name:account_banking_sepa_direct_debit.recurrent_sequence_type_final msgid "Sequence Type set to Final" -msgstr "" +msgstr "Reeks soort ingesteld op definitief" #. module: account_banking_sepa_direct_debit #: field:sdd.mandate,message_is_follower:0 @@ -500,16 +538,18 @@ msgid "" "When the field 'Migrated to SEPA' is not active, this field will be used as " "the Original Mandate Identification in the Direct Debit file." msgstr "" +"Wanneer het veld 'gemigreerd naar SEPA' niet actief is, zal dit veld worden " +"gebruikt als de originele machtiging identificatie in het incasso bestand." #. module: account_banking_sepa_direct_debit #: view:payment.order:0 msgid "SDD Mandate" -msgstr "" +msgstr "SDD machtiging" #. module: account_banking_sepa_direct_debit #: field:sdd.mandate,original_mandate_identification:0 msgid "Original Mandate Identification" -msgstr "" +msgstr "Originele machtiging indificatie" #. module: account_banking_sepa_direct_debit #: model:ir.model,name:account_banking_sepa_direct_debit.model_res_company @@ -524,7 +564,7 @@ msgstr "Samenvatting" #. module: account_banking_sepa_direct_debit #: model:res.groups,name:account_banking_sepa_direct_debit.group_original_mandate_required msgid "Original Mandate Required (SEPA)" -msgstr "" +msgstr "Originele machtiging benodigd (SEPA)" #. module: account_banking_sepa_direct_debit #: field:account.invoice,sdd_mandate_id:0 @@ -532,7 +572,7 @@ msgstr "" #: field:payment.line,sdd_mandate_id:0 #: view:sdd.mandate:0 msgid "SEPA Direct Debit Mandate" -msgstr "" +msgstr "SEPA incasso machtiging" #. module: account_banking_sepa_direct_debit #: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:193 @@ -541,6 +581,8 @@ msgid "" "Missing SEPA Direct Debit mandate on the payment line with partner '%s' and " "Invoice ref '%s'." msgstr "" +"Ontbrekende SEPA incasso machtiging op de betaalregel met relatie '%s' en " +"factuur referentie '%s'." #. module: account_banking_sepa_direct_debit #: code:addons/account_banking_sepa_direct_debit/wizard/export_sdd.py:210 @@ -549,26 +591,29 @@ msgid "" "The mandate with reference '%s' for partner '%s' has type set to 'One-Off' " "and it has a last debit date set to '%s', so we can't use it." msgstr "" +"De machtiging referentie '%s' voor relatie %s' is ingesteld op 'eenmalig' en " +"de laatste incasso datum is ingesteld op '%s'. Zodoende kunnen we deze niet " +"gebruiken." #. module: account_banking_sepa_direct_debit #: field:sdd.mandate,scan:0 msgid "Scan of the Mandate" -msgstr "" +msgstr "Scan van de machteging" #. module: account_banking_sepa_direct_debit #: field:sdd.mandate,last_debit_date:0 msgid "Date of the Last Debit" -msgstr "" +msgstr "Datum van laatste incasso" #. module: account_banking_sepa_direct_debit #: model:mail.message.subtype,name:account_banking_sepa_direct_debit.mandate_expired msgid "Mandate Expired" -msgstr "" +msgstr "Machtiging verlopen" #. module: account_banking_sepa_direct_debit #: constraint:res.company:0 msgid "Invalid SEPA Creditor Identifier." -msgstr "" +msgstr "Ongeldige SEPA Incassant-ID." #. module: account_banking_sepa_direct_debit #: model:ir.model,name:account_banking_sepa_direct_debit.model_res_partner_bank @@ -587,6 +632,14 @@ msgid "" "

\n" " " msgstr "" +"

\n" +" Klik voor het maken van een nieuwe SEPA incasso machtiging.\n" +"

\n" +" Een SEPA incasso machtiging is een document ondertekend door uw " +"klant, welke u toestemming geeft om incasso's uit te voeren op zijn " +"bankrekening.\n" +"

\n" +" " #. module: account_banking_sepa_direct_debit #: view:banking.export.sdd:0 @@ -614,7 +667,7 @@ msgstr "Annuleer" #: view:sdd.mandate:0 #: field:sdd.mandate,payment_line_ids:0 msgid "Related Payment Lines" -msgstr "" +msgstr "Gerelateerde betaalregels" #. module: account_banking_sepa_direct_debit #: view:sdd.mandate:0 @@ -625,22 +678,22 @@ msgstr "Terugkerend" #. module: account_banking_sepa_direct_debit #: field:sdd.mandate,type:0 msgid "Type of Mandate" -msgstr "" +msgstr "Soort machtiging" #. module: account_banking_sepa_direct_debit #: model:mail.message.subtype,name:account_banking_sepa_direct_debit.mandate_valid msgid "Mandate Validated" -msgstr "" +msgstr "Machtiging bevestigd" #. module: account_banking_sepa_direct_debit #: field:banking.export.sdd,file:0 msgid "SEPA File" -msgstr "" +msgstr "SEPA bestand" #. module: account_banking_sepa_direct_debit #: field:res.company,sepa_creditor_identifier:0 msgid "SEPA Creditor Identifier" -msgstr "" +msgstr "SEPA Incassant-ID" #. module: account_banking_sepa_direct_debit #: model:ir.model,name:account_banking_sepa_direct_debit.model_banking_export_sdd @@ -665,12 +718,15 @@ msgid "" "You must set the 'Original Mandate Identification' on the recurrent mandate " "'%s' which is not marked as 'Migrated to SEPA'." msgstr "" +"U dient de 'Originele machtiging identificatie' in te stellen op de " +"herhalende machtiging '%s' welke niet is gemarkeerd als 'Gemigreerd naar " +"SEPA'" #. module: account_banking_sepa_direct_debit #: model:mail.message.subtype,description:account_banking_sepa_direct_debit.recurrent_sequence_type_first #: model:mail.message.subtype,name:account_banking_sepa_direct_debit.recurrent_sequence_type_first msgid "Sequence Type set to First" -msgstr "" +msgstr "Reeks ingesteld op eerste" #. module: account_banking_sepa_direct_debit #: code:addons/account_banking_sepa_direct_debit/account_banking_sdd.py:291 @@ -679,6 +735,8 @@ msgid "" "As you changed the bank account attached to this mandate, the 'Sequence " "Type' has been set back to 'First'." msgstr "" +"Omdat u de gekoppelde bankrekening heeft gewijzigd is de reeks terug gezet " +"naar 'Eerste'." #. module: account_banking_sepa_direct_debit #: help:sdd.mandate,message_ids:0 @@ -688,7 +746,7 @@ msgstr "Berichten en communicatie historie" #. module: account_banking_sepa_direct_debit #: view:sdd.mandate:0 msgid "Search SEPA Direct Debit Mandates" -msgstr "" +msgstr "Zoek SEPA incasso machtigingen" #. module: account_banking_sepa_direct_debit #: field:banking.export.sdd.wizard,file:0