diff --git a/addons/l10n_ch/v11/v11.py b/addons/l10n_ch/v11/v11.py index 1f15435b79f..cb8446dcda3 100644 --- a/addons/l10n_ch/v11/v11.py +++ b/addons/l10n_ch/v11/v11.py @@ -35,11 +35,17 @@ class account_v11(osv.osv): _columns = { 'name': fields.char('Date', size=64), # pe mettre une sequence 'file': fields.binary('V11 file'), + 'state': fields.selection([('new','New'), # completely new file + ('partial','Partial'), # file with unknown lines + ('error','Error'), # file completely wrong + ('done','Done')], # file ok even if some lines were ignored + 'State',readonly= True), 'note': fields.text('Import log'), } _defaults= { 'name': lambda *a : time.strftime('%Y-%m-%d'), + 'state': lambda *a : 'new', } account_v11() diff --git a/addons/l10n_ch/v11/v11_import.py b/addons/l10n_ch/v11/v11_import.py index d565214017a..a3127861cbf 100644 --- a/addons/l10n_ch/v11/v11_import.py +++ b/addons/l10n_ch/v11/v11_import.py @@ -27,139 +27,166 @@ import pooler import time import wizard -import ir import netsvc -from time import sleep from base64 import b64decode +from osv import osv - -test_form = """ +ask_form = """
- - + + + + """ -test_fields = { +ask_fields = { 'journal_id' : { 'string':'Destination Journal', 'type':'many2one', 'relation':'account.journal', 'required':True, -# 'domain':[('type','=','sale')] + }, + 'v11' : { + 'string':'V11 file', + 'type':'binary', + 'required':True, }, } +res_form = """ +
+ + + + + + + +""" + +res_fields = { + 'journal_id' : { + 'string':'Destination Journal', + 'type':'many2one', + 'relation':'account.journal', + 'required':True, + }, + 'v11' : { + 'string':'V11 file', + 'type':'binary', + 'required':True, + }, + + 'note' : {'string':'Log','type':'text'} + +} + + def _v11_parsing(self, cr, uid, data, context): pool = pooler.get_pool(cr.dbname) - v11_obj = pool.get('account.v11') + v11 = data['form']['v11'] - for v11 in v11_obj.browse(cr, uid, data['ids']): - line="" - record={} - total={} - total_compute= 0 - rec_list=[] - log='' + line="" + record={} + total={} + total_compute= 0 + rec_list=[] + log='' + nb_err=0 + + # v11 parsing : + for char in b64decode(v11): + + if not char == '\n': + line += char + + else : + + record['genre'] = line[0:3] + + if record['genre'] == '999': - # v11 parsing : - for char in b64decode(v11.file): - if not char == '\n': - line += char + total={'n_postal': line[3:12], + 'cle': line[12:39], + 'tot_montant': line[39:51], + 'nb_rec': line[51:63], + 'date_etabl': line[63:69], + 'tot_frais_encaissement': line[69:78], + } else : - record['genre'] = line[0:3] + record={'n_postal': line[3:12], + 'n_ref': line[12:39], + 'montant': line[39:49], + 'reserve': line[49:59], + 'date_remise': line[59:65], + 'date_comptable': line[65:71], + 'date_valeur': line[71:77], + 'invoice_ref': line[77:87], + 'reserve2': line[87:96], + 'frais_encaissement': line[96:100], + 'line':line, + } - if record['genre'] == '999': + total_compute+= int(record['montant']) + rec_list.append( record ) + + line="" + + + # check the amounts : + if not total_compute == int(total['tot_montant']): + return {'note': 'Incoherent V11 file ! IMPORT ABORTED.' } - total={'n_postal': line[3:12], - 'cle': line[12:39], - 'tot_montant': line[39:51], - 'nb_rec': line[51:63], - 'date_etabl': line[63:69], - 'tot_frais_encaissement': line[69:78], - } + period_id = pool.get('account.period').find(cr,uid, context=context) + if not period_id: + return {'note': 'No period found ! IMPORT ABORTED.' } - else : + period_id = period_id[0] + invoice_obj= pool.get('account.invoice') - record={'n_postal': line[3:12], - 'n_ref': line[12:39], - 'montant': line[39:49], - 'reserve': line[49:59], - 'date_remise': line[59:65], - 'date_comptable': line[65:71], - 'date_valeur': line[71:77], - 'internal_ref': line[77:87], - 'reserve2': line[87:96], - 'frais_encaissement': line[96:100], - 'line':line, - } - - total_compute+= int(record['montant']) - rec_list.append( record ) - - line="" + acc2 = pool.get('account.journal').browse(cr,uid,data['form']['journal_id'],context).default_debit_account_id.id + if not acc2: + return {'note': 'No debit account specified for this journal ! IMPORT ABORTED.' } - # check the amounts : - if not total_compute == int(total['tot_montant']): - raise wizard.except_wizard('warning', 'Incoherent v11 file !') + + for rec in rec_list: + + # get the invoice via his number + try: + invoice_id= invoice_obj.search(cr,uid,[ ('number','=',int(rec['invoice_ref'])) ])[0] + except: + log = log + '\n * No invoice with invoice number '+ rec['invoice_ref'].lstrip('0') + '.\n line : '+rec['line'] + nb_err+=1 continue - - - - period_id = pool.get('account.period').find(cr,uid, context=context) - if not period_id: - raise wizard.except_wizard('No period found !', 'Unable to find a valid period !') - period_id = period_id[0] - invoice_obj= pool.get('account.invoice') - for rec in rec_list: - - - - # recherche sur l'id (pr garder un num absolu): - # implique de mettre l'id sur le bvr.. - invoice_id= invoice_obj.search(cr,uid,[ ('id','=',int(rec['internal_ref'])) ])[0] - print invoice_id - invoice = invoice_obj.browse(cr, uid, invoice_id) - invoice_obj.write(cr,uid,[invoice_id],{'state':'paid'}) - - - - # TODO feedbacker en log les erreurs - acc2 = pool.get('account.journal').browse(cr,uid,data['form']['journal_id'],context).default_debit_account_id.id - if not acc2: - raise wizard.except_wizard('Warning !', 'No debit account specified for this journal !') - continue - - # TODO idem - try: - acc1 = invoice.partner_id.property_account_receivable[0] - except: - raise wizard.except_wizard('Warning !','invoice with number '+str(int(rec['internal_ref'])) +' has no partner !') - continue - + invoice = invoice_obj.browse(cr, uid, invoice_id) + try: + acc1 = invoice.partner_id.property_account_receivable[0] + except: + log = log + '\n * invoice with number '+ rec['invoice_ref'].lstrip('0') +' has no partner !'+ '\n line : '+rec['line'] + nb_err+=1 + continue + try: move_id = pool.get('account.move').create(cr, uid, { 'name': 'Imported from v11', 'period_id': period_id, 'journal_id': data['form']['journal_id'] - }) - - - - pool.get('account.move.line').create(cr,uid,{ - 'name': 'v11', + }) + line_id = pool.get('account.move.line').create(cr,uid,{ + 'name': 'v11', # maybe a better name .. 'debit': 0, 'credit': rec['montant'], 'account_id': acc1, @@ -182,42 +209,65 @@ def _v11_parsing(self, cr, uid, data, context): 'journal_id': data['form']['journal_id'] }) + account_move_lines = invoice.move_line_id_payment_get(cr,uid,[invoice.id]) + + if not account_move_lines: + raise Exception("No moves associated to invoice number "+ rec['invoice_ref'].lstrip('0')) + account_move_lines.append(line_id ) + pool.get('account.move.line').reconcile(cr,uid,account_move_lines, + writeoff_acc_id=0,#FIXME + writeoff_journal_id=0,#FIXME + writeoff_period_id= 0, + ) + cr.commit() + + except osv.except_osv, e: + cr.rollback() + nb_err+=1 + if e.value.startswith('You have to provide an account for the write off entry !'): + log= log +'\n * Error amount mismatch for invoice '+ rec['invoice_ref'].lstrip('0')+ ':\n line : '+rec['line'] + else: + log= log +'\n * '+str(e.value)+ ' :\n line : '+rec['line'] + #raise # REMOVEME + + except Exception, e: + cr.rollback() + nb_err+=1 + log= log +'\n * '+str(e)+ ' :\n line : '+rec['line'] + #raise # REMOVEME + except : + cr.rollback() + nb_err+=1 + log= log +'\n * Reconciliation Error\n line : '+rec['line'] + #raise + + log= log + '-'*5 +'\nNumber of parsed lines : '+ str(len(rec_list)) +'\nNumber of error : '+ str(nb_err) + + return {'note':log,'journal_id': data['form']['journal_id'], 'v11': data['form']['v11']} - - log= log + 'Number of parsed lines : '+ str(len(rec_list)) +'\nTotal amount for this bvr : '+ str(int(total['tot_montant']))+' '+invoice.currency_id.name - - - v11.write(cr,uid,[v11.id],{'note': log }) - - # peut-etre retourner un nouvel onglet avec la liste des ecritures generee : - return {} - - - +# def _init(self, cr, uid, data, context): +# if not data['form']: +# return {} +# return {'journal_id': data['form']['journal_id'], 'v11': data['form']['v11']} class v11_import(wizard.interface): states = { 'init' : { 'actions' : [], 'result' : {'type' : 'form', - 'arch' : test_form, - 'fields' : test_fields, + 'arch' : ask_form, + 'fields' : ask_fields, 'state' : [('end', 'Cancel'),('extraction', 'Yes') ]} }, 'extraction' : { 'actions' : [_v11_parsing], - 'result' : {'type' : 'state', 'state' : 'end'} + 'result' : {'type' : 'form', + 'arch' : res_form, + 'fields' : res_fields, + 'state' : [('extraction', 'Retry') ,('end', 'Quit') ]} }, -# 'result' : { -# 'actions' : [], -# 'result' : {'type' : 'form', -# 'state' : 'end'} -# }, - - - } v11_import("account.v11_import") diff --git a/addons/l10n_ch/v11/v11_view.xml b/addons/l10n_ch/v11/v11_view.xml index 2f4f68a5223..a6653daea30 100644 --- a/addons/l10n_ch/v11/v11_view.xml +++ b/addons/l10n_ch/v11/v11_view.xml @@ -5,33 +5,34 @@ - - - account.v11.form - account.v11 - form - -
- - - - - - -
+ + + + + + + + + + + + + + + - - - account.v11 - ir.actions.act_window - account.v11 - form - form,tree - + + + + + + + + - + diff --git a/addons/l10n_ch/v11/v11_wizard.xml b/addons/l10n_ch/v11/v11_wizard.xml index 6b32ea31d92..ed971d50fdb 100644 --- a/addons/l10n_ch/v11/v11_wizard.xml +++ b/addons/l10n_ch/v11/v11_wizard.xml @@ -4,11 +4,12 @@ +