odoo/addons/l10n_ch/wizard/bvr_import.py

267 lines
11 KiB
Python

# -*- encoding: utf-8 -*-
##############################################################################
#
# Author: Nicolas Bessi. Copyright Camptocamp SA
# Donors: Hasa Sàrl, Open Net Sàrl and Prisme Solutions Informatique SA
#
# 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.
#
# 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/>.
#
##############################################################################
import base64
import time
import re
from tools.translate import _
from osv import osv, fields
from tools import mod10r
import pooler
def _reconstruct_invoice_ref(cursor, user, reference, context=None):
###
id_invoice = False
# On fait d'abord une recherche sur toutes les factures
# we now search for an invoice
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 and type='out_invoice'",
(user_current.company_id.id,))
result_invoice = cursor.fetchall()
REF = re.compile('[^0-9]')
for inv_id,inv_name in result_invoice:
inv_name = REF.sub('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(self, cursor, user, data, context=None):
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')
property_obj = self.pool.get('ir.property')
model_fields_obj = self.pool.get('ir.model.fields')
attachment_obj = self.pool.get('ir.attachment')
statement_obj = self.pool.get('account.bank.statement')
property_obj = self.pool.get('ir.property')
file = data['form']['file']
if not file:
raise osv.except_osv(_('User Error!'),
_('Please select a file first.'))
statement_id = data['id']
records = []
total_amount = 0
total_cost = 0
find_total = False
if context is None:
context = {}
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 osv.except_osv(_('Error!'),
_('Too much total record found.'))
find_total = True
if lines:
raise osv.except_osv(_('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 osv.except_osv(_('Error!'),
_('Total record different from the computed.'))
if int(line[51:63]) != len(records):
raise osv.except_osv(_('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 osv.except_osv(_('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)
account_receivable = False
account_payable = False
statement = statement_obj.browse(cursor, user, statement_id, context=context)
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)
partner_id = False
account_id = False
for line in move_line_obj.browse(cursor, user, line_ids, context=context):
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
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
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)
voucher_res = { 'type': 'receipt' ,
'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']),
'period_id': statement.period_id.id
}
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']:
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
if voucher_line_dict:
voucher_line_dict.update({'voucher_id':voucher_id})
voucher_line_obj.create(cursor, user, voucher_line_dict, context=context)
if not account_id:
if record['amount'] >= 0:
account_id = account_receivable
else:
account_id = account_payable
##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(
cursor,
user,
[
('name','=',name),
('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 and account receivable are not set.'))
if not account_id and line_ids:
raise osv.except_osv(_('Error!'),
_('The properties account payable and account receivable are not set.'))
values['account_id'] = account_id
values['partner_id'] = partner_id
statement_line_obj.create(cursor, user, values, context=context)
attachment_obj.create(cursor, user, {
'name': 'BVR %s'%time.strftime("%Y-%m-%d_%H:%M:%S", time.gmtime()),
'datas': file,
'datas_fname': 'BVR %s.txt'%time.strftime("%Y-%m-%d_%H:%M:%S", time.gmtime()),
'res_model': 'account.bank.statement',
'res_id': statement_id,
}, context=context)
return {}
class bvr_import_wizard(osv.osv_memory):
_name = 'bvr.import.wizard'
_columns = {
'file':fields.binary('BVR File')
}
def import_bvr(self, cr, uid, ids, context=None):
data = {}
if context is None:
context = {}
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']
_import(self, cr, uid, data, context=context)
return {}
bvr_import_wizard()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: