odoo/addons/l10n_ch/wizard/bvr_import.py

253 lines
9.4 KiB
Python

# -*- 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 = """<?xml version="1.0"?>
<form string="BVR Import">
<field name="file"/>
</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: