# -*- coding: utf-8 -*- # # bvr_import.py # l10n_ch # # Created by Nicolas Bessi based on Credric Krier contribution # # Copyright (c) 2009 CamptoCamp. All rights reserved. ############################################################################## # WARNING: This program as such is intended to be used by professional # programmers who take the whole responsability of assessing all potential # consequences resulting from its eventual inadequacies and bugs # End users who are looking for a ready-to-use solution with commercial # garantees and support are strongly adviced to contract a Free Software # Service Company # # This program is Free Software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ############################################################################## import wizard import pooler import base64 import time from tools import mod10r import re from tools.translate import _ ASK_FORM = """
""" ASK_FIELDS = { 'file': { 'string': 'BVR file', 'type': 'binary', 'required': True, }, } def _reconstruct_invoice_ref(cursor, user, reference, context): ### id_invoice = False # On fait d'abord une recherche sur toutes les factures # we now searhc for company user_obj=pooler.get_pool(cursor.dbname).get('res.users') user_current=user_obj.browse(cursor, user, user) ## cursor.execute("SELECT inv.id,inv.number from account_invoice AS inv where inv.company_id = %s" ,(user_current.company_id.id,)) result_invoice = cursor.fetchall() for inv_id,inv_name in result_invoice: inv_name = re.sub('[^0-9]', '0', str(inv_name)) if inv_name == reference: id_invoice = inv_id break if id_invoice: cursor.execute('SELECT l.id ' \ 'FROM account_move_line l, account_invoice i ' \ 'WHERE l.move_id = i.move_id AND l.reconcile_id is NULL ' \ 'AND i.id IN %s',(tuple([id_invoice]),)) inv_line = [] for id_line in cursor.fetchall(): inv_line.append(id_line[0]) return inv_line else: return [] return True def _import(obj, cursor, user, data, context): pool = pooler.get_pool(cursor.dbname) statement_line_obj = pool.get('account.bank.statement.line') statement_reconcile_obj = pool.get('account.bank.statement.reconcile') move_line_obj = pool.get('account.move.line') property_obj = pool.get('ir.property') model_fields_obj = pool.get('ir.model.fields') attachment_obj = pool.get('ir.attachment') file = data['form']['file'] statement_id = data['id'] records = [] total_amount = 0 total_cost = 0 find_total = False for lines in base64.decodestring(file).split("\n"): # Manage files without carriage return while lines: (line, lines) = (lines[:128], lines[128:]) record = {} if line[0:3] in ('999', '995'): if find_total: raise wizard.except_wizard(_('Error'), _('Too much total record found!')) find_total = True if lines: raise wizard.except_wizard(_('Error'), _('Record found after total record!')) amount = float(line[39:49]) + (float(line[49:51]) / 100) cost = float(line[69:76]) + (float(line[76:78]) / 100) if line[2] == '5': amount *= -1 cost *= -1 if round(amount - total_amount, 2) >= 0.01 \ or round(cost - total_cost, 2) >= 0.01: raise wizard.except_wizard(_('Error'), _('Total record different from the computed!')) if int(line[51:63]) != len(records): raise wizard.except_wizard(_('Error'), _('Number record different from the computed!')) else: record = { 'reference': line[12:39], 'amount': float(line[39:47]) + (float(line[47:49]) / 100), 'date': time.strftime('%Y-%m-%d', time.strptime(line[65:71], '%y%m%d')), 'cost': float(line[96:98]) + (float(line[98:100]) / 100), } if record['reference'] != mod10r(record['reference'][:-1]): raise wizard.except_wizard(_('Error'), _('Recursive mod10 is invalid for reference: %s') % \ record['reference']) if line[2] == '5': record['amount'] *= -1 record['cost'] *= -1 total_amount += record['amount'] total_cost += record['cost'] records.append(record) model_fields_ids = model_fields_obj.search(cursor, user, [ ('name', 'in', ['property_account_receivable', 'property_account_payable']), ('model', '=', 'res.partner'), ], context=context) property_ids = property_obj.search(cursor, user, [ ('fields_id', 'in', model_fields_ids), ('res_id', '=', False), ], context=context) account_receivable = False account_payable = False for property in property_obj.browse(cursor, user, property_ids, context=context): if property.fields_id.name == 'property_account_receivable': account_receivable = int(property.value.split(',')[1]) elif property.fields_id.name == 'property_account_payable': account_payable = int(property.value.split(',')[1]) for record in records: # Remove the 11 first char because it can be adherent number # TODO check if 11 is the right number reference = record['reference'][11:-1].lstrip('0') values = { 'name': 'IN '+ reference, 'date': record['date'], 'amount': record['amount'], 'ref': reference, 'type': (record['amount'] >= 0 and 'customer') or 'supplier', 'statement_id': statement_id, } line_ids = move_line_obj.search(cursor, user, [ ('ref', 'like', reference), ('reconcile_id', '=', False), ('account_id.type', 'in', ['receivable', 'payable']), ], order='date desc', context=context) if not line_ids: line_ids = _reconstruct_invoice_ref(cursor,user,reference,None) line2reconcile = False partner_id = False account_id = False for line in move_line_obj.browse(cursor, user, line_ids, context=context): if line.partner_id.id: partner_id = line.partner_id.id if record['amount'] >= 0: if round(record['amount'] - line.debit, 2) < 0.01: line2reconcile = line.id account_id = line.account_id.id break else: if round(line.credit + record['amount'], 2) < 0.01: line2reconcile = line.id account_id = line.account_id.id break if not account_id: if record['amount'] >= 0: account_id = account_receivable else: account_id = account_payable if not account_id : raise wizard.except_wizard(_('Error'), _('The properties account payable account receivable')) values['account_id'] = account_id values['partner_id'] = partner_id if line2reconcile: values['reconcile_id'] = statement_reconcile_obj.create(cursor, user, { 'line_ids': [(6, 0, [line2reconcile])], }, context=context) statement_line_obj.create(cursor, user, values, context=context) attachment_obj.create(cursor, user, { 'name': 'BVR', 'datas': file, 'datas_fname': 'BVR.txt', 'res_model': 'account.bank.statement', 'res_id': statement_id, }, context=context) return {} class BVRImport(wizard.interface): states = { 'init': { 'actions': [], 'result': { 'type': 'form', 'arch': ASK_FORM, 'fields': ASK_FIELDS, 'state': [ ('end', 'Cancel', 'gtk-cancel'), ('import', 'Import', 'gtk-ok', True), ], }, }, 'import': { 'actions': [], 'result': { 'type': 'action', 'action': _import, 'state': 'end', }, }, } BVRImport('l10n_ch.bvr_import') # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: