1 # -*- encoding: utf-8 -*-
6 # Created by Nicolas Bessi based on Credric Krier contribution
8 # Copyright (c) 2009 CamptoCamp. All rights reserved.
9 ##############################################################################
10 # WARNING: This program as such is intended to be used by professional
11 # programmers who take the whole responsability of assessing all potential
12 # consequences resulting from its eventual inadequacies and bugs
13 # End users who are looking for a ready-to-use solution with commercial
14 # garantees and support are strongly adviced to contract a Free Software
17 # This program is Free Software; you can redistribute it and/or
18 # modify it under the terms of the GNU General Public License
19 # as published by the Free Software Foundation; either version 2
20 # of the License, or (at your option) any later version.
22 # This program is distributed in the hope that it will be useful,
23 # but WITHOUT ANY WARRANTY; without even the implied warranty of
24 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 # GNU General Public License for more details.
27 # You should have received a copy of the GNU General Public License
28 # along with this program; if not, write to the Free Software
29 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 ##############################################################################
38 from tools.translate import _
41 FORM = """<?xml version="1.0"?>
42 <form string="DTA file creation - Results">
43 <separator colspan="4" string="Clic on 'Save as' to save the DTA file :" />
69 s = s.replace(k[0],k[1])
71 res= s.encode('ascii','replace')
79 def __init__(self, global_context_dict):
80 for i in global_context_dict:
81 global_context_dict[i] = global_context_dict[i] \
82 and tr(global_context_dict[i])
84 self.global_values = global_context_dict
95 self.post={'date_value_hdr': '000000', 'type_paiement': '0'}
96 self.init_local_context()
98 def init_local_context(self):
100 Must instanciate a fields list, field = (name,size)
101 and update a local_values dict.
103 raise _('not implemented')
107 for field in self.fields :
108 if self.pre.has_key(field[0]):
109 value = self.pre[field[0]]
110 elif self.global_values.has_key(field[0]):
111 value = self.global_values[field[0]]
112 elif self.post.has_key(field[0]):
113 value = self.post[field[0]]
116 #raise Exception(field[0]+' not found !')
118 res = res + c_ljust(value, field[1])
124 class record_gt826(record):
128 def init_local_context(self):
132 ('date_value_hdr', 6),
133 ('partner_bank_clearing', 12),
135 ('creation_date', 6),
136 ('comp_bank_clearing', 7),
140 ('type_paiement', 1),
145 ('comp_bank_iban', 24),
148 ('amount_to_pay', 12),
156 ('comp_country', 20),
160 ('partner_bvr', 12),#numero d'adherent bvr
161 ('partner_name', 20),
162 ('partner_street', 20),
164 ('partner_city', 10),
165 ('partner_country', 20),
166 ('reference', 27),#communication structuree
167 ('padding', 2),#cle de controle
171 'date_value_hdr': self.global_values['date_value'],
173 'partner_bank_clearing': '',
174 'partner_cpt_benef': '',
175 'genre_trans': '826',
177 'option_id_bank': 'D',
178 'partner_bvr': '/C/'+ self.global_values['partner_bvr'],
184 class record_gt827(record):
186 interne suisse (bvpost et bvbank)
188 def init_local_context(self):
192 ('date_value_hdr', 6),
193 ('partner_bank_clearing', 12),
195 ('creation_date', 6),
196 ('comp_bank_clearing', 7),
200 ('type_paiement', 1),
205 ('comp_bank_iban', 24),
208 ('amount_to_pay', 12),
216 ('comp_country', 20),
220 ('partner_bank_number', 30),
221 ('partner_name', 24),
222 ('partner_street', 24),
224 ('partner_city', 12),
225 ('partner_country', 24),
235 'date_value_hdr': self.global_values['date_value'],
237 'partner_cpt_benef': '',
238 'type_paiement': '0',
239 'genre_trans': '827',
241 'option_id_bank': 'D',
248 class record_gt836(record):
252 def init_local_context(self):
256 ('date_value_hdr', 6),
257 ('partner_bank_clearing', 12),
259 ('creation_date', 6),
260 ('comp_bank_clearing', 7),
264 ('type_paiement', 1),
269 ('comp_bank_iban', 24),
272 ('amount_to_pay', 15),
285 ('option_id_bank', 1),
286 ('partner_bank_ident', 70),
287 ('partner_bank_iban', 34),
291 ('partner_name', 35),
292 ('partner_street', 35),
293 ('partner_country', 3),
295 ('partner_city', 22),
305 'partner_bank_clearing': '',
306 'partner_cpt_benef': '',
307 'type_paiement': '0',
308 'genre_trans': '836',
310 'reference': self.global_values['reference'],
315 self.post.update({'option_motif': 'U'})
318 class record_gt890(record):
322 def init_local_context(self):
326 ('date_value_hdr', 6),
327 ('partner_bank_clearing', 12),
329 ('creation_date', 6),
330 ('comp_bank_clearing', 7),
334 ('type_paiement', 1),
337 ('amount_total', 16),
340 self.pre.update({'partner_bank_clearing': '', 'partner_cpt_benef': '',
341 'company_bank_clearing': '', 'genre_trans': '890'})
343 def c_ljust(s, size):
345 check before calling ljust
350 s = s.decode('utf-8').encode('latin1','replace').ljust(size)
353 def _create_dta(obj, cr, uid, data, context):
356 v['creation_date']= time.strftime('%y%m%d')
359 pool = pooler.get_pool(cr.dbname)
360 payment_obj = pool.get('payment.order')
361 attachment_obj = pool.get('ir.attachment')
363 payment = payment_obj.browse(cr, uid, data['id'], context=context)
365 if not payment.mode or payment.mode.type.code != 'dta':
366 raise wizard.except_wizard(_('Error'),
367 _('No payment mode or payment type code invalid.'))
368 bank = payment.mode.bank_id
370 raise wizard.except_wizard(_('Error'), _('No bank account for the company.'))
372 v['comp_bank_name']= bank.bank and bank.bank.name or False
373 v['comp_bank_clearing'] = bank.bank.clearing
375 if not v['comp_bank_clearing']:
376 raise wizard.except_wizard(_('Error'),
377 _('You must provide a Clearing Number for your bank account.'))
379 user = pool.get('res.users').browse(cr,uid,[uid])[0]
380 company= user.company_id
381 #XXX dirty code use get_addr
382 co_addr= company.partner_id.address[0]
383 v['comp_country'] = co_addr.country_id and co_addr.country_id.name or ''
384 v['comp_street'] = co_addr.street or ''
385 v['comp_zip'] = co_addr.zip
386 v['comp_city'] = co_addr.city
387 v['comp_name'] = co_addr.name
388 v['comp_dta'] = bank.dta_code or '' #XXX not mandatory in pratice
391 v['comp_bank_number'] = bank.acc_number or ''
393 v['comp_bank_iban'] = bank.iban.replace(' ','') or ''
395 v['comp_bank_iban'] = ''
396 if not v['comp_bank_iban']:
397 raise wizard.except_wizard(_('Error'),
398 _('No IBAN for the company bank account.'))
400 dta_line_obj = pool.get('account.dta.line')
401 res_partner_bank_obj = pool.get('res.partner.bank')
405 amount_currency_tot = 0
407 for pline in payment.line_ids:
408 if not pline.bank_id:
409 raise wizard.except_wizard(_('Error'), _('No bank account defined\n' \
410 'on line: %s') % pline.name)
411 if not pline.bank_id.bank:
412 raise wizard.except_wizard(_('Error'), _('No bank defined\n' \
413 'for the bank account: %s\n' \
414 'on the partner: %s\n' \
415 'on line: %s') + (pline.bank_id.state, pline.partner_id.name, pline.name))
417 v['sequence'] = str(seq).rjust(5).replace(' ', '0')
418 v['amount_to_pay']= str(pline.amount_currency).replace('.', ',')
419 v['number'] = pline.name
420 v['currency'] = pline.currency.code
422 v['partner_bank_name'] = pline.bank_id.bank.name or False
423 v['partner_bank_clearing'] = pline.bank_id.bank.clearing or False
424 if not v['partner_bank_name'] :
425 raise wizard.except_wizard(_('Error'), _('No bank name defined\n' \
426 'for the bank account: %s\n' \
427 'on the partner: %s\n' \
428 'on line: %s') % (pline.bank_id.state, pline.partner_id.name, pline.name))
430 v['partner_bank_iban']= pline.bank_id.iban or False
431 v['partner_bank_number']= pline.bank_id.acc_number \
432 and pline.bank_id.acc_number.replace('.','').replace('-','') \
434 v['partner_post_number']= pline.bank_id.post_number \
435 and pline.bank_id.post_number.replace('.', '').replace('-', '') \
437 v['partner_bvr'] = pline.bank_id.bvr_number or ''
439 v['partner_bvr'] = v['partner_bvr'].replace('-','')
440 if len(v['partner_bvr']) < 9:
441 v['partner_bvr'] = v['partner_bvr'][:2] + '0' * \
442 (9 - len(v['partner_bvr'])) + v['partner_bvr'][2:]
444 if pline.bank_id.bank:
445 v['partner_bank_city'] = pline.bank_id.bank.city or False
446 v['partner_bank_street'] = pline.bank_id.bank.street or ''
447 v['partner_bank_zip'] = pline.bank_id.bank.zip or ''
448 v['partner_bank_country'] = pline.bank_id.bank.country and \
449 pline.bank_id.bank.country.name or ''
451 v['partner_bank_code'] = pline.bank_id.bank.bic
452 v['reference'] = pline.move_line_id.ref
453 v['partner_name'] = pline.partner_id and pline.partner_id.name or ''
454 if pline.partner_id and pline.partner_id.address \
455 and pline.partner_id.address[0]:
456 v['partner_street'] = pline.partner_id.address[0].street
457 v['partner_city']= pline.partner_id.address[0].city
458 v['partner_zip']= pline.partner_id.address[0].zip
459 # If iban => country=country code for space reason
460 elec_pay = pline.bank_id.state #Bank type
461 if elec_pay == 'iban':
462 v['partner_country']= pline.partner_id.address[0].country_id \
463 and pline.partner_id.address[0].country_id.code+'-' \
466 v['partner_country']= pline.partner_id.address[0].country_id \
467 and pline.partner_id.address[0].country_id.name \
470 v['partner_street'] =''
471 v['partner_city']= ''
473 v['partner_country']= ''
474 raise wizard.except_wizard(_('Error'), _('No address defined \n' \
475 'for the partner: %s\n' \
476 'on line: %s') % (pline.partner_id.name, pline.name))
478 if pline.order_id.date_planned :
479 date_value = mx.DateTime.strptime(pline.order_id.date_planned, '%Y-%m-%d')
481 date_value = mx.DateTime.strptime(pline.date, '%Y-%m-%d')
483 date_value = mx.DateTime.now()
484 v['date_value'] = date_value.strftime("%y%m%d")
486 # si compte iban -> iban (836)
487 # si payment structure -> bvr (826)
490 if elec_pay == 'dta_iban':
491 # If iban => country=country code for space reason
492 v['comp_country'] = co_addr.country_id and co_addr.country_id.code+'-' or ''
493 record_type = record_gt836
494 if not v['partner_bank_iban']:
495 raise wizard.except_wizard(_('Error'), _('No IBAN defined \n' \
496 'for the bank account: %s\n' + \
497 'on line: %s') % (res_partner_bank_obj.name_get(cr, uid, [pline.bank_id.id], context)[0][1] , pline.name))
499 if v['partner_bank_code'] : # bank code is swift (BIC address)
500 v['option_id_bank']= 'A'
501 v['partner_bank_ident']= v['partner_bank_code']
502 elif v['partner_bank_city']:
504 v['option_id_bank']= 'D'
505 v['partner_bank_ident']= v['partner_bank_name'] \
506 + ' ' + v['partner_bank_street'] \
507 + ' ' + v['partner_bank_zip'] \
508 + ' ' + v['partner_bank_city'] \
509 + ' ' + v['partner_bank_country']
511 raise wizard.except_wizard(_('Error'), _('You must provide the bank city '
512 'or the bic code for the partner bank: \n %d\n' + \
513 'on line: %s') %(res_partner_bank_obj.name_get(cr, uid, [pline.bank_id.id], context)[0][1], pline.name))
515 elif elec_pay == 'bvrbank' or elec_pay == 'bvrpost':
516 from tools import mod10r
518 v['reference'] = v['reference'].replace(' ',
519 '').rjust(27).replace(' ', '0')
520 if not v['reference'] \
521 or mod10r(v['reference'][:-1]) != v['reference']:
522 raise wizard.except_wizard(_('Error'), _('You must provide ' \
523 'a valid BVR reference number \n' \
524 'for the line: %s') % pline.name)
525 if not v['partner_bvr']:
526 raise wizard.except_wizard(_('Error'), _('You must provide a BVR number\n'
527 'for the bank account: %s' \
528 'on line: %s') % (res_partner_bank_obj.name_get(cr, uid, [pline.bank_id.id],context)[0][1] ,pline.name))
529 record_type = record_gt826
531 elif elec_pay == 'bvbank':
532 if not v['partner_bank_number'] :
533 if v['partner_bank_iban'] :
534 v['partner_bank_number']= v['partner_bank_iban']
536 raise wizard.except_wizard(_('Error'), _('You must provide ' \
538 'for the partner bank: %s\n' \
539 'on line: %s') % (res_partner_bank_obj.name_get(cr, uid, [pline.bank_id.id], context)[0][1] , pline.name))
540 if not v['partner_bank_clearing']:
541 raise wizard.except_wizard(_('Error'), _('You must provide ' \
542 'a Clearing Number\n' \
543 'for the partner bank: %s\n' \
544 'on line %s') % (res_partner_bank_obj.name_get(cr, uid, [pline.bank_id.id], context)[0][1] , pline.name))
545 v['partner_bank_number'] = '/C/'+v['partner_bank_number']
546 record_type = record_gt827
547 elif elec_pay == 'bvpost':
548 if not v['partner_post_number']:
549 raise wizard.except_wizard(_('Error'), _('You must provide ' \
551 'for the partner bank: %s\n' \
552 'on line: %s') % (res_partner_bank_obj.name_get(cr, uid, [pline.bank_id.id], context)[0][1] ,pline.name))
553 v['partner_bank_clearing']= ''
554 v['partner_bank_number'] = '/C/'+v['partner_post_number']
555 record_type = record_gt827
557 raise wizard.except_wizard(_('Error'), _('The Bank type %s of the bank account: %s is not supported') \
558 % (elec_pay, res_partner_bank_obj.name_get(cr, uid, [pline.bank_id.id], context)[0][1],))
560 dta_line = record_type(v).generate()
563 amount_tot += pline.amount
564 amount_currency_tot += pline.amount_currency
568 v['amount_total'] = str(amount_currency_tot).replace('.',',')
569 v['sequence'] = str(seq).rjust(5).replace(' ','0')
571 dta = dta + record_gt890(v).generate()
573 dta_data= base64.encodestring(dta)
574 payment_obj.set_done(cr, uid, data['id'], context)
575 attachment_obj.create(cr, uid, {
578 'datas_fname': 'DTA.txt',
579 'res_model': 'payment.order',
580 'res_id': data['id'],
582 return {'dta': dta_data}
585 class wizard_dta_create(wizard.interface):
588 'actions' : [_create_dta],
589 'result' : {'type' : 'form',
592 'state' : [('end', 'OK', 'gtk-ok', True)]
597 wizard_dta_create('account.dta_create')
598 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: