Commit 29aef25a authored by Rémi - Le Filament's avatar Rémi - Le Filament
Browse files

Module initialization

parents
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
:alt: License: AGPL-3
=========================
Import CSV Bank Statement
=========================
This module adds support for the import of bank statements in `CSV format` for BPCE exports.
Known issues / Roadmap
======================
* None
Bug Tracker
===========
Bugs are tracked on `GitHub Issues
<https://github.com/OCA/bank-statement-import/issues>`_. In case of trouble, please
check there if your issue has already been reported. If you spotted it first,
help us smashing it by providing a detailed and welcomed feedback.
Credits
=======
Contributors
------------
* Odoo SA
* Alexis de Lattre <alexis@via.ecp.fr>
* Laurent Mignon <laurent.mignon@acsone.eu>
* Ronald Portier <rportier@therp.nl>
* Sylvain LE GAL <https://twitter.com/legalsylvain>
* Nicolas JEUDY <https://github.com/njeudy>
* Aurélien DUMAINE
# -*- coding: utf-8 -*-
from . import wizard
# -*- coding: utf-8 -*-
{
'name': 'Import BPCE Bank Statement',
'category': 'Banking addons',
'version': '10.0.1.0.0',
'license': 'AGPL-3',
'author': 'Odoo SA,'
'Akretion,'
'La Louve,'
'GRAP,'
'Nicolas JEUDY,'
'Aurélien DUMAINE',
'Odoo Community Association (OCA)',
'website': 'https://odoo-community.org/',
'depends': [
'account_bank_statement_import',
],
'data': [
'views/view_account_bank_statement_import.xml',
],
'installable': True,
}
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_account_bank_statement_import_form" model="ir.ui.view">
<field name="model">account.bank.statement.import</field>
<field name="inherit_id" ref="account_bank_statement_import.account_bank_statement_import_view"/>
<field name="arch" type="xml">
<xpath expr="//ul[@id='statement_format']" position="inside">
<li>BPCE CSV File (.CSV)</li>
</xpath>
</field>
</record>
</odoo>
# -*- coding: utf-8 -*-
from . import account_bank_statement_import
# -*- coding: utf-8 -*-
import logging
import StringIO
import re
import datetime
from odoo import api, models, _
from odoo.exceptions import Warning
_logger = logging.getLogger(__name__)
class AccountBankStatementImport(models.TransientModel):
_inherit = 'account.bank.statement.import'
regexp_version = {
'version_A' : {
'line_1' : u"^Code de la banque : (?P<bank_group_code>\d{5});Code de l'agence : (?P<bank_local_code>\d{5});Date de début de téléchargement : (?P<opening_date>\d{2}/\d{2}/\d{4});Date de fin de téléchargement : (?P<closing_date>\d{2}/\d{2}/\d{4});;$",
'line_2' : u"^Numéro de compte : (?P<bank_account_number>\d{11});Nom du compte : (?P<bank_account_name>.*);Devise : (?P<currency>.{3});;;$",
'line_closing_balance' : u"^Solde en fin de période;;;;(?P<balance>\d+(,\d{1,2})?);$",
'line_opening_balance' : u"^Solde en début de période;;;;(?P<balance>\d+(,\d{1,2})?);$",
'line_credit' : u"^(?P<date>\d{2}/\d{2}/\d{4});(?P<unique_import_id>.*);(?P<name>.*);;(?P<credit>\d+(,\d{1,2})?);(?P<note>.*)$",
'line_debit' : u"^(?P<date>\d{2}/\d{2}/\d{4});(?P<unique_import_id>.*);(?P<name>.*);(?P<debit>-\d+(,\d{1,2})?);;(?P<note>.*)$",
'line_date_format' : '%d/%m/%Y',
},
'version_B' : {
'line_1' : u"^Code de la banque : (?P<bank_group_code>\d{5});Date de début de téléchargement : (?P<opening_date>\d{2}/\d{2}/\d{4});Date de fin de téléchargement : (?P<closing_date>\d{2}/\d{2}/\d{4});;$",
'line_2' : u"^Numéro de compte : (?P<bank_account_number>\d{11});Devise : (?P<currency>.{3});;;$",
'line_closing_balance' : u"^Solde en fin de période;;;(?P<balance>\d+(,\d{1,2})?);$",
'line_opening_balance' : u"^Solde en début de période;;;(?P<balance>\d+(,\d{1,2})?);$",
'line_credit' : u"^(?P<date>\d{2}/\d{2}/\d{4});(?P<name>.*);;(?P<credit>\d+(,\d{1,2})?);(?P<note>.*)$",
'line_debit' : u"^(?P<date>\d{2}/\d{2}/\d{4});(?P<name>.*);(?P<debit>-\d+(,\d{1,2})?);;(?P<note>.*)$",
'line_date_format' : '%d/%m/%Y',
},
'version_C' : {
'line_1' : u"^Code de la banque : (?P<bank_group_code>\d{5});Code de l'agence : (?P<bank_local_code>\d{5});Date de début de téléchargement : (?P<opening_date>\d{2}/\d{2}/\d{4});Date de fin de téléchargement : (?P<closing_date>\d{2}/\d{2}/\d{4});$",
'line_2' : u"^Numéro de compte : (?P<bank_account_number>\d{11});Nom du compte : (?P<nom_compte>.*);Devise : (?P<currency>.{3});$",
'line_closing_balance' : u"^Solde en fin de période;;;;(?P<balance>(\+|-)?\d+(,\d{1,2})?)$",
'line_opening_balance' : u"^Solde en début de période;;;;(?P<balance>(\+|-)?\d+(,\d{1,2})?)$",
'line_credit' : u"^(?P<date>\d{2}/\d{2}/\d{2});(?P<ref>.*);(?P<name>.*);;\+(?P<credit>\d+(,\d{1,2})?);(?P<note>.*);$",
'line_debit' : u"^(?P<date>\d{2}/\d{2}/\d{2});(?P<ref>.*);(?P<name>.*);(?P<debit>-\d+(,\d{1,2})?);;(?P<note>.*);$",
'line_date_format' : '%d/%m/%y',
}
}
@api.model
def _find_bank_account_id(self, account_number):
""" Get res.partner.bank ID """
bank_account_id = None
if account_number and len(account_number) > 4:
bank_account_ids = self.env['res.partner.bank'].search(
[('acc_number', '=', account_number)], limit=1)
if bank_account_ids:
bank_account_id = bank_account_ids[0].id
return bank_account_id
@api.model
def _check_file(self, data_file):
try:
file_version = "version_A"
#for files generated before june 2017
test_versionA = re.compile(self.regexp_version[file_version]['line_1']).search(data_file[0])
if (test_versionA == None):
#for files generated after june 2017 and before decembre 2017
file_version = "version_B"
test_versionB = re.compile(self.regexp_version[file_version]['line_1']).search(data_file[0])
if (test_versionB == None):
#for files generated after december 2017
file_version = "version_C"
parse_line_1 = re.compile(self.regexp_version[file_version]['line_1']).search(data_file[0])
bank_group_code = parse_line_1.group('bank_group_code')
openning_date = parse_line_1.group('opening_date')
closing_date = parse_line_1.group('closing_date')
parse_line_2 = re.compile(self.regexp_version[file_version]['line_2']).search(data_file[1])
bank_account_number = parse_line_2.group('bank_account_number')
currency = parse_line_2.group('currency')
closing_balance = float(re.compile(self.regexp_version[file_version]['line_closing_balance']).search(data_file[3]).group('balance').replace(',','.'))
opening_balance = float(re.compile(self.regexp_version[file_version]['line_opening_balance']).search(data_file[len(data_file)-1]).group('balance').replace(',','.'))
except Exception as e:
_logger.debug(e)
return False
return (file_version,bank_group_code,openning_date,closing_date,bank_account_number,opening_balance,closing_balance,currency)
@api.model
def _parse_file(self, data_file):
data_file = data_file.splitlines()
result = self._check_file(data_file)
if not result:
return super(AccountBankStatementImport, self)._parse_file(
data_file)
file_version,bank_group_code,openning_date,closing_date,bank_account_number,opening_balance,closing_balance,currency = result
transactions = []
total_amt = 0.00
try:
index = 0
for line in data_file[5:len(data_file)-1]:
transaction = re.compile(self.regexp_version[file_version]['line_debit']).search(line)
if (transaction != None):
transaction_amount = float(transaction.group('debit').replace(',','.'))
else :
transaction = re.compile(self.regexp_version[file_version]['line_credit']).search(line)
transaction_amount = float(transaction.group('credit').replace(',','.'))
libelle = transaction.group('name')
if transaction.group('note') != "":
libelle += " */* "+transaction.group('note')
vals_line = {
'date': datetime.datetime.strptime(transaction.group('date'), self.regexp_version[file_version]['line_date_format']).strftime('%Y-%m-%d'),
'name': libelle,
#'ref': transaction.group('unique_import_id'),
'amount': transaction_amount,
#'note': transaction.group('note'),
'unique_import_id': str(index)+transaction.group('date')+transaction.group('name')+str(transaction_amount)+transaction.group('note'),
'account_number': bank_account_number,
'partner_id': False,
'bank_account_id': self._find_bank_account_id(bank_account_number),
}
total_amt += transaction_amount
transactions.append(vals_line)
index = index + 1
if (abs(opening_balance+total_amt-closing_balance) > 0.00001):
raise ValueError(_("Sum of opening balance and transaction lines is not equel to closing balance."))
except Exception as e:
raise Warning(_("The following problem occurred during import. The file might not be valid.\n\n %s" % e.message))
vals_bank_statement = {
'name': bank_account_number+"/"+openning_date,
'date': datetime.datetime.strptime(openning_date, '%d/%m/%Y').strftime('%Y-%m-%d'),
'transactions': list(reversed(transactions)),
'balance_start': opening_balance,
'balance_end_real': closing_balance,
}
return currency, bank_account_number, [vals_bank_statement]
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment