2011-01-14 12:41:54 +00:00
|
|
|
# -*- encoding: utf-8 -*-
|
2009-02-13 15:53:46 +00:00
|
|
|
##############################################################################
|
|
|
|
#
|
2011-01-14 12:41:54 +00:00
|
|
|
# Author: Nicolas Bessi. Copyright Camptocamp SA
|
|
|
|
# Donors: Hasa Sàrl, Open Net Sàrl and Prisme Solutions Informatique SA
|
2009-02-13 15:53:46 +00:00
|
|
|
#
|
2011-01-14 12:41:54 +00:00
|
|
|
# This program is free software: you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU Affero General Public License as
|
|
|
|
# published by the Free Software Foundation, either version 3 of the
|
|
|
|
# License, or (at your option) any later version.
|
2009-02-13 15:53:46 +00:00
|
|
|
#
|
2011-01-14 12:41:54 +00:00
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU Affero General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU Affero General Public License
|
|
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2009-02-13 15:53:46 +00:00
|
|
|
#
|
|
|
|
##############################################################################
|
|
|
|
import base64
|
|
|
|
import time
|
|
|
|
import re
|
2009-03-06 22:18:24 +00:00
|
|
|
|
2010-08-19 05:44:05 +00:00
|
|
|
from tools.translate import _
|
2010-08-19 04:51:10 +00:00
|
|
|
from osv import osv, fields
|
2010-08-19 05:44:05 +00:00
|
|
|
from tools import mod10r
|
2010-08-19 04:51:10 +00:00
|
|
|
import pooler
|
2009-02-13 15:53:46 +00:00
|
|
|
|
2010-08-19 05:44:05 +00:00
|
|
|
def _reconstruct_invoice_ref(cursor, user, reference, context=None):
|
2009-10-16 11:25:20 +00:00
|
|
|
###
|
|
|
|
id_invoice = False
|
|
|
|
# On fait d'abord une recherche sur toutes les factures
|
2011-02-07 11:04:05 +00:00
|
|
|
# we now search for an invoice
|
2010-08-19 05:44:05 +00:00
|
|
|
user_obj = pooler.get_pool(cursor.dbname).get('res.users')
|
2009-10-16 11:25:20 +00:00
|
|
|
user_current=user_obj.browse(cursor, user, user)
|
2009-11-25 12:04:43 +00:00
|
|
|
|
2009-10-16 11:25:20 +00:00
|
|
|
##
|
2011-09-16 14:32:55 +00:00
|
|
|
cursor.execute("SELECT inv.id,inv.number from account_invoice "
|
|
|
|
"AS inv where inv.company_id = %s and type='out_invoice'",
|
|
|
|
(user_current.company_id.id,))
|
2009-10-16 11:25:20 +00:00
|
|
|
result_invoice = cursor.fetchall()
|
2011-02-07 11:04:05 +00:00
|
|
|
REF = re.compile('[^0-9]')
|
2009-10-16 11:25:20 +00:00
|
|
|
for inv_id,inv_name in result_invoice:
|
2011-02-07 11:04:05 +00:00
|
|
|
inv_name = REF.sub('0', str(inv_name))
|
2009-10-16 11:25:20 +00:00
|
|
|
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 ' \
|
2010-06-10 13:34:19 +00:00
|
|
|
'AND i.id IN %s',(tuple([id_invoice]),))
|
2009-10-16 11:25:20 +00:00
|
|
|
inv_line = []
|
|
|
|
for id_line in cursor.fetchall():
|
|
|
|
inv_line.append(id_line[0])
|
|
|
|
return inv_line
|
|
|
|
else:
|
|
|
|
return []
|
|
|
|
return True
|
2010-08-19 05:44:05 +00:00
|
|
|
|
2010-10-26 15:02:22 +00:00
|
|
|
def _import(self, cursor, user, data, context=None):
|
2009-02-13 15:53:46 +00:00
|
|
|
|
2010-10-26 15:02:22 +00:00
|
|
|
statement_line_obj = self.pool.get('account.bank.statement.line')
|
|
|
|
voucher_obj = self.pool.get('account.voucher')
|
|
|
|
voucher_line_obj = self.pool.get('account.voucher.line')
|
|
|
|
move_line_obj = self.pool.get('account.move.line')
|
2011-01-14 12:41:54 +00:00
|
|
|
property_obj = self.pool.get('ir.property')
|
|
|
|
model_fields_obj = self.pool.get('ir.model.fields')
|
2010-10-26 15:02:22 +00:00
|
|
|
attachment_obj = self.pool.get('ir.attachment')
|
2011-02-07 11:04:05 +00:00
|
|
|
statement_obj = self.pool.get('account.bank.statement')
|
|
|
|
property_obj = self.pool.get('ir.property')
|
2009-10-16 11:25:20 +00:00
|
|
|
file = data['form']['file']
|
2012-01-17 17:21:53 +00:00
|
|
|
if not file:
|
|
|
|
raise osv.except_osv(_('UserError'),
|
|
|
|
_('Please select a file first!'))
|
2009-10-16 11:25:20 +00:00
|
|
|
statement_id = data['id']
|
|
|
|
records = []
|
|
|
|
total_amount = 0
|
|
|
|
total_cost = 0
|
|
|
|
find_total = False
|
|
|
|
|
2010-08-19 05:44:05 +00:00
|
|
|
if context is None:
|
|
|
|
context = {}
|
2009-10-16 11:25:20 +00:00
|
|
|
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:
|
2010-08-19 04:51:10 +00:00
|
|
|
raise osv.except_osv(_('Error'),
|
2009-10-16 11:25:20 +00:00
|
|
|
_('Too much total record found!'))
|
|
|
|
find_total = True
|
|
|
|
if lines:
|
2010-08-19 04:51:10 +00:00
|
|
|
raise osv.except_osv(_('Error'),
|
2009-10-16 11:25:20 +00:00
|
|
|
_('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:
|
2010-08-19 04:51:10 +00:00
|
|
|
raise osv.except_osv(_('Error'),
|
2009-10-16 11:25:20 +00:00
|
|
|
_('Total record different from the computed!'))
|
|
|
|
if int(line[51:63]) != len(records):
|
2010-08-19 04:51:10 +00:00
|
|
|
raise osv.except_osv(_('Error'),
|
2009-10-16 11:25:20 +00:00
|
|
|
_('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]):
|
2010-08-19 04:51:10 +00:00
|
|
|
raise osv.except_osv(_('Error'),
|
2009-10-16 11:25:20 +00:00
|
|
|
_('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)
|
|
|
|
|
|
|
|
account_receivable = False
|
|
|
|
account_payable = False
|
2010-10-07 12:39:29 +00:00
|
|
|
statement = statement_obj.browse(cursor, user, statement_id, context=context)
|
2010-10-08 10:12:47 +00:00
|
|
|
|
2009-10-16 11:25:20 +00:00
|
|
|
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,
|
|
|
|
}
|
2010-10-08 10:12:47 +00:00
|
|
|
|
2009-10-16 11:25:20 +00:00
|
|
|
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:
|
2010-08-19 05:44:05 +00:00
|
|
|
line_ids = _reconstruct_invoice_ref(cursor, user, reference, None)
|
2009-10-16 11:25:20 +00:00
|
|
|
partner_id = False
|
|
|
|
account_id = False
|
|
|
|
for line in move_line_obj.browse(cursor, user, line_ids, context=context):
|
2010-10-07 12:39:29 +00:00
|
|
|
account_receivable = line.partner_id.property_account_receivable.id
|
|
|
|
account_payable = line.partner_id.property_account_payable.id
|
|
|
|
partner_id = line.partner_id.id
|
|
|
|
move_id = line.move_id.id
|
2009-10-16 11:25:20 +00:00
|
|
|
if record['amount'] >= 0:
|
|
|
|
if round(record['amount'] - line.debit, 2) < 0.01:
|
2010-10-08 10:12:47 +00:00
|
|
|
# line2reconcile = line.id
|
2009-10-16 11:25:20 +00:00
|
|
|
account_id = line.account_id.id
|
|
|
|
break
|
|
|
|
else:
|
|
|
|
if round(line.credit + record['amount'], 2) < 0.01:
|
2010-10-08 10:12:47 +00:00
|
|
|
# line2reconcile = line.id
|
2009-10-16 11:25:20 +00:00
|
|
|
account_id = line.account_id.id
|
|
|
|
break
|
2011-12-08 08:30:34 +00:00
|
|
|
result = voucher_obj.onchange_partner_id(cursor, user, [], partner_id, journal_id=statement.journal_id.id, amount=abs(record['amount']), currency_id= statement.currency.id, ttype='receipt', date=statement.date ,context=context)
|
2011-02-07 11:04:05 +00:00
|
|
|
voucher_res = { 'type': 'receipt' ,
|
2010-10-26 15:02:22 +00:00
|
|
|
|
|
|
|
'name': values['name'],
|
|
|
|
'partner_id': partner_id,
|
|
|
|
'journal_id': statement.journal_id.id,
|
|
|
|
'account_id': result.get('account_id', statement.journal_id.default_credit_account_id.id),
|
|
|
|
'company_id': statement.company_id.id,
|
|
|
|
'currency_id': statement.currency.id,
|
|
|
|
'date': record['date'] or time.strftime('%Y-%m-%d'),
|
|
|
|
'amount': abs(record['amount']),
|
2010-10-07 12:39:29 +00:00
|
|
|
'period_id': statement.period_id.id
|
2010-10-26 15:02:22 +00:00
|
|
|
}
|
2010-10-07 12:39:29 +00:00
|
|
|
voucher_id = voucher_obj.create(cursor, user, voucher_res, context=context)
|
|
|
|
context.update({'move_line_ids': line_ids})
|
|
|
|
values['voucher_id'] = voucher_id
|
|
|
|
voucher_line_dict = False
|
|
|
|
if result['value']['line_ids']:
|
2011-01-14 12:41:54 +00:00
|
|
|
for line_dict in result['value']['line_ids']:
|
|
|
|
move_line = move_line_obj.browse(cursor, user, line_dict['move_line_id'], context)
|
|
|
|
if move_id == move_line.move_id.id:
|
|
|
|
voucher_line_dict = line_dict
|
2010-10-07 12:39:29 +00:00
|
|
|
if voucher_line_dict:
|
2011-01-14 12:41:54 +00:00
|
|
|
voucher_line_dict.update({'voucher_id':voucher_id})
|
2011-09-16 14:32:55 +00:00
|
|
|
voucher_line_obj.create(cursor, user, voucher_line_dict, context=context)
|
|
|
|
|
2009-10-16 11:25:20 +00:00
|
|
|
if not account_id:
|
|
|
|
if record['amount'] >= 0:
|
|
|
|
account_id = account_receivable
|
|
|
|
else:
|
|
|
|
account_id = account_payable
|
2011-02-07 11:04:05 +00:00
|
|
|
##If line not linked to an invoice we create a line not linked to a voucher
|
|
|
|
if not account_id and not line_ids:
|
|
|
|
name = "property_account_receivable"
|
|
|
|
if record['amount'] < 0:
|
|
|
|
name = "property_account_payable"
|
|
|
|
prop = property_obj.search(
|
2011-09-16 14:32:55 +00:00
|
|
|
cursor,
|
2011-02-07 11:04:05 +00:00
|
|
|
user,
|
|
|
|
[
|
2011-09-16 14:32:55 +00:00
|
|
|
('name','=',name),
|
2011-02-07 11:04:05 +00:00
|
|
|
('company_id','=',statement.company_id.id),
|
|
|
|
('res_id', '=', False)
|
|
|
|
]
|
|
|
|
)
|
|
|
|
if prop:
|
|
|
|
value = property_obj.read(cursor, user, prop[0], ['value_reference']).get('value_reference', False)
|
|
|
|
if value :
|
|
|
|
account_id = int(value.split(',')[1])
|
|
|
|
else :
|
|
|
|
raise osv.except_osv(_('Error'),
|
|
|
|
_('The properties account payable account receivable are not set'))
|
|
|
|
if not account_id and line_ids:
|
2010-08-19 04:51:10 +00:00
|
|
|
raise osv.except_osv(_('Error'),
|
2011-02-07 11:04:05 +00:00
|
|
|
_('The properties account payable account receivable are not set'))
|
2009-10-16 11:25:20 +00:00
|
|
|
values['account_id'] = account_id
|
|
|
|
values['partner_id'] = partner_id
|
|
|
|
statement_line_obj.create(cursor, user, values, context=context)
|
|
|
|
attachment_obj.create(cursor, user, {
|
2011-09-16 14:32:55 +00:00
|
|
|
'name': 'BVR %s'%time.strftime("%Y-%m-%d_%H:%M:%S", time.gmtime()),
|
2009-10-16 11:25:20 +00:00
|
|
|
'datas': file,
|
2011-09-16 14:32:55 +00:00
|
|
|
'datas_fname': 'BVR %s.txt'%time.strftime("%Y-%m-%d_%H:%M:%S", time.gmtime()),
|
2009-10-16 11:25:20 +00:00
|
|
|
'res_model': 'account.bank.statement',
|
|
|
|
'res_id': statement_id,
|
|
|
|
}, context=context)
|
2010-08-19 05:44:05 +00:00
|
|
|
|
2009-10-16 11:25:20 +00:00
|
|
|
return {}
|
2009-02-13 15:53:46 +00:00
|
|
|
|
2010-08-19 04:51:10 +00:00
|
|
|
class bvr_import_wizard(osv.osv_memory):
|
2010-08-19 05:44:05 +00:00
|
|
|
_name = 'bvr.import.wizard'
|
|
|
|
_columns = {
|
2012-01-17 17:21:53 +00:00
|
|
|
'file':fields.binary('BVR File')
|
2010-08-19 05:44:05 +00:00
|
|
|
}
|
|
|
|
|
2010-08-19 04:51:10 +00:00
|
|
|
def import_bvr(self, cr, uid, ids, context=None):
|
2010-08-19 05:44:05 +00:00
|
|
|
data = {}
|
|
|
|
if context is None:
|
|
|
|
context = {}
|
2010-08-19 04:51:10 +00:00
|
|
|
active_ids = context.get('active_ids', [])
|
|
|
|
active_id = context.get('active_id', False)
|
|
|
|
data['form'] = {}
|
|
|
|
data['ids'] = active_ids
|
|
|
|
data['id'] = active_id
|
|
|
|
data['form']['file'] = ''
|
|
|
|
res = self.read(cr, uid, ids[0], ['file'])
|
|
|
|
if res:
|
|
|
|
data['form']['file'] = res['file']
|
2010-08-19 05:44:05 +00:00
|
|
|
_import(self, cr, uid, data, context=context)
|
2011-01-14 12:41:54 +00:00
|
|
|
return {}
|
2010-08-19 05:44:05 +00:00
|
|
|
|
2010-08-19 04:51:10 +00:00
|
|
|
bvr_import_wizard()
|
2009-02-13 15:53:46 +00:00
|
|
|
|
2010-10-26 15:02:22 +00:00
|
|
|
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|