Merge lp:~akretion-team/banking-addons/70-sepa-trf-dd-updates into lp:banking-addons
- 70-sepa-trf-dd-updates
- Merge into banking-addons-70
Status: | Merged |
---|---|
Merged at revision: | 219 |
Proposed branch: | lp:~akretion-team/banking-addons/70-sepa-trf-dd-updates |
Merge into: | lp:banking-addons |
Diff against target: |
8121 lines (+6854/-635) 51 files modified
account_banking_pain_base/__init__.py (+26/-0) account_banking_pain_base/__openerp__.py (+50/-0) account_banking_pain_base/banking_export_pain.py (+439/-0) account_banking_pain_base/company.py (+78/-0) account_banking_pain_base/company_view.xml (+24/-0) account_banking_pain_base/i18n/account_banking_pain_base.pot (+146/-0) account_banking_pain_base/i18n/fr.po (+146/-0) account_banking_pain_base/payment_line.py (+52/-0) account_banking_pain_base/payment_line_view.xml (+41/-0) account_banking_pain_base/payment_mode.py (+39/-0) account_banking_pain_base/payment_mode_view.xml (+22/-0) account_banking_payment/__openerp__.py (+1/-0) account_banking_payment/model/__init__.py (+1/-1) account_banking_payment/model/account_payment.py (+1/-0) account_banking_payment/model/payment_mode.py (+7/-4) account_banking_payment/view/payment_mode.xml (+1/-0) account_banking_payment/view/payment_order_create_view.xml (+23/-0) account_banking_sepa_credit_transfer/__openerp__.py (+1/-1) account_banking_sepa_credit_transfer/account_banking_sepa.py (+15/-6) account_banking_sepa_credit_transfer/account_banking_sepa_view.xml (+0/-2) account_banking_sepa_credit_transfer/i18n/account_banking_sepa_credit_transfer.pot (+12/-70) account_banking_sepa_credit_transfer/i18n/fr.po (+29/-235) account_banking_sepa_credit_transfer/wizard/export_sepa.py (+130/-284) account_banking_sepa_credit_transfer/wizard/export_sepa_view.xml (+0/-1) account_banking_sepa_direct_debit/__init__.py (+25/-0) account_banking_sepa_direct_debit/__openerp__.py (+60/-0) account_banking_sepa_direct_debit/account_banking_sdd.py (+424/-0) account_banking_sepa_direct_debit/account_banking_sdd_view.xml (+80/-0) account_banking_sepa_direct_debit/account_invoice_view.xml (+22/-0) account_banking_sepa_direct_debit/account_payment_view.xml (+26/-0) account_banking_sepa_direct_debit/company.py (+89/-0) account_banking_sepa_direct_debit/company_view.xml (+23/-0) account_banking_sepa_direct_debit/data/mandate_reference_sequence.xml (+21/-0) account_banking_sepa_direct_debit/data/pain.008.001.02.xsd (+879/-0) account_banking_sepa_direct_debit/data/pain.008.001.03.xsd (+925/-0) account_banking_sepa_direct_debit/data/pain.008.001.04.xsd (+892/-0) account_banking_sepa_direct_debit/data/payment_type_sdd.xml (+37/-0) account_banking_sepa_direct_debit/i18n/account_banking_sepa_direct_debit.pot (+633/-0) account_banking_sepa_direct_debit/i18n/fr.po (+642/-0) account_banking_sepa_direct_debit/mandate_expire_cron.xml (+26/-0) account_banking_sepa_direct_debit/res_partner_bank_view.xml (+48/-0) account_banking_sepa_direct_debit/sdd_mandate_view.xml (+149/-0) account_banking_sepa_direct_debit/security/ir.model.access.csv (+4/-0) account_banking_sepa_direct_debit/security/original_mandate_required_security.xml (+17/-0) account_banking_sepa_direct_debit/wizard/__init__.py (+23/-0) account_banking_sepa_direct_debit/wizard/export_sdd.py (+451/-0) account_banking_sepa_direct_debit/wizard/export_sdd_view.xml (+37/-0) account_direct_debit/model/account_invoice.py (+3/-3) account_direct_debit/model/account_move_line.py (+31/-0) account_direct_debit/model/account_payment.py (+0/-28) account_direct_debit/view/account_payment.xml (+3/-0) |
To merge this branch: | bzr merge lp:~akretion-team/banking-addons/70-sepa-trf-dd-updates |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Guewen Baconnier @ Camptocamp | Approve | ||
Christophe Combelles (community) | Approve | ||
Stefan Rijnhart (Opener) | Approve | ||
Stéphane Bidoul (Acsone) (community) | test sct | Approve | |
Review via email: mp+200019@code.launchpad.net |
Commit message
Description of the change
This branch contains :
- support for SEPA direct debit
- the work I carried out with Luc de Meyer (Noviat) during a code sprint on November 21st to get the additionnal features that were present in Luc's module account_pain for SEPA credit transfer (including the "Initiating Party Issuer", which is required by a few countries including Belgium and structured remittance info)
- the module account_
This merge proposal replaces my former merge proposal which took too much time (the code was already out-dated) :
https:/
P.S. : 38 days left before SEPA migration deadline !
Alexis de Lattre (alexis-via) wrote : | # |
Stefan Rijnhart (Opener) (stefan-opener) wrote : | # |
Hi,
first of all sorry for my absense on the community front, I have been too busy with first of January deadlines. Hope to show my face more often soon.
So I just had a quick glance and I must thank you Alexis and Luc for your great work. Just one thought about the removal of the communication2 field from the payment line view: does SEPA not allow additional comments on the order lines? And if it really doesn't, maybe we could make the payment view a little bit more dynamic depending on the payment type in a future proposal. Could you leave it in for now?
A cosmetic thing: it seems that remittance_
Stéphane Bidoul (Acsone) (sbi) wrote : | # |
Thanks Alexis and Luc for this great effort.
I made a quick test of account_
In combination with base_iban_
On the nitpicking side, I noticed a few "return True" and the end of generate_*_block methods which are unncessary.
- 226. By Alexis de Lattre
-
Put the field communication2 back in the view of payment lines.
Rename a badly named variable (thanks to Stefan Rijnhart for spotting this)
Alexis de Lattre (alexis-via) wrote : | # |
@Stefan :
I fixed the variable name, thanks for spotting.
About the communication2 field :
- for the unstructured remittance info, there is only a single field of 140 chars. The PAIN standard says "[0..n]" for the unstructured tag, but the EPC guidelines explicitely say "Format Rule: Only one occurrence of ‘Unstructured’ is allowed."
- for the structured remittance info, we use the communication field for the 2.126 reference field (35 chars) ; maybe we could use the communication2 field for the 2.129 "Additionnal Remittance information" field, which is fully optional. But, at the moment, when you have the communication type set to structured, OpenERP prevent you from using the field "communication2" ; it seems that this is managed by addons-
I must say that I don't like to have these 2 fields "communication" and "communication2", because I find it confusing for the users, and I would prefer a single field "communication" to make things simple and avoid mistakes.
By the way, investigating this made me realize that, when communication type = "Free", you can't use the field "communication" because it is readonly ; only the field "communication2" is usable in this case. This is really a mess and the help message on the communication fields don't mention that at all ; I find it very confusing.
@Stéphane Bidoul:
About the "BIC not required". First, looking at the XSD file is not enough, because the target is to respect the guidelines of the European Payment Council (EPC) for SEPA, which may add some constrains that are not in the PAIN standard and thus that are not in the XSD file. When I look at the EPC guidelines, I understand this :
- for the Debtor agent (2.21), this tag is [1..1], but it seems possible to not use the "BIC" and set "Debtor Agent > Financial Institution Identification > Other > Identification" to "NOTPROVIDED".
- for the Creditor agent (2.77), it says explicitely "Usage Rule: Only BIC is allowed", but the Credit Agent tag (2.77) is [0..1], so it may be dropped.
From what I understand, BIC is required for international payments but not required for national payment. When I look at the code of the module "base_iban_
So who handles the check that BIC is present if the IBAN is from a different country than the country of the company ?
Option A : we update the module "base_iban_
Option B : I handle this check in the code of the SEPA modules.
I think option B is better because it will block user earlier in the process (when entering the bank account in OpenERP, not when generating the SEPA XML file). If we agree on option B :
- someone has to update the module "base_iban_
- I will update ...
Stefan Rijnhart (Opener) (stefan-opener) wrote : | # |
Thanks for your changes! As for optional bics, you wrote you preferred B but I when I read carefully you mean option A.
However, res.partner.bank is not linked to a company, unless it is a bank account of the company itself. Therefore, I do think option B is the only feasible possibility for the constraint, because only then the company and therefore its country is known.
Alexis de Lattre (alexis-via) wrote : | # |
@Stefan
Yes, I meant option A, but I understand you remark about the fact that res.partner.bank is not linked to a company.
So it leaves us with option B... which means I will have to do all the work in my code ! :) But it shouldn't be very hard, as I just have to check that the 2 first letters of the IBAN of the creditor correspond to the country of the debtor (for a SCT).
- 227. By Alexis de Lattre
-
If it's a national payment, we now support "BIC not provided".
Alexis de Lattre (alexis-via) wrote : | # |
@Stéphane Bidoul:
I have implemented option B in revno 227.
I am wondering something : if it's a cross-border credit transfer, we have to provide the BIC of the foreign creditors (my code checks this and raises a nice error msg if it's not the case), but do we have to provide the BIC of the debtor (= Your Company) ?
I am still interested in reading more documentation about the "BIC not required", because I haven't found accurate info about it yet.
Stefan Rijnhart (Opener) (stefan-opener) wrote : | # |
Basic facts:
The Business Identifier Code (BIC) may still be required until 1 February 2014 for domestic payments and 1 February 2016 for cross-border payments. Member States may defer the requirement relating to the provision of the BIC for national payment transactions until 1 February 2016.
http://
This is expressed differently in different bank's specifications. One bank says: the BIC field is ignored, don't use it. Another bank says: the field is optional. You should use it if the bank cannot determine the BIC by itself.
I know it's not that well specified, but it seems to me that there is even less need for the bank to know the BIC of their own customers. Then again, it seems just good practice if the company BIC were stored properly in OpenERP (I think it is printed by default in the standard report footer). Maybe this is something that can be implemented as a contraint in the not_required module.
Stefan Rijnhart (Opener) (stefan-opener) wrote : | # |
BTW thanks for already coding the support for missing BICs. In this code, you catch the general exception. Can you catch the actual exception raised instead, or if it's only an exception caused by missing BIC, deal with this differently than a try/catch block?
- 228. By Alexis de Lattre
-
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 !)
Alexis de Lattre (alexis-via) wrote : | # |
@Stefan
Thanks for your very clear explaination about BIC and for the URL you provided. It is very clear for me now.
I made some test on the website of a French bank and read this interesting document which precisely deal with this topic (the doc is in French, sorry) :
http://
This document underline a small detail that I didn't catch when reading the guidelines of the EPC : in a credit transfer, for the creditor, you should not put the CreditorAgent block at all (but, in a direct debit, for the debtor, you should use the current implementation Financial Institution Identification > Other > Identification = NOTPROVIDED). I checked again in the guidelines of the EPC and it confirm this. So I have just modified my code to reflect this.
About the exception, you are right, my code is not as good as it should. I am not an expert in this, but i'll try to do better in a later commit.
Stéphane Bidoul (Acsone) (sbi) wrote : | # |
Thanks a lot for the improvement with missing BICs.
I tested it again and checked with the ING validator.
LGTM for SCT.
- 229. By Alexis de Lattre
-
Only catch the openerp exception in generate_
party_agent( ), as suggested by Stefan on the MP.
Alexis de Lattre (alexis-via) wrote : | # |
@Stefan
Could you tell me if my last commit revno 229 addresses your point about the management of the exception ?
Stefan Rijnhart (Opener) (stefan-opener) wrote : | # |
To be honest, I am still wondering what exception is actually raised in the 'try' block. Is it a direct consequence of the missing BIC? In that case, a simple if-clause would be nicer.
Alexis de Lattre (alexis-via) wrote : | # |
@Stefan
Yes, it is a direct consequence of the support of the missing BIC. I can't put an "if" clause, because the content of the if would be different depending on the origin of the function call :
- if we are in block B, we would have to test "sepa_export.
- if we are in block C, we would have to test "line.bank_
I think that, if we want to avoid this "try/except" in generate_
- check if we have a BIC or not in wizard/
- then I could remove the try/except in the function generate_
So, if you still want me to remove the try/except in generate_
Stefan Rijnhart (Opener) (stefan-opener) wrote : | # |
Thank you for your response, Alexis. I see it is a little more complicated than a simple if-clause. An alternative solution could be to throw proper ValueError (if it is empty) and TypeError (if it is not a str/unicode) exceptions in _prepare_field, so you could catch these specific exceptions in the try/catch block. But if these were to occur elsewhere, the user would be confronted with a backtrace instead of a popup error from the except_orm.
Given the deadline, maybe this issue should better be put this on the todo list so I'll approve this one now.
Christophe Combelles (ccomb) wrote : | # |
We're successfully using this module in production for a few weeks,
thanks for the work!
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote : | # |
Excellent work. Thanks
Preview Diff
1 | === added directory 'account_banking_pain_base' | |||
2 | === added file 'account_banking_pain_base/__init__.py' | |||
3 | --- account_banking_pain_base/__init__.py 1970-01-01 00:00:00 +0000 | |||
4 | +++ account_banking_pain_base/__init__.py 2014-01-13 12:42:46 +0000 | |||
5 | @@ -0,0 +1,26 @@ | |||
6 | 1 | # -*- encoding: utf-8 -*- | ||
7 | 2 | ############################################################################## | ||
8 | 3 | # | ||
9 | 4 | # PAIN Base module for OpenERP | ||
10 | 5 | # Copyright (C) 2013 Akretion (http://www.akretion.com) | ||
11 | 6 | # @author: Alexis de Lattre <alexis.delattre@akretion.com> | ||
12 | 7 | # | ||
13 | 8 | # This program is free software: you can redistribute it and/or modify | ||
14 | 9 | # it under the terms of the GNU Affero General Public License as | ||
15 | 10 | # published by the Free Software Foundation, either version 3 of the | ||
16 | 11 | # License, or (at your option) any later version. | ||
17 | 12 | # | ||
18 | 13 | # This program is distributed in the hope that it will be useful, | ||
19 | 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | 16 | # GNU Affero General Public License for more details. | ||
22 | 17 | # | ||
23 | 18 | # You should have received a copy of the GNU Affero General Public License | ||
24 | 19 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
25 | 20 | # | ||
26 | 21 | ############################################################################## | ||
27 | 22 | |||
28 | 23 | from . import payment_line | ||
29 | 24 | from . import payment_mode | ||
30 | 25 | from . import company | ||
31 | 26 | from . import banking_export_pain | ||
32 | 0 | 27 | ||
33 | === added file 'account_banking_pain_base/__openerp__.py' | |||
34 | --- account_banking_pain_base/__openerp__.py 1970-01-01 00:00:00 +0000 | |||
35 | +++ account_banking_pain_base/__openerp__.py 2014-01-13 12:42:46 +0000 | |||
36 | @@ -0,0 +1,50 @@ | |||
37 | 1 | ############################################################################## | ||
38 | 2 | # | ||
39 | 3 | # PAIN base module for OpenERP | ||
40 | 4 | # Copyright (C) 2013 Akretion (http://www.akretion.com) | ||
41 | 5 | # @author: Alexis de Lattre <alexis.delattre@akretion.com> | ||
42 | 6 | # | ||
43 | 7 | # This program is free software: you can redistribute it and/or modify | ||
44 | 8 | # it under the terms of the GNU Affero General Public License as | ||
45 | 9 | # published by the Free Software Foundation, either version 3 of the | ||
46 | 10 | # License, or (at your option) any later version. | ||
47 | 11 | # | ||
48 | 12 | # This program is distributed in the hope that it will be useful, | ||
49 | 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
50 | 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
51 | 15 | # GNU Affero General Public License for more details. | ||
52 | 16 | # | ||
53 | 17 | # You should have received a copy of the GNU Affero General Public License | ||
54 | 18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
55 | 19 | # | ||
56 | 20 | ############################################################################## | ||
57 | 21 | { | ||
58 | 22 | 'name': 'Account Banking PAIN Base Module', | ||
59 | 23 | 'summary': 'Base module for PAIN file generation', | ||
60 | 24 | 'version': '0.1', | ||
61 | 25 | 'license': 'AGPL-3', | ||
62 | 26 | 'author': 'Akretion, Noviat', | ||
63 | 27 | 'website': 'http://openerp-community-association.org/', | ||
64 | 28 | 'category': 'Hidden', | ||
65 | 29 | 'depends': ['account_banking_payment_export'], | ||
66 | 30 | 'external_dependencies': { | ||
67 | 31 | 'python': ['unidecode', 'lxml'], | ||
68 | 32 | }, | ||
69 | 33 | 'data': [ | ||
70 | 34 | 'payment_line_view.xml', | ||
71 | 35 | 'payment_mode_view.xml', | ||
72 | 36 | 'company_view.xml', | ||
73 | 37 | ], | ||
74 | 38 | 'description': ''' | ||
75 | 39 | Base module for PAIN file generation | ||
76 | 40 | ==================================== | ||
77 | 41 | |||
78 | 42 | 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. | ||
79 | 43 | |||
80 | 44 | This module is part of the banking addons: https://launchpad.net/banking-addons | ||
81 | 45 | |||
82 | 46 | This module was started during the Akretion-Noviat code sprint of November 21st 2013 in Epiais les Louvres (France). | ||
83 | 47 | ''', | ||
84 | 48 | 'active': False, | ||
85 | 49 | 'installable': True, | ||
86 | 50 | } | ||
87 | 0 | 51 | ||
88 | === added file 'account_banking_pain_base/banking_export_pain.py' | |||
89 | --- account_banking_pain_base/banking_export_pain.py 1970-01-01 00:00:00 +0000 | |||
90 | +++ account_banking_pain_base/banking_export_pain.py 2014-01-13 12:42:46 +0000 | |||
91 | @@ -0,0 +1,439 @@ | |||
92 | 1 | # -*- encoding: utf-8 -*- | ||
93 | 2 | ############################################################################## | ||
94 | 3 | # | ||
95 | 4 | # PAIN Base module for OpenERP | ||
96 | 5 | # Copyright (C) 2013 Akretion (http://www.akretion.com) | ||
97 | 6 | # @author: Alexis de Lattre <alexis.delattre@akretion.com> | ||
98 | 7 | # | ||
99 | 8 | # This program is free software: you can redistribute it and/or modify | ||
100 | 9 | # it under the terms of the GNU Affero General Public License as | ||
101 | 10 | # published by the Free Software Foundation, either version 3 of the | ||
102 | 11 | # License, or (at your option) any later version. | ||
103 | 12 | # | ||
104 | 13 | # This program is distributed in the hope that it will be useful, | ||
105 | 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
106 | 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
107 | 16 | # GNU Affero General Public License for more details. | ||
108 | 17 | # | ||
109 | 18 | # You should have received a copy of the GNU Affero General Public License | ||
110 | 19 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
111 | 20 | # | ||
112 | 21 | ############################################################################## | ||
113 | 22 | |||
114 | 23 | from openerp.osv import orm | ||
115 | 24 | from openerp.tools.translate import _ | ||
116 | 25 | from openerp.tools.safe_eval import safe_eval | ||
117 | 26 | from datetime import datetime | ||
118 | 27 | from unidecode import unidecode | ||
119 | 28 | from lxml import etree | ||
120 | 29 | from openerp import tools | ||
121 | 30 | import logging | ||
122 | 31 | import base64 | ||
123 | 32 | |||
124 | 33 | logger = logging.getLogger(__name__) | ||
125 | 34 | |||
126 | 35 | |||
127 | 36 | class banking_export_pain(orm.AbstractModel): | ||
128 | 37 | _name = 'banking.export.pain' | ||
129 | 38 | |||
130 | 39 | def _validate_iban(self, cr, uid, iban, context=None): | ||
131 | 40 | '''if IBAN is valid, returns IBAN | ||
132 | 41 | if IBAN is NOT valid, raises an error message''' | ||
133 | 42 | partner_bank_obj = self.pool.get('res.partner.bank') | ||
134 | 43 | if partner_bank_obj.is_iban_valid(cr, uid, iban, context=context): | ||
135 | 44 | return iban.replace(' ', '') | ||
136 | 45 | else: | ||
137 | 46 | raise orm.except_orm( | ||
138 | 47 | _('Error:'), _("This IBAN is not valid : %s") % iban) | ||
139 | 48 | |||
140 | 49 | def _prepare_field( | ||
141 | 50 | self, cr, uid, field_name, field_value, eval_ctx, max_size=0, | ||
142 | 51 | gen_args=None, context=None): | ||
143 | 52 | '''This function is designed to be inherited !''' | ||
144 | 53 | if gen_args is None: | ||
145 | 54 | gen_args = {} | ||
146 | 55 | assert isinstance(eval_ctx, dict), 'eval_ctx must contain a dict' | ||
147 | 56 | try: | ||
148 | 57 | value = safe_eval(field_value, eval_ctx) | ||
149 | 58 | # SEPA uses XML ; XML = UTF-8 ; UTF-8 = support for all characters | ||
150 | 59 | # But we are dealing with banks... | ||
151 | 60 | # and many banks don't want non-ASCCI characters ! | ||
152 | 61 | # cf section 1.4 "Character set" of the SEPA Credit Transfer | ||
153 | 62 | # Scheme Customer-to-bank guidelines | ||
154 | 63 | if gen_args.get('convert_to_ascii'): | ||
155 | 64 | value = unidecode(value) | ||
156 | 65 | unallowed_ascii_chars = [ | ||
157 | 66 | '"', '#', '$', '%', '&', '*', ';', '<', '>', '=', '@', | ||
158 | 67 | '[', ']', '^', '_', '`', '{', '}', '|', '~', '\\', '!'] | ||
159 | 68 | for unallowed_ascii_char in unallowed_ascii_chars: | ||
160 | 69 | value = value.replace(unallowed_ascii_char, '-') | ||
161 | 70 | except: | ||
162 | 71 | line = eval_ctx.get('line') | ||
163 | 72 | if line: | ||
164 | 73 | raise orm.except_orm( | ||
165 | 74 | _('Error:'), | ||
166 | 75 | _("Cannot compute the '%s' of the Payment Line with " | ||
167 | 76 | "reference '%s'.") | ||
168 | 77 | % (field_name, line.name)) | ||
169 | 78 | else: | ||
170 | 79 | raise orm.except_orm( | ||
171 | 80 | _('Error:'), | ||
172 | 81 | _("Cannot compute the '%s'.") % field_name) | ||
173 | 82 | if not isinstance(value, (str, unicode)): | ||
174 | 83 | raise orm.except_orm( | ||
175 | 84 | _('Field type error:'), | ||
176 | 85 | _("The type of the field '%s' is %s. It should be a string " | ||
177 | 86 | "or unicode.") | ||
178 | 87 | % (field_name, type(value))) | ||
179 | 88 | if not value: | ||
180 | 89 | raise orm.except_orm( | ||
181 | 90 | _('Error:'), | ||
182 | 91 | _("The '%s' is empty or 0. It should have a non-null value.") | ||
183 | 92 | % field_name) | ||
184 | 93 | if max_size and len(value) > max_size: | ||
185 | 94 | value = value[0:max_size] | ||
186 | 95 | return value | ||
187 | 96 | |||
188 | 97 | def _prepare_export_sepa( | ||
189 | 98 | self, cr, uid, total_amount, transactions_count, xml_string, | ||
190 | 99 | gen_args, context=None): | ||
191 | 100 | return { | ||
192 | 101 | 'batch_booking': gen_args['sepa_export'].batch_booking, | ||
193 | 102 | 'charge_bearer': gen_args['sepa_export'].charge_bearer, | ||
194 | 103 | 'total_amount': total_amount, | ||
195 | 104 | 'nb_transactions': transactions_count, | ||
196 | 105 | 'file': base64.encodestring(xml_string), | ||
197 | 106 | 'payment_order_ids': [( | ||
198 | 107 | 6, 0, [x.id for x in gen_args['sepa_export'].payment_order_ids] | ||
199 | 108 | )], | ||
200 | 109 | } | ||
201 | 110 | |||
202 | 111 | def _validate_xml(self, cr, uid, xml_string, gen_args, context=None): | ||
203 | 112 | xsd_etree_obj = etree.parse( | ||
204 | 113 | tools.file_open(gen_args['pain_xsd_file'])) | ||
205 | 114 | official_pain_schema = etree.XMLSchema(xsd_etree_obj) | ||
206 | 115 | |||
207 | 116 | try: | ||
208 | 117 | root_to_validate = etree.fromstring(xml_string) | ||
209 | 118 | official_pain_schema.assertValid(root_to_validate) | ||
210 | 119 | except Exception, e: | ||
211 | 120 | logger.warning( | ||
212 | 121 | "The XML file is invalid against the XML Schema Definition") | ||
213 | 122 | logger.warning(xml_string) | ||
214 | 123 | logger.warning(e) | ||
215 | 124 | raise orm.except_orm( | ||
216 | 125 | _('Error:'), | ||
217 | 126 | _("The generated XML file is not valid against the official " | ||
218 | 127 | "XML Schema Definition. The generated XML file and the " | ||
219 | 128 | "full error have been written in the server logs. Here " | ||
220 | 129 | "is the error, which may give you an idea on the cause " | ||
221 | 130 | "of the problem : %s") | ||
222 | 131 | % str(e)) | ||
223 | 132 | return True | ||
224 | 133 | |||
225 | 134 | def finalize_sepa_file_creation( | ||
226 | 135 | self, cr, uid, ids, xml_root, total_amount, transactions_count, | ||
227 | 136 | gen_args, context=None): | ||
228 | 137 | xml_string = etree.tostring( | ||
229 | 138 | xml_root, pretty_print=True, encoding='UTF-8', | ||
230 | 139 | xml_declaration=True) | ||
231 | 140 | logger.debug( | ||
232 | 141 | "Generated SEPA XML file in format %s below" | ||
233 | 142 | % gen_args['pain_flavor']) | ||
234 | 143 | logger.debug(xml_string) | ||
235 | 144 | self._validate_xml(cr, uid, xml_string, gen_args, context=context) | ||
236 | 145 | |||
237 | 146 | file_id = gen_args['file_obj'].create( | ||
238 | 147 | cr, uid, self._prepare_export_sepa( | ||
239 | 148 | cr, uid, total_amount, transactions_count, | ||
240 | 149 | xml_string, gen_args, context=context), | ||
241 | 150 | context=context) | ||
242 | 151 | |||
243 | 152 | self.write( | ||
244 | 153 | cr, uid, ids, { | ||
245 | 154 | 'file_id': file_id, | ||
246 | 155 | 'state': 'finish', | ||
247 | 156 | }, context=context) | ||
248 | 157 | |||
249 | 158 | action = { | ||
250 | 159 | 'name': 'SEPA File', | ||
251 | 160 | 'type': 'ir.actions.act_window', | ||
252 | 161 | 'view_type': 'form', | ||
253 | 162 | 'view_mode': 'form,tree', | ||
254 | 163 | 'res_model': self._name, | ||
255 | 164 | 'res_id': ids[0], | ||
256 | 165 | 'target': 'new', | ||
257 | 166 | } | ||
258 | 167 | return action | ||
259 | 168 | |||
260 | 169 | def generate_group_header_block( | ||
261 | 170 | self, cr, uid, parent_node, gen_args, context=None): | ||
262 | 171 | group_header_1_0 = etree.SubElement(parent_node, 'GrpHdr') | ||
263 | 172 | message_identification_1_1 = etree.SubElement( | ||
264 | 173 | group_header_1_0, 'MsgId') | ||
265 | 174 | message_identification_1_1.text = self._prepare_field( | ||
266 | 175 | cr, uid, 'Message Identification', | ||
267 | 176 | 'sepa_export.payment_order_ids[0].reference', | ||
268 | 177 | {'sepa_export': gen_args['sepa_export']}, 35, | ||
269 | 178 | gen_args=gen_args, context=context) | ||
270 | 179 | creation_date_time_1_2 = etree.SubElement(group_header_1_0, 'CreDtTm') | ||
271 | 180 | creation_date_time_1_2.text = datetime.strftime( | ||
272 | 181 | datetime.today(), '%Y-%m-%dT%H:%M:%S') | ||
273 | 182 | if gen_args.get('pain_flavor') == 'pain.001.001.02': | ||
274 | 183 | # batch_booking is in "Group header" with pain.001.001.02 | ||
275 | 184 | # and in "Payment info" in pain.001.001.03/04 | ||
276 | 185 | batch_booking = etree.SubElement(group_header_1_0, 'BtchBookg') | ||
277 | 186 | batch_booking.text = \ | ||
278 | 187 | str(gen_args['sepa_export'].batch_booking).lower() | ||
279 | 188 | nb_of_transactions_1_6 = etree.SubElement( | ||
280 | 189 | group_header_1_0, 'NbOfTxs') | ||
281 | 190 | control_sum_1_7 = etree.SubElement(group_header_1_0, 'CtrlSum') | ||
282 | 191 | # Grpg removed in pain.001.001.03 | ||
283 | 192 | if gen_args.get('pain_flavor') == 'pain.001.001.02': | ||
284 | 193 | grouping = etree.SubElement(group_header_1_0, 'Grpg') | ||
285 | 194 | grouping.text = 'GRPD' | ||
286 | 195 | self.generate_initiating_party_block( | ||
287 | 196 | cr, uid, group_header_1_0, gen_args, | ||
288 | 197 | context=context) | ||
289 | 198 | return group_header_1_0, nb_of_transactions_1_6, control_sum_1_7 | ||
290 | 199 | |||
291 | 200 | def generate_start_payment_info_block( | ||
292 | 201 | self, cr, uid, parent_node, payment_info_ident, | ||
293 | 202 | priority, local_instrument, sequence_type, requested_date, | ||
294 | 203 | eval_ctx, gen_args, context=None): | ||
295 | 204 | payment_info_2_0 = etree.SubElement(parent_node, 'PmtInf') | ||
296 | 205 | payment_info_identification_2_1 = etree.SubElement( | ||
297 | 206 | payment_info_2_0, 'PmtInfId') | ||
298 | 207 | payment_info_identification_2_1.text = self._prepare_field( | ||
299 | 208 | cr, uid, 'Payment Information Identification', | ||
300 | 209 | payment_info_ident, eval_ctx, 35, | ||
301 | 210 | gen_args=gen_args, context=context) | ||
302 | 211 | payment_method_2_2 = etree.SubElement(payment_info_2_0, 'PmtMtd') | ||
303 | 212 | payment_method_2_2.text = gen_args['payment_method'] | ||
304 | 213 | if gen_args.get('pain_flavor') != 'pain.001.001.02': | ||
305 | 214 | batch_booking_2_3 = etree.SubElement(payment_info_2_0, 'BtchBookg') | ||
306 | 215 | batch_booking_2_3.text = \ | ||
307 | 216 | str(gen_args['sepa_export'].batch_booking).lower() | ||
308 | 217 | # The "SEPA Customer-to-bank | ||
309 | 218 | # Implementation guidelines" for SCT and SDD says that control sum | ||
310 | 219 | # and nb_of_transactions should be present | ||
311 | 220 | # at both "group header" level and "payment info" level | ||
312 | 221 | nb_of_transactions_2_4 = etree.SubElement( | ||
313 | 222 | payment_info_2_0, 'NbOfTxs') | ||
314 | 223 | control_sum_2_5 = etree.SubElement(payment_info_2_0, 'CtrlSum') | ||
315 | 224 | payment_type_info_2_6 = etree.SubElement( | ||
316 | 225 | payment_info_2_0, 'PmtTpInf') | ||
317 | 226 | if priority: | ||
318 | 227 | instruction_priority_2_7 = etree.SubElement( | ||
319 | 228 | payment_type_info_2_6, 'InstrPrty') | ||
320 | 229 | instruction_priority_2_7.text = priority | ||
321 | 230 | service_level_2_8 = etree.SubElement( | ||
322 | 231 | payment_type_info_2_6, 'SvcLvl') | ||
323 | 232 | service_level_code_2_9 = etree.SubElement(service_level_2_8, 'Cd') | ||
324 | 233 | service_level_code_2_9.text = 'SEPA' | ||
325 | 234 | if local_instrument: | ||
326 | 235 | local_instrument_2_11 = etree.SubElement( | ||
327 | 236 | payment_type_info_2_6, 'LclInstrm') | ||
328 | 237 | local_instr_code_2_12 = etree.SubElement( | ||
329 | 238 | local_instrument_2_11, 'Cd') | ||
330 | 239 | local_instr_code_2_12.text = local_instrument | ||
331 | 240 | if sequence_type: | ||
332 | 241 | sequence_type_2_14 = etree.SubElement( | ||
333 | 242 | payment_type_info_2_6, 'SeqTp') | ||
334 | 243 | sequence_type_2_14.text = sequence_type | ||
335 | 244 | |||
336 | 245 | if gen_args['payment_method'] == 'DD': | ||
337 | 246 | request_date_tag = 'ReqdColltnDt' | ||
338 | 247 | else: | ||
339 | 248 | request_date_tag = 'ReqdExctnDt' | ||
340 | 249 | requested_date_2_17 = etree.SubElement( | ||
341 | 250 | payment_info_2_0, request_date_tag) | ||
342 | 251 | requested_date_2_17.text = requested_date | ||
343 | 252 | return payment_info_2_0, nb_of_transactions_2_4, control_sum_2_5 | ||
344 | 253 | |||
345 | 254 | def generate_initiating_party_block( | ||
346 | 255 | self, cr, uid, parent_node, gen_args, context=None): | ||
347 | 256 | my_company_name = self._prepare_field( | ||
348 | 257 | cr, uid, 'Company Name', | ||
349 | 258 | 'sepa_export.payment_order_ids[0].mode.bank_id.partner_id.name', | ||
350 | 259 | {'sepa_export': gen_args['sepa_export']}, | ||
351 | 260 | gen_args.get('name_maxsize'), gen_args=gen_args, context=context) | ||
352 | 261 | initiating_party_1_8 = etree.SubElement(parent_node, 'InitgPty') | ||
353 | 262 | initiating_party_name = etree.SubElement(initiating_party_1_8, 'Nm') | ||
354 | 263 | initiating_party_name.text = my_company_name | ||
355 | 264 | initiating_party_identifier = self.pool['res.company'].\ | ||
356 | 265 | _get_initiating_party_identifier( | ||
357 | 266 | cr, uid, | ||
358 | 267 | gen_args['sepa_export'].payment_order_ids[0].company_id.id, | ||
359 | 268 | context=context) | ||
360 | 269 | initiating_party_issuer = gen_args['sepa_export'].\ | ||
361 | 270 | payment_order_ids[0].company_id.initiating_party_issuer | ||
362 | 271 | if initiating_party_identifier and initiating_party_issuer: | ||
363 | 272 | iniparty_id = etree.SubElement(initiating_party_1_8, 'Id') | ||
364 | 273 | iniparty_org_id = etree.SubElement(iniparty_id, 'OrgId') | ||
365 | 274 | iniparty_org_other = etree.SubElement(iniparty_org_id, 'Othr') | ||
366 | 275 | iniparty_org_other_id = etree.SubElement(iniparty_org_other, 'Id') | ||
367 | 276 | iniparty_org_other_id.text = initiating_party_identifier | ||
368 | 277 | iniparty_org_other_issuer = etree.SubElement( | ||
369 | 278 | iniparty_org_other, 'Issr') | ||
370 | 279 | iniparty_org_other_issuer.text = initiating_party_issuer | ||
371 | 280 | return True | ||
372 | 281 | |||
373 | 282 | def generate_party_agent( | ||
374 | 283 | self, cr, uid, parent_node, party_type, party_type_label, | ||
375 | 284 | order, party_name, iban, bic, eval_ctx, gen_args, context=None): | ||
376 | 285 | '''Generate the piece of the XML file corresponding to BIC | ||
377 | 286 | This code is mutualized between TRF and DD''' | ||
378 | 287 | assert order in ('B', 'C'), "Order can be 'B' or 'C'" | ||
379 | 288 | try: | ||
380 | 289 | bic = self._prepare_field( | ||
381 | 290 | cr, uid, '%s BIC' % party_type_label, bic, eval_ctx, | ||
382 | 291 | gen_args=gen_args, context=context) | ||
383 | 292 | party_agent = etree.SubElement(parent_node, '%sAgt' % party_type) | ||
384 | 293 | party_agent_institution = etree.SubElement( | ||
385 | 294 | party_agent, 'FinInstnId') | ||
386 | 295 | party_agent_bic = etree.SubElement( | ||
387 | 296 | party_agent_institution, gen_args.get('bic_xml_tag')) | ||
388 | 297 | party_agent_bic.text = bic | ||
389 | 298 | except except_orm: | ||
390 | 299 | if order == 'C': | ||
391 | 300 | if iban[0:2] != gen_args['initiating_party_country_code']: | ||
392 | 301 | raise orm.except_orm( | ||
393 | 302 | _('Error:'), | ||
394 | 303 | _("The bank account with IBAN '%s' of partner '%s' " | ||
395 | 304 | "must have an associated BIC because it is a " | ||
396 | 305 | "cross-border SEPA operation.") | ||
397 | 306 | % (iban, party_name)) | ||
398 | 307 | if order == 'B' or ( | ||
399 | 308 | order == 'C' and gen_args['payment_method'] == 'DD'): | ||
400 | 309 | party_agent = etree.SubElement( | ||
401 | 310 | parent_node, '%sAgt' % party_type) | ||
402 | 311 | party_agent_institution = etree.SubElement( | ||
403 | 312 | party_agent, 'FinInstnId') | ||
404 | 313 | party_agent_other = etree.SubElement( | ||
405 | 314 | party_agent_institution, 'Othr') | ||
406 | 315 | party_agent_other_identification = etree.SubElement( | ||
407 | 316 | party_agent_other, 'Id') | ||
408 | 317 | party_agent_other_identification.text = 'NOTPROVIDED' | ||
409 | 318 | # for Credit Transfers, in the 'C' block, if BIC is not provided, | ||
410 | 319 | # we should not put the 'Creditor Agent' block at all, | ||
411 | 320 | # as per the guidelines of the EPC | ||
412 | 321 | return True | ||
413 | 322 | |||
414 | 323 | def generate_party_block( | ||
415 | 324 | self, cr, uid, parent_node, party_type, order, name, iban, bic, | ||
416 | 325 | eval_ctx, gen_args, context=None): | ||
417 | 326 | '''Generate the piece of the XML file corresponding to Name+IBAN+BIC | ||
418 | 327 | This code is mutualized between TRF and DD''' | ||
419 | 328 | assert order in ('B', 'C'), "Order can be 'B' or 'C'" | ||
420 | 329 | if party_type == 'Cdtr': | ||
421 | 330 | party_type_label = 'Creditor' | ||
422 | 331 | elif party_type == 'Dbtr': | ||
423 | 332 | party_type_label = 'Debtor' | ||
424 | 333 | party_name = self._prepare_field( | ||
425 | 334 | cr, uid, '%s Name' % party_type_label, name, eval_ctx, | ||
426 | 335 | gen_args.get('name_maxsize'), | ||
427 | 336 | gen_args=gen_args, context=context) | ||
428 | 337 | piban = self._prepare_field( | ||
429 | 338 | cr, uid, '%s IBAN' % party_type_label, iban, eval_ctx, | ||
430 | 339 | gen_args=gen_args, | ||
431 | 340 | context=context) | ||
432 | 341 | viban = self._validate_iban(cr, uid, piban, context=context) | ||
433 | 342 | # At C level, the order is : BIC, Name, IBAN | ||
434 | 343 | # At B level, the order is : Name, IBAN, BIC | ||
435 | 344 | if order == 'B': | ||
436 | 345 | gen_args['initiating_party_country_code'] = viban[0:2] | ||
437 | 346 | elif order == 'C': | ||
438 | 347 | self.generate_party_agent( | ||
439 | 348 | cr, uid, parent_node, party_type, party_type_label, | ||
440 | 349 | order, party_name, viban, bic, | ||
441 | 350 | eval_ctx, gen_args, context=context) | ||
442 | 351 | party = etree.SubElement(parent_node, party_type) | ||
443 | 352 | party_nm = etree.SubElement(party, 'Nm') | ||
444 | 353 | party_nm.text = party_name | ||
445 | 354 | party_account = etree.SubElement( | ||
446 | 355 | parent_node, '%sAcct' % party_type) | ||
447 | 356 | party_account_id = etree.SubElement(party_account, 'Id') | ||
448 | 357 | party_account_iban = etree.SubElement( | ||
449 | 358 | party_account_id, 'IBAN') | ||
450 | 359 | party_account_iban.text = viban | ||
451 | 360 | if order == 'B': | ||
452 | 361 | self.generate_party_agent( | ||
453 | 362 | cr, uid, parent_node, party_type, party_type_label, | ||
454 | 363 | order, party_name, viban, bic, | ||
455 | 364 | eval_ctx, gen_args, context=context) | ||
456 | 365 | return True | ||
457 | 366 | |||
458 | 367 | def generate_remittance_info_block( | ||
459 | 368 | self, cr, uid, parent_node, line, gen_args, context=None): | ||
460 | 369 | |||
461 | 370 | remittance_info_2_91 = etree.SubElement( | ||
462 | 371 | parent_node, 'RmtInf') | ||
463 | 372 | if line.state == 'normal': | ||
464 | 373 | remittance_info_unstructured_2_99 = etree.SubElement( | ||
465 | 374 | remittance_info_2_91, 'Ustrd') | ||
466 | 375 | remittance_info_unstructured_2_99.text = \ | ||
467 | 376 | self._prepare_field( | ||
468 | 377 | cr, uid, 'Remittance Unstructured Information', | ||
469 | 378 | 'line.communication', {'line': line}, 140, | ||
470 | 379 | gen_args=gen_args, | ||
471 | 380 | context=context) | ||
472 | 381 | else: | ||
473 | 382 | if not line.struct_communication_type: | ||
474 | 383 | raise orm.except_orm( | ||
475 | 384 | _('Error:'), | ||
476 | 385 | _("Missing 'Structured Communication Type' on payment " | ||
477 | 386 | "line with reference '%s'.") | ||
478 | 387 | % (line.name)) | ||
479 | 388 | remittance_info_structured_2_100 = etree.SubElement( | ||
480 | 389 | remittance_info_2_91, 'Strd') | ||
481 | 390 | creditor_ref_information_2_120 = etree.SubElement( | ||
482 | 391 | remittance_info_structured_2_100, 'CdtrRefInf') | ||
483 | 392 | if gen_args.get('pain_flavor') == 'pain.001.001.02': | ||
484 | 393 | creditor_ref_info_type_2_121 = etree.SubElement( | ||
485 | 394 | creditor_ref_information_2_120, 'CdtrRefTp') | ||
486 | 395 | creditor_ref_info_type_code_2_123 = etree.SubElement( | ||
487 | 396 | creditor_ref_info_type_2_121, 'Cd') | ||
488 | 397 | creditor_ref_info_type_issuer_2_125 = etree.SubElement( | ||
489 | 398 | creditor_ref_info_type_2_121, 'Issr') | ||
490 | 399 | creditor_reference_2_126 = etree.SubElement( | ||
491 | 400 | creditor_ref_information_2_120, 'CdtrRef') | ||
492 | 401 | else: | ||
493 | 402 | creditor_ref_info_type_2_121 = etree.SubElement( | ||
494 | 403 | creditor_ref_information_2_120, 'Tp') | ||
495 | 404 | creditor_ref_info_type_or_2_122 = etree.SubElement( | ||
496 | 405 | creditor_ref_info_type_2_121, 'CdOrPrtry') | ||
497 | 406 | creditor_ref_info_type_code_2_123 = etree.SubElement( | ||
498 | 407 | creditor_ref_info_type_or_2_122, 'Cd') | ||
499 | 408 | creditor_ref_info_type_issuer_2_125 = etree.SubElement( | ||
500 | 409 | creditor_ref_info_type_2_121, 'Issr') | ||
501 | 410 | creditor_reference_2_126 = etree.SubElement( | ||
502 | 411 | creditor_ref_information_2_120, 'Ref') | ||
503 | 412 | |||
504 | 413 | creditor_ref_info_type_code_2_123.text = 'SCOR' | ||
505 | 414 | creditor_ref_info_type_issuer_2_125.text = \ | ||
506 | 415 | line.struct_communication_type | ||
507 | 416 | creditor_reference_2_126.text = \ | ||
508 | 417 | self._prepare_field( | ||
509 | 418 | cr, uid, 'Creditor Structured Reference', | ||
510 | 419 | 'line.communication', {'line': line}, 35, | ||
511 | 420 | gen_args=gen_args, | ||
512 | 421 | context=context) | ||
513 | 422 | return True | ||
514 | 423 | |||
515 | 424 | def generate_creditor_scheme_identification( | ||
516 | 425 | self, cr, uid, parent_node, identification, identification_label, | ||
517 | 426 | eval_ctx, scheme_name_proprietary, gen_args, context=None): | ||
518 | 427 | csi_id = etree.SubElement( | ||
519 | 428 | parent_node, 'Id') | ||
520 | 429 | csi_privateid = csi_id = etree.SubElement(csi_id, 'PrvtId') | ||
521 | 430 | csi_other = etree.SubElement(csi_privateid, 'Othr') | ||
522 | 431 | csi_other_id = etree.SubElement(csi_other, 'Id') | ||
523 | 432 | csi_other_id.text = self._prepare_field( | ||
524 | 433 | cr, uid, identification_label, identification, eval_ctx, | ||
525 | 434 | gen_args=gen_args, context=context) | ||
526 | 435 | csi_scheme_name = etree.SubElement(csi_other, 'SchmeNm') | ||
527 | 436 | csi_scheme_name_proprietary = etree.SubElement( | ||
528 | 437 | csi_scheme_name, 'Prtry') | ||
529 | 438 | csi_scheme_name_proprietary.text = scheme_name_proprietary | ||
530 | 439 | return True | ||
531 | 0 | 440 | ||
532 | === added file 'account_banking_pain_base/company.py' | |||
533 | --- account_banking_pain_base/company.py 1970-01-01 00:00:00 +0000 | |||
534 | +++ account_banking_pain_base/company.py 2014-01-13 12:42:46 +0000 | |||
535 | @@ -0,0 +1,78 @@ | |||
536 | 1 | # -*- encoding: utf-8 -*- | ||
537 | 2 | ############################################################################## | ||
538 | 3 | # | ||
539 | 4 | # PAIN Base module for OpenERP | ||
540 | 5 | # Copyright (C) 2013 Akretion (http://www.akretion.com) | ||
541 | 6 | # Copyright (C) 2013 Noviat (http://www.noviat.com) | ||
542 | 7 | # @author: Alexis de Lattre <alexis.delattre@akretion.com> | ||
543 | 8 | # @author: Luc de Meyer (Noviat) | ||
544 | 9 | # | ||
545 | 10 | # This program is free software: you can redistribute it and/or modify | ||
546 | 11 | # it under the terms of the GNU Affero General Public License as | ||
547 | 12 | # published by the Free Software Foundation, either version 3 of the | ||
548 | 13 | # License, or (at your option) any later version. | ||
549 | 14 | # | ||
550 | 15 | # This program is distributed in the hope that it will be useful, | ||
551 | 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
552 | 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
553 | 18 | # GNU Affero General Public License for more details. | ||
554 | 19 | # | ||
555 | 20 | # You should have received a copy of the GNU Affero General Public License | ||
556 | 21 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
557 | 22 | # | ||
558 | 23 | ############################################################################## | ||
559 | 24 | |||
560 | 25 | from openerp.osv import orm, fields | ||
561 | 26 | |||
562 | 27 | |||
563 | 28 | class res_company(orm.Model): | ||
564 | 29 | _inherit = 'res.company' | ||
565 | 30 | |||
566 | 31 | _columns = { | ||
567 | 32 | 'initiating_party_issuer': fields.char( | ||
568 | 33 | 'Initiating Party Issuer', size=35, | ||
569 | 34 | help="This will be used as the 'Initiating Party Issuer' in the " | ||
570 | 35 | "PAIN files generated by OpenERP."), | ||
571 | 36 | } | ||
572 | 37 | |||
573 | 38 | def _get_initiating_party_identifier( | ||
574 | 39 | self, cr, uid, company_id, context=None): | ||
575 | 40 | '''The code here may be different from one country to another. | ||
576 | 41 | If you need to add support for an additionnal country, you can | ||
577 | 42 | contribute your code here or inherit this function in the | ||
578 | 43 | localization modules for your country''' | ||
579 | 44 | assert isinstance(company_id, int), 'Only one company ID' | ||
580 | 45 | company = self.browse(cr, uid, company_id, context=context) | ||
581 | 46 | company_vat = company.vat | ||
582 | 47 | party_identifier = False | ||
583 | 48 | if company_vat and company_vat[0:2].upper() in ['BE']: | ||
584 | 49 | party_identifier = company_vat[2:].replace(' ', '') | ||
585 | 50 | return party_identifier | ||
586 | 51 | |||
587 | 52 | def _initiating_party_issuer_default(self, cr, uid, context=None): | ||
588 | 53 | '''If you need to add support for an additionnal country, you can | ||
589 | 54 | add an entry in the dict "party_issuer_per_country" here | ||
590 | 55 | or inherit this function in the localization modules for | ||
591 | 56 | your country''' | ||
592 | 57 | initiating_party_issuer = '' | ||
593 | 58 | # If your country require the 'Initiating Party Issuer', you should | ||
594 | 59 | # contribute the entry for your country in the dict below | ||
595 | 60 | party_issuer_per_country = { | ||
596 | 61 | 'BE': 'KBO-BCE', # KBO-BCE = the registry of companies in Belgium | ||
597 | 62 | } | ||
598 | 63 | company_id = self._company_default_get( | ||
599 | 64 | cr, uid, 'res.company', context=context) | ||
600 | 65 | if company_id: | ||
601 | 66 | company = self.browse(cr, uid, company_id, context=context) | ||
602 | 67 | country_code = company.country_id.code | ||
603 | 68 | initiating_party_issuer = party_issuer_per_country.get( | ||
604 | 69 | country_code, '') | ||
605 | 70 | return initiating_party_issuer | ||
606 | 71 | |||
607 | 72 | def _initiating_party_issuer_def(self, cr, uid, context=None): | ||
608 | 73 | return self._initiating_party_issuer_default( | ||
609 | 74 | cr, uid, context=context) | ||
610 | 75 | |||
611 | 76 | _defaults = { | ||
612 | 77 | 'initiating_party_issuer': _initiating_party_issuer_def, | ||
613 | 78 | } | ||
614 | 0 | 79 | ||
615 | === added file 'account_banking_pain_base/company_view.xml' | |||
616 | --- account_banking_pain_base/company_view.xml 1970-01-01 00:00:00 +0000 | |||
617 | +++ account_banking_pain_base/company_view.xml 2014-01-13 12:42:46 +0000 | |||
618 | @@ -0,0 +1,24 @@ | |||
619 | 1 | <?xml version="1.0" encoding="utf-8"?> | ||
620 | 2 | <!-- | ||
621 | 3 | Copyright (C) 2013 Akretion (http://www.akretion.com) | ||
622 | 4 | @author: Alexis de Lattre <alexis.delattre@akretion.com> | ||
623 | 5 | The licence is in the file __openerp__.py | ||
624 | 6 | --> | ||
625 | 7 | <openerp> | ||
626 | 8 | <data> | ||
627 | 9 | |||
628 | 10 | <record id="view_company_form" model="ir.ui.view"> | ||
629 | 11 | <field name="name">pain.group.on.res.company.form</field> | ||
630 | 12 | <field name="model">res.company</field> | ||
631 | 13 | <field name="inherit_id" ref="base.view_company_form"/> | ||
632 | 14 | <field name="arch" type="xml"> | ||
633 | 15 | <group name="account_grp" position="after"> | ||
634 | 16 | <group name="pain" string="Payment Initiation"> | ||
635 | 17 | <field name="initiating_party_issuer"/> | ||
636 | 18 | </group> | ||
637 | 19 | </group> | ||
638 | 20 | </field> | ||
639 | 21 | </record> | ||
640 | 22 | |||
641 | 23 | </data> | ||
642 | 24 | </openerp> | ||
643 | 0 | 25 | ||
644 | === added directory 'account_banking_pain_base/i18n' | |||
645 | === added file 'account_banking_pain_base/i18n/account_banking_pain_base.pot' | |||
646 | --- account_banking_pain_base/i18n/account_banking_pain_base.pot 1970-01-01 00:00:00 +0000 | |||
647 | +++ account_banking_pain_base/i18n/account_banking_pain_base.pot 2014-01-13 12:42:46 +0000 | |||
648 | @@ -0,0 +1,146 @@ | |||
649 | 1 | # Translation of OpenERP Server. | ||
650 | 2 | # This file contains the translation of the following modules: | ||
651 | 3 | # * account_banking_pain_base | ||
652 | 4 | # | ||
653 | 5 | msgid "" | ||
654 | 6 | msgstr "" | ||
655 | 7 | "Project-Id-Version: OpenERP Server 7.0\n" | ||
656 | 8 | "Report-Msgid-Bugs-To: \n" | ||
657 | 9 | "POT-Creation-Date: 2013-12-23 21:26+0000\n" | ||
658 | 10 | "PO-Revision-Date: 2013-12-23 21:26+0000\n" | ||
659 | 11 | "Last-Translator: <>\n" | ||
660 | 12 | "Language-Team: \n" | ||
661 | 13 | "MIME-Version: 1.0\n" | ||
662 | 14 | "Content-Type: text/plain; charset=UTF-8\n" | ||
663 | 15 | "Content-Transfer-Encoding: \n" | ||
664 | 16 | "Plural-Forms: \n" | ||
665 | 17 | |||
666 | 18 | #. module: account_banking_pain_base | ||
667 | 19 | #: field:res.company,initiating_party_issuer:0 | ||
668 | 20 | msgid "Initiating Party Issuer" | ||
669 | 21 | msgstr "" | ||
670 | 22 | |||
671 | 23 | #. module: account_banking_pain_base | ||
672 | 24 | #: code:addons/account_banking_pain_base/banking_export_pain.py:122 | ||
673 | 25 | #, python-format | ||
674 | 26 | 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" | ||
675 | 27 | msgstr "" | ||
676 | 28 | |||
677 | 29 | #. module: account_banking_pain_base | ||
678 | 30 | #: field:payment.line,priority:0 | ||
679 | 31 | msgid "Priority" | ||
680 | 32 | msgstr "" | ||
681 | 33 | |||
682 | 34 | #. module: account_banking_pain_base | ||
683 | 35 | #: model:ir.model,name:account_banking_pain_base.model_payment_line | ||
684 | 36 | msgid "Payment Line" | ||
685 | 37 | msgstr "" | ||
686 | 38 | |||
687 | 39 | #. module: account_banking_pain_base | ||
688 | 40 | #: model:ir.model,name:account_banking_pain_base.model_payment_mode | ||
689 | 41 | msgid "Payment Mode" | ||
690 | 42 | msgstr "" | ||
691 | 43 | |||
692 | 44 | #. module: account_banking_pain_base | ||
693 | 45 | #: help:res.company,initiating_party_issuer:0 | ||
694 | 46 | msgid "This will be used as the 'Initiating Party Issuer' in the PAIN files generated by OpenERP." | ||
695 | 47 | msgstr "" | ||
696 | 48 | |||
697 | 49 | #. module: account_banking_pain_base | ||
698 | 50 | #: code:addons/account_banking_pain_base/banking_export_pain.py:351 | ||
699 | 51 | #, python-format | ||
700 | 52 | msgid "Missing 'Structured Communication Type' on payment line with reference '%s'." | ||
701 | 53 | msgstr "" | ||
702 | 54 | |||
703 | 55 | #. module: account_banking_pain_base | ||
704 | 56 | #: selection:payment.line,priority:0 | ||
705 | 57 | msgid "Normal" | ||
706 | 58 | msgstr "" | ||
707 | 59 | |||
708 | 60 | #. module: account_banking_pain_base | ||
709 | 61 | #: code:addons/account_banking_pain_base/banking_export_pain.py:70 | ||
710 | 62 | #, python-format | ||
711 | 63 | msgid "Cannot compute the '%s' of the Payment Line with reference '%s'." | ||
712 | 64 | msgstr "" | ||
713 | 65 | |||
714 | 66 | #. module: account_banking_pain_base | ||
715 | 67 | #: code:addons/account_banking_pain_base/banking_export_pain.py:77 | ||
716 | 68 | #, python-format | ||
717 | 69 | msgid "Cannot compute the '%s'." | ||
718 | 70 | msgstr "" | ||
719 | 71 | |||
720 | 72 | #. module: account_banking_pain_base | ||
721 | 73 | #: code:addons/account_banking_pain_base/banking_export_pain.py:81 | ||
722 | 74 | #, python-format | ||
723 | 75 | msgid "The type of the field '%s' is %s. It should be a string or unicode." | ||
724 | 76 | msgstr "" | ||
725 | 77 | |||
726 | 78 | #. module: account_banking_pain_base | ||
727 | 79 | #: code:addons/account_banking_pain_base/banking_export_pain.py:47 | ||
728 | 80 | #: code:addons/account_banking_pain_base/banking_export_pain.py:69 | ||
729 | 81 | #: code:addons/account_banking_pain_base/banking_export_pain.py:76 | ||
730 | 82 | #: code:addons/account_banking_pain_base/banking_export_pain.py:86 | ||
731 | 83 | #: code:addons/account_banking_pain_base/banking_export_pain.py:121 | ||
732 | 84 | #: code:addons/account_banking_pain_base/banking_export_pain.py:350 | ||
733 | 85 | #, python-format | ||
734 | 86 | msgid "Error:" | ||
735 | 87 | msgstr "" | ||
736 | 88 | |||
737 | 89 | #. module: account_banking_pain_base | ||
738 | 90 | #: model:ir.model,name:account_banking_pain_base.model_res_company | ||
739 | 91 | msgid "Companies" | ||
740 | 92 | msgstr "" | ||
741 | 93 | |||
742 | 94 | #. module: account_banking_pain_base | ||
743 | 95 | #: code:addons/account_banking_pain_base/banking_export_pain.py:47 | ||
744 | 96 | #, python-format | ||
745 | 97 | msgid "This IBAN is not valid : %s" | ||
746 | 98 | msgstr "" | ||
747 | 99 | |||
748 | 100 | #. module: account_banking_pain_base | ||
749 | 101 | #: code:addons/account_banking_pain_base/banking_export_pain.py:80 | ||
750 | 102 | #, python-format | ||
751 | 103 | msgid "Field type error:" | ||
752 | 104 | msgstr "" | ||
753 | 105 | |||
754 | 106 | #. module: account_banking_pain_base | ||
755 | 107 | #: field:payment.line,struct_communication_type:0 | ||
756 | 108 | msgid "Structured Communication Type" | ||
757 | 109 | msgstr "" | ||
758 | 110 | |||
759 | 111 | #. module: account_banking_pain_base | ||
760 | 112 | #: code:addons/account_banking_pain_base/banking_export_pain.py:87 | ||
761 | 113 | #, python-format | ||
762 | 114 | msgid "The '%s' is empty or 0. It should have a non-null value." | ||
763 | 115 | msgstr "" | ||
764 | 116 | |||
765 | 117 | #. module: account_banking_pain_base | ||
766 | 118 | #: model:ir.model,name:account_banking_pain_base.model_banking_export_pain | ||
767 | 119 | msgid "banking.export.pain" | ||
768 | 120 | msgstr "" | ||
769 | 121 | |||
770 | 122 | #. module: account_banking_pain_base | ||
771 | 123 | #: help:payment.mode,convert_to_ascii:0 | ||
772 | 124 | 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." | ||
773 | 125 | msgstr "" | ||
774 | 126 | |||
775 | 127 | #. module: account_banking_pain_base | ||
776 | 128 | #: help:payment.line,priority:0 | ||
777 | 129 | msgid "This field will be used as the 'Instruction Priority' in the generated PAIN file." | ||
778 | 130 | msgstr "" | ||
779 | 131 | |||
780 | 132 | #. module: account_banking_pain_base | ||
781 | 133 | #: view:res.company:0 | ||
782 | 134 | msgid "Payment Initiation" | ||
783 | 135 | msgstr "" | ||
784 | 136 | |||
785 | 137 | #. module: account_banking_pain_base | ||
786 | 138 | #: selection:payment.line,priority:0 | ||
787 | 139 | msgid "High" | ||
788 | 140 | msgstr "" | ||
789 | 141 | |||
790 | 142 | #. module: account_banking_pain_base | ||
791 | 143 | #: field:payment.mode,convert_to_ascii:0 | ||
792 | 144 | msgid "Convert to ASCII" | ||
793 | 145 | msgstr "" | ||
794 | 146 | |||
795 | 0 | 147 | ||
796 | === added file 'account_banking_pain_base/i18n/fr.po' | |||
797 | --- account_banking_pain_base/i18n/fr.po 1970-01-01 00:00:00 +0000 | |||
798 | +++ account_banking_pain_base/i18n/fr.po 2014-01-13 12:42:46 +0000 | |||
799 | @@ -0,0 +1,146 @@ | |||
800 | 1 | # Translation of OpenERP Server. | ||
801 | 2 | # This file contains the translation of the following modules: | ||
802 | 3 | # * account_banking_pain_base | ||
803 | 4 | # | ||
804 | 5 | msgid "" | ||
805 | 6 | msgstr "" | ||
806 | 7 | "Project-Id-Version: OpenERP Server 7.0\n" | ||
807 | 8 | "Report-Msgid-Bugs-To: \n" | ||
808 | 9 | "POT-Creation-Date: 2013-12-23 21:27+0000\n" | ||
809 | 10 | "PO-Revision-Date: 2013-12-23 21:27+0000\n" | ||
810 | 11 | "Last-Translator: <>\n" | ||
811 | 12 | "Language-Team: \n" | ||
812 | 13 | "MIME-Version: 1.0\n" | ||
813 | 14 | "Content-Type: text/plain; charset=UTF-8\n" | ||
814 | 15 | "Content-Transfer-Encoding: \n" | ||
815 | 16 | "Plural-Forms: \n" | ||
816 | 17 | |||
817 | 18 | #. module: account_banking_pain_base | ||
818 | 19 | #: field:res.company,initiating_party_issuer:0 | ||
819 | 20 | msgid "Initiating Party Issuer" | ||
820 | 21 | msgstr "Initiating Party Issuer" | ||
821 | 22 | |||
822 | 23 | #. module: account_banking_pain_base | ||
823 | 24 | #: code:addons/account_banking_pain_base/banking_export_pain.py:122 | ||
824 | 25 | #, python-format | ||
825 | 26 | 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" | ||
826 | 27 | 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" | ||
827 | 28 | |||
828 | 29 | #. module: account_banking_pain_base | ||
829 | 30 | #: field:payment.line,priority:0 | ||
830 | 31 | msgid "Priority" | ||
831 | 32 | msgstr "Priorité" | ||
832 | 33 | |||
833 | 34 | #. module: account_banking_pain_base | ||
834 | 35 | #: model:ir.model,name:account_banking_pain_base.model_payment_line | ||
835 | 36 | msgid "Payment Line" | ||
836 | 37 | msgstr "Ligne de paiement" | ||
837 | 38 | |||
838 | 39 | #. module: account_banking_pain_base | ||
839 | 40 | #: model:ir.model,name:account_banking_pain_base.model_payment_mode | ||
840 | 41 | msgid "Payment Mode" | ||
841 | 42 | msgstr "Mode de paiement" | ||
842 | 43 | |||
843 | 44 | #. module: account_banking_pain_base | ||
844 | 45 | #: help:res.company,initiating_party_issuer:0 | ||
845 | 46 | msgid "This will be used as the 'Initiating Party Issuer' in the PAIN files generated by OpenERP." | ||
846 | 47 | msgstr "Ce champ sera le 'Initiating Party Issuer' dans les fichiers PAIN générés par OpenERP." | ||
847 | 48 | |||
848 | 49 | #. module: account_banking_pain_base | ||
849 | 50 | #: code:addons/account_banking_pain_base/banking_export_pain.py:351 | ||
850 | 51 | #, python-format | ||
851 | 52 | msgid "Missing 'Structured Communication Type' on payment line with reference '%s'." | ||
852 | 53 | msgstr "Le 'Type de communication structuré' n'est pas renseigné sur la ligne de paiement ayant la référence '%s'." | ||
853 | 54 | |||
854 | 55 | #. module: account_banking_pain_base | ||
855 | 56 | #: selection:payment.line,priority:0 | ||
856 | 57 | msgid "Normal" | ||
857 | 58 | msgstr "Normal" | ||
858 | 59 | |||
859 | 60 | #. module: account_banking_pain_base | ||
860 | 61 | #: code:addons/account_banking_pain_base/banking_export_pain.py:70 | ||
861 | 62 | #, python-format | ||
862 | 63 | msgid "Cannot compute the '%s' of the Payment Line with reference '%s'." | ||
863 | 64 | msgstr "Impossible de calculer le '%s' de la ligne de paiement ayant la référence '%s'." | ||
864 | 65 | |||
865 | 66 | #. module: account_banking_pain_base | ||
866 | 67 | #: code:addons/account_banking_pain_base/banking_export_pain.py:77 | ||
867 | 68 | #, python-format | ||
868 | 69 | msgid "Cannot compute the '%s'." | ||
869 | 70 | msgstr "Impossible de calculer le '%s'." | ||
870 | 71 | |||
871 | 72 | #. module: account_banking_pain_base | ||
872 | 73 | #: code:addons/account_banking_pain_base/banking_export_pain.py:81 | ||
873 | 74 | #, python-format | ||
874 | 75 | msgid "The type of the field '%s' is %s. It should be a string or unicode." | ||
875 | 76 | msgstr "Le type du champ '%s' est %s. Il devrait être de type string ou unicode." | ||
876 | 77 | |||
877 | 78 | #. module: account_banking_pain_base | ||
878 | 79 | #: code:addons/account_banking_pain_base/banking_export_pain.py:47 | ||
879 | 80 | #: code:addons/account_banking_pain_base/banking_export_pain.py:69 | ||
880 | 81 | #: code:addons/account_banking_pain_base/banking_export_pain.py:76 | ||
881 | 82 | #: code:addons/account_banking_pain_base/banking_export_pain.py:86 | ||
882 | 83 | #: code:addons/account_banking_pain_base/banking_export_pain.py:121 | ||
883 | 84 | #: code:addons/account_banking_pain_base/banking_export_pain.py:350 | ||
884 | 85 | #, python-format | ||
885 | 86 | msgid "Error:" | ||
886 | 87 | msgstr "Erreur :" | ||
887 | 88 | |||
888 | 89 | #. module: account_banking_pain_base | ||
889 | 90 | #: model:ir.model,name:account_banking_pain_base.model_res_company | ||
890 | 91 | msgid "Companies" | ||
891 | 92 | msgstr "Sociétés" | ||
892 | 93 | |||
893 | 94 | #. module: account_banking_pain_base | ||
894 | 95 | #: code:addons/account_banking_pain_base/banking_export_pain.py:47 | ||
895 | 96 | #, python-format | ||
896 | 97 | msgid "This IBAN is not valid : %s" | ||
897 | 98 | msgstr "Cet IBAN n'est pas valide : %s" | ||
898 | 99 | |||
899 | 100 | #. module: account_banking_pain_base | ||
900 | 101 | #: code:addons/account_banking_pain_base/banking_export_pain.py:80 | ||
901 | 102 | #, python-format | ||
902 | 103 | msgid "Field type error:" | ||
903 | 104 | msgstr "Erreur dans le type de champ :" | ||
904 | 105 | |||
905 | 106 | #. module: account_banking_pain_base | ||
906 | 107 | #: field:payment.line,struct_communication_type:0 | ||
907 | 108 | msgid "Structured Communication Type" | ||
908 | 109 | msgstr "Type de communication structurée" | ||
909 | 110 | |||
910 | 111 | #. module: account_banking_pain_base | ||
911 | 112 | #: code:addons/account_banking_pain_base/banking_export_pain.py:87 | ||
912 | 113 | #, python-format | ||
913 | 114 | msgid "The '%s' is empty or 0. It should have a non-null value." | ||
914 | 115 | msgstr "Le '%s' est vide ou égal à 0. Il devrait avoir une valeur non-nulle." | ||
915 | 116 | |||
916 | 117 | #. module: account_banking_pain_base | ||
917 | 118 | #: model:ir.model,name:account_banking_pain_base.model_banking_export_pain | ||
918 | 119 | msgid "banking.export.pain" | ||
919 | 120 | msgstr "banking.export.pain" | ||
920 | 121 | |||
921 | 122 | #. module: account_banking_pain_base | ||
922 | 123 | #: help:payment.mode,convert_to_ascii:0 | ||
923 | 124 | 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." | ||
924 | 125 | 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é." | ||
925 | 126 | |||
926 | 127 | #. module: account_banking_pain_base | ||
927 | 128 | #: help:payment.line,priority:0 | ||
928 | 129 | msgid "This field will be used as the 'Instruction Priority' in the generated PAIN file." | ||
929 | 130 | msgstr "Ce champ sera le 'Instruction Priority' dans le fichier PAIN généré." | ||
930 | 131 | |||
931 | 132 | #. module: account_banking_pain_base | ||
932 | 133 | #: view:res.company:0 | ||
933 | 134 | msgid "Payment Initiation" | ||
934 | 135 | msgstr "Payment Initiation" | ||
935 | 136 | |||
936 | 137 | #. module: account_banking_pain_base | ||
937 | 138 | #: selection:payment.line,priority:0 | ||
938 | 139 | msgid "High" | ||
939 | 140 | msgstr "Élevé" | ||
940 | 141 | |||
941 | 142 | #. module: account_banking_pain_base | ||
942 | 143 | #: field:payment.mode,convert_to_ascii:0 | ||
943 | 144 | msgid "Convert to ASCII" | ||
944 | 145 | msgstr "Convertir en ASCII" | ||
945 | 146 | |||
946 | 0 | 147 | ||
947 | === added file 'account_banking_pain_base/payment_line.py' | |||
948 | --- account_banking_pain_base/payment_line.py 1970-01-01 00:00:00 +0000 | |||
949 | +++ account_banking_pain_base/payment_line.py 2014-01-13 12:42:46 +0000 | |||
950 | @@ -0,0 +1,52 @@ | |||
951 | 1 | # -*- encoding: utf-8 -*- | ||
952 | 2 | ############################################################################## | ||
953 | 3 | # | ||
954 | 4 | # PAIN Base module for OpenERP | ||
955 | 5 | # Copyright (C) 2013 Akretion (http://www.akretion.com) | ||
956 | 6 | # @author: Alexis de Lattre <alexis.delattre@akretion.com> | ||
957 | 7 | # | ||
958 | 8 | # This program is free software: you can redistribute it and/or modify | ||
959 | 9 | # it under the terms of the GNU Affero General Public License as | ||
960 | 10 | # published by the Free Software Foundation, either version 3 of the | ||
961 | 11 | # License, or (at your option) any later version. | ||
962 | 12 | # | ||
963 | 13 | # This program is distributed in the hope that it will be useful, | ||
964 | 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
965 | 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
966 | 16 | # GNU Affero General Public License for more details. | ||
967 | 17 | # | ||
968 | 18 | # You should have received a copy of the GNU Affero General Public License | ||
969 | 19 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
970 | 20 | # | ||
971 | 21 | ############################################################################## | ||
972 | 22 | |||
973 | 23 | from openerp.osv import orm, fields | ||
974 | 24 | |||
975 | 25 | |||
976 | 26 | class payment_line(orm.Model): | ||
977 | 27 | _inherit = 'payment.line' | ||
978 | 28 | |||
979 | 29 | def _get_struct_communication_types(self, cr, uid, context=None): | ||
980 | 30 | return [('ISO', 'ISO')] | ||
981 | 31 | |||
982 | 32 | _columns = { | ||
983 | 33 | 'priority': fields.selection([ | ||
984 | 34 | ('NORM', 'Normal'), | ||
985 | 35 | ('HIGH', 'High'), | ||
986 | 36 | ], 'Priority', | ||
987 | 37 | help="This field will be used as the 'Instruction Priority' in " | ||
988 | 38 | "the generated PAIN file."), | ||
989 | 39 | # Update size from 64 to 140, because PAIN allows 140 caracters | ||
990 | 40 | 'communication': fields.char( | ||
991 | 41 | 'Communication', size=140, required=True, | ||
992 | 42 | help="Used as the message between ordering customer and current " | ||
993 | 43 | "company. Depicts 'What do you want to say to the recipient " | ||
994 | 44 | "about this order ?'"), | ||
995 | 45 | 'struct_communication_type': fields.selection( | ||
996 | 46 | _get_struct_communication_types, 'Structured Communication Type'), | ||
997 | 47 | } | ||
998 | 48 | |||
999 | 49 | _defaults = { | ||
1000 | 50 | 'priority': 'NORM', | ||
1001 | 51 | 'struct_communication_type': 'ISO', | ||
1002 | 52 | } | ||
1003 | 0 | 53 | ||
1004 | === added file 'account_banking_pain_base/payment_line_view.xml' | |||
1005 | --- account_banking_pain_base/payment_line_view.xml 1970-01-01 00:00:00 +0000 | |||
1006 | +++ account_banking_pain_base/payment_line_view.xml 2014-01-13 12:42:46 +0000 | |||
1007 | @@ -0,0 +1,41 @@ | |||
1008 | 1 | <?xml version="1.0" encoding="utf-8"?> | ||
1009 | 2 | <!-- | ||
1010 | 3 | Copyright (C) 2013 Akretion (http://www.akretion.com) | ||
1011 | 4 | @author: Alexis de Lattre <alexis.delattre@akretion.com> | ||
1012 | 5 | The licence is in the file __openerp__.py | ||
1013 | 6 | --> | ||
1014 | 7 | <openerp> | ||
1015 | 8 | <data> | ||
1016 | 9 | |||
1017 | 10 | <record id="view_payment_line_form" model="ir.ui.view"> | ||
1018 | 11 | <field name="name">pain.base.payment.line.form</field> | ||
1019 | 12 | <field name="model">payment.line</field> | ||
1020 | 13 | <field name="inherit_id" ref="account_payment.view_payment_line_form"/> | ||
1021 | 14 | <field name="arch" type="xml"> | ||
1022 | 15 | <field name="bank_id" position="after"> | ||
1023 | 16 | <field name="priority"/> | ||
1024 | 17 | <newline /> | ||
1025 | 18 | </field> | ||
1026 | 19 | <field name="state" position="after"> | ||
1027 | 20 | <field name="struct_communication_type" attrs="{'invisible': [('state', '!=', 'structured')], 'required': [('state', '=', 'structured')]}"/> | ||
1028 | 21 | </field> | ||
1029 | 22 | </field> | ||
1030 | 23 | </record> | ||
1031 | 24 | |||
1032 | 25 | <record id="view_payment_order_form" model="ir.ui.view"> | ||
1033 | 26 | <field name="name">pain.base.payment.line.inside.order.form</field> | ||
1034 | 27 | <field name="model">payment.order</field> | ||
1035 | 28 | <field name="inherit_id" ref="account_payment.view_payment_order_form"/> | ||
1036 | 29 | <field name="arch" type="xml"> | ||
1037 | 30 | <xpath expr="//field[@name='line_ids']/form//field[@name='bank_id']" position="after"> | ||
1038 | 31 | <field name="priority"/> | ||
1039 | 32 | <newline /> | ||
1040 | 33 | </xpath> | ||
1041 | 34 | <xpath expr="//field[@name='line_ids']/form//field[@name='state']" position="after"> | ||
1042 | 35 | <field name="struct_communication_type" attrs="{'invisible': [('state', '!=', 'structured')], 'required': [('state', '=', 'structured')]}"/> | ||
1043 | 36 | </xpath> | ||
1044 | 37 | </field> | ||
1045 | 38 | </record> | ||
1046 | 39 | |||
1047 | 40 | </data> | ||
1048 | 41 | </openerp> | ||
1049 | 0 | 42 | ||
1050 | === added file 'account_banking_pain_base/payment_mode.py' | |||
1051 | --- account_banking_pain_base/payment_mode.py 1970-01-01 00:00:00 +0000 | |||
1052 | +++ account_banking_pain_base/payment_mode.py 2014-01-13 12:42:46 +0000 | |||
1053 | @@ -0,0 +1,39 @@ | |||
1054 | 1 | # -*- encoding: utf-8 -*- | ||
1055 | 2 | ############################################################################## | ||
1056 | 3 | # | ||
1057 | 4 | # PAIN Base module for OpenERP | ||
1058 | 5 | # Copyright (C) 2013 Akretion (http://www.akretion.com) | ||
1059 | 6 | # @author: Alexis de Lattre <alexis.delattre@akretion.com> | ||
1060 | 7 | # | ||
1061 | 8 | # This program is free software: you can redistribute it and/or modify | ||
1062 | 9 | # it under the terms of the GNU Affero General Public License as | ||
1063 | 10 | # published by the Free Software Foundation, either version 3 of the | ||
1064 | 11 | # License, or (at your option) any later version. | ||
1065 | 12 | # | ||
1066 | 13 | # This program is distributed in the hope that it will be useful, | ||
1067 | 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1068 | 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1069 | 16 | # GNU Affero General Public License for more details. | ||
1070 | 17 | # | ||
1071 | 18 | # You should have received a copy of the GNU Affero General Public License | ||
1072 | 19 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1073 | 20 | # | ||
1074 | 21 | ############################################################################## | ||
1075 | 22 | |||
1076 | 23 | from openerp.osv import orm, fields | ||
1077 | 24 | |||
1078 | 25 | |||
1079 | 26 | class payment_mode(orm.Model): | ||
1080 | 27 | _inherit = 'payment.mode' | ||
1081 | 28 | |||
1082 | 29 | _columns = { | ||
1083 | 30 | 'convert_to_ascii': fields.boolean( | ||
1084 | 31 | 'Convert to ASCII', | ||
1085 | 32 | help="If active, OpenERP will convert each accented caracter to " | ||
1086 | 33 | "the corresponding unaccented caracter, so that only ASCII " | ||
1087 | 34 | "caracters are used in the generated PAIN file."), | ||
1088 | 35 | } | ||
1089 | 36 | |||
1090 | 37 | _defaults = { | ||
1091 | 38 | 'convert_to_ascii': True, | ||
1092 | 39 | } | ||
1093 | 0 | 40 | ||
1094 | === added file 'account_banking_pain_base/payment_mode_view.xml' | |||
1095 | --- account_banking_pain_base/payment_mode_view.xml 1970-01-01 00:00:00 +0000 | |||
1096 | +++ account_banking_pain_base/payment_mode_view.xml 2014-01-13 12:42:46 +0000 | |||
1097 | @@ -0,0 +1,22 @@ | |||
1098 | 1 | <?xml version="1.0" encoding="utf-8"?> | ||
1099 | 2 | <!-- | ||
1100 | 3 | Copyright (C) 2013 Akretion (http://www.akretion.com) | ||
1101 | 4 | @author: Alexis de Lattre <alexis.delattre@akretion.com> | ||
1102 | 5 | The licence is in the file __openerp__.py | ||
1103 | 6 | --> | ||
1104 | 7 | <openerp> | ||
1105 | 8 | <data> | ||
1106 | 9 | |||
1107 | 10 | <record id="view_payment_mode_form_inherit" model="ir.ui.view"> | ||
1108 | 11 | <field name="name">add.convert_to_ascii.in.payment.mode.form</field> | ||
1109 | 12 | <field name="model">payment.mode</field> | ||
1110 | 13 | <field name="inherit_id" ref="account_banking_payment_export.view_payment_mode_form_inherit"/> | ||
1111 | 14 | <field name="arch" type="xml"> | ||
1112 | 15 | <field name="type" position="after"> | ||
1113 | 16 | <field name="convert_to_ascii"/> | ||
1114 | 17 | </field> | ||
1115 | 18 | </field> | ||
1116 | 19 | </record> | ||
1117 | 20 | |||
1118 | 21 | </data> | ||
1119 | 22 | </openerp> | ||
1120 | 0 | 23 | ||
1121 | === modified file 'account_banking_payment/__openerp__.py' | |||
1122 | --- account_banking_payment/__openerp__.py 2013-08-13 09:18:15 +0000 | |||
1123 | +++ account_banking_payment/__openerp__.py 2014-01-13 12:42:46 +0000 | |||
1124 | @@ -39,6 +39,7 @@ | |||
1125 | 39 | 'view/banking_transaction_wizard.xml', | 39 | 'view/banking_transaction_wizard.xml', |
1126 | 40 | 'view/payment_mode.xml', | 40 | 'view/payment_mode.xml', |
1127 | 41 | 'view/payment_mode_type.xml', | 41 | 'view/payment_mode_type.xml', |
1128 | 42 | 'view/payment_order_create_view.xml', | ||
1129 | 42 | 'workflow/account_payment.xml', | 43 | 'workflow/account_payment.xml', |
1130 | 43 | ], | 44 | ], |
1131 | 44 | 'description': ''' | 45 | 'description': ''' |
1132 | 45 | 46 | ||
1133 | === modified file 'account_banking_payment/model/__init__.py' | |||
1134 | --- account_banking_payment/model/__init__.py 2013-08-13 09:18:15 +0000 | |||
1135 | +++ account_banking_payment/model/__init__.py 2014-01-13 12:42:46 +0000 | |||
1136 | @@ -1,7 +1,7 @@ | |||
1137 | 1 | import account_payment | 1 | import account_payment |
1138 | 2 | import payment_line | 2 | import payment_line |
1139 | 3 | import payment_mode_type | ||
1140 | 3 | import payment_mode | 4 | import payment_mode |
1141 | 4 | import payment_mode_type | ||
1142 | 5 | import payment_order_create | 5 | import payment_order_create |
1143 | 6 | import banking_import_transaction | 6 | import banking_import_transaction |
1144 | 7 | import banking_transaction_wizard | 7 | import banking_transaction_wizard |
1145 | 8 | 8 | ||
1146 | === modified file 'account_banking_payment/model/account_payment.py' | |||
1147 | --- account_banking_payment/model/account_payment.py 2013-10-14 11:18:42 +0000 | |||
1148 | +++ account_banking_payment/model/account_payment.py 2014-01-13 12:42:46 +0000 | |||
1149 | @@ -107,6 +107,7 @@ | |||
1150 | 107 | 'payment_order_type': fields.selection( | 107 | 'payment_order_type': fields.selection( |
1151 | 108 | [('payment', 'Payment'),('debit', 'Direct debit')], | 108 | [('payment', 'Payment'),('debit', 'Direct debit')], |
1152 | 109 | 'Payment order type', required=True, | 109 | 'Payment order type', required=True, |
1153 | 110 | readonly=True, states={'draft': [('readonly', False)]}, | ||
1154 | 110 | ), | 111 | ), |
1155 | 111 | 'date_sent': fields.date('Send date', readonly=True), | 112 | 'date_sent': fields.date('Send date', readonly=True), |
1156 | 112 | } | 113 | } |
1157 | 113 | 114 | ||
1158 | === modified file 'account_banking_payment/model/payment_mode.py' | |||
1159 | --- account_banking_payment/model/payment_mode.py 2013-08-13 09:18:15 +0000 | |||
1160 | +++ account_banking_payment/model/payment_mode.py 2014-01-13 12:42:46 +0000 | |||
1161 | @@ -34,10 +34,9 @@ | |||
1162 | 34 | 'account.account', 'Transfer account', | 34 | 'account.account', 'Transfer account', |
1163 | 35 | domain=[('type', '=', 'other'), | 35 | domain=[('type', '=', 'other'), |
1164 | 36 | ('reconcile', '=', True)], | 36 | ('reconcile', '=', True)], |
1169 | 37 | help=('Pay off lines in sent orders with a ' | 37 | help=('Pay off lines in sent orders with a move on this ' |
1170 | 38 | 'move on this account. For debit type modes only. ' | 38 | 'account. You can only select accounts of type regular ' |
1171 | 39 | 'You can only select accounts of type regular that ' | 39 | 'that are marked for reconciliation'), |
1168 | 40 | 'are marked for reconciliation'), | ||
1172 | 41 | ), | 40 | ), |
1173 | 42 | 'transfer_journal_id': fields.many2one( | 41 | 'transfer_journal_id': fields.many2one( |
1174 | 43 | 'account.journal', 'Transfer journal', | 42 | 'account.journal', 'Transfer journal', |
1175 | @@ -50,4 +49,8 @@ | |||
1176 | 50 | help=('Limit selected invoices to invoices with these payment ' | 49 | help=('Limit selected invoices to invoices with these payment ' |
1177 | 51 | 'terms') | 50 | 'terms') |
1178 | 52 | ), | 51 | ), |
1179 | 52 | 'payment_order_type': fields.related( | ||
1180 | 53 | 'type', 'payment_order_type', readonly=True, type='selection', | ||
1181 | 54 | selection=[('payment', 'Payment'), ('debit', 'Direct debit')], | ||
1182 | 55 | string="Payment Order Type"), | ||
1183 | 53 | } | 56 | } |
1184 | 54 | 57 | ||
1185 | === modified file 'account_banking_payment/view/payment_mode.xml' | |||
1186 | --- account_banking_payment/view/payment_mode.xml 2013-08-13 09:18:15 +0000 | |||
1187 | +++ account_banking_payment/view/payment_mode.xml 2014-01-13 12:42:46 +0000 | |||
1188 | @@ -11,6 +11,7 @@ | |||
1189 | 11 | <field name="inherit_id" ref="account_banking_payment_export.view_payment_mode_form_inherit"/> | 11 | <field name="inherit_id" ref="account_banking_payment_export.view_payment_mode_form_inherit"/> |
1190 | 12 | <field name="arch" type="xml"> | 12 | <field name="arch" type="xml"> |
1191 | 13 | <field name="type" position="after"> | 13 | <field name="type" position="after"> |
1192 | 14 | <field name="payment_order_type"/> | ||
1193 | 14 | <group colspan="4" col="4"> | 15 | <group colspan="4" col="4"> |
1194 | 15 | <group colspan="2"> | 16 | <group colspan="2"> |
1195 | 16 | <separator colspan="2" | 17 | <separator colspan="2" |
1196 | 17 | 18 | ||
1197 | === added file 'account_banking_payment/view/payment_order_create_view.xml' | |||
1198 | --- account_banking_payment/view/payment_order_create_view.xml 1970-01-01 00:00:00 +0000 | |||
1199 | +++ account_banking_payment/view/payment_order_create_view.xml 2014-01-13 12:42:46 +0000 | |||
1200 | @@ -0,0 +1,23 @@ | |||
1201 | 1 | <?xml version="1.0" encoding="utf-8"?> | ||
1202 | 2 | <!-- | ||
1203 | 3 | Copyright (C) 2013 Akretion (http://www.akretion.com) | ||
1204 | 4 | @author: Alexis de Lattre <alexis.delattre@akretion.com> | ||
1205 | 5 | The licence is in the file __openerp__.py | ||
1206 | 6 | --> | ||
1207 | 7 | <openerp> | ||
1208 | 8 | <data> | ||
1209 | 9 | |||
1210 | 10 | <record id="view_create_payment_order_lines" model="ir.ui.view"> | ||
1211 | 11 | <field name="name">add.context.to.display.maturity.date</field> | ||
1212 | 12 | <field name="model">payment.order.create</field> | ||
1213 | 13 | <field name="inherit_id" ref="account_payment.view_create_payment_order_lines"/> | ||
1214 | 14 | <field name="arch" type="xml"> | ||
1215 | 15 | <field name="entries" position="attributes"> | ||
1216 | 16 | <attribute name="context">{'journal_type': 'sale'}</attribute> | ||
1217 | 17 | <attribute name="nolabel">1</attribute> | ||
1218 | 18 | </field> | ||
1219 | 19 | </field> | ||
1220 | 20 | </record> | ||
1221 | 21 | |||
1222 | 22 | </data> | ||
1223 | 23 | </openerp> | ||
1224 | 0 | 24 | ||
1225 | === modified file 'account_banking_sepa_credit_transfer/__openerp__.py' | |||
1226 | --- account_banking_sepa_credit_transfer/__openerp__.py 2013-11-13 08:19:50 +0000 | |||
1227 | +++ account_banking_sepa_credit_transfer/__openerp__.py 2014-01-13 12:42:46 +0000 | |||
1228 | @@ -26,7 +26,7 @@ | |||
1229 | 26 | 'author': 'Akretion', | 26 | 'author': 'Akretion', |
1230 | 27 | 'website': 'http://www.akretion.com', | 27 | 'website': 'http://www.akretion.com', |
1231 | 28 | 'category': 'Banking addons', | 28 | 'category': 'Banking addons', |
1233 | 29 | 'depends': ['account_banking_payment_export'], | 29 | 'depends': ['account_banking_pain_base'], |
1234 | 30 | 'external_dependencies': { | 30 | 'external_dependencies': { |
1235 | 31 | 'python': ['unidecode', 'lxml'], | 31 | 'python': ['unidecode', 'lxml'], |
1236 | 32 | }, | 32 | }, |
1237 | 33 | 33 | ||
1238 | === modified file 'account_banking_sepa_credit_transfer/account_banking_sepa.py' | |||
1239 | --- account_banking_sepa_credit_transfer/account_banking_sepa.py 2013-11-12 21:38:21 +0000 | |||
1240 | +++ account_banking_sepa_credit_transfer/account_banking_sepa.py 2014-01-13 12:42:46 +0000 | |||
1241 | @@ -48,22 +48,31 @@ | |||
1242 | 48 | 'banking_export_sepa_id', 'account_order_id', | 48 | 'banking_export_sepa_id', 'account_order_id', |
1243 | 49 | 'Payment Orders', | 49 | 'Payment Orders', |
1244 | 50 | readonly=True), | 50 | readonly=True), |
1245 | 51 | 'prefered_exec_date': fields.date( | ||
1246 | 52 | 'Prefered Execution Date', readonly=True), | ||
1247 | 53 | 'nb_transactions': fields.integer( | 51 | 'nb_transactions': fields.integer( |
1248 | 54 | 'Number of Transactions', readonly=True), | 52 | 'Number of Transactions', readonly=True), |
1251 | 55 | 'total_amount': fields.float('Total Amount', | 53 | 'total_amount': fields.float( |
1252 | 56 | digits_compute=dp.get_precision('Account'), readonly=True), | 54 | 'Total Amount', digits_compute=dp.get_precision('Account'), |
1253 | 55 | readonly=True), | ||
1254 | 57 | 'batch_booking': fields.boolean( | 56 | 'batch_booking': fields.boolean( |
1255 | 58 | 'Batch Booking', readonly=True, | 57 | 'Batch Booking', readonly=True, |
1257 | 59 | 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."), | 58 | help="If true, the bank statement will display only one debit " |
1258 | 59 | "line for all the wire transfers of the SEPA XML file ; " | ||
1259 | 60 | "if false, the bank statement will display one debit line " | ||
1260 | 61 | "per wire transfer of the SEPA XML file."), | ||
1261 | 60 | 'charge_bearer': fields.selection([ | 62 | 'charge_bearer': fields.selection([ |
1262 | 61 | ('SLEV', 'Following Service Level'), | 63 | ('SLEV', 'Following Service Level'), |
1263 | 62 | ('SHAR', 'Shared'), | 64 | ('SHAR', 'Shared'), |
1264 | 63 | ('CRED', 'Borne by Creditor'), | 65 | ('CRED', 'Borne by Creditor'), |
1265 | 64 | ('DEBT', 'Borne by Debtor'), | 66 | ('DEBT', 'Borne by Debtor'), |
1266 | 65 | ], 'Charge Bearer', readonly=True, | 67 | ], 'Charge Bearer', readonly=True, |
1268 | 66 | 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.'), | 68 | help="Following service level : transaction charges are to be " |
1269 | 69 | "applied following the rules agreed in the service level and/or " | ||
1270 | 70 | "scheme (SEPA Core messages must use this). Shared : " | ||
1271 | 71 | "transaction charges on the creditor side are to be borne by " | ||
1272 | 72 | "the creditor, transaction charges on the debtor side are to " | ||
1273 | 73 | "be borne by the debtor. Borne by creditor : all transaction " | ||
1274 | 74 | "charges are to be borne by the creditor. Borne by debtor : " | ||
1275 | 75 | "all transaction charges are to be borne by the debtor."), | ||
1276 | 67 | 'create_date': fields.datetime('Generation Date', readonly=True), | 76 | 'create_date': fields.datetime('Generation Date', readonly=True), |
1277 | 68 | 'file': fields.binary('SEPA XML File', readonly=True), | 77 | 'file': fields.binary('SEPA XML File', readonly=True), |
1278 | 69 | 'filename': fields.function( | 78 | 'filename': fields.function( |
1279 | 70 | 79 | ||
1280 | === modified file 'account_banking_sepa_credit_transfer/account_banking_sepa_view.xml' | |||
1281 | --- account_banking_sepa_credit_transfer/account_banking_sepa_view.xml 2013-11-07 11:50:36 +0000 | |||
1282 | +++ account_banking_sepa_credit_transfer/account_banking_sepa_view.xml 2014-01-13 12:42:46 +0000 | |||
1283 | @@ -16,7 +16,6 @@ | |||
1284 | 16 | <page string="General Information"> | 16 | <page string="General Information"> |
1285 | 17 | <field name="total_amount" /> | 17 | <field name="total_amount" /> |
1286 | 18 | <field name="nb_transactions" /> | 18 | <field name="nb_transactions" /> |
1287 | 19 | <field name="prefered_exec_date" /> | ||
1288 | 20 | <field name="batch_booking" /> | 19 | <field name="batch_booking" /> |
1289 | 21 | <field name="charge_bearer"/> | 20 | <field name="charge_bearer"/> |
1290 | 22 | <field name="create_date" /> | 21 | <field name="create_date" /> |
1291 | @@ -47,7 +46,6 @@ | |||
1292 | 47 | <field name="arch" type="xml"> | 46 | <field name="arch" type="xml"> |
1293 | 48 | <tree string="SEPA Credit Transfer"> | 47 | <tree string="SEPA Credit Transfer"> |
1294 | 49 | <field name="filename"/> | 48 | <field name="filename"/> |
1295 | 50 | <field name="prefered_exec_date"/> | ||
1296 | 51 | <field name="create_date"/> | 49 | <field name="create_date"/> |
1297 | 52 | <field name="nb_transactions"/> | 50 | <field name="nb_transactions"/> |
1298 | 53 | </tree> | 51 | </tree> |
1299 | 54 | 52 | ||
1300 | === modified file 'account_banking_sepa_credit_transfer/i18n/account_banking_sepa_credit_transfer.pot' | |||
1301 | --- account_banking_sepa_credit_transfer/i18n/account_banking_sepa_credit_transfer.pot 2013-11-13 09:17:33 +0000 | |||
1302 | +++ account_banking_sepa_credit_transfer/i18n/account_banking_sepa_credit_transfer.pot 2014-01-13 12:42:46 +0000 | |||
1303 | @@ -6,8 +6,8 @@ | |||
1304 | 6 | msgstr "" | 6 | msgstr "" |
1305 | 7 | "Project-Id-Version: OpenERP Server 7.0\n" | 7 | "Project-Id-Version: OpenERP Server 7.0\n" |
1306 | 8 | "Report-Msgid-Bugs-To: \n" | 8 | "Report-Msgid-Bugs-To: \n" |
1309 | 9 | "POT-Creation-Date: 2013-11-13 09:13+0000\n" | 9 | "POT-Creation-Date: 2013-12-23 22:49+0000\n" |
1310 | 10 | "PO-Revision-Date: 2013-11-13 09:13+0000\n" | 10 | "PO-Revision-Date: 2013-12-23 22:49+0000\n" |
1311 | 11 | "Last-Translator: <>\n" | 11 | "Last-Translator: <>\n" |
1312 | 12 | "Language-Team: \n" | 12 | "Language-Team: \n" |
1313 | 13 | "MIME-Version: 1.0\n" | 13 | "MIME-Version: 1.0\n" |
1314 | @@ -16,12 +16,6 @@ | |||
1315 | 16 | "Plural-Forms: \n" | 16 | "Plural-Forms: \n" |
1316 | 17 | 17 | ||
1317 | 18 | #. module: account_banking_sepa_credit_transfer | 18 | #. module: account_banking_sepa_credit_transfer |
1318 | 19 | #: field:banking.export.sepa,prefered_exec_date:0 | ||
1319 | 20 | #: field:banking.export.sepa.wizard,prefered_exec_date:0 | ||
1320 | 21 | msgid "Prefered Execution Date" | ||
1321 | 22 | msgstr "" | ||
1322 | 23 | |||
1323 | 24 | #. module: account_banking_sepa_credit_transfer | ||
1324 | 25 | #: selection:banking.export.sepa.wizard,state:0 | 19 | #: selection:banking.export.sepa.wizard,state:0 |
1325 | 26 | msgid "Create" | 20 | msgid "Create" |
1326 | 27 | msgstr "" | 21 | msgstr "" |
1327 | @@ -55,12 +49,6 @@ | |||
1328 | 55 | msgstr "" | 49 | msgstr "" |
1329 | 56 | 50 | ||
1330 | 57 | #. module: account_banking_sepa_credit_transfer | 51 | #. module: account_banking_sepa_credit_transfer |
1331 | 58 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:117 | ||
1332 | 59 | #, python-format | ||
1333 | 60 | msgid "Cannot compute the '%s' of the Payment Line with Invoice Reference '%s'." | ||
1334 | 61 | msgstr "" | ||
1335 | 62 | |||
1336 | 63 | #. module: account_banking_sepa_credit_transfer | ||
1337 | 64 | #: selection:banking.export.sepa,charge_bearer:0 | 52 | #: selection:banking.export.sepa,charge_bearer:0 |
1338 | 65 | #: selection:banking.export.sepa.wizard,charge_bearer:0 | 53 | #: selection:banking.export.sepa.wizard,charge_bearer:0 |
1339 | 66 | msgid "Shared" | 54 | msgid "Shared" |
1340 | @@ -73,8 +61,13 @@ | |||
1341 | 73 | msgstr "" | 61 | msgstr "" |
1342 | 74 | 62 | ||
1343 | 75 | #. module: account_banking_sepa_credit_transfer | 63 | #. module: account_banking_sepa_credit_transfer |
1344 | 64 | #: selection:banking.export.sepa,state:0 | ||
1345 | 65 | msgid "Sent" | ||
1346 | 66 | msgstr "" | ||
1347 | 67 | |||
1348 | 68 | #. module: account_banking_sepa_credit_transfer | ||
1349 | 76 | #: model:ir.model,name:account_banking_sepa_credit_transfer.model_banking_export_sepa_wizard | 69 | #: model:ir.model,name:account_banking_sepa_credit_transfer.model_banking_export_sepa_wizard |
1351 | 77 | msgid "Export SEPA Credit Transfer XML file" | 70 | msgid "Export SEPA Credit Transfer File" |
1352 | 78 | msgstr "" | 71 | msgstr "" |
1353 | 79 | 72 | ||
1354 | 80 | #. module: account_banking_sepa_credit_transfer | 73 | #. module: account_banking_sepa_credit_transfer |
1355 | @@ -105,23 +98,6 @@ | |||
1356 | 105 | msgstr "" | 98 | msgstr "" |
1357 | 106 | 99 | ||
1358 | 107 | #. module: account_banking_sepa_credit_transfer | 100 | #. module: account_banking_sepa_credit_transfer |
1359 | 108 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:122 | ||
1360 | 109 | #, python-format | ||
1361 | 110 | msgid "Cannot compute the '%s'." | ||
1362 | 111 | msgstr "" | ||
1363 | 112 | |||
1364 | 113 | #. module: account_banking_sepa_credit_transfer | ||
1365 | 114 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:126 | ||
1366 | 115 | #, python-format | ||
1367 | 116 | msgid "The type of the field '%s' is %s. It should be a string or unicode." | ||
1368 | 117 | msgstr "" | ||
1369 | 118 | |||
1370 | 119 | #. module: account_banking_sepa_credit_transfer | ||
1371 | 120 | #: selection:banking.export.sepa,state:0 | ||
1372 | 121 | msgid "Sent" | ||
1373 | 122 | msgstr "" | ||
1374 | 123 | |||
1375 | 124 | #. module: account_banking_sepa_credit_transfer | ||
1376 | 125 | #: view:banking.export.sepa.wizard:0 | 101 | #: view:banking.export.sepa.wizard:0 |
1377 | 126 | msgid "Validate" | 102 | msgid "Validate" |
1378 | 127 | msgstr "" | 103 | msgstr "" |
1379 | @@ -132,25 +108,14 @@ | |||
1380 | 132 | msgstr "" | 108 | msgstr "" |
1381 | 133 | 109 | ||
1382 | 134 | #. module: account_banking_sepa_credit_transfer | 110 | #. module: account_banking_sepa_credit_transfer |
1383 | 135 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:169 | ||
1384 | 136 | #, python-format | ||
1385 | 137 | 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" | ||
1386 | 138 | msgstr "" | ||
1387 | 139 | |||
1388 | 140 | #. module: account_banking_sepa_credit_transfer | ||
1389 | 141 | #: selection:banking.export.sepa,charge_bearer:0 | 111 | #: selection:banking.export.sepa,charge_bearer:0 |
1390 | 142 | #: selection:banking.export.sepa.wizard,charge_bearer:0 | 112 | #: selection:banking.export.sepa.wizard,charge_bearer:0 |
1391 | 143 | msgid "Borne by Debtor" | 113 | msgid "Borne by Debtor" |
1392 | 144 | msgstr "" | 114 | msgstr "" |
1393 | 145 | 115 | ||
1394 | 146 | #. module: account_banking_sepa_credit_transfer | 116 | #. module: account_banking_sepa_credit_transfer |
1402 | 147 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:90 | 117 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:128 |
1403 | 148 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:116 | 118 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:245 |
1397 | 149 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:121 | ||
1398 | 150 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:130 | ||
1399 | 151 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:168 | ||
1400 | 152 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:206 | ||
1401 | 153 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:350 | ||
1404 | 154 | #, python-format | 119 | #, python-format |
1405 | 155 | msgid "Error:" | 120 | msgid "Error:" |
1406 | 156 | msgstr "" | 121 | msgstr "" |
1407 | @@ -173,18 +138,12 @@ | |||
1408 | 173 | msgstr "" | 138 | msgstr "" |
1409 | 174 | 139 | ||
1410 | 175 | #. module: account_banking_sepa_credit_transfer | 140 | #. module: account_banking_sepa_credit_transfer |
1411 | 176 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:125 | ||
1412 | 177 | #, python-format | ||
1413 | 178 | msgid "Field type error:" | ||
1414 | 179 | msgstr "" | ||
1415 | 180 | |||
1416 | 181 | #. module: account_banking_sepa_credit_transfer | ||
1417 | 182 | #: model:ir.model,name:account_banking_sepa_credit_transfer.model_banking_export_sepa | 141 | #: model:ir.model,name:account_banking_sepa_credit_transfer.model_banking_export_sepa |
1418 | 183 | msgid "SEPA export" | 142 | msgid "SEPA export" |
1419 | 184 | msgstr "" | 143 | msgstr "" |
1420 | 185 | 144 | ||
1421 | 186 | #. module: account_banking_sepa_credit_transfer | 145 | #. module: account_banking_sepa_credit_transfer |
1423 | 187 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:351 | 146 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:246 |
1424 | 188 | #, python-format | 147 | #, python-format |
1425 | 189 | msgid "Missing Bank Account on invoice '%s' (payment order line reference '%s')." | 148 | msgid "Missing Bank Account on invoice '%s' (payment order line reference '%s')." |
1426 | 190 | msgstr "" | 149 | msgstr "" |
1427 | @@ -196,29 +155,17 @@ | |||
1428 | 196 | msgstr "" | 155 | msgstr "" |
1429 | 197 | 156 | ||
1430 | 198 | #. module: account_banking_sepa_credit_transfer | 157 | #. module: account_banking_sepa_credit_transfer |
1431 | 199 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:131 | ||
1432 | 200 | #, python-format | ||
1433 | 201 | msgid "The '%s' is empty or 0. It should have a non-null value." | ||
1434 | 202 | msgstr "" | ||
1435 | 203 | |||
1436 | 204 | #. module: account_banking_sepa_credit_transfer | ||
1437 | 205 | #: help:banking.export.sepa,charge_bearer:0 | 158 | #: help:banking.export.sepa,charge_bearer:0 |
1438 | 206 | 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." | 159 | 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." |
1439 | 207 | msgstr "" | 160 | msgstr "" |
1440 | 208 | 161 | ||
1441 | 209 | #. module: account_banking_sepa_credit_transfer | 162 | #. module: account_banking_sepa_credit_transfer |
1443 | 210 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:207 | 163 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:129 |
1444 | 211 | #, python-format | 164 | #, python-format |
1445 | 212 | 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'." | 165 | 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'." |
1446 | 213 | msgstr "" | 166 | msgstr "" |
1447 | 214 | 167 | ||
1448 | 215 | #. module: account_banking_sepa_credit_transfer | 168 | #. module: account_banking_sepa_credit_transfer |
1449 | 216 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:90 | ||
1450 | 217 | #, python-format | ||
1451 | 218 | msgid "This IBAN is not valid : %s" | ||
1452 | 219 | msgstr "" | ||
1453 | 220 | |||
1454 | 221 | #. module: account_banking_sepa_credit_transfer | ||
1455 | 222 | #: view:banking.export.sepa:0 | 169 | #: view:banking.export.sepa:0 |
1456 | 223 | #: field:banking.export.sepa,payment_order_ids:0 | 170 | #: field:banking.export.sepa,payment_order_ids:0 |
1457 | 224 | #: field:banking.export.sepa.wizard,payment_order_ids:0 | 171 | #: field:banking.export.sepa.wizard,payment_order_ids:0 |
1458 | @@ -244,11 +191,6 @@ | |||
1459 | 244 | msgstr "" | 191 | msgstr "" |
1460 | 245 | 192 | ||
1461 | 246 | #. module: account_banking_sepa_credit_transfer | 193 | #. module: account_banking_sepa_credit_transfer |
1462 | 247 | #: help:banking.export.sepa.wizard,prefered_exec_date:0 | ||
1463 | 248 | 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." | ||
1464 | 249 | msgstr "" | ||
1465 | 250 | |||
1466 | 251 | #. module: account_banking_sepa_credit_transfer | ||
1467 | 252 | #: field:banking.export.sepa.wizard,file:0 | 194 | #: field:banking.export.sepa.wizard,file:0 |
1468 | 253 | msgid "File" | 195 | msgid "File" |
1469 | 254 | msgstr "" | 196 | msgstr "" |
1470 | 255 | 197 | ||
1471 | === modified file 'account_banking_sepa_credit_transfer/i18n/fr.po' | |||
1472 | --- account_banking_sepa_credit_transfer/i18n/fr.po 2013-12-03 06:20:09 +0000 | |||
1473 | +++ account_banking_sepa_credit_transfer/i18n/fr.po 2014-01-13 12:42:46 +0000 | |||
1474 | @@ -6,21 +6,14 @@ | |||
1475 | 6 | msgstr "" | 6 | msgstr "" |
1476 | 7 | "Project-Id-Version: OpenERP Server 7.0\n" | 7 | "Project-Id-Version: OpenERP Server 7.0\n" |
1477 | 8 | "Report-Msgid-Bugs-To: \n" | 8 | "Report-Msgid-Bugs-To: \n" |
1481 | 9 | "POT-Creation-Date: 2013-11-13 09:13+0000\n" | 9 | "POT-Creation-Date: 2013-12-23 22:52+0000\n" |
1482 | 10 | "PO-Revision-Date: 2013-12-02 16:36+0000\n" | 10 | "PO-Revision-Date: 2013-12-23 22:52+0000\n" |
1483 | 11 | "Last-Translator: Alexis de Lattre <alexis@via.ecp.fr>\n" | 11 | "Last-Translator: <>\n" |
1484 | 12 | "Language-Team: \n" | 12 | "Language-Team: \n" |
1485 | 13 | "MIME-Version: 1.0\n" | 13 | "MIME-Version: 1.0\n" |
1486 | 14 | "Content-Type: text/plain; charset=UTF-8\n" | 14 | "Content-Type: text/plain; charset=UTF-8\n" |
1496 | 15 | "Content-Transfer-Encoding: 8bit\n" | 15 | "Content-Transfer-Encoding: \n" |
1497 | 16 | "X-Launchpad-Export-Date: 2013-12-03 06:20+0000\n" | 16 | "Plural-Forms: \n" |
1489 | 17 | "X-Generator: Launchpad (build 16856)\n" | ||
1490 | 18 | |||
1491 | 19 | #. module: account_banking_sepa_credit_transfer | ||
1492 | 20 | #: field:banking.export.sepa,prefered_exec_date:0 | ||
1493 | 21 | #: field:banking.export.sepa.wizard,prefered_exec_date:0 | ||
1494 | 22 | msgid "Prefered Execution Date" | ||
1495 | 23 | msgstr "Date d'exécution demandée" | ||
1498 | 24 | 17 | ||
1499 | 25 | #. module: account_banking_sepa_credit_transfer | 18 | #. module: account_banking_sepa_credit_transfer |
1500 | 26 | #: selection:banking.export.sepa.wizard,state:0 | 19 | #: selection:banking.export.sepa.wizard,state:0 |
1501 | @@ -52,31 +45,8 @@ | |||
1502 | 52 | 45 | ||
1503 | 53 | #. module: account_banking_sepa_credit_transfer | 46 | #. module: account_banking_sepa_credit_transfer |
1504 | 54 | #: help:banking.export.sepa.wizard,charge_bearer:0 | 47 | #: help:banking.export.sepa.wizard,charge_bearer:0 |
1530 | 55 | msgid "" | 48 | 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." |
1531 | 56 | "Following service level : transaction charges are to be applied following " | 49 | 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." |
1507 | 57 | "the rules agreed in the service level and/or scheme (SEPA Core messages must " | ||
1508 | 58 | "use this). Shared : transaction charges on the debtor side are to be borne " | ||
1509 | 59 | "by the debtor, transaction charges on the creditor side are to be borne by " | ||
1510 | 60 | "the creditor. Borne by creditor : all transaction charges are to be borne by " | ||
1511 | 61 | "the creditor. Borne by debtor : all transaction charges are to be borne by " | ||
1512 | 62 | "the debtor." | ||
1513 | 63 | msgstr "" | ||
1514 | 64 | "Suivant le niveau de service : la répartition des frais bancaires suit les " | ||
1515 | 65 | "règles pré-établies dans le schema ou dans le contrat avec la banque (les " | ||
1516 | 66 | "messages SEPA Core doivent utiliser ce paramètre). Partagés : les frais " | ||
1517 | 67 | "bancaires côté débiteur sont à la charge du débiteur, les frais bancaires " | ||
1518 | 68 | "côté créancier sont à la charge du créancier. Supportés par le créancier : " | ||
1519 | 69 | "tous les frais bancaires sont à la charge du créancier. Supportés par le " | ||
1520 | 70 | "débiteur : tous les frais bancaires sont à la charge du débiteur." | ||
1521 | 71 | |||
1522 | 72 | #. module: account_banking_sepa_credit_transfer | ||
1523 | 73 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:117 | ||
1524 | 74 | #, python-format | ||
1525 | 75 | msgid "" | ||
1526 | 76 | "Cannot compute the '%s' of the Payment Line with Invoice Reference '%s'." | ||
1527 | 77 | msgstr "" | ||
1528 | 78 | "Impossible de générer le '%s' de la ligne de paiement ayant la référence de " | ||
1529 | 79 | "facture '%s'." | ||
1532 | 80 | 50 | ||
1533 | 81 | #. module: account_banking_sepa_credit_transfer | 51 | #. module: account_banking_sepa_credit_transfer |
1534 | 82 | #: selection:banking.export.sepa,charge_bearer:0 | 52 | #: selection:banking.export.sepa,charge_bearer:0 |
1535 | @@ -91,9 +61,14 @@ | |||
1536 | 91 | msgstr "Débit groupé" | 61 | msgstr "Débit groupé" |
1537 | 92 | 62 | ||
1538 | 93 | #. module: account_banking_sepa_credit_transfer | 63 | #. module: account_banking_sepa_credit_transfer |
1539 | 64 | #: selection:banking.export.sepa,state:0 | ||
1540 | 65 | msgid "Sent" | ||
1541 | 66 | msgstr "Envoyé" | ||
1542 | 67 | |||
1543 | 68 | #. module: account_banking_sepa_credit_transfer | ||
1544 | 94 | #: model:ir.model,name:account_banking_sepa_credit_transfer.model_banking_export_sepa_wizard | 69 | #: model:ir.model,name:account_banking_sepa_credit_transfer.model_banking_export_sepa_wizard |
1547 | 95 | msgid "Export SEPA Credit Transfer XML file" | 70 | msgid "Export SEPA Credit Transfer File" |
1548 | 96 | msgstr "Exporte the fichier de virement SEPA XML" | 71 | msgstr "Exporte le fichier de virement SEPA" |
1549 | 97 | 72 | ||
1550 | 98 | #. module: account_banking_sepa_credit_transfer | 73 | #. module: account_banking_sepa_credit_transfer |
1551 | 99 | #: view:banking.export.sepa:0 | 74 | #: view:banking.export.sepa:0 |
1552 | @@ -123,24 +98,6 @@ | |||
1553 | 123 | msgstr "Supportés par le destinataire" | 98 | msgstr "Supportés par le destinataire" |
1554 | 124 | 99 | ||
1555 | 125 | #. module: account_banking_sepa_credit_transfer | 100 | #. module: account_banking_sepa_credit_transfer |
1556 | 126 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:122 | ||
1557 | 127 | #, python-format | ||
1558 | 128 | msgid "Cannot compute the '%s'." | ||
1559 | 129 | msgstr "Impossible de générer le '%s'." | ||
1560 | 130 | |||
1561 | 131 | #. module: account_banking_sepa_credit_transfer | ||
1562 | 132 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:126 | ||
1563 | 133 | #, python-format | ||
1564 | 134 | msgid "The type of the field '%s' is %s. It should be a string or unicode." | ||
1565 | 135 | msgstr "" | ||
1566 | 136 | "Le champ '%s' est de type %s. Le type devrait être string ou unicode." | ||
1567 | 137 | |||
1568 | 138 | #. module: account_banking_sepa_credit_transfer | ||
1569 | 139 | #: selection:banking.export.sepa,state:0 | ||
1570 | 140 | msgid "Sent" | ||
1571 | 141 | msgstr "Envoyé" | ||
1572 | 142 | |||
1573 | 143 | #. module: account_banking_sepa_credit_transfer | ||
1574 | 144 | #: view:banking.export.sepa.wizard:0 | 101 | #: view:banking.export.sepa.wizard:0 |
1575 | 145 | msgid "Validate" | 102 | msgid "Validate" |
1576 | 146 | msgstr "Valider" | 103 | msgstr "Valider" |
1577 | @@ -151,33 +108,14 @@ | |||
1578 | 151 | msgstr "Générer" | 108 | msgstr "Générer" |
1579 | 152 | 109 | ||
1580 | 153 | #. module: account_banking_sepa_credit_transfer | 110 | #. module: account_banking_sepa_credit_transfer |
1581 | 154 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:169 | ||
1582 | 155 | #, python-format | ||
1583 | 156 | msgid "" | ||
1584 | 157 | "The generated XML file is not valid against the official XML Schema " | ||
1585 | 158 | "Definition. The generated XML file and the full error have been written in " | ||
1586 | 159 | "the server logs. Here is the error, which may give you an idea on the cause " | ||
1587 | 160 | "of the problem : %s" | ||
1588 | 161 | msgstr "" | ||
1589 | 162 | "Le fichier XML généré n'est pas valide par rapport à la Définition du Schéma " | ||
1590 | 163 | "XML officiel. Le fichier XML généré et le message d'erreur complet ont été " | ||
1591 | 164 | "écrits dans les logs du serveur. Voici l'erreur, qui vous donnera peut-être " | ||
1592 | 165 | "une idée sur la cause du problème : %s" | ||
1593 | 166 | |||
1594 | 167 | #. module: account_banking_sepa_credit_transfer | ||
1595 | 168 | #: selection:banking.export.sepa,charge_bearer:0 | 111 | #: selection:banking.export.sepa,charge_bearer:0 |
1596 | 169 | #: selection:banking.export.sepa.wizard,charge_bearer:0 | 112 | #: selection:banking.export.sepa.wizard,charge_bearer:0 |
1597 | 170 | msgid "Borne by Debtor" | 113 | msgid "Borne by Debtor" |
1598 | 171 | msgstr "Supportés par l'émetteur" | 114 | msgstr "Supportés par l'émetteur" |
1599 | 172 | 115 | ||
1600 | 173 | #. module: account_banking_sepa_credit_transfer | 116 | #. module: account_banking_sepa_credit_transfer |
1608 | 174 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:90 | 117 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:128 |
1609 | 175 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:116 | 118 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:245 |
1603 | 176 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:121 | ||
1604 | 177 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:130 | ||
1605 | 178 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:168 | ||
1606 | 179 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:206 | ||
1607 | 180 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:350 | ||
1610 | 181 | #, python-format | 119 | #, python-format |
1611 | 182 | msgid "Error:" | 120 | msgid "Error:" |
1612 | 183 | msgstr "Erreur :" | 121 | msgstr "Erreur :" |
1613 | @@ -200,24 +138,15 @@ | |||
1614 | 200 | msgstr "Génération du fichier SEPA" | 138 | msgstr "Génération du fichier SEPA" |
1615 | 201 | 139 | ||
1616 | 202 | #. module: account_banking_sepa_credit_transfer | 140 | #. module: account_banking_sepa_credit_transfer |
1617 | 203 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:125 | ||
1618 | 204 | #, python-format | ||
1619 | 205 | msgid "Field type error:" | ||
1620 | 206 | msgstr "Erreur dans le type de champ:" | ||
1621 | 207 | |||
1622 | 208 | #. module: account_banking_sepa_credit_transfer | ||
1623 | 209 | #: model:ir.model,name:account_banking_sepa_credit_transfer.model_banking_export_sepa | 141 | #: model:ir.model,name:account_banking_sepa_credit_transfer.model_banking_export_sepa |
1624 | 210 | msgid "SEPA export" | 142 | msgid "SEPA export" |
1625 | 211 | msgstr "Export SEPA" | 143 | msgstr "Export SEPA" |
1626 | 212 | 144 | ||
1627 | 213 | #. module: account_banking_sepa_credit_transfer | 145 | #. module: account_banking_sepa_credit_transfer |
1629 | 214 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:351 | 146 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:246 |
1630 | 215 | #, python-format | 147 | #, python-format |
1636 | 216 | msgid "" | 148 | msgid "Missing Bank Account on invoice '%s' (payment order line reference '%s')." |
1637 | 217 | "Missing Bank Account on invoice '%s' (payment order line reference '%s')." | 149 | msgstr "Compte bancaire manquant sur la facture '%s' (référence de la ligne de paiement : '%s')." |
1633 | 218 | msgstr "" | ||
1634 | 219 | "Compte bancaire manquant sur la facture '%s' (référence de la ligne de " | ||
1635 | 220 | "paiement : '%s')." | ||
1638 | 221 | 150 | ||
1639 | 222 | #. module: account_banking_sepa_credit_transfer | 151 | #. module: account_banking_sepa_credit_transfer |
1640 | 223 | #: field:banking.export.sepa,file:0 | 152 | #: field:banking.export.sepa,file:0 |
1641 | @@ -226,47 +155,15 @@ | |||
1642 | 226 | msgstr "Fichier SEPA XML" | 155 | msgstr "Fichier SEPA XML" |
1643 | 227 | 156 | ||
1644 | 228 | #. module: account_banking_sepa_credit_transfer | 157 | #. module: account_banking_sepa_credit_transfer |
1645 | 229 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:131 | ||
1646 | 230 | #, python-format | ||
1647 | 231 | msgid "The '%s' is empty or 0. It should have a non-null value." | ||
1648 | 232 | msgstr "Le '%s' est vide ou égal à 0. La valeur devrait être non nulle." | ||
1649 | 233 | |||
1650 | 234 | #. module: account_banking_sepa_credit_transfer | ||
1651 | 235 | #: help:banking.export.sepa,charge_bearer:0 | 158 | #: help:banking.export.sepa,charge_bearer:0 |
1686 | 236 | msgid "" | 159 | 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." |
1687 | 237 | "Following service level : transaction charges are to be applied following " | 160 | 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." |
1688 | 238 | "the rules agreed in the service level and/or scheme (SEPA Core messages must " | 161 | |
1689 | 239 | "use this). Shared : transaction charges on the creditor side are to be borne " | 162 | #. module: account_banking_sepa_credit_transfer |
1690 | 240 | "by the creditor, transaction charges on the debtor side are to be borne by " | 163 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:129 |
1691 | 241 | "the debtor. Borne by creditor : all transaction charges are to be borne by " | 164 | #, python-format |
1692 | 242 | "the creditor. Borne by debtor : all transaction charges are to be borne by " | 165 | 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'." |
1693 | 243 | "the debtor." | 166 | 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'." |
1660 | 244 | msgstr "" | ||
1661 | 245 | "Suivant le niveau de service : la répartition des frais bancaires suit les " | ||
1662 | 246 | "règles pré-établies dans le schema ou dans le contrat avec la banque (les " | ||
1663 | 247 | "messages SEPA Core doivent utiliser ce paramètre). Partagés : les frais " | ||
1664 | 248 | "bancaires côté débiteur sont à la charge du débiteur, les frais bancaires " | ||
1665 | 249 | "côté créancier sont à la charge du créancier. Supportés par le créancier : " | ||
1666 | 250 | "tous les frais bancaires sont à la charge du créancier. Supportés par le " | ||
1667 | 251 | "débiteur : tous les frais bancaires sont à la charge du débiteur." | ||
1668 | 252 | |||
1669 | 253 | #. module: account_banking_sepa_credit_transfer | ||
1670 | 254 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:207 | ||
1671 | 255 | #, python-format | ||
1672 | 256 | msgid "" | ||
1673 | 257 | "Payment Type Code '%s' is not supported. The only Payment Type Codes " | ||
1674 | 258 | "supported for SEPA Credit Transfers are 'pain.001.001.02', " | ||
1675 | 259 | "'pain.001.001.03', 'pain.001.001.04' and 'pain.001.001.05'." | ||
1676 | 260 | msgstr "" | ||
1677 | 261 | "Le code du Type de paiement '%s' n'est pas supporté. Les seuls codes de Type " | ||
1678 | 262 | "de paiement supportés pour les virements SEPA sont 'pain.001.001.02', " | ||
1679 | 263 | "'pain.001.001.03', 'pain.001.001.04' et 'pain.001.001.05'." | ||
1680 | 264 | |||
1681 | 265 | #. module: account_banking_sepa_credit_transfer | ||
1682 | 266 | #: code:addons/account_banking_sepa_credit_transfer/wizard/export_sepa.py:90 | ||
1683 | 267 | #, python-format | ||
1684 | 268 | msgid "This IBAN is not valid : %s" | ||
1685 | 269 | msgstr "Cet IBAN n'est pas valide : %s" | ||
1694 | 270 | 167 | ||
1695 | 271 | #. module: account_banking_sepa_credit_transfer | 168 | #. module: account_banking_sepa_credit_transfer |
1696 | 272 | #: view:banking.export.sepa:0 | 169 | #: view:banking.export.sepa:0 |
1697 | @@ -290,26 +187,8 @@ | |||
1698 | 290 | #. module: account_banking_sepa_credit_transfer | 187 | #. module: account_banking_sepa_credit_transfer |
1699 | 291 | #: help:banking.export.sepa,batch_booking:0 | 188 | #: help:banking.export.sepa,batch_booking:0 |
1700 | 292 | #: help:banking.export.sepa.wizard,batch_booking:0 | 189 | #: help:banking.export.sepa.wizard,batch_booking:0 |
1721 | 293 | msgid "" | 190 | 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." |
1722 | 294 | "If true, the bank statement will display only one debit line for all the " | 191 | 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." |
1703 | 295 | "wire transfers of the SEPA XML file ; if false, the bank statement will " | ||
1704 | 296 | "display one debit line per wire transfer of the SEPA XML file." | ||
1705 | 297 | msgstr "" | ||
1706 | 298 | "Si coché, le relevé de compte ne comportera qu'une ligne de débit pour tous " | ||
1707 | 299 | "les virements du fichier SEPA XML ; si non coché, le relevé de compte " | ||
1708 | 300 | "comportera une ligne de débit pour chaque virement du fichier SEPA XML." | ||
1709 | 301 | |||
1710 | 302 | #. module: account_banking_sepa_credit_transfer | ||
1711 | 303 | #: help:banking.export.sepa.wizard,prefered_exec_date:0 | ||
1712 | 304 | msgid "" | ||
1713 | 305 | "This is the date on which the file should be processed by the bank. Please " | ||
1714 | 306 | "keep in mind that banks only execute on working days and typically use a " | ||
1715 | 307 | "delay of two days between execution date and effective transfer date." | ||
1716 | 308 | msgstr "" | ||
1717 | 309 | "C'est la date à laquelle le fichier doit être traité par la banque. Gardez " | ||
1718 | 310 | "en tête que les banques réalisent des traitements seulement les jours ouvrés " | ||
1719 | 311 | "et ont habituellement un délai de 2 jours entre la date de traitement et la " | ||
1720 | 312 | "date du transfert effectif." | ||
1723 | 313 | 192 | ||
1724 | 314 | #. module: account_banking_sepa_credit_transfer | 193 | #. module: account_banking_sepa_credit_transfer |
1725 | 315 | #: field:banking.export.sepa.wizard,file:0 | 194 | #: field:banking.export.sepa.wizard,file:0 |
1726 | @@ -326,88 +205,3 @@ | |||
1727 | 326 | msgid "Generation Date" | 205 | msgid "Generation Date" |
1728 | 327 | msgstr "Date de génération" | 206 | msgstr "Date de génération" |
1729 | 328 | 207 | ||
1730 | 329 | #~ msgid "SEPA XML file" | ||
1731 | 330 | #~ msgstr "Fichier SEPA XML" | ||
1732 | 331 | |||
1733 | 332 | #~ msgid "Payment order" | ||
1734 | 333 | #~ msgstr "Ordre de paiement" | ||
1735 | 334 | |||
1736 | 335 | #~ msgid "" | ||
1737 | 336 | #~ "This is the message identification of the entire SEPA XML file. 35 " | ||
1738 | 337 | #~ "characters max." | ||
1739 | 338 | #~ msgstr "" | ||
1740 | 339 | #~ "Ceci est le libellé d'identification du fichier SEPA XML. 35 caractères " | ||
1741 | 340 | #~ "maximum." | ||
1742 | 341 | |||
1743 | 342 | #~ msgid "Prefered execution date" | ||
1744 | 343 | #~ msgstr "Date d'exécution demandée" | ||
1745 | 344 | |||
1746 | 345 | #~ msgid "Generation date" | ||
1747 | 346 | #~ msgstr "Date de génération" | ||
1748 | 347 | |||
1749 | 348 | #~ msgid "Message identification" | ||
1750 | 349 | #~ msgstr "Libellé d'identification" | ||
1751 | 350 | |||
1752 | 351 | #~ msgid "Total amount" | ||
1753 | 352 | #~ msgstr "Montant total" | ||
1754 | 353 | |||
1755 | 354 | #~ msgid "" | ||
1756 | 355 | #~ "Shared : transaction charges on the sender side are to be borne by the " | ||
1757 | 356 | #~ "debtor, transaction charges on the receiver side are to be borne by the " | ||
1758 | 357 | #~ "creditor (most transfers use this). Borne by creditor : all transaction " | ||
1759 | 358 | #~ "charges are to be borne by the creditor. Borne by debtor : all transaction " | ||
1760 | 359 | #~ "charges are to be borne by the debtor. Following service level : transaction " | ||
1761 | 360 | #~ "charges are to be applied following the rules agreed in the service level " | ||
1762 | 361 | #~ "and/or scheme." | ||
1763 | 362 | #~ msgstr "" | ||
1764 | 363 | #~ "Partagés : les frais bancaires côté émetteur sont à la charge de l'émetteur " | ||
1765 | 364 | #~ "et les frais bancaires côté destinataire sont à la charge du destinataire " | ||
1766 | 365 | #~ "(la plupart des virements utilisent cette répartition). Supportés par le " | ||
1767 | 366 | #~ "destinataire : tous les frais bancaires sont à la charge du destinataire. " | ||
1768 | 367 | #~ "Supportés par l'émetteur : tous les frais bancaires sont à la charge de " | ||
1769 | 368 | #~ "l'émetteur. Suivant le niveau de service : la répartition des frais " | ||
1770 | 369 | #~ "bancaires suit les règles pré-établies dans le contrat avec la banque." | ||
1771 | 370 | |||
1772 | 371 | #~ msgid "Borne by creditor" | ||
1773 | 372 | #~ msgstr "Supportés par le destinataire" | ||
1774 | 373 | |||
1775 | 374 | #~ msgid "Payment orders" | ||
1776 | 375 | #~ msgstr "Ordres de paiement" | ||
1777 | 376 | |||
1778 | 377 | #~ msgid "SEPA XML file generation" | ||
1779 | 378 | #~ msgstr "Génération du fichier SEPA XML" | ||
1780 | 379 | |||
1781 | 380 | #~ msgid "Reference for further communication" | ||
1782 | 381 | #~ msgstr "Référence pour communication ultérieure" | ||
1783 | 382 | |||
1784 | 383 | #~ msgid "Processing details" | ||
1785 | 384 | #~ msgstr "Paramètres" | ||
1786 | 385 | |||
1787 | 386 | #~ msgid "Borne by debtor" | ||
1788 | 387 | #~ msgstr "Supportés par l'émetteur" | ||
1789 | 388 | |||
1790 | 389 | #~ msgid "Number of transactions" | ||
1791 | 390 | #~ msgstr "Nombre de transactions" | ||
1792 | 391 | |||
1793 | 392 | #~ msgid "Following service level" | ||
1794 | 393 | #~ msgstr "Suivant le niveau de service" | ||
1795 | 394 | |||
1796 | 395 | #~ msgid "Charge bearer" | ||
1797 | 396 | #~ msgstr "Répartition des frais" | ||
1798 | 397 | |||
1799 | 398 | #, python-format | ||
1800 | 399 | #~ msgid "" | ||
1801 | 400 | #~ "Payment Type Code '%s' is not supported. The only Payment Type Codes " | ||
1802 | 401 | #~ "supported for SEPA Credit Transfers are 'pain.001.001.02', 'pain.001.001.03' " | ||
1803 | 402 | #~ "and 'pain.001.001.04'." | ||
1804 | 403 | #~ msgstr "" | ||
1805 | 404 | #~ "Le code '%s' pour le Type de Paiment n'est pas supporté. Les seuls codes de " | ||
1806 | 405 | #~ "Types de Paiement supportés pour les virements SEPA sont 'pain.001.001.02', " | ||
1807 | 406 | #~ "'pain.001.001.03' et 'pain.001.001.04'." | ||
1808 | 407 | |||
1809 | 408 | #, python-format | ||
1810 | 409 | #~ msgid "Error :" | ||
1811 | 410 | #~ msgstr "Erreur :" | ||
1812 | 411 | |||
1813 | 412 | #~ msgid "Batch booking" | ||
1814 | 413 | #~ msgstr "Débit groupé" | ||
1815 | 414 | 208 | ||
1816 | === modified file 'account_banking_sepa_credit_transfer/wizard/export_sepa.py' | |||
1817 | --- account_banking_sepa_credit_transfer/wizard/export_sepa.py 2013-11-12 21:38:21 +0000 | |||
1818 | +++ account_banking_sepa_credit_transfer/wizard/export_sepa.py 2014-01-13 12:42:46 +0000 | |||
1819 | @@ -22,20 +22,14 @@ | |||
1820 | 22 | 22 | ||
1821 | 23 | 23 | ||
1822 | 24 | from openerp.osv import orm, fields | 24 | from openerp.osv import orm, fields |
1823 | 25 | import base64 | ||
1824 | 26 | from datetime import datetime | ||
1825 | 27 | from openerp.tools.translate import _ | 25 | from openerp.tools.translate import _ |
1828 | 28 | from openerp.tools.safe_eval import safe_eval | 26 | from openerp import netsvc |
1827 | 29 | from openerp import tools, netsvc | ||
1829 | 30 | from lxml import etree | 27 | from lxml import etree |
1830 | 31 | import logging | ||
1831 | 32 | from unidecode import unidecode | ||
1832 | 33 | |||
1833 | 34 | _logger = logging.getLogger(__name__) | ||
1834 | 35 | 28 | ||
1835 | 36 | 29 | ||
1836 | 37 | class banking_export_sepa_wizard(orm.TransientModel): | 30 | class banking_export_sepa_wizard(orm.TransientModel): |
1837 | 38 | _name = 'banking.export.sepa.wizard' | 31 | _name = 'banking.export.sepa.wizard' |
1838 | 32 | _inherit = ['banking.export.pain'] | ||
1839 | 39 | _description = 'Export SEPA Credit Transfer File' | 33 | _description = 'Export SEPA Credit Transfer File' |
1840 | 40 | 34 | ||
1841 | 41 | _columns = { | 35 | _columns = { |
1842 | @@ -45,17 +39,24 @@ | |||
1843 | 45 | ], 'State', readonly=True), | 39 | ], 'State', readonly=True), |
1844 | 46 | 'batch_booking': fields.boolean( | 40 | 'batch_booking': fields.boolean( |
1845 | 47 | 'Batch Booking', | 41 | 'Batch Booking', |
1850 | 48 | 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."), | 42 | help="If true, the bank statement will display only one debit " |
1851 | 49 | 'prefered_exec_date': fields.date( | 43 | "line for all the wire transfers of the SEPA XML file ; if " |
1852 | 50 | 'Prefered Execution Date', | 44 | "false, the bank statement will display one debit line per wire " |
1853 | 51 | 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.'), | 45 | "transfer of the SEPA XML file."), |
1854 | 52 | 'charge_bearer': fields.selection([ | 46 | 'charge_bearer': fields.selection([ |
1855 | 53 | ('SLEV', 'Following Service Level'), | 47 | ('SLEV', 'Following Service Level'), |
1856 | 54 | ('SHAR', 'Shared'), | 48 | ('SHAR', 'Shared'), |
1857 | 55 | ('CRED', 'Borne by Creditor'), | 49 | ('CRED', 'Borne by Creditor'), |
1858 | 56 | ('DEBT', 'Borne by Debtor'), | 50 | ('DEBT', 'Borne by Debtor'), |
1859 | 57 | ], 'Charge Bearer', required=True, | 51 | ], 'Charge Bearer', required=True, |
1861 | 58 | 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.'), | 52 | help="Following service level : transaction charges are to be " |
1862 | 53 | "applied following the rules agreed in the service level and/or " | ||
1863 | 54 | "scheme (SEPA Core messages must use this). Shared : transaction " | ||
1864 | 55 | "charges on the debtor side are to be borne by the debtor, " | ||
1865 | 56 | "transaction charges on the creditor side are to be borne by " | ||
1866 | 57 | "the creditor. Borne by creditor : all transaction charges are " | ||
1867 | 58 | "to be borne by the creditor. Borne by debtor : all transaction " | ||
1868 | 59 | "charges are to be borne by the debtor."), | ||
1869 | 59 | 'nb_transactions': fields.related( | 60 | 'nb_transactions': fields.related( |
1870 | 60 | 'file_id', 'nb_transactions', type='integer', | 61 | 'file_id', 'nb_transactions', type='integer', |
1871 | 61 | string='Number of Transactions', readonly=True), | 62 | string='Number of Transactions', readonly=True), |
1872 | @@ -79,16 +80,6 @@ | |||
1873 | 79 | 'state': 'create', | 80 | 'state': 'create', |
1874 | 80 | } | 81 | } |
1875 | 81 | 82 | ||
1876 | 82 | def _validate_iban(self, cr, uid, iban, context=None): | ||
1877 | 83 | '''if IBAN is valid, returns IBAN | ||
1878 | 84 | if IBAN is NOT valid, raises an error message''' | ||
1879 | 85 | partner_bank_obj = self.pool.get('res.partner.bank') | ||
1880 | 86 | if partner_bank_obj.is_iban_valid(cr, uid, iban, context=context): | ||
1881 | 87 | return iban.replace(' ', '') | ||
1882 | 88 | else: | ||
1883 | 89 | raise orm.except_orm( | ||
1884 | 90 | _('Error:'), _("This IBAN is not valid : %s") % iban) | ||
1885 | 91 | |||
1886 | 92 | def create(self, cr, uid, vals, context=None): | 83 | def create(self, cr, uid, vals, context=None): |
1887 | 93 | payment_order_ids = context.get('active_ids', []) | 84 | payment_order_ids = context.get('active_ids', []) |
1888 | 94 | vals.update({ | 85 | vals.update({ |
1889 | @@ -97,85 +88,16 @@ | |||
1890 | 97 | return super(banking_export_sepa_wizard, self).create( | 88 | return super(banking_export_sepa_wizard, self).create( |
1891 | 98 | cr, uid, vals, context=context) | 89 | cr, uid, vals, context=context) |
1892 | 99 | 90 | ||
1893 | 100 | def _prepare_field( | ||
1894 | 101 | self, cr, uid, field_name, field_value, eval_ctx, max_size=0, | ||
1895 | 102 | context=None): | ||
1896 | 103 | '''This function is designed to be inherited !''' | ||
1897 | 104 | assert isinstance(eval_ctx, dict), 'eval_ctx must contain a dict' | ||
1898 | 105 | try: | ||
1899 | 106 | # SEPA uses XML ; XML = UTF-8 ; UTF-8 = support for all characters | ||
1900 | 107 | # But we are dealing with banks... | ||
1901 | 108 | # and many banks don't want non-ASCCI characters ! | ||
1902 | 109 | # cf section 1.4 "Character set" of the SEPA Credit Transfer | ||
1903 | 110 | # Scheme Customer-to-bank guidelines | ||
1904 | 111 | value = unidecode(safe_eval(field_value, eval_ctx)) | ||
1905 | 112 | except: | ||
1906 | 113 | line = eval_ctx.get('line') | ||
1907 | 114 | if line: | ||
1908 | 115 | raise orm.except_orm( | ||
1909 | 116 | _('Error:'), | ||
1910 | 117 | _("Cannot compute the '%s' of the Payment Line with Invoice Reference '%s'.") | ||
1911 | 118 | % (field_name, self.pool['account.invoice'].name_get(cr, uid, [line.ml_inv_ref.id], context=context)[0][1])) | ||
1912 | 119 | else: | ||
1913 | 120 | raise orm.except_orm( | ||
1914 | 121 | _('Error:'), | ||
1915 | 122 | _("Cannot compute the '%s'.") % field_name) | ||
1916 | 123 | if not isinstance(value, (str, unicode)): | ||
1917 | 124 | raise orm.except_orm( | ||
1918 | 125 | _('Field type error:'), | ||
1919 | 126 | _("The type of the field '%s' is %s. It should be a string or unicode.") | ||
1920 | 127 | % (field_name, type(value))) | ||
1921 | 128 | if not value: | ||
1922 | 129 | raise orm.except_orm( | ||
1923 | 130 | _('Error:'), | ||
1924 | 131 | _("The '%s' is empty or 0. It should have a non-null value.") | ||
1925 | 132 | % field_name) | ||
1926 | 133 | if max_size and len(value) > max_size: | ||
1927 | 134 | value = value[0:max_size] | ||
1928 | 135 | return value | ||
1929 | 136 | |||
1930 | 137 | def _prepare_export_sepa( | ||
1931 | 138 | self, cr, uid, sepa_export, total_amount, transactions_count, | ||
1932 | 139 | xml_string, context=None): | ||
1933 | 140 | return { | ||
1934 | 141 | 'batch_booking': sepa_export.batch_booking, | ||
1935 | 142 | 'charge_bearer': sepa_export.charge_bearer, | ||
1936 | 143 | 'prefered_exec_date': sepa_export.prefered_exec_date, | ||
1937 | 144 | 'total_amount': total_amount, | ||
1938 | 145 | 'nb_transactions': transactions_count, | ||
1939 | 146 | 'file': base64.encodestring(xml_string), | ||
1940 | 147 | 'payment_order_ids': [ | ||
1941 | 148 | (6, 0, [x.id for x in sepa_export.payment_order_ids]) | ||
1942 | 149 | ], | ||
1943 | 150 | } | ||
1944 | 151 | |||
1945 | 152 | def _validate_xml(self, cr, uid, xml_string, pain_flavor): | ||
1946 | 153 | xsd_etree_obj = etree.parse( | ||
1947 | 154 | tools.file_open( | ||
1948 | 155 | 'account_banking_sepa_credit_transfer/data/%s.xsd' | ||
1949 | 156 | % pain_flavor)) | ||
1950 | 157 | official_pain_schema = etree.XMLSchema(xsd_etree_obj) | ||
1951 | 158 | |||
1952 | 159 | try: | ||
1953 | 160 | root_to_validate = etree.fromstring(xml_string) | ||
1954 | 161 | official_pain_schema.assertValid(root_to_validate) | ||
1955 | 162 | except Exception, e: | ||
1956 | 163 | _logger.warning( | ||
1957 | 164 | "The XML file is invalid against the XML Schema Definition") | ||
1958 | 165 | _logger.warning(xml_string) | ||
1959 | 166 | _logger.warning(e) | ||
1960 | 167 | raise orm.except_orm( | ||
1961 | 168 | _('Error:'), | ||
1962 | 169 | _('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') | ||
1963 | 170 | % str(e)) | ||
1964 | 171 | return True | ||
1965 | 172 | |||
1966 | 173 | def create_sepa(self, cr, uid, ids, context=None): | 91 | def create_sepa(self, cr, uid, ids, context=None): |
1967 | 174 | ''' | 92 | ''' |
1968 | 175 | Creates the SEPA Credit Transfer file. That's the important code ! | 93 | Creates the SEPA Credit Transfer file. That's the important code ! |
1969 | 176 | ''' | 94 | ''' |
1970 | 95 | if context is None: | ||
1971 | 96 | context = {} | ||
1972 | 177 | sepa_export = self.browse(cr, uid, ids[0], context=context) | 97 | sepa_export = self.browse(cr, uid, ids[0], context=context) |
1973 | 178 | pain_flavor = sepa_export.payment_order_ids[0].mode.type.code | 98 | pain_flavor = sepa_export.payment_order_ids[0].mode.type.code |
1974 | 99 | convert_to_ascii = \ | ||
1975 | 100 | sepa_export.payment_order_ids[0].mode.convert_to_ascii | ||
1976 | 179 | if pain_flavor == 'pain.001.001.02': | 101 | if pain_flavor == 'pain.001.001.02': |
1977 | 180 | bic_xml_tag = 'BIC' | 102 | bic_xml_tag = 'BIC' |
1978 | 181 | name_maxsize = 70 | 103 | name_maxsize = 70 |
1979 | @@ -204,124 +126,98 @@ | |||
1980 | 204 | else: | 126 | else: |
1981 | 205 | raise orm.except_orm( | 127 | raise orm.except_orm( |
1982 | 206 | _('Error:'), | 128 | _('Error:'), |
1984 | 207 | _("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'.") | 129 | _("Payment Type Code '%s' is not supported. The only " |
1985 | 130 | "Payment Type Codes supported for SEPA Credit Transfers " | ||
1986 | 131 | "are 'pain.001.001.02', 'pain.001.001.03', " | ||
1987 | 132 | "'pain.001.001.04' and 'pain.001.001.05'.") | ||
1988 | 208 | % pain_flavor) | 133 | % pain_flavor) |
1994 | 209 | if sepa_export.prefered_exec_date: | 134 | |
1995 | 210 | my_requested_exec_date = sepa_export.prefered_exec_date | 135 | gen_args = { |
1996 | 211 | else: | 136 | 'bic_xml_tag': bic_xml_tag, |
1997 | 212 | my_requested_exec_date = fields.date.context_today( | 137 | 'name_maxsize': name_maxsize, |
1998 | 213 | self, cr, uid, context=context) | 138 | 'convert_to_ascii': convert_to_ascii, |
1999 | 139 | 'payment_method': 'TRF', | ||
2000 | 140 | 'pain_flavor': pain_flavor, | ||
2001 | 141 | 'sepa_export': sepa_export, | ||
2002 | 142 | 'file_obj': self.pool['banking.export.sepa'], | ||
2003 | 143 | 'pain_xsd_file': | ||
2004 | 144 | 'account_banking_sepa_credit_transfer/data/%s.xsd' | ||
2005 | 145 | % pain_flavor, | ||
2006 | 146 | } | ||
2007 | 214 | 147 | ||
2008 | 215 | pain_ns = { | 148 | pain_ns = { |
2009 | 216 | 'xsi': 'http://www.w3.org/2001/XMLSchema-instance', | 149 | 'xsi': 'http://www.w3.org/2001/XMLSchema-instance', |
2010 | 217 | None: 'urn:iso:std:iso:20022:tech:xsd:%s' % pain_flavor, | 150 | None: 'urn:iso:std:iso:20022:tech:xsd:%s' % pain_flavor, |
2011 | 218 | } | 151 | } |
2012 | 219 | 152 | ||
2020 | 220 | root = etree.Element('Document', nsmap=pain_ns) | 153 | xml_root = etree.Element('Document', nsmap=pain_ns) |
2021 | 221 | pain_root = etree.SubElement(root, root_xml_tag) | 154 | pain_root = etree.SubElement(xml_root, root_xml_tag) |
2022 | 222 | 155 | pain_03_to_05 = \ | |
2023 | 223 | my_company_name = self._prepare_field( | 156 | ['pain.001.001.03', 'pain.001.001.04', 'pain.001.001.05'] |
2017 | 224 | cr, uid, 'Company Name', | ||
2018 | 225 | 'sepa_export.payment_order_ids[0].mode.bank_id.partner_id.name', | ||
2019 | 226 | {'sepa_export': sepa_export}, name_maxsize, context=context) | ||
2024 | 227 | 157 | ||
2025 | 228 | # A. Group header | 158 | # A. Group header |
2114 | 229 | group_header_1_0 = etree.SubElement(pain_root, 'GrpHdr') | 159 | group_header_1_0, nb_of_transactions_1_6, control_sum_1_7 = \ |
2115 | 230 | message_identification_1_1 = etree.SubElement( | 160 | self.generate_group_header_block( |
2116 | 231 | group_header_1_0, 'MsgId') | 161 | cr, uid, pain_root, gen_args, context=context) |
2117 | 232 | message_identification_1_1.text = self._prepare_field( | 162 | |
2118 | 233 | cr, uid, 'Message Identification', | 163 | transactions_count_1_6 = 0 |
2031 | 234 | 'sepa_export.payment_order_ids[0].reference', | ||
2032 | 235 | {'sepa_export': sepa_export}, 35, context=context) | ||
2033 | 236 | creation_date_time_1_2 = etree.SubElement(group_header_1_0, 'CreDtTm') | ||
2034 | 237 | creation_date_time_1_2.text = datetime.strftime( | ||
2035 | 238 | datetime.today(), '%Y-%m-%dT%H:%M:%S') | ||
2036 | 239 | if pain_flavor == 'pain.001.001.02': | ||
2037 | 240 | # batch_booking is in "Group header" with pain.001.001.02 | ||
2038 | 241 | # and in "Payment info" in pain.001.001.03/04 | ||
2039 | 242 | batch_booking = etree.SubElement(group_header_1_0, 'BtchBookg') | ||
2040 | 243 | batch_booking.text = str(sepa_export.batch_booking).lower() | ||
2041 | 244 | nb_of_transactions_1_6 = etree.SubElement( | ||
2042 | 245 | group_header_1_0, 'NbOfTxs') | ||
2043 | 246 | control_sum_1_7 = etree.SubElement(group_header_1_0, 'CtrlSum') | ||
2044 | 247 | # Grpg removed in pain.001.001.03 | ||
2045 | 248 | if pain_flavor == 'pain.001.001.02': | ||
2046 | 249 | grouping = etree.SubElement(group_header_1_0, 'Grpg') | ||
2047 | 250 | grouping.text = 'GRPD' | ||
2048 | 251 | initiating_party_1_8 = etree.SubElement(group_header_1_0, 'InitgPty') | ||
2049 | 252 | initiating_party_name = etree.SubElement(initiating_party_1_8, 'Nm') | ||
2050 | 253 | initiating_party_name.text = my_company_name | ||
2051 | 254 | |||
2052 | 255 | # B. Payment info | ||
2053 | 256 | payment_info_2_0 = etree.SubElement(pain_root, 'PmtInf') | ||
2054 | 257 | payment_info_identification_2_1 = etree.SubElement( | ||
2055 | 258 | payment_info_2_0, 'PmtInfId') | ||
2056 | 259 | payment_info_identification_2_1.text = self._prepare_field( | ||
2057 | 260 | cr, uid, 'Payment Information Identification', | ||
2058 | 261 | "sepa_export.payment_order_ids[0].reference", | ||
2059 | 262 | {'sepa_export': sepa_export}, 35, context=context) | ||
2060 | 263 | payment_method_2_2 = etree.SubElement(payment_info_2_0, 'PmtMtd') | ||
2061 | 264 | payment_method_2_2.text = 'TRF' | ||
2062 | 265 | if pain_flavor in [ | ||
2063 | 266 | 'pain.001.001.03', 'pain.001.001.04', 'pain.001.001.05']: | ||
2064 | 267 | # batch_booking is in "Group header" with pain.001.001.02 | ||
2065 | 268 | # and in "Payment info" in pain.001.001.03/04 | ||
2066 | 269 | batch_booking_2_3 = etree.SubElement(payment_info_2_0, 'BtchBookg') | ||
2067 | 270 | batch_booking_2_3.text = str(sepa_export.batch_booking).lower() | ||
2068 | 271 | # It may seem surprising, but the | ||
2069 | 272 | # "SEPA Credit Transfer Scheme Customer-to-bank Implementation | ||
2070 | 273 | # guidelines" v6.0 says that control sum and nb_of_transactions | ||
2071 | 274 | # should be present at both "group header" level and "payment info" | ||
2072 | 275 | # level. This seems to be confirmed by the tests carried out at | ||
2073 | 276 | # BNP Paribas in PAIN v001.001.03 | ||
2074 | 277 | if pain_flavor in [ | ||
2075 | 278 | 'pain.001.001.03', 'pain.001.001.04', 'pain.001.001.05']: | ||
2076 | 279 | nb_of_transactions_2_4 = etree.SubElement( | ||
2077 | 280 | payment_info_2_0, 'NbOfTxs') | ||
2078 | 281 | control_sum_2_5 = etree.SubElement(payment_info_2_0, 'CtrlSum') | ||
2079 | 282 | payment_type_info_2_6 = etree.SubElement(payment_info_2_0, 'PmtTpInf') | ||
2080 | 283 | service_level_2_8 = etree.SubElement(payment_type_info_2_6, 'SvcLvl') | ||
2081 | 284 | service_level_code_2_9 = etree.SubElement(service_level_2_8, 'Cd') | ||
2082 | 285 | service_level_code_2_9.text = 'SEPA' | ||
2083 | 286 | requested_exec_date_2_17 = etree.SubElement( | ||
2084 | 287 | payment_info_2_0, 'ReqdExctnDt') | ||
2085 | 288 | requested_exec_date_2_17.text = my_requested_exec_date | ||
2086 | 289 | debtor_2_19 = etree.SubElement(payment_info_2_0, 'Dbtr') | ||
2087 | 290 | debtor_name = etree.SubElement(debtor_2_19, 'Nm') | ||
2088 | 291 | debtor_name.text = my_company_name | ||
2089 | 292 | debtor_account_2_20 = etree.SubElement(payment_info_2_0, 'DbtrAcct') | ||
2090 | 293 | debtor_account_id = etree.SubElement(debtor_account_2_20, 'Id') | ||
2091 | 294 | debtor_account_iban = etree.SubElement(debtor_account_id, 'IBAN') | ||
2092 | 295 | debtor_account_iban.text = self._validate_iban( | ||
2093 | 296 | cr, uid, self._prepare_field( | ||
2094 | 297 | cr, uid, 'Company IBAN', | ||
2095 | 298 | 'sepa_export.payment_order_ids[0].mode.bank_id.acc_number', | ||
2096 | 299 | {'sepa_export': sepa_export}, context=context), | ||
2097 | 300 | context=context) | ||
2098 | 301 | debtor_agent_2_21 = etree.SubElement(payment_info_2_0, 'DbtrAgt') | ||
2099 | 302 | debtor_agent_institution = etree.SubElement( | ||
2100 | 303 | debtor_agent_2_21, 'FinInstnId') | ||
2101 | 304 | debtor_agent_bic = etree.SubElement( | ||
2102 | 305 | debtor_agent_institution, bic_xml_tag) | ||
2103 | 306 | # TODO validate BIC with pattern | ||
2104 | 307 | # [A-Z]{6,6}[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3,3}){0,1} | ||
2105 | 308 | # because OpenERP doesn't have a constraint on BIC | ||
2106 | 309 | debtor_agent_bic.text = self._prepare_field( | ||
2107 | 310 | cr, uid, 'Company BIC', | ||
2108 | 311 | 'sepa_export.payment_order_ids[0].mode.bank_id.bank.bic', | ||
2109 | 312 | {'sepa_export': sepa_export}, context=context) | ||
2110 | 313 | charge_bearer_2_24 = etree.SubElement(payment_info_2_0, 'ChrgBr') | ||
2111 | 314 | charge_bearer_2_24.text = sepa_export.charge_bearer | ||
2112 | 315 | |||
2113 | 316 | transactions_count = 0 | ||
2119 | 317 | total_amount = 0.0 | 164 | total_amount = 0.0 |
2122 | 318 | amount_control_sum = 0.0 | 165 | amount_control_sum_1_7 = 0.0 |
2123 | 319 | # Iterate on payment orders | 166 | lines_per_group = {} |
2124 | 167 | # key = (requested_date, priority) | ||
2125 | 168 | # values = list of lines as object | ||
2126 | 169 | today = fields.date.context_today(self, cr, uid, context=context) | ||
2127 | 320 | for payment_order in sepa_export.payment_order_ids: | 170 | for payment_order in sepa_export.payment_order_ids: |
2128 | 321 | total_amount = total_amount + payment_order.total | 171 | total_amount = total_amount + payment_order.total |
2129 | 322 | # Iterate each payment lines | ||
2130 | 323 | for line in payment_order.line_ids: | 172 | for line in payment_order.line_ids: |
2132 | 324 | transactions_count += 1 | 173 | priority = line.priority |
2133 | 174 | if payment_order.date_prefered == 'due': | ||
2134 | 175 | requested_date = line.ml_maturity_date or today | ||
2135 | 176 | elif payment_order.date_prefered == 'fixed': | ||
2136 | 177 | requested_date = payment_order.date_scheduled or today | ||
2137 | 178 | else: | ||
2138 | 179 | requested_date = today | ||
2139 | 180 | key = (requested_date, priority) | ||
2140 | 181 | if key in lines_per_group: | ||
2141 | 182 | lines_per_group[key].append(line) | ||
2142 | 183 | else: | ||
2143 | 184 | lines_per_group[key] = [line] | ||
2144 | 185 | # Write requested_date on 'Payment date' of the pay line | ||
2145 | 186 | if requested_date != line.date: | ||
2146 | 187 | self.pool['payment.line'].write( | ||
2147 | 188 | cr, uid, line.id, | ||
2148 | 189 | {'date': requested_date}, context=context) | ||
2149 | 190 | |||
2150 | 191 | for (requested_date, priority), lines in lines_per_group.items(): | ||
2151 | 192 | # B. Payment info | ||
2152 | 193 | payment_info_2_0, nb_of_transactions_2_4, control_sum_2_5 = \ | ||
2153 | 194 | self.generate_start_payment_info_block( | ||
2154 | 195 | cr, uid, pain_root, | ||
2155 | 196 | "sepa_export.payment_order_ids[0].reference + '-' " | ||
2156 | 197 | "+ requested_date.replace('-', '') + '-' + priority", | ||
2157 | 198 | priority, False, False, requested_date, { | ||
2158 | 199 | 'sepa_export': sepa_export, | ||
2159 | 200 | 'priority': priority, | ||
2160 | 201 | 'requested_date': requested_date, | ||
2161 | 202 | }, gen_args, context=context) | ||
2162 | 203 | |||
2163 | 204 | self.generate_party_block( | ||
2164 | 205 | cr, uid, payment_info_2_0, 'Dbtr', 'B', | ||
2165 | 206 | 'sepa_export.payment_order_ids[0].mode.bank_id.partner_id.' | ||
2166 | 207 | 'name', | ||
2167 | 208 | 'sepa_export.payment_order_ids[0].mode.bank_id.acc_number', | ||
2168 | 209 | 'sepa_export.payment_order_ids[0].mode.bank_id.bank.bic', | ||
2169 | 210 | {'sepa_export': sepa_export}, | ||
2170 | 211 | gen_args, context=context) | ||
2171 | 212 | |||
2172 | 213 | charge_bearer_2_24 = etree.SubElement(payment_info_2_0, 'ChrgBr') | ||
2173 | 214 | charge_bearer_2_24.text = sepa_export.charge_bearer | ||
2174 | 215 | |||
2175 | 216 | transactions_count_2_4 = 0 | ||
2176 | 217 | amount_control_sum_2_5 = 0.0 | ||
2177 | 218 | for line in lines: | ||
2178 | 219 | transactions_count_1_6 += 1 | ||
2179 | 220 | transactions_count_2_4 += 1 | ||
2180 | 325 | # C. Credit Transfer Transaction Info | 221 | # C. Credit Transfer Transaction Info |
2181 | 326 | credit_transfer_transaction_info_2_27 = etree.SubElement( | 222 | credit_transfer_transaction_info_2_27 = etree.SubElement( |
2182 | 327 | payment_info_2_0, 'CdtTrfTxInf') | 223 | payment_info_2_0, 'CdtTrfTxInf') |
2183 | @@ -331,104 +227,54 @@ | |||
2184 | 331 | payment_identification_2_28, 'EndToEndId') | 227 | payment_identification_2_28, 'EndToEndId') |
2185 | 332 | end2end_identification_2_30.text = self._prepare_field( | 228 | end2end_identification_2_30.text = self._prepare_field( |
2186 | 333 | cr, uid, 'End to End Identification', 'line.name', | 229 | cr, uid, 'End to End Identification', 'line.name', |
2188 | 334 | {'line': line}, 35, context=context) | 230 | {'line': line}, 35, gen_args=gen_args, |
2189 | 231 | context=context) | ||
2190 | 335 | currency_name = self._prepare_field( | 232 | currency_name = self._prepare_field( |
2191 | 336 | cr, uid, 'Currency Code', 'line.currency.name', | 233 | cr, uid, 'Currency Code', 'line.currency.name', |
2193 | 337 | {'line': line}, 3, context=context) | 234 | {'line': line}, 3, gen_args=gen_args, |
2194 | 235 | context=context) | ||
2195 | 338 | amount_2_42 = etree.SubElement( | 236 | amount_2_42 = etree.SubElement( |
2196 | 339 | credit_transfer_transaction_info_2_27, 'Amt') | 237 | credit_transfer_transaction_info_2_27, 'Amt') |
2197 | 340 | instructed_amount_2_43 = etree.SubElement( | 238 | instructed_amount_2_43 = etree.SubElement( |
2198 | 341 | amount_2_42, 'InstdAmt', Ccy=currency_name) | 239 | amount_2_42, 'InstdAmt', Ccy=currency_name) |
2199 | 342 | instructed_amount_2_43.text = '%.2f' % line.amount_currency | 240 | instructed_amount_2_43.text = '%.2f' % line.amount_currency |
2205 | 343 | amount_control_sum += line.amount_currency | 241 | amount_control_sum_1_7 += line.amount_currency |
2206 | 344 | creditor_agent_2_77 = etree.SubElement( | 242 | amount_control_sum_2_5 += line.amount_currency |
2207 | 345 | credit_transfer_transaction_info_2_27, 'CdtrAgt') | 243 | |
2203 | 346 | creditor_agent_institution = etree.SubElement( | ||
2204 | 347 | creditor_agent_2_77, 'FinInstnId') | ||
2208 | 348 | if not line.bank_id: | 244 | if not line.bank_id: |
2209 | 349 | raise orm.except_orm( | 245 | raise orm.except_orm( |
2210 | 350 | _('Error:'), | 246 | _('Error:'), |
2212 | 351 | _("Missing Bank Account on invoice '%s' (payment order line reference '%s').") | 247 | _("Missing Bank Account on invoice '%s' (payment " |
2213 | 248 | "order line reference '%s').") | ||
2214 | 352 | % (line.ml_inv_ref.number, line.name)) | 249 | % (line.ml_inv_ref.number, line.name)) |
2237 | 353 | creditor_agent_bic = etree.SubElement( | 250 | self.generate_party_block( |
2238 | 354 | creditor_agent_institution, bic_xml_tag) | 251 | cr, uid, credit_transfer_transaction_info_2_27, 'Cdtr', |
2239 | 355 | creditor_agent_bic.text = self._prepare_field( | 252 | 'C', 'line.partner_id.name', 'line.bank_id.acc_number', |
2240 | 356 | cr, uid, 'Customer BIC', 'line.bank_id.bank.bic', | 253 | 'line.bank_id.bank.bic', {'line': line}, gen_args, |
2219 | 357 | {'line': line}, context=context) | ||
2220 | 358 | creditor_2_79 = etree.SubElement( | ||
2221 | 359 | credit_transfer_transaction_info_2_27, 'Cdtr') | ||
2222 | 360 | creditor_name = etree.SubElement(creditor_2_79, 'Nm') | ||
2223 | 361 | creditor_name.text = self._prepare_field( | ||
2224 | 362 | cr, uid, 'Customer Name', 'line.partner_id.name', | ||
2225 | 363 | {'line': line}, name_maxsize, context=context) | ||
2226 | 364 | creditor_account_2_80 = etree.SubElement( | ||
2227 | 365 | credit_transfer_transaction_info_2_27, 'CdtrAcct') | ||
2228 | 366 | creditor_account_id = etree.SubElement( | ||
2229 | 367 | creditor_account_2_80, 'Id') | ||
2230 | 368 | creditor_account_iban = etree.SubElement( | ||
2231 | 369 | creditor_account_id, 'IBAN') | ||
2232 | 370 | creditor_account_iban.text = self._validate_iban( | ||
2233 | 371 | cr, uid, self._prepare_field( | ||
2234 | 372 | cr, uid, 'Customer IBAN', | ||
2235 | 373 | 'line.bank_id.acc_number', {'line': line}, | ||
2236 | 374 | context=context), | ||
2241 | 375 | context=context) | 254 | context=context) |
2259 | 376 | remittance_info_2_91 = etree.SubElement( | 255 | |
2260 | 377 | credit_transfer_transaction_info_2_27, 'RmtInf') | 256 | self.generate_remittance_info_block( |
2261 | 378 | # switch to Structured (Strdr) ? | 257 | cr, uid, credit_transfer_transaction_info_2_27, |
2262 | 379 | # If we do it, beware that the format is not the same | 258 | line, gen_args, context=context) |
2263 | 380 | # between pain 02 and pain 03 | 259 | |
2264 | 381 | remittance_info_unstructured_2_99 = etree.SubElement( | 260 | if pain_flavor in pain_03_to_05: |
2265 | 382 | remittance_info_2_91, 'Ustrd') | 261 | nb_of_transactions_2_4.text = str(transactions_count_2_4) |
2266 | 383 | remittance_info_unstructured_2_99.text = self._prepare_field( | 262 | control_sum_2_5.text = '%.2f' % amount_control_sum_2_5 |
2267 | 384 | cr, uid, 'Remittance Information', 'line.communication', | 263 | |
2268 | 385 | {'line': line}, 140, context=context) | 264 | if pain_flavor in pain_03_to_05: |
2269 | 386 | 265 | nb_of_transactions_1_6.text = str(transactions_count_1_6) | |
2270 | 387 | if pain_flavor in [ | 266 | control_sum_1_7.text = '%.2f' % amount_control_sum_1_7 |
2254 | 388 | 'pain.001.001.03', 'pain.001.001.04', 'pain.001.001.05']: | ||
2255 | 389 | nb_of_transactions_1_6.text = nb_of_transactions_2_4.text = \ | ||
2256 | 390 | str(transactions_count) | ||
2257 | 391 | control_sum_1_7.text = control_sum_2_5.text = \ | ||
2258 | 392 | '%.2f' % amount_control_sum | ||
2271 | 393 | else: | 267 | else: |
2306 | 394 | nb_of_transactions_1_6.text = str(transactions_count) | 268 | nb_of_transactions_1_6.text = str(transactions_count_1_6) |
2307 | 395 | control_sum_1_7.text = '%.2f' % amount_control_sum | 269 | control_sum_1_7.text = '%.2f' % amount_control_sum_1_7 |
2308 | 396 | 270 | ||
2309 | 397 | xml_string = etree.tostring( | 271 | return self.finalize_sepa_file_creation( |
2310 | 398 | root, pretty_print=True, encoding='UTF-8', xml_declaration=True) | 272 | cr, uid, ids, xml_root, total_amount, transactions_count_1_6, |
2311 | 399 | _logger.debug( | 273 | gen_args, context=context) |
2278 | 400 | "Generated SEPA Credit Transfer XML file in format %s below" | ||
2279 | 401 | % pain_flavor) | ||
2280 | 402 | _logger.debug(xml_string) | ||
2281 | 403 | self._validate_xml(cr, uid, xml_string, pain_flavor) | ||
2282 | 404 | |||
2283 | 405 | # CREATE the banking.export.sepa record | ||
2284 | 406 | file_id = self.pool.get('banking.export.sepa').create( | ||
2285 | 407 | cr, uid, self._prepare_export_sepa( | ||
2286 | 408 | cr, uid, sepa_export, total_amount, transactions_count, | ||
2287 | 409 | xml_string, context=context), | ||
2288 | 410 | context=context) | ||
2289 | 411 | |||
2290 | 412 | self.write( | ||
2291 | 413 | cr, uid, ids, { | ||
2292 | 414 | 'file_id': file_id, | ||
2293 | 415 | 'state': 'finish', | ||
2294 | 416 | }, context=context) | ||
2295 | 417 | |||
2296 | 418 | action = { | ||
2297 | 419 | 'name': 'SEPA Credit Transfer File', | ||
2298 | 420 | 'type': 'ir.actions.act_window', | ||
2299 | 421 | 'view_type': 'form', | ||
2300 | 422 | 'view_mode': 'form,tree', | ||
2301 | 423 | 'res_model': self._name, | ||
2302 | 424 | 'res_id': ids[0], | ||
2303 | 425 | 'target': 'new', | ||
2304 | 426 | } | ||
2305 | 427 | return action | ||
2312 | 428 | 274 | ||
2313 | 429 | def cancel_sepa(self, cr, uid, ids, context=None): | 275 | def cancel_sepa(self, cr, uid, ids, context=None): |
2314 | 430 | ''' | 276 | ''' |
2316 | 431 | Cancel the SEPA PAIN: just drop the file | 277 | Cancel the SEPA file: just drop the file |
2317 | 432 | ''' | 278 | ''' |
2318 | 433 | sepa_export = self.browse(cr, uid, ids[0], context=context) | 279 | sepa_export = self.browse(cr, uid, ids[0], context=context) |
2319 | 434 | self.pool.get('banking.export.sepa').unlink( | 280 | self.pool.get('banking.export.sepa').unlink( |
2320 | @@ -437,7 +283,7 @@ | |||
2321 | 437 | 283 | ||
2322 | 438 | def save_sepa(self, cr, uid, ids, context=None): | 284 | def save_sepa(self, cr, uid, ids, context=None): |
2323 | 439 | ''' | 285 | ''' |
2325 | 440 | Save the SEPA PAIN: send the done signal to all payment | 286 | Save the SEPA file: send the done signal to all payment |
2326 | 441 | orders in the file. With the default workflow, they will | 287 | orders in the file. With the default workflow, they will |
2327 | 442 | transition to 'done', while with the advanced workflow in | 288 | transition to 'done', while with the advanced workflow in |
2328 | 443 | account_banking_payment they will transition to 'sent' waiting | 289 | account_banking_payment they will transition to 'sent' waiting |
2329 | 444 | 290 | ||
2330 | === modified file 'account_banking_sepa_credit_transfer/wizard/export_sepa_view.xml' | |||
2331 | --- account_banking_sepa_credit_transfer/wizard/export_sepa_view.xml 2013-11-07 11:50:36 +0000 | |||
2332 | +++ account_banking_sepa_credit_transfer/wizard/export_sepa_view.xml 2014-01-13 12:42:46 +0000 | |||
2333 | @@ -15,7 +15,6 @@ | |||
2334 | 15 | <field name="state" invisible="True"/> | 15 | <field name="state" invisible="True"/> |
2335 | 16 | <group states="create"> | 16 | <group states="create"> |
2336 | 17 | <field name="batch_booking" /> | 17 | <field name="batch_booking" /> |
2337 | 18 | <field name="prefered_exec_date" /> | ||
2338 | 19 | <field name="charge_bearer" /> | 18 | <field name="charge_bearer" /> |
2339 | 20 | </group> | 19 | </group> |
2340 | 21 | <group states="finish"> | 20 | <group states="finish"> |
2341 | 22 | 21 | ||
2342 | === added directory 'account_banking_sepa_direct_debit' | |||
2343 | === added file 'account_banking_sepa_direct_debit/__init__.py' | |||
2344 | --- account_banking_sepa_direct_debit/__init__.py 1970-01-01 00:00:00 +0000 | |||
2345 | +++ account_banking_sepa_direct_debit/__init__.py 2014-01-13 12:42:46 +0000 | |||
2346 | @@ -0,0 +1,25 @@ | |||
2347 | 1 | # -*- encoding: utf-8 -*- | ||
2348 | 2 | ############################################################################## | ||
2349 | 3 | # | ||
2350 | 4 | # SEPA Direct Debit module for OpenERP | ||
2351 | 5 | # Copyright (C) 2013 Akretion (http://www.akretion.com) | ||
2352 | 6 | # @author: Alexis de Lattre <alexis.delattre@akretion.com> | ||
2353 | 7 | # | ||
2354 | 8 | # This program is free software: you can redistribute it and/or modify | ||
2355 | 9 | # it under the terms of the GNU Affero General Public License as | ||
2356 | 10 | # published by the Free Software Foundation, either version 3 of the | ||
2357 | 11 | # License, or (at your option) any later version. | ||
2358 | 12 | # | ||
2359 | 13 | # This program is distributed in the hope that it will be useful, | ||
2360 | 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
2361 | 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
2362 | 16 | # GNU Affero General Public License for more details. | ||
2363 | 17 | # | ||
2364 | 18 | # You should have received a copy of the GNU Affero General Public License | ||
2365 | 19 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2366 | 20 | # | ||
2367 | 21 | ############################################################################## | ||
2368 | 22 | |||
2369 | 23 | from . import company | ||
2370 | 24 | from . import wizard | ||
2371 | 25 | from . import account_banking_sdd | ||
2372 | 0 | 26 | ||
2373 | === added file 'account_banking_sepa_direct_debit/__openerp__.py' | |||
2374 | --- account_banking_sepa_direct_debit/__openerp__.py 1970-01-01 00:00:00 +0000 | |||
2375 | +++ account_banking_sepa_direct_debit/__openerp__.py 2014-01-13 12:42:46 +0000 | |||
2376 | @@ -0,0 +1,60 @@ | |||
2377 | 1 | ############################################################################## | ||
2378 | 2 | # | ||
2379 | 3 | # SEPA Direct Debit module for OpenERP | ||
2380 | 4 | # Copyright (C) 2013 Akretion (http://www.akretion.com) | ||
2381 | 5 | # @author: Alexis de Lattre <alexis.delattre@akretion.com> | ||
2382 | 6 | # | ||
2383 | 7 | # This program is free software: you can redistribute it and/or modify | ||
2384 | 8 | # it under the terms of the GNU Affero General Public License as | ||
2385 | 9 | # published by the Free Software Foundation, either version 3 of the | ||
2386 | 10 | # License, or (at your option) any later version. | ||
2387 | 11 | # | ||
2388 | 12 | # This program is distributed in the hope that it will be useful, | ||
2389 | 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
2390 | 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
2391 | 15 | # GNU Affero General Public License for more details. | ||
2392 | 16 | # | ||
2393 | 17 | # You should have received a copy of the GNU Affero General Public License | ||
2394 | 18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2395 | 19 | # | ||
2396 | 20 | ############################################################################## | ||
2397 | 21 | { | ||
2398 | 22 | 'name': 'Account Banking SEPA Direct Debit', | ||
2399 | 23 | 'summary': 'Create SEPA files for Direct Debit', | ||
2400 | 24 | 'version': '0.1', | ||
2401 | 25 | 'license': 'AGPL-3', | ||
2402 | 26 | 'author': 'Akretion', | ||
2403 | 27 | 'website': 'http://www.akretion.com', | ||
2404 | 28 | 'category': 'Banking addons', | ||
2405 | 29 | 'depends': ['account_direct_debit', 'account_banking_pain_base'], | ||
2406 | 30 | 'external_dependencies': { | ||
2407 | 31 | 'python': ['unidecode', 'lxml'], | ||
2408 | 32 | }, | ||
2409 | 33 | 'data': [ | ||
2410 | 34 | 'security/original_mandate_required_security.xml', | ||
2411 | 35 | 'account_banking_sdd_view.xml', | ||
2412 | 36 | 'sdd_mandate_view.xml', | ||
2413 | 37 | 'res_partner_bank_view.xml', | ||
2414 | 38 | 'account_payment_view.xml', | ||
2415 | 39 | 'company_view.xml', | ||
2416 | 40 | 'mandate_expire_cron.xml', | ||
2417 | 41 | 'account_invoice_view.xml', | ||
2418 | 42 | 'wizard/export_sdd_view.xml', | ||
2419 | 43 | 'data/payment_type_sdd.xml', | ||
2420 | 44 | 'data/mandate_reference_sequence.xml', | ||
2421 | 45 | 'security/ir.model.access.csv', | ||
2422 | 46 | ], | ||
2423 | 47 | 'description': ''' | ||
2424 | 48 | Module to export direct debit payment orders in SEPA XML file format. | ||
2425 | 49 | |||
2426 | 50 | 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. | ||
2427 | 51 | |||
2428 | 52 | 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. | ||
2429 | 53 | |||
2430 | 54 | This module uses the framework provided by the banking addons, cf https://launchpad.net/banking-addons | ||
2431 | 55 | |||
2432 | 56 | Please contact Alexis de Lattre from Akretion <alexis.delattre@akretion.com> for any help or question about this module. | ||
2433 | 57 | ''', | ||
2434 | 58 | 'active': False, | ||
2435 | 59 | 'installable': True, | ||
2436 | 60 | } | ||
2437 | 0 | 61 | ||
2438 | === added file 'account_banking_sepa_direct_debit/account_banking_sdd.py' | |||
2439 | --- account_banking_sepa_direct_debit/account_banking_sdd.py 1970-01-01 00:00:00 +0000 | |||
2440 | +++ account_banking_sepa_direct_debit/account_banking_sdd.py 2014-01-13 12:42:46 +0000 | |||
2441 | @@ -0,0 +1,424 @@ | |||
2442 | 1 | ############################################################################## | ||
2443 | 2 | # | ||
2444 | 3 | # SEPA Direct Debit module for OpenERP | ||
2445 | 4 | # Copyright (C) 2013 Akretion (http://www.akretion.com) | ||
2446 | 5 | # @author: Alexis de Lattre <alexis.delattre@akretion.com> | ||
2447 | 6 | # | ||
2448 | 7 | # This program is free software: you can redistribute it and/or modify | ||
2449 | 8 | # it under the terms of the GNU Affero General Public License as | ||
2450 | 9 | # published by the Free Software Foundation, either version 3 of the | ||
2451 | 10 | # License, or (at your option) any later version. | ||
2452 | 11 | # | ||
2453 | 12 | # This program is distributed in the hope that it will be useful, | ||
2454 | 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
2455 | 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
2456 | 15 | # GNU Affero General Public License for more details. | ||
2457 | 16 | # | ||
2458 | 17 | # You should have received a copy of the GNU Affero General Public License | ||
2459 | 18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2460 | 19 | # | ||
2461 | 20 | ############################################################################## | ||
2462 | 21 | |||
2463 | 22 | from openerp.osv import orm, fields | ||
2464 | 23 | from openerp.tools.translate import _ | ||
2465 | 24 | from openerp.addons.decimal_precision import decimal_precision as dp | ||
2466 | 25 | from unidecode import unidecode | ||
2467 | 26 | from datetime import datetime | ||
2468 | 27 | from dateutil.relativedelta import relativedelta | ||
2469 | 28 | import logging | ||
2470 | 29 | |||
2471 | 30 | NUMBER_OF_UNUSED_MONTHS_BEFORE_EXPIRY = 36 | ||
2472 | 31 | |||
2473 | 32 | logger = logging.getLogger(__name__) | ||
2474 | 33 | |||
2475 | 34 | |||
2476 | 35 | class banking_export_sdd(orm.Model): | ||
2477 | 36 | '''SEPA Direct Debit export''' | ||
2478 | 37 | _name = 'banking.export.sdd' | ||
2479 | 38 | _description = __doc__ | ||
2480 | 39 | _rec_name = 'filename' | ||
2481 | 40 | |||
2482 | 41 | def _generate_filename(self, cr, uid, ids, name, arg, context=None): | ||
2483 | 42 | res = {} | ||
2484 | 43 | for sepa_file in self.browse(cr, uid, ids, context=context): | ||
2485 | 44 | ref = sepa_file.payment_order_ids[0].reference | ||
2486 | 45 | if ref: | ||
2487 | 46 | label = unidecode(ref.replace('/', '-')) | ||
2488 | 47 | else: | ||
2489 | 48 | label = 'error' | ||
2490 | 49 | res[sepa_file.id] = 'sdd_%s.xml' % label | ||
2491 | 50 | return res | ||
2492 | 51 | |||
2493 | 52 | _columns = { | ||
2494 | 53 | 'payment_order_ids': fields.many2many( | ||
2495 | 54 | 'payment.order', | ||
2496 | 55 | 'account_payment_order_sdd_rel', | ||
2497 | 56 | 'banking_export_sepa_id', 'account_order_id', | ||
2498 | 57 | 'Payment Orders', | ||
2499 | 58 | readonly=True), | ||
2500 | 59 | 'nb_transactions': fields.integer( | ||
2501 | 60 | 'Number of Transactions', readonly=True), | ||
2502 | 61 | 'total_amount': fields.float( | ||
2503 | 62 | 'Total Amount', digits_compute=dp.get_precision('Account'), | ||
2504 | 63 | readonly=True), | ||
2505 | 64 | 'batch_booking': fields.boolean( | ||
2506 | 65 | 'Batch Booking', readonly=True, | ||
2507 | 66 | help="If true, the bank statement will display only one credit " | ||
2508 | 67 | "line for all the direct debits of the SEPA file ; if false, " | ||
2509 | 68 | "the bank statement will display one credit line per direct " | ||
2510 | 69 | "debit of the SEPA file."), | ||
2511 | 70 | 'charge_bearer': fields.selection([ | ||
2512 | 71 | ('SLEV', 'Following Service Level'), | ||
2513 | 72 | ('SHAR', 'Shared'), | ||
2514 | 73 | ('CRED', 'Borne by Creditor'), | ||
2515 | 74 | ('DEBT', 'Borne by Debtor'), | ||
2516 | 75 | ], 'Charge Bearer', readonly=True, | ||
2517 | 76 | help="Following service level : transaction charges are to be " | ||
2518 | 77 | "applied following the rules agreed in the service level and/or " | ||
2519 | 78 | "scheme (SEPA Core messages must use this). Shared : " | ||
2520 | 79 | "transaction charges on the creditor side are to be borne by " | ||
2521 | 80 | "the creditor, transaction charges on the debtor side are to be " | ||
2522 | 81 | "borne by the debtor. Borne by creditor : all transaction " | ||
2523 | 82 | "charges are to be borne by the creditor. Borne by debtor : " | ||
2524 | 83 | "all transaction charges are to be borne by the debtor."), | ||
2525 | 84 | 'create_date': fields.datetime('Generation Date', readonly=True), | ||
2526 | 85 | 'file': fields.binary('SEPA File', readonly=True), | ||
2527 | 86 | 'filename': fields.function( | ||
2528 | 87 | _generate_filename, type='char', size=256, | ||
2529 | 88 | string='Filename', readonly=True, store=True), | ||
2530 | 89 | 'state': fields.selection([ | ||
2531 | 90 | ('draft', 'Draft'), | ||
2532 | 91 | ('sent', 'Sent'), | ||
2533 | 92 | ('done', 'Reconciled'), | ||
2534 | 93 | ], 'State', readonly=True), | ||
2535 | 94 | } | ||
2536 | 95 | |||
2537 | 96 | _defaults = { | ||
2538 | 97 | 'state': 'draft', | ||
2539 | 98 | } | ||
2540 | 99 | |||
2541 | 100 | |||
2542 | 101 | class sdd_mandate(orm.Model): | ||
2543 | 102 | '''SEPA Direct Debit Mandate''' | ||
2544 | 103 | _name = 'sdd.mandate' | ||
2545 | 104 | _description = __doc__ | ||
2546 | 105 | _rec_name = 'unique_mandate_reference' | ||
2547 | 106 | _inherit = ['mail.thread'] | ||
2548 | 107 | _order = 'signature_date desc' | ||
2549 | 108 | _track = { | ||
2550 | 109 | 'state': { | ||
2551 | 110 | 'account_banking_sepa_direct_debit.mandate_valid': | ||
2552 | 111 | lambda self, cr, uid, obj, ctx=None: | ||
2553 | 112 | obj['state'] == 'valid', | ||
2554 | 113 | 'account_banking_sepa_direct_debit.mandate_expired': | ||
2555 | 114 | lambda self, cr, uid, obj, ctx=None: | ||
2556 | 115 | obj['state'] == 'expired', | ||
2557 | 116 | 'account_banking_sepa_direct_debit.mandate_cancel': | ||
2558 | 117 | lambda self, cr, uid, obj, ctx=None: | ||
2559 | 118 | obj['state'] == 'cancel', | ||
2560 | 119 | }, | ||
2561 | 120 | 'recurrent_sequence_type': { | ||
2562 | 121 | 'account_banking_sepa_direct_debit.recurrent_sequence_type_first': | ||
2563 | 122 | lambda self, cr, uid, obj, ctx=None: | ||
2564 | 123 | obj['recurrent_sequence_type'] == 'first', | ||
2565 | 124 | 'account_banking_sepa_direct_debit.' | ||
2566 | 125 | 'recurrent_sequence_type_recurring': | ||
2567 | 126 | lambda self, cr, uid, obj, ctx=None: | ||
2568 | 127 | obj['recurrent_sequence_type'] == 'recurring', | ||
2569 | 128 | 'account_banking_sepa_direct_debit.recurrent_sequence_type_final': | ||
2570 | 129 | lambda self, cr, uid, obj, ctx=None: | ||
2571 | 130 | obj['recurrent_sequence_type'] == 'final', | ||
2572 | 131 | } | ||
2573 | 132 | } | ||
2574 | 133 | |||
2575 | 134 | _columns = { | ||
2576 | 135 | 'partner_bank_id': fields.many2one( | ||
2577 | 136 | 'res.partner.bank', 'Bank Account', track_visibility='onchange'), | ||
2578 | 137 | 'partner_id': fields.related( | ||
2579 | 138 | 'partner_bank_id', 'partner_id', type='many2one', | ||
2580 | 139 | relation='res.partner', string='Partner', readonly=True), | ||
2581 | 140 | 'company_id': fields.many2one('res.company', 'Company', required=True), | ||
2582 | 141 | 'unique_mandate_reference': fields.char( | ||
2583 | 142 | 'Unique Mandate Reference', size=35, readonly=True, | ||
2584 | 143 | track_visibility='always'), | ||
2585 | 144 | 'type': fields.selection([ | ||
2586 | 145 | ('recurrent', 'Recurrent'), | ||
2587 | 146 | ('oneoff', 'One-Off'), | ||
2588 | 147 | ], 'Type of Mandate', required=True, track_visibility='always'), | ||
2589 | 148 | 'recurrent_sequence_type': fields.selection([ | ||
2590 | 149 | ('first', 'First'), | ||
2591 | 150 | ('recurring', 'Recurring'), | ||
2592 | 151 | ('final', 'Final'), | ||
2593 | 152 | ], 'Sequence Type for Next Debit', track_visibility='onchange', | ||
2594 | 153 | help="This field is only used for Recurrent mandates, not for " | ||
2595 | 154 | "One-Off mandates."), | ||
2596 | 155 | 'signature_date': fields.date( | ||
2597 | 156 | 'Date of Signature of the Mandate', track_visibility='onchange'), | ||
2598 | 157 | 'scan': fields.binary('Scan of the Mandate'), | ||
2599 | 158 | 'last_debit_date': fields.date( | ||
2600 | 159 | 'Date of the Last Debit', readonly=True), | ||
2601 | 160 | 'state': fields.selection([ | ||
2602 | 161 | ('draft', 'Draft'), | ||
2603 | 162 | ('valid', 'Valid'), | ||
2604 | 163 | ('expired', 'Expired'), | ||
2605 | 164 | ('cancel', 'Cancelled'), | ||
2606 | 165 | ], 'Status', | ||
2607 | 166 | help="Only valid mandates can be used in a payment line. A " | ||
2608 | 167 | "cancelled mandate is a mandate that has been cancelled by " | ||
2609 | 168 | "the customer. A one-off mandate expires after its first use. " | ||
2610 | 169 | "A recurrent mandate expires after it's final use or if it " | ||
2611 | 170 | "hasn't been used for 36 months."), | ||
2612 | 171 | 'payment_line_ids': fields.one2many( | ||
2613 | 172 | 'payment.line', 'sdd_mandate_id', "Related Payment Lines"), | ||
2614 | 173 | 'sepa_migrated': fields.boolean( | ||
2615 | 174 | 'Migrated to SEPA', track_visibility='onchange', | ||
2616 | 175 | help="If this field is not active, the mandate section of the " | ||
2617 | 176 | "next direct debit file that include this mandate will contain " | ||
2618 | 177 | "the 'Original Mandate Identification' and the 'Original " | ||
2619 | 178 | "Creditor Scheme Identification'. This is required in a few " | ||
2620 | 179 | "countries (Belgium for instance), but not in all countries. " | ||
2621 | 180 | "If this is not required in your country, you should keep this " | ||
2622 | 181 | "field always active."), | ||
2623 | 182 | 'original_mandate_identification': fields.char( | ||
2624 | 183 | 'Original Mandate Identification', size=35, | ||
2625 | 184 | track_visibility='onchange', | ||
2626 | 185 | help="When the field 'Migrated to SEPA' is not active, this " | ||
2627 | 186 | "field will be used as the Original Mandate Identification in " | ||
2628 | 187 | "the Direct Debit file."), | ||
2629 | 188 | } | ||
2630 | 189 | |||
2631 | 190 | _defaults = { | ||
2632 | 191 | 'company_id': lambda self, cr, uid, context: | ||
2633 | 192 | self.pool['res.company']._company_default_get( | ||
2634 | 193 | cr, uid, 'sdd.mandate', context=context), | ||
2635 | 194 | 'unique_mandate_reference': lambda self, cr, uid, ctx: | ||
2636 | 195 | self.pool['ir.sequence'].get(cr, uid, 'sdd.mandate.reference'), | ||
2637 | 196 | 'state': 'draft', | ||
2638 | 197 | 'sepa_migrated': True, | ||
2639 | 198 | } | ||
2640 | 199 | |||
2641 | 200 | _sql_constraints = [( | ||
2642 | 201 | 'mandate_ref_company_uniq', | ||
2643 | 202 | 'unique(unique_mandate_reference, company_id)', | ||
2644 | 203 | 'A Mandate with the same reference already exists for this company !' | ||
2645 | 204 | )] | ||
2646 | 205 | |||
2647 | 206 | def _check_sdd_mandate(self, cr, uid, ids): | ||
2648 | 207 | for mandate in self.browse(cr, uid, ids): | ||
2649 | 208 | if (mandate.signature_date and | ||
2650 | 209 | mandate.signature_date > | ||
2651 | 210 | datetime.today().strftime('%Y-%m-%d')): | ||
2652 | 211 | raise orm.except_orm( | ||
2653 | 212 | _('Error:'), | ||
2654 | 213 | _("The date of signature of mandate '%s' is in the " | ||
2655 | 214 | "future !") | ||
2656 | 215 | % mandate.unique_mandate_reference) | ||
2657 | 216 | if mandate.state == 'valid' and not mandate.signature_date: | ||
2658 | 217 | raise orm.except_orm( | ||
2659 | 218 | _('Error:'), | ||
2660 | 219 | _("Cannot validate the mandate '%s' without a date of " | ||
2661 | 220 | "signature.") | ||
2662 | 221 | % mandate.unique_mandate_reference) | ||
2663 | 222 | if mandate.state == 'valid' and not mandate.partner_bank_id: | ||
2664 | 223 | raise orm.except_orm( | ||
2665 | 224 | _('Error:'), | ||
2666 | 225 | _("Cannot validate the mandate '%s' because it is not " | ||
2667 | 226 | "attached to a bank account.") | ||
2668 | 227 | % mandate.unique_mandate_reference) | ||
2669 | 228 | |||
2670 | 229 | if (mandate.signature_date and mandate.last_debit_date and | ||
2671 | 230 | mandate.signature_date > mandate.last_debit_date): | ||
2672 | 231 | raise orm.except_orm( | ||
2673 | 232 | _('Error:'), | ||
2674 | 233 | _("The mandate '%s' can't have a date of last debit " | ||
2675 | 234 | "before the date of signature.") | ||
2676 | 235 | % mandate.unique_mandate_reference) | ||
2677 | 236 | if (mandate.type == 'recurrent' | ||
2678 | 237 | and not mandate.recurrent_sequence_type): | ||
2679 | 238 | raise orm.except_orm( | ||
2680 | 239 | _('Error:'), | ||
2681 | 240 | _("The recurrent mandate '%s' must have a sequence type.") | ||
2682 | 241 | % mandate.unique_mandate_reference) | ||
2683 | 242 | if (mandate.type == 'recurrent' and not mandate.sepa_migrated | ||
2684 | 243 | and mandate.recurrent_sequence_type != 'first'): | ||
2685 | 244 | raise orm.except_orm( | ||
2686 | 245 | _('Error:'), | ||
2687 | 246 | _("The recurrent mandate '%s' which is not marked as " | ||
2688 | 247 | "'Migrated to SEPA' must have its recurrent sequence " | ||
2689 | 248 | "type set to 'First'.") | ||
2690 | 249 | % mandate.unique_mandate_reference) | ||
2691 | 250 | if (mandate.type == 'recurrent' and not mandate.sepa_migrated | ||
2692 | 251 | and not mandate.original_mandate_identification): | ||
2693 | 252 | raise orm.except_orm( | ||
2694 | 253 | _('Error:'), | ||
2695 | 254 | _("You must set the 'Original Mandate Identification' " | ||
2696 | 255 | "on the recurrent mandate '%s' which is not marked " | ||
2697 | 256 | "as 'Migrated to SEPA'.") | ||
2698 | 257 | % mandate.unique_mandate_reference) | ||
2699 | 258 | return True | ||
2700 | 259 | |||
2701 | 260 | _constraints = [ | ||
2702 | 261 | (_check_sdd_mandate, "Error msg in raise", [ | ||
2703 | 262 | 'last_debit_date', 'signature_date', 'state', 'partner_bank_id', | ||
2704 | 263 | 'type', 'recurrent_sequence_type', 'sepa_migrated', | ||
2705 | 264 | 'original_mandate_identification', | ||
2706 | 265 | ]), | ||
2707 | 266 | ] | ||
2708 | 267 | |||
2709 | 268 | def mandate_type_change(self, cr, uid, ids, type): | ||
2710 | 269 | if type == 'recurrent': | ||
2711 | 270 | recurrent_sequence_type = 'first' | ||
2712 | 271 | else: | ||
2713 | 272 | recurrent_sequence_type = False | ||
2714 | 273 | res = {'value': {'recurrent_sequence_type': recurrent_sequence_type}} | ||
2715 | 274 | return res | ||
2716 | 275 | |||
2717 | 276 | def mandate_partner_bank_change( | ||
2718 | 277 | self, cr, uid, ids, partner_bank_id, type, recurrent_sequence_type, | ||
2719 | 278 | last_debit_date, state): | ||
2720 | 279 | res = {'value': {}} | ||
2721 | 280 | if partner_bank_id: | ||
2722 | 281 | partner_bank_read = self.pool['res.partner.bank'].read( | ||
2723 | 282 | cr, uid, partner_bank_id, ['partner_id'])['partner_id'] | ||
2724 | 283 | if partner_bank_read: | ||
2725 | 284 | res['value']['partner_id'] = partner_bank_read[0] | ||
2726 | 285 | if (state == 'valid' and partner_bank_id | ||
2727 | 286 | and type == 'recurrent' | ||
2728 | 287 | and recurrent_sequence_type != 'first'): | ||
2729 | 288 | res['value']['recurrent_sequence_type'] = 'first' | ||
2730 | 289 | res['warning'] = { | ||
2731 | 290 | 'title': _('Mandate update'), | ||
2732 | 291 | 'message': _( | ||
2733 | 292 | "As you changed the bank account attached to this " | ||
2734 | 293 | "mandate, the 'Sequence Type' has been set back to " | ||
2735 | 294 | "'First'."), | ||
2736 | 295 | } | ||
2737 | 296 | return res | ||
2738 | 297 | |||
2739 | 298 | def validate(self, cr, uid, ids, context=None): | ||
2740 | 299 | to_validate_ids = [] | ||
2741 | 300 | for mandate in self.browse(cr, uid, ids, context=context): | ||
2742 | 301 | assert mandate.state == 'draft', 'Mandate should be in draft state' | ||
2743 | 302 | to_validate_ids.append(mandate.id) | ||
2744 | 303 | self.write( | ||
2745 | 304 | cr, uid, to_validate_ids, {'state': 'valid'}, context=context) | ||
2746 | 305 | return True | ||
2747 | 306 | |||
2748 | 307 | def cancel(self, cr, uid, ids, context=None): | ||
2749 | 308 | to_cancel_ids = [] | ||
2750 | 309 | for mandate in self.browse(cr, uid, ids, context=context): | ||
2751 | 310 | assert mandate.state in ('draft', 'valid'),\ | ||
2752 | 311 | 'Mandate should be in draft or valid state' | ||
2753 | 312 | to_cancel_ids.append(mandate.id) | ||
2754 | 313 | self.write( | ||
2755 | 314 | cr, uid, to_cancel_ids, {'state': 'cancel'}, context=context) | ||
2756 | 315 | return True | ||
2757 | 316 | |||
2758 | 317 | def _sdd_mandate_set_state_to_expired(self, cr, uid, context=None): | ||
2759 | 318 | logger.info('Searching for SDD Mandates that must be set to Expired') | ||
2760 | 319 | expire_limit_date = datetime.today() + \ | ||
2761 | 320 | relativedelta(months=-NUMBER_OF_UNUSED_MONTHS_BEFORE_EXPIRY) | ||
2762 | 321 | expire_limit_date_str = expire_limit_date.strftime('%Y-%m-%d') | ||
2763 | 322 | expired_mandate_ids = self.search(cr, uid, [ | ||
2764 | 323 | '|', | ||
2765 | 324 | ('last_debit_date', '=', False), | ||
2766 | 325 | ('last_debit_date', '<=', expire_limit_date_str), | ||
2767 | 326 | ('state', '=', 'valid'), | ||
2768 | 327 | ('signature_date', '<=', expire_limit_date_str), | ||
2769 | 328 | ], context=context) | ||
2770 | 329 | if expired_mandate_ids: | ||
2771 | 330 | self.write( | ||
2772 | 331 | cr, uid, expired_mandate_ids, {'state': 'expired'}, | ||
2773 | 332 | context=context) | ||
2774 | 333 | logger.info( | ||
2775 | 334 | 'The following SDD Mandate IDs has been set to expired: %s' | ||
2776 | 335 | % expired_mandate_ids) | ||
2777 | 336 | else: | ||
2778 | 337 | logger.info('0 SDD Mandates must be set to Expired') | ||
2779 | 338 | return True | ||
2780 | 339 | |||
2781 | 340 | |||
2782 | 341 | class res_partner_bank(orm.Model): | ||
2783 | 342 | _inherit = 'res.partner.bank' | ||
2784 | 343 | |||
2785 | 344 | _columns = { | ||
2786 | 345 | 'sdd_mandate_ids': fields.one2many( | ||
2787 | 346 | 'sdd.mandate', 'partner_bank_id', 'SEPA Direct Debit Mandates'), | ||
2788 | 347 | } | ||
2789 | 348 | |||
2790 | 349 | |||
2791 | 350 | class payment_line(orm.Model): | ||
2792 | 351 | _inherit = 'payment.line' | ||
2793 | 352 | |||
2794 | 353 | _columns = { | ||
2795 | 354 | 'sdd_mandate_id': fields.many2one( | ||
2796 | 355 | 'sdd.mandate', 'SEPA Direct Debit Mandate', | ||
2797 | 356 | domain=[('state', '=', 'valid')]), | ||
2798 | 357 | } | ||
2799 | 358 | |||
2800 | 359 | def create(self, cr, uid, vals, context=None): | ||
2801 | 360 | '''If the customer invoice has a mandate, take it | ||
2802 | 361 | otherwise, take the first valid mandate of the bank account''' | ||
2803 | 362 | if context is None: | ||
2804 | 363 | context = {} | ||
2805 | 364 | if not vals: | ||
2806 | 365 | vals = {} | ||
2807 | 366 | partner_bank_id = vals.get('bank_id') | ||
2808 | 367 | move_line_id = vals.get('move_line_id') | ||
2809 | 368 | if (context.get('default_payment_order_type') == 'debit' | ||
2810 | 369 | and 'sdd_mandate_id' not in vals): | ||
2811 | 370 | if move_line_id: | ||
2812 | 371 | line = self.pool['account.move.line'].browse( | ||
2813 | 372 | cr, uid, move_line_id, context=context) | ||
2814 | 373 | if (line.invoice and line.invoice.type == 'out_invoice' | ||
2815 | 374 | and line.invoice.sdd_mandate_id): | ||
2816 | 375 | vals.update({ | ||
2817 | 376 | 'sdd_mandate_id': line.invoice.sdd_mandate_id.id, | ||
2818 | 377 | 'bank_id': | ||
2819 | 378 | line.invoice.sdd_mandate_id.partner_bank_id.id, | ||
2820 | 379 | }) | ||
2821 | 380 | if partner_bank_id and 'sdd_mandate_id' not in vals: | ||
2822 | 381 | mandate_ids = self.pool['sdd.mandate'].search(cr, uid, [ | ||
2823 | 382 | ('partner_bank_id', '=', partner_bank_id), | ||
2824 | 383 | ('state', '=', 'valid'), | ||
2825 | 384 | ], context=context) | ||
2826 | 385 | if mandate_ids: | ||
2827 | 386 | vals['sdd_mandate_id'] = mandate_ids[0] | ||
2828 | 387 | return super(payment_line, self).create(cr, uid, vals, context=context) | ||
2829 | 388 | |||
2830 | 389 | def _check_mandate_bank_link(self, cr, uid, ids): | ||
2831 | 390 | for payline in self.browse(cr, uid, ids): | ||
2832 | 391 | if (payline.sdd_mandate_id and payline.bank_id | ||
2833 | 392 | and payline.sdd_mandate_id.partner_bank_id.id != | ||
2834 | 393 | payline.bank_id.id): | ||
2835 | 394 | raise orm.except_orm( | ||
2836 | 395 | _('Error:'), | ||
2837 | 396 | _("The payment line with reference '%s' has the bank " | ||
2838 | 397 | "account '%s' which is not attached to the mandate " | ||
2839 | 398 | "'%s' (this mandate is attached to the bank account " | ||
2840 | 399 | "'%s').") % ( | ||
2841 | 400 | payline.name, | ||
2842 | 401 | self.pool['res.partner.bank'].name_get( | ||
2843 | 402 | cr, uid, [payline.bank_id.id])[0][1], | ||
2844 | 403 | payline.sdd_mandate_id.unique_mandate_reference, | ||
2845 | 404 | self.pool['res.partner.bank'].name_get( | ||
2846 | 405 | cr, uid, | ||
2847 | 406 | [payline.sdd_mandate_id.partner_bank_id.id])[0][1], | ||
2848 | 407 | )) | ||
2849 | 408 | return True | ||
2850 | 409 | |||
2851 | 410 | _constraints = [ | ||
2852 | 411 | (_check_mandate_bank_link, 'Error msg in raise', | ||
2853 | 412 | ['sdd_mandate_id', 'bank_id']), | ||
2854 | 413 | ] | ||
2855 | 414 | |||
2856 | 415 | |||
2857 | 416 | class account_invoice(orm.Model): | ||
2858 | 417 | _inherit = 'account.invoice' | ||
2859 | 418 | |||
2860 | 419 | _columns = { | ||
2861 | 420 | 'sdd_mandate_id': fields.many2one( | ||
2862 | 421 | 'sdd.mandate', 'SEPA Direct Debit Mandate', | ||
2863 | 422 | domain=[('state', '=', 'valid')], readonly=True, | ||
2864 | 423 | states={'draft': [('readonly', False)]}) | ||
2865 | 424 | } | ||
2866 | 0 | 425 | ||
2867 | === added file 'account_banking_sepa_direct_debit/account_banking_sdd_view.xml' | |||
2868 | --- account_banking_sepa_direct_debit/account_banking_sdd_view.xml 1970-01-01 00:00:00 +0000 | |||
2869 | +++ account_banking_sepa_direct_debit/account_banking_sdd_view.xml 2014-01-13 12:42:46 +0000 | |||
2870 | @@ -0,0 +1,80 @@ | |||
2871 | 1 | <?xml version="1.0" encoding="utf-8"?> | ||
2872 | 2 | <!-- | ||
2873 | 3 | Copyright (C) 2013 Akretion (http://www.akretion.com) | ||
2874 | 4 | @author: Alexis de Lattre <alexis.delattre@akretion.com> | ||
2875 | 5 | The licence is in the file __openerp__.py | ||
2876 | 6 | --> | ||
2877 | 7 | <openerp> | ||
2878 | 8 | <data> | ||
2879 | 9 | |||
2880 | 10 | <record id="view_banking_export_sdd_form" model="ir.ui.view"> | ||
2881 | 11 | <field name="name">account.banking.export.sdd.form</field> | ||
2882 | 12 | <field name="model">banking.export.sdd</field> | ||
2883 | 13 | <field name="arch" type="xml"> | ||
2884 | 14 | <form string="SEPA Direct Debit"> | ||
2885 | 15 | <notebook> | ||
2886 | 16 | <page string="General Information"> | ||
2887 | 17 | <field name="total_amount" /> | ||
2888 | 18 | <field name="nb_transactions" /> | ||
2889 | 19 | <field name="batch_booking" /> | ||
2890 | 20 | <field name="charge_bearer"/> | ||
2891 | 21 | <field name="create_date" /> | ||
2892 | 22 | <newline /> | ||
2893 | 23 | <field name="file" filename="filename"/> | ||
2894 | 24 | <field name="filename" invisible="True"/> | ||
2895 | 25 | </page> | ||
2896 | 26 | <page string="Payment Orders"> | ||
2897 | 27 | <field name="payment_order_ids" colspan="4" nolabel="1"> | ||
2898 | 28 | <tree colors="blue:state in ('draft');gray:state in ('cancel','done');black:state in ('open')" string="Payment Orders"> | ||
2899 | 29 | <field name="reference"/> | ||
2900 | 30 | <field name="date_created"/> | ||
2901 | 31 | <field name="date_done"/> | ||
2902 | 32 | <field name="total"/> | ||
2903 | 33 | <field name="state"/> | ||
2904 | 34 | </tree> | ||
2905 | 35 | </field> | ||
2906 | 36 | </page> | ||
2907 | 37 | </notebook> | ||
2908 | 38 | </form> | ||
2909 | 39 | </field> | ||
2910 | 40 | </record> | ||
2911 | 41 | |||
2912 | 42 | |||
2913 | 43 | <record id="view_banking_export_sdd_tree" model="ir.ui.view"> | ||
2914 | 44 | <field name="name">account.banking.export.sdd.tree</field> | ||
2915 | 45 | <field name="model">banking.export.sdd</field> | ||
2916 | 46 | <field name="arch" type="xml"> | ||
2917 | 47 | <tree string="SEPA Direct Debit"> | ||
2918 | 48 | <field name="filename"/> | ||
2919 | 49 | <field name="create_date"/> | ||
2920 | 50 | <field name="nb_transactions"/> | ||
2921 | 51 | </tree> | ||
2922 | 52 | </field> | ||
2923 | 53 | </record> | ||
2924 | 54 | |||
2925 | 55 | |||
2926 | 56 | <record id="action_account_banking_sdd" model="ir.actions.act_window"> | ||
2927 | 57 | <field name="name">SEPA Direct Debit Files</field> | ||
2928 | 58 | <field name="res_model">banking.export.sdd</field> | ||
2929 | 59 | <field name="view_type">form</field> | ||
2930 | 60 | <field name="view_mode">tree,form</field> | ||
2931 | 61 | </record> | ||
2932 | 62 | |||
2933 | 63 | |||
2934 | 64 | <menuitem id="menu_account_banking_sdd" | ||
2935 | 65 | parent="account_payment.menu_main_payment" | ||
2936 | 66 | action="action_account_banking_sdd" | ||
2937 | 67 | sequence="20" | ||
2938 | 68 | /> | ||
2939 | 69 | |||
2940 | 70 | <act_window id="act_banking_export_sdd_payment_order" | ||
2941 | 71 | name="Generated SEPA Direct Debit Files" | ||
2942 | 72 | domain="[('payment_order_ids', '=', active_id)]" | ||
2943 | 73 | res_model="banking.export.sdd" | ||
2944 | 74 | src_model="payment.order" | ||
2945 | 75 | view_type="form" | ||
2946 | 76 | view_mode="tree,form" | ||
2947 | 77 | /> | ||
2948 | 78 | |||
2949 | 79 | </data> | ||
2950 | 80 | </openerp> | ||
2951 | 0 | 81 | ||
2952 | === added file 'account_banking_sepa_direct_debit/account_invoice_view.xml' | |||
2953 | --- account_banking_sepa_direct_debit/account_invoice_view.xml 1970-01-01 00:00:00 +0000 | |||
2954 | +++ account_banking_sepa_direct_debit/account_invoice_view.xml 2014-01-13 12:42:46 +0000 | |||
2955 | @@ -0,0 +1,22 @@ | |||
2956 | 1 | <?xml version="1.0" encoding="utf-8"?> | ||
2957 | 2 | <!-- | ||
2958 | 3 | Copyright (C) 2013 Akretion (http://www.akretion.com) | ||
2959 | 4 | @author: Alexis de Lattre <alexis.delattre@akretion.com> | ||
2960 | 5 | The licence is in the file __openerp__.py | ||
2961 | 6 | --> | ||
2962 | 7 | <openerp> | ||
2963 | 8 | <data> | ||
2964 | 9 | |||
2965 | 10 | <record id="invoice_form" model="ir.ui.view"> | ||
2966 | 11 | <field name="name">add.sdd.mandate.on.customer.invoice.form</field> | ||
2967 | 12 | <field name="model">account.invoice</field> | ||
2968 | 13 | <field name="inherit_id" ref="account.invoice_form"/> | ||
2969 | 14 | <field name="arch" type="xml"> | ||
2970 | 15 | <field name="partner_bank_id" position="after"> | ||
2971 | 16 | <field name="sdd_mandate_id" domain="[('partner_id', '=', partner_id), ('state', '=', 'valid')]" attrs="{'invisible': [('type', '=', 'out_refund')]}"/> | ||
2972 | 17 | </field> | ||
2973 | 18 | </field> | ||
2974 | 19 | </record> | ||
2975 | 20 | |||
2976 | 21 | </data> | ||
2977 | 22 | </openerp> | ||
2978 | 0 | 23 | ||
2979 | === added file 'account_banking_sepa_direct_debit/account_payment_view.xml' | |||
2980 | --- account_banking_sepa_direct_debit/account_payment_view.xml 1970-01-01 00:00:00 +0000 | |||
2981 | +++ account_banking_sepa_direct_debit/account_payment_view.xml 2014-01-13 12:42:46 +0000 | |||
2982 | @@ -0,0 +1,26 @@ | |||
2983 | 1 | <?xml version="1.0" encoding="utf-8"?> | ||
2984 | 2 | <!-- | ||
2985 | 3 | Copyright (C) 2013 Akretion (http://www.akretion.com) | ||
2986 | 4 | @author: Alexis de Lattre <alexis.delattre@akretion.com> | ||
2987 | 5 | The licence is in the file __openerp__.py | ||
2988 | 6 | --> | ||
2989 | 7 | <openerp> | ||
2990 | 8 | <data> | ||
2991 | 9 | |||
2992 | 10 | <record id="sdd_view_payment_order_form" model="ir.ui.view"> | ||
2993 | 11 | <field name="name">sdd.payment.order.form</field> | ||
2994 | 12 | <field name="model">payment.order</field> | ||
2995 | 13 | <field name="inherit_id" ref="account_payment.view_payment_order_form"/> | ||
2996 | 14 | <field name="arch" type="xml"> | ||
2997 | 15 | <xpath expr="//field[@name='line_ids']/form/notebook/page/group/field[@name='bank_id']" position="after"> | ||
2998 | 16 | <field name="sdd_mandate_id" domain="[('partner_bank_id', '=', bank_id), ('state', '=', 'valid')]" invisible="context.get('default_payment_order_type')!='debit'" context="{'default_partner_bank_id': bank_id}"/> | ||
2999 | 17 | <newline /> | ||
3000 | 18 | </xpath> | ||
3001 | 19 | <xpath expr="//field[@name='line_ids']/tree/field[@name='bank_id']" position="after"> | ||
3002 | 20 | <field name="sdd_mandate_id" string="SDD Mandate" invisible="context.get('default_payment_order_type')!='debit'"/> | ||
3003 | 21 | </xpath> | ||
3004 | 22 | </field> | ||
3005 | 23 | </record> | ||
3006 | 24 | |||
3007 | 25 | </data> | ||
3008 | 26 | </openerp> | ||
3009 | 0 | 27 | ||
3010 | === added file 'account_banking_sepa_direct_debit/company.py' | |||
3011 | --- account_banking_sepa_direct_debit/company.py 1970-01-01 00:00:00 +0000 | |||
3012 | +++ account_banking_sepa_direct_debit/company.py 2014-01-13 12:42:46 +0000 | |||
3013 | @@ -0,0 +1,89 @@ | |||
3014 | 1 | ############################################################################## | ||
3015 | 2 | # | ||
3016 | 3 | # SEPA Direct Debit module for OpenERP | ||
3017 | 4 | # Copyright (C) 2013 Akretion (http://www.akretion.com) | ||
3018 | 5 | # @author: Alexis de Lattre <alexis.delattre@akretion.com> | ||
3019 | 6 | # | ||
3020 | 7 | # This program is free software: you can redistribute it and/or modify | ||
3021 | 8 | # it under the terms of the GNU Affero General Public License as | ||
3022 | 9 | # published by the Free Software Foundation, either version 3 of the | ||
3023 | 10 | # License, or (at your option) any later version. | ||
3024 | 11 | # | ||
3025 | 12 | # This program is distributed in the hope that it will be useful, | ||
3026 | 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
3027 | 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
3028 | 15 | # GNU Affero General Public License for more details. | ||
3029 | 16 | # | ||
3030 | 17 | # You should have received a copy of the GNU Affero General Public License | ||
3031 | 18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
3032 | 19 | # | ||
3033 | 20 | ############################################################################## | ||
3034 | 21 | |||
3035 | 22 | from openerp.osv import orm, fields | ||
3036 | 23 | import logging | ||
3037 | 24 | |||
3038 | 25 | logger = logging.getLogger(__name__) | ||
3039 | 26 | |||
3040 | 27 | |||
3041 | 28 | class res_company(orm.Model): | ||
3042 | 29 | _inherit = 'res.company' | ||
3043 | 30 | |||
3044 | 31 | _columns = { | ||
3045 | 32 | 'sepa_creditor_identifier': fields.char( | ||
3046 | 33 | 'SEPA Creditor Identifier', size=35, | ||
3047 | 34 | help="Enter the Creditor Identifier that has been attributed " | ||
3048 | 35 | "to your company to make SEPA Direct Debits. This identifier " | ||
3049 | 36 | "is composed of :\n- your country ISO code (2 letters)\n- a " | ||
3050 | 37 | "2-digits checkum\n- a 3-letters business code\n- a " | ||
3051 | 38 | "country-specific identifier"), | ||
3052 | 39 | 'original_creditor_identifier': fields.char( | ||
3053 | 40 | 'Original Creditor Identifier', size=70), | ||
3054 | 41 | } | ||
3055 | 42 | |||
3056 | 43 | def is_sepa_creditor_identifier_valid( | ||
3057 | 44 | self, cr, uid, sepa_creditor_identifier, context=None): | ||
3058 | 45 | """Check if SEPA Creditor Identifier is valid | ||
3059 | 46 | @param sepa_creditor_identifier: SEPA Creditor Identifier as str | ||
3060 | 47 | or unicode | ||
3061 | 48 | @return: True if valid, False otherwise | ||
3062 | 49 | """ | ||
3063 | 50 | if not isinstance(sepa_creditor_identifier, (str, unicode)): | ||
3064 | 51 | return False | ||
3065 | 52 | try: | ||
3066 | 53 | sci_str = str(sepa_creditor_identifier) | ||
3067 | 54 | except: | ||
3068 | 55 | logger.warning( | ||
3069 | 56 | "SEPA Creditor ID should contain only ASCII caracters.") | ||
3070 | 57 | return False | ||
3071 | 58 | sci = sci_str.lower() | ||
3072 | 59 | if len(sci) < 9: | ||
3073 | 60 | return False | ||
3074 | 61 | before_replacement = sci[7:] + sci[0:2] + '00' | ||
3075 | 62 | logger.debug( | ||
3076 | 63 | "SEPA ID check before_replacement = %s" % before_replacement) | ||
3077 | 64 | after_replacement = '' | ||
3078 | 65 | for char in before_replacement: | ||
3079 | 66 | if char.isalpha(): | ||
3080 | 67 | after_replacement += str(ord(char)-87) | ||
3081 | 68 | else: | ||
3082 | 69 | after_replacement += char | ||
3083 | 70 | logger.debug( | ||
3084 | 71 | "SEPA ID check after_replacement = %s" % after_replacement) | ||
3085 | 72 | if int(sci[2:4]) == (98 - (int(after_replacement) % 97)): | ||
3086 | 73 | return True | ||
3087 | 74 | else: | ||
3088 | 75 | return False | ||
3089 | 76 | |||
3090 | 77 | def _check_sepa_creditor_identifier(self, cr, uid, ids): | ||
3091 | 78 | for company in self.browse(cr, uid, ids): | ||
3092 | 79 | if company.sepa_creditor_identifier: | ||
3093 | 80 | if not self.is_sepa_creditor_identifier_valid( | ||
3094 | 81 | cr, uid, company.sepa_creditor_identifier): | ||
3095 | 82 | return False | ||
3096 | 83 | return True | ||
3097 | 84 | |||
3098 | 85 | _constraints = [ | ||
3099 | 86 | (_check_sepa_creditor_identifier, | ||
3100 | 87 | "Invalid SEPA Creditor Identifier.", | ||
3101 | 88 | ['sepa_creditor_identifier']), | ||
3102 | 89 | ] | ||
3103 | 0 | 90 | ||
3104 | === added file 'account_banking_sepa_direct_debit/company_view.xml' | |||
3105 | --- account_banking_sepa_direct_debit/company_view.xml 1970-01-01 00:00:00 +0000 | |||
3106 | +++ account_banking_sepa_direct_debit/company_view.xml 2014-01-13 12:42:46 +0000 | |||
3107 | @@ -0,0 +1,23 @@ | |||
3108 | 1 | <?xml version="1.0" encoding="utf-8"?> | ||
3109 | 2 | <!-- | ||
3110 | 3 | Copyright (C) 2013 Akretion (http://www.akretion.com) | ||
3111 | 4 | @author: Alexis de Lattre <alexis.delattre@akretion.com> | ||
3112 | 5 | The licence is in the file __openerp__.py | ||
3113 | 6 | --> | ||
3114 | 7 | <openerp> | ||
3115 | 8 | <data> | ||
3116 | 9 | |||
3117 | 10 | <record id="sdd_res_company_form" model="ir.ui.view"> | ||
3118 | 11 | <field name="name">sepa_direct_debit.res.company.form</field> | ||
3119 | 12 | <field name="model">res.company</field> | ||
3120 | 13 | <field name="inherit_id" ref="account_banking_pain_base.view_company_form"/> | ||
3121 | 14 | <field name="arch" type="xml"> | ||
3122 | 15 | <group name="pain" position="inside"> | ||
3123 | 16 | <field name="sepa_creditor_identifier"/> | ||
3124 | 17 | <field name="original_creditor_identifier" groups="account_banking_sepa_direct_debit.group_original_mandate_required"/> | ||
3125 | 18 | </group> | ||
3126 | 19 | </field> | ||
3127 | 20 | </record> | ||
3128 | 21 | |||
3129 | 22 | </data> | ||
3130 | 23 | </openerp> | ||
3131 | 0 | 24 | ||
3132 | === added directory 'account_banking_sepa_direct_debit/data' | |||
3133 | === added file 'account_banking_sepa_direct_debit/data/mandate_reference_sequence.xml' | |||
3134 | --- account_banking_sepa_direct_debit/data/mandate_reference_sequence.xml 1970-01-01 00:00:00 +0000 | |||
3135 | +++ account_banking_sepa_direct_debit/data/mandate_reference_sequence.xml 2014-01-13 12:42:46 +0000 | |||
3136 | @@ -0,0 +1,21 @@ | |||
3137 | 1 | <?xml version="1.0" encoding="utf-8"?> | ||
3138 | 2 | <openerp> | ||
3139 | 3 | <data noupdate="1"> | ||
3140 | 4 | |||
3141 | 5 | |||
3142 | 6 | <record id="sdd_mandate_seq_type" model="ir.sequence.type"> | ||
3143 | 7 | <field name="name">SDD Mandate Reference</field> | ||
3144 | 8 | <field name="code">sdd.mandate.reference</field> | ||
3145 | 9 | </record> | ||
3146 | 10 | |||
3147 | 11 | <record id="sdd_mandate_seq" model="ir.sequence"> | ||
3148 | 12 | <field name="name">SDD Mandate Reference</field> | ||
3149 | 13 | <field name="code">sdd.mandate.reference</field> | ||
3150 | 14 | <field name="prefix">RUM</field> | ||
3151 | 15 | <field name="padding" eval="7"/> | ||
3152 | 16 | <!-- remember that max size for the mandate ref is 35 --> | ||
3153 | 17 | </record> | ||
3154 | 18 | |||
3155 | 19 | |||
3156 | 20 | </data> | ||
3157 | 21 | </openerp> | ||
3158 | 0 | 22 | ||
3159 | === added file 'account_banking_sepa_direct_debit/data/pain.008.001.02.xsd' | |||
3160 | --- account_banking_sepa_direct_debit/data/pain.008.001.02.xsd 1970-01-01 00:00:00 +0000 | |||
3161 | +++ account_banking_sepa_direct_debit/data/pain.008.001.02.xsd 2014-01-13 12:42:46 +0000 | |||
3162 | @@ -0,0 +1,879 @@ | |||
3163 | 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||
3164 | 2 | <!--Generated by SWIFTStandards Workstation (build:R6.1.0.2) on 2009 Jan 08 17:30:53--> | ||
3165 | 3 | <xs:schema xmlns="urn:iso:std:iso:20022:tech:xsd:pain.008.001.02" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="urn:iso:std:iso:20022:tech:xsd:pain.008.001.02"> | ||
3166 | 4 | <xs:element name="Document" type="Document"/> | ||
3167 | 5 | <xs:complexType name="AccountIdentification4Choice"> | ||
3168 | 6 | <xs:sequence> | ||
3169 | 7 | <xs:choice> | ||
3170 | 8 | <xs:element name="IBAN" type="IBAN2007Identifier"/> | ||
3171 | 9 | <xs:element name="Othr" type="GenericAccountIdentification1"/> | ||
3172 | 10 | </xs:choice> | ||
3173 | 11 | </xs:sequence> | ||
3174 | 12 | </xs:complexType> | ||
3175 | 13 | <xs:complexType name="AccountSchemeName1Choice"> | ||
3176 | 14 | <xs:sequence> | ||
3177 | 15 | <xs:choice> | ||
3178 | 16 | <xs:element name="Cd" type="ExternalAccountIdentification1Code"/> | ||
3179 | 17 | <xs:element name="Prtry" type="Max35Text"/> | ||
3180 | 18 | </xs:choice> | ||
3181 | 19 | </xs:sequence> | ||
3182 | 20 | </xs:complexType> | ||
3183 | 21 | <xs:simpleType name="ActiveOrHistoricCurrencyAndAmount_SimpleType"> | ||
3184 | 22 | <xs:restriction base="xs:decimal"> | ||
3185 | 23 | <xs:minInclusive value="0"/> | ||
3186 | 24 | <xs:fractionDigits value="5"/> | ||
3187 | 25 | <xs:totalDigits value="18"/> | ||
3188 | 26 | </xs:restriction> | ||
3189 | 27 | </xs:simpleType> | ||
3190 | 28 | <xs:complexType name="ActiveOrHistoricCurrencyAndAmount"> | ||
3191 | 29 | <xs:simpleContent> | ||
3192 | 30 | <xs:extension base="ActiveOrHistoricCurrencyAndAmount_SimpleType"> | ||
3193 | 31 | <xs:attribute name="Ccy" type="ActiveOrHistoricCurrencyCode" use="required"/> | ||
3194 | 32 | </xs:extension> | ||
3195 | 33 | </xs:simpleContent> | ||
3196 | 34 | </xs:complexType> | ||
3197 | 35 | <xs:simpleType name="ActiveOrHistoricCurrencyCode"> | ||
3198 | 36 | <xs:restriction base="xs:string"> | ||
3199 | 37 | <xs:pattern value="[A-Z]{3,3}"/> | ||
3200 | 38 | </xs:restriction> | ||
3201 | 39 | </xs:simpleType> | ||
3202 | 40 | <xs:simpleType name="AddressType2Code"> | ||
3203 | 41 | <xs:restriction base="xs:string"> | ||
3204 | 42 | <xs:enumeration value="ADDR"/> | ||
3205 | 43 | <xs:enumeration value="PBOX"/> | ||
3206 | 44 | <xs:enumeration value="HOME"/> | ||
3207 | 45 | <xs:enumeration value="BIZZ"/> | ||
3208 | 46 | <xs:enumeration value="MLTO"/> | ||
3209 | 47 | <xs:enumeration value="DLVY"/> | ||
3210 | 48 | </xs:restriction> | ||
3211 | 49 | </xs:simpleType> | ||
3212 | 50 | <xs:complexType name="AmendmentInformationDetails6"> | ||
3213 | 51 | <xs:sequence> | ||
3214 | 52 | <xs:element maxOccurs="1" minOccurs="0" name="OrgnlMndtId" type="Max35Text"/> | ||
3215 | 53 | <xs:element maxOccurs="1" minOccurs="0" name="OrgnlCdtrSchmeId" type="PartyIdentification32"/> | ||
3216 | 54 | <xs:element maxOccurs="1" minOccurs="0" name="OrgnlCdtrAgt" type="BranchAndFinancialInstitutionIdentification4"/> | ||
3217 | 55 | <xs:element maxOccurs="1" minOccurs="0" name="OrgnlCdtrAgtAcct" type="CashAccount16"/> | ||
3218 | 56 | <xs:element maxOccurs="1" minOccurs="0" name="OrgnlDbtr" type="PartyIdentification32"/> | ||
3219 | 57 | <xs:element maxOccurs="1" minOccurs="0" name="OrgnlDbtrAcct" type="CashAccount16"/> | ||
3220 | 58 | <xs:element maxOccurs="1" minOccurs="0" name="OrgnlDbtrAgt" type="BranchAndFinancialInstitutionIdentification4"/> | ||
3221 | 59 | <xs:element maxOccurs="1" minOccurs="0" name="OrgnlDbtrAgtAcct" type="CashAccount16"/> | ||
3222 | 60 | <xs:element maxOccurs="1" minOccurs="0" name="OrgnlFnlColltnDt" type="ISODate"/> | ||
3223 | 61 | <xs:element maxOccurs="1" minOccurs="0" name="OrgnlFrqcy" type="Frequency1Code"/> | ||
3224 | 62 | </xs:sequence> | ||
3225 | 63 | </xs:complexType> | ||
3226 | 64 | <xs:simpleType name="AnyBICIdentifier"> | ||
3227 | 65 | <xs:restriction base="xs:string"> | ||
3228 | 66 | <xs:pattern value="[A-Z]{6,6}[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3,3}){0,1}"/> | ||
3229 | 67 | </xs:restriction> | ||
3230 | 68 | </xs:simpleType> | ||
3231 | 69 | <xs:complexType name="Authorisation1Choice"> | ||
3232 | 70 | <xs:sequence> | ||
3233 | 71 | <xs:choice> | ||
3234 | 72 | <xs:element name="Cd" type="Authorisation1Code"/> | ||
3235 | 73 | <xs:element name="Prtry" type="Max128Text"/> | ||
3236 | 74 | </xs:choice> | ||
3237 | 75 | </xs:sequence> | ||
3238 | 76 | </xs:complexType> | ||
3239 | 77 | <xs:simpleType name="Authorisation1Code"> | ||
3240 | 78 | <xs:restriction base="xs:string"> | ||
3241 | 79 | <xs:enumeration value="AUTH"/> | ||
3242 | 80 | <xs:enumeration value="FDET"/> | ||
3243 | 81 | <xs:enumeration value="FSUM"/> | ||
3244 | 82 | <xs:enumeration value="ILEV"/> | ||
3245 | 83 | </xs:restriction> | ||
3246 | 84 | </xs:simpleType> | ||
3247 | 85 | <xs:simpleType name="BICIdentifier"> | ||
3248 | 86 | <xs:restriction base="xs:string"> | ||
3249 | 87 | <xs:pattern value="[A-Z]{6,6}[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3,3}){0,1}"/> | ||
3250 | 88 | </xs:restriction> | ||
3251 | 89 | </xs:simpleType> | ||
3252 | 90 | <xs:simpleType name="BatchBookingIndicator"> | ||
3253 | 91 | <xs:restriction base="xs:boolean"/> | ||
3254 | 92 | </xs:simpleType> | ||
3255 | 93 | <xs:complexType name="BranchAndFinancialInstitutionIdentification4"> | ||
3256 | 94 | <xs:sequence> | ||
3257 | 95 | <xs:element name="FinInstnId" type="FinancialInstitutionIdentification7"/> | ||
3258 | 96 | <xs:element maxOccurs="1" minOccurs="0" name="BrnchId" type="BranchData2"/> | ||
3259 | 97 | </xs:sequence> | ||
3260 | 98 | </xs:complexType> | ||
3261 | 99 | <xs:complexType name="BranchData2"> | ||
3262 | 100 | <xs:sequence> | ||
3263 | 101 | <xs:element maxOccurs="1" minOccurs="0" name="Id" type="Max35Text"/> | ||
3264 | 102 | <xs:element maxOccurs="1" minOccurs="0" name="Nm" type="Max140Text"/> | ||
3265 | 103 | <xs:element maxOccurs="1" minOccurs="0" name="PstlAdr" type="PostalAddress6"/> | ||
3266 | 104 | </xs:sequence> | ||
3267 | 105 | </xs:complexType> | ||
3268 | 106 | <xs:complexType name="CashAccount16"> | ||
3269 | 107 | <xs:sequence> | ||
3270 | 108 | <xs:element name="Id" type="AccountIdentification4Choice"/> | ||
3271 | 109 | <xs:element maxOccurs="1" minOccurs="0" name="Tp" type="CashAccountType2"/> | ||
3272 | 110 | <xs:element maxOccurs="1" minOccurs="0" name="Ccy" type="ActiveOrHistoricCurrencyCode"/> | ||
3273 | 111 | <xs:element maxOccurs="1" minOccurs="0" name="Nm" type="Max70Text"/> | ||
3274 | 112 | </xs:sequence> | ||
3275 | 113 | </xs:complexType> | ||
3276 | 114 | <xs:complexType name="CashAccountType2"> | ||
3277 | 115 | <xs:sequence> | ||
3278 | 116 | <xs:choice> | ||
3279 | 117 | <xs:element name="Cd" type="CashAccountType4Code"/> | ||
3280 | 118 | <xs:element name="Prtry" type="Max35Text"/> | ||
3281 | 119 | </xs:choice> | ||
3282 | 120 | </xs:sequence> | ||
3283 | 121 | </xs:complexType> | ||
3284 | 122 | <xs:simpleType name="CashAccountType4Code"> | ||
3285 | 123 | <xs:restriction base="xs:string"> | ||
3286 | 124 | <xs:enumeration value="CASH"/> | ||
3287 | 125 | <xs:enumeration value="CHAR"/> | ||
3288 | 126 | <xs:enumeration value="COMM"/> | ||
3289 | 127 | <xs:enumeration value="TAXE"/> | ||
3290 | 128 | <xs:enumeration value="CISH"/> | ||
3291 | 129 | <xs:enumeration value="TRAS"/> | ||
3292 | 130 | <xs:enumeration value="SACC"/> | ||
3293 | 131 | <xs:enumeration value="CACC"/> | ||
3294 | 132 | <xs:enumeration value="SVGS"/> | ||
3295 | 133 | <xs:enumeration value="ONDP"/> | ||
3296 | 134 | <xs:enumeration value="MGLD"/> | ||
3297 | 135 | <xs:enumeration value="NREX"/> | ||
3298 | 136 | <xs:enumeration value="MOMA"/> | ||
3299 | 137 | <xs:enumeration value="LOAN"/> | ||
3300 | 138 | <xs:enumeration value="SLRY"/> | ||
3301 | 139 | <xs:enumeration value="ODFT"/> | ||
3302 | 140 | </xs:restriction> | ||
3303 | 141 | </xs:simpleType> | ||
3304 | 142 | <xs:complexType name="CategoryPurpose1Choice"> | ||
3305 | 143 | <xs:sequence> | ||
3306 | 144 | <xs:choice> | ||
3307 | 145 | <xs:element name="Cd" type="ExternalCategoryPurpose1Code"/> | ||
3308 | 146 | <xs:element name="Prtry" type="Max35Text"/> | ||
3309 | 147 | </xs:choice> | ||
3310 | 148 | </xs:sequence> | ||
3311 | 149 | </xs:complexType> | ||
3312 | 150 | <xs:simpleType name="ChargeBearerType1Code"> | ||
3313 | 151 | <xs:restriction base="xs:string"> | ||
3314 | 152 | <xs:enumeration value="DEBT"/> | ||
3315 | 153 | <xs:enumeration value="CRED"/> | ||
3316 | 154 | <xs:enumeration value="SHAR"/> | ||
3317 | 155 | <xs:enumeration value="SLEV"/> | ||
3318 | 156 | </xs:restriction> | ||
3319 | 157 | </xs:simpleType> | ||
3320 | 158 | <xs:complexType name="ClearingSystemIdentification2Choice"> | ||
3321 | 159 | <xs:sequence> | ||
3322 | 160 | <xs:choice> | ||
3323 | 161 | <xs:element name="Cd" type="ExternalClearingSystemIdentification1Code"/> | ||
3324 | 162 | <xs:element name="Prtry" type="Max35Text"/> | ||
3325 | 163 | </xs:choice> | ||
3326 | 164 | </xs:sequence> | ||
3327 | 165 | </xs:complexType> | ||
3328 | 166 | <xs:complexType name="ClearingSystemMemberIdentification2"> | ||
3329 | 167 | <xs:sequence> | ||
3330 | 168 | <xs:element maxOccurs="1" minOccurs="0" name="ClrSysId" type="ClearingSystemIdentification2Choice"/> | ||
3331 | 169 | <xs:element name="MmbId" type="Max35Text"/> | ||
3332 | 170 | </xs:sequence> | ||
3333 | 171 | </xs:complexType> | ||
3334 | 172 | <xs:complexType name="ContactDetails2"> | ||
3335 | 173 | <xs:sequence> | ||
3336 | 174 | <xs:element maxOccurs="1" minOccurs="0" name="NmPrfx" type="NamePrefix1Code"/> | ||
3337 | 175 | <xs:element maxOccurs="1" minOccurs="0" name="Nm" type="Max140Text"/> | ||
3338 | 176 | <xs:element maxOccurs="1" minOccurs="0" name="PhneNb" type="PhoneNumber"/> | ||
3339 | 177 | <xs:element maxOccurs="1" minOccurs="0" name="MobNb" type="PhoneNumber"/> | ||
3340 | 178 | <xs:element maxOccurs="1" minOccurs="0" name="FaxNb" type="PhoneNumber"/> | ||
3341 | 179 | <xs:element maxOccurs="1" minOccurs="0" name="EmailAdr" type="Max2048Text"/> | ||
3342 | 180 | <xs:element maxOccurs="1" minOccurs="0" name="Othr" type="Max35Text"/> | ||
3343 | 181 | </xs:sequence> | ||
3344 | 182 | </xs:complexType> | ||
3345 | 183 | <xs:simpleType name="CountryCode"> | ||
3346 | 184 | <xs:restriction base="xs:string"> | ||
3347 | 185 | <xs:pattern value="[A-Z]{2,2}"/> | ||
3348 | 186 | </xs:restriction> | ||
3349 | 187 | </xs:simpleType> | ||
3350 | 188 | <xs:simpleType name="CreditDebitCode"> | ||
3351 | 189 | <xs:restriction base="xs:string"> | ||
3352 | 190 | <xs:enumeration value="CRDT"/> | ||
3353 | 191 | <xs:enumeration value="DBIT"/> | ||
3354 | 192 | </xs:restriction> | ||
3355 | 193 | </xs:simpleType> | ||
3356 | 194 | <xs:complexType name="CreditorReferenceInformation2"> | ||
3357 | 195 | <xs:sequence> | ||
3358 | 196 | <xs:element maxOccurs="1" minOccurs="0" name="Tp" type="CreditorReferenceType2"/> | ||
3359 | 197 | <xs:element maxOccurs="1" minOccurs="0" name="Ref" type="Max35Text"/> | ||
3360 | 198 | </xs:sequence> | ||
3361 | 199 | </xs:complexType> | ||
3362 | 200 | <xs:complexType name="CreditorReferenceType1Choice"> | ||
3363 |
One small note for the PEP8 fundamentalists : the 3 modules account_ banking_ pain_base, account_ banking_ sepa_credit_ transfer and account_ banking_ sepa_direct_ debit are fully PEP8 compliant, so you won't be able to block this merge proposal for such a stupid reason :)