mirror of
https://github.com/OCA/account-reconcile.git
synced 2025-01-20 12:27:39 +02:00
[MOV] move addons out of __unported__ (they remain not installable)
This commit is contained in:
23
account_statement_base_import/__init__.py
Normal file
23
account_statement_base_import/__init__.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Joel Grand-Guillaume
|
||||
# Copyright 2011-2012 Camptocamp 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/>.
|
||||
#
|
||||
##############################################################################
|
||||
from . import parser
|
||||
from . import wizard
|
||||
from . import statement
|
||||
73
account_statement_base_import/__openerp__.py
Normal file
73
account_statement_base_import/__openerp__.py
Normal file
@@ -0,0 +1,73 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Joel Grand-Guillaume
|
||||
# Copyright 2011-2012 Camptocamp 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/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
{'name': "Bank statement base import",
|
||||
'version': '1.2',
|
||||
'author': "Camptocamp,Odoo Community Association (OCA)",
|
||||
'maintainer': 'Camptocamp',
|
||||
'category': 'Finance',
|
||||
'complexity': 'normal',
|
||||
'depends': [
|
||||
'account_statement_ext',
|
||||
'account_statement_base_completion'
|
||||
],
|
||||
'description': """
|
||||
This module brings basic methods and fields on bank statement to deal with
|
||||
the importation of different bank and offices. A generic abstract method is
|
||||
defined and an example that gives you a basic way of importing bank statement
|
||||
through a standard file is provided.
|
||||
|
||||
This module improves the bank statement and allows you to import your bank
|
||||
transactions with a standard .csv or .xls file (you'll find it in the 'data'
|
||||
folder). It respects the profile (provided by the accouhnt_statement_ext
|
||||
module) to pass the entries. That means, you'll have to choose a file format
|
||||
for each profile.
|
||||
In order to achieve this it uses the `xlrd` Python module which you will need
|
||||
to install separately in your environment.
|
||||
|
||||
This module can handle a commission taken by the payment office and has the
|
||||
following format:
|
||||
|
||||
* __ref__: the SO number, INV number or any matching ref found. It'll be used
|
||||
as reference in the generated entries and will be useful for reconciliation
|
||||
process
|
||||
* __date__: date of the payment
|
||||
* __amount__: amount paid in the currency of the journal used in the
|
||||
importation profile
|
||||
* __label__: the comunication given by the payment office, used as
|
||||
communication in the generated entries.
|
||||
|
||||
The goal is here to populate the statement lines of a bank statement with the
|
||||
infos that the bank or office give you. Fell free to inherit from this module
|
||||
to add your own format. Then, if you need to complete data from there, add
|
||||
your own account_statement_*_completion module and implement the needed rules.
|
||||
""",
|
||||
'website': 'http://www.camptocamp.com',
|
||||
'data': [
|
||||
"wizard/import_statement_view.xml",
|
||||
"statement_view.xml",
|
||||
],
|
||||
'test': [],
|
||||
'installable': False,
|
||||
'images': [],
|
||||
'auto_install': False,
|
||||
'license': 'AGPL-3',
|
||||
}
|
||||
4
account_statement_base_import/data/statement.csv
Normal file
4
account_statement_base_import/data/statement.csv
Normal file
@@ -0,0 +1,4 @@
|
||||
"ref";"date";"amount";"commission_amount";"label"
|
||||
50969286;2011-03-07 13:45:14;118.4;-11.84;"label a"
|
||||
51065326;2011-03-02 13:45:14;189;-15.12;"label b"
|
||||
51179306;2011-03-02 17:45:14;189;-15.12;"label c"
|
||||
|
BIN
account_statement_base_import/data/statement.xls
Normal file
BIN
account_statement_base_import/data/statement.xls
Normal file
Binary file not shown.
@@ -0,0 +1,289 @@
|
||||
# Translation of OpenERP Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * account_statement_base_import
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: OpenERP Server 7.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2014-01-21 11:58+0000\n"
|
||||
"PO-Revision-Date: 2014-01-21 11:58+0000\n"
|
||||
"Last-Translator: <>\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Plural-Forms: \n"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: view:credit.statement.import:0
|
||||
#: model:ir.actions.act_window,name:account_statement_base_import.statement_importer_action
|
||||
msgid "Import statement"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: view:account.statement.profile:0
|
||||
msgid "Historical Import Logs"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: model:ir.model,name:account_statement_base_import.model_credit_statement_import
|
||||
msgid "credit.statement.import"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: field:credit.statement.import,input_statement:0
|
||||
msgid "Statement file"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/statement.py:168
|
||||
#, python-format
|
||||
msgid "Column %s you try to import is not present in the bank statement line!"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/statement.py:162
|
||||
#, python-format
|
||||
msgid "Nothing to import"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: field:credit.statement.import,journal_id:0
|
||||
msgid "Financial journal to use transaction"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:108
|
||||
#, python-format
|
||||
msgid "Column %s not present in file"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: view:account.statement.profile:0
|
||||
#: model:ir.ui.menu,name:account_statement_base_import.statement_importer_menu
|
||||
msgid "Import Bank Statement"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:54
|
||||
#, python-format
|
||||
msgid "User Error"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/statement.py:223
|
||||
#, python-format
|
||||
msgid "The statement cannot be created: %s"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/statement.py:167
|
||||
#, python-format
|
||||
msgid "Missing column!"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/parser.py:150
|
||||
#, python-format
|
||||
msgid "No buffer file given."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:107
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:171
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:205
|
||||
#, python-format
|
||||
msgid "Invalid data"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: field:account.statement.profile,launch_import_completion:0
|
||||
msgid "Launch completion after import"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: field:credit.statement.import,partner_id:0
|
||||
msgid "Credit insitute partner"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: view:account.statement.profile:0
|
||||
msgid "Import related infos"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/statement.py:163
|
||||
#, python-format
|
||||
msgid "The file is empty"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/wizard/import_statement.py:90
|
||||
#, python-format
|
||||
msgid "Please use a file with an extention"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:172
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:206
|
||||
#, python-format
|
||||
msgid "Value %s of column %s is not valid.\n"
|
||||
" Please check the line with ref %s:\n"
|
||||
" \n"
|
||||
" Detail: %s"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:29
|
||||
#: code:addons/account_statement_base_import/parser/generic_file_parser.py:30
|
||||
#, python-format
|
||||
msgid "Please install python lib xlrd"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:160
|
||||
#, python-format
|
||||
msgid " It should be YYYY-MM-DD for column: %s value: %s \n"
|
||||
" \n"
|
||||
" \n"
|
||||
" Please check the line with ref: %s \n"
|
||||
" \n"
|
||||
" Detail: %s"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: field:account.statement.profile,last_import_date:0
|
||||
msgid "Last Import Date"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: model:ir.model,name:account_statement_base_import.model_account_statement_profile
|
||||
msgid "Statement Profile"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/statement.py:222
|
||||
#, python-format
|
||||
msgid "Statement import error"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:193
|
||||
#, python-format
|
||||
msgid "Please modify the cell formatting to date format for column: %s value: %s\n"
|
||||
" Please check the line with ref: %s\n"
|
||||
" \n"
|
||||
" Detail: %s"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:192
|
||||
#, python-format
|
||||
msgid "Date format is not valid"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: field:account.statement.profile,import_type:0
|
||||
msgid "Type of import"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: help:account.statement.profile,launch_import_completion:0
|
||||
msgid "Tic that box to automatically launch the completion on each imported file using this profile."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: help:credit.statement.import,balance_check:0
|
||||
msgid "Tic that box if you want OpenERP to control the start/end balance before confirming a bank statement. If don't ticked, no balance control will be done."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/statement.py:154
|
||||
#, python-format
|
||||
msgid "No Profile!"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:159
|
||||
#, python-format
|
||||
msgid "Date format is not valid."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: field:credit.statement.import,profile_id:0
|
||||
msgid "Import configuration parameter"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: field:account.statement.profile,rec_log:0
|
||||
msgid "log"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: view:credit.statement.import:0
|
||||
msgid "Import Parameters Summary"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: field:credit.statement.import,balance_check:0
|
||||
msgid "Balance check"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: field:credit.statement.import,force_partner_on_bank:0
|
||||
msgid "Force partner on bank move"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: field:credit.statement.import,file_name:0
|
||||
msgid "File Name"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:55
|
||||
#, python-format
|
||||
msgid "Invalid file type %s. Please use csv or xls"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/statement.py:155
|
||||
#, python-format
|
||||
msgid "You must provide a valid profile to import a bank statement!"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/statement.py:83
|
||||
#, python-format
|
||||
msgid "Statement ID %s have been imported with %s lines."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: field:credit.statement.import,receivable_account_id:0
|
||||
msgid "Force Receivable/Payable Account"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:164
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:174
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:198
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:208
|
||||
#, python-format
|
||||
msgid "Missing"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: help:account.statement.profile,import_type:0
|
||||
msgid "Choose here the method by which you want to import bank statement for this profile."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: view:credit.statement.import:0
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: help:credit.statement.import,force_partner_on_bank:0
|
||||
msgid "Tic that box if you want to use the credit insitute partner in the counterpart of the treasury/banking move."
|
||||
msgstr ""
|
||||
|
||||
329
account_statement_base_import/i18n/es.po
Normal file
329
account_statement_base_import/i18n/es.po
Normal file
@@ -0,0 +1,329 @@
|
||||
# Spanish translation for banking-addons
|
||||
# Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014
|
||||
# This file is distributed under the same license as the banking-addons package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2014.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: banking-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2014-01-21 11:58+0000\n"
|
||||
"PO-Revision-Date: 2014-06-05 22:11+0000\n"
|
||||
"Last-Translator: Pedro Manuel Baeza <pedro.baeza@gmail.com>\n"
|
||||
"Language-Team: Spanish <es@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2014-06-06 06:36+0000\n"
|
||||
"X-Generator: Launchpad (build 17031)\n"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: view:credit.statement.import:0
|
||||
#: model:ir.actions.act_window,name:account_statement_base_import.statement_importer_action
|
||||
msgid "Import statement"
|
||||
msgstr "Importar extracto"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: view:account.statement.profile:0
|
||||
msgid "Historical Import Logs"
|
||||
msgstr "Registro histórico de importaciones"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: model:ir.model,name:account_statement_base_import.model_credit_statement_import
|
||||
msgid "credit.statement.import"
|
||||
msgstr "credit.statement.import"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: field:credit.statement.import,input_statement:0
|
||||
msgid "Statement file"
|
||||
msgstr "Archivo de extracto"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/statement.py:168
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Column %s you try to import is not present in the bank statement line!"
|
||||
msgstr ""
|
||||
"La columna %s que intenta importar no está presente en la línea del extracto "
|
||||
"bancario."
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/statement.py:162
|
||||
#, python-format
|
||||
msgid "Nothing to import"
|
||||
msgstr "Nada que importar"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: field:credit.statement.import,journal_id:0
|
||||
msgid "Financial journal to use transaction"
|
||||
msgstr "Diario contable a usar"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:102
|
||||
#, python-format
|
||||
msgid "Column %s not present in file"
|
||||
msgstr "La columna %s no está presente en el archivo"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: view:account.statement.profile:0
|
||||
#: model:ir.ui.menu,name:account_statement_base_import.statement_importer_menu
|
||||
msgid "Import Bank Statement"
|
||||
msgstr "Importar extracto bancario"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:54
|
||||
#, python-format
|
||||
msgid "User Error"
|
||||
msgstr "Error de usuario"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/statement.py:223
|
||||
#, python-format
|
||||
msgid "The statement cannot be created: %s"
|
||||
msgstr "El extracto no puede ser creado: %s"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/statement.py:167
|
||||
#, python-format
|
||||
msgid "Missing column!"
|
||||
msgstr "Columna ausente"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/parser.py:166
|
||||
#, python-format
|
||||
msgid "No buffer file given."
|
||||
msgstr "No se ha proporcionado ningún búfer de archivo."
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:107
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:171
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:205
|
||||
#, python-format
|
||||
msgid "Invalid data"
|
||||
msgstr "Datos inválidos"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: field:account.statement.profile,launch_import_completion:0
|
||||
msgid "Launch completion after import"
|
||||
msgstr "Lanzar el completado después de la importación"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: field:credit.statement.import,partner_id:0
|
||||
msgid "Credit insitute partner"
|
||||
msgstr "Empresa para el agente financiero"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: view:account.statement.profile:0
|
||||
msgid "Import related infos"
|
||||
msgstr "Importar información relacionada"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/statement.py:163
|
||||
#, python-format
|
||||
msgid "The file is empty"
|
||||
msgstr "El archivo está vacío"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/wizard/import_statement.py:93
|
||||
#, python-format
|
||||
msgid "Please use a file with an extention"
|
||||
msgstr "Use por favor un archivo con extensión"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:172
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:206
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Value %s of column %s is not valid.\n"
|
||||
" Please check the line with ref %s:\n"
|
||||
" \n"
|
||||
" Detail: %s"
|
||||
msgstr ""
|
||||
"El valor %s de la columna %s no es válido.\n"
|
||||
"\n"
|
||||
"Compruebe por favor la línea con referencia %s\n"
|
||||
" \n"
|
||||
"Detalles: %s"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:29
|
||||
#: code:addons/account_statement_base_import/parser/generic_file_parser.py:31
|
||||
#, python-format
|
||||
msgid "Please install python lib xlrd"
|
||||
msgstr "Por favor instale la librería de Python xlrd"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:160
|
||||
#, python-format
|
||||
msgid ""
|
||||
" It should be YYYY-MM-DD for column: %s value: %s \n"
|
||||
" \n"
|
||||
" \n"
|
||||
" Please check the line with ref: %s \n"
|
||||
" \n"
|
||||
" Detail: %s"
|
||||
msgstr ""
|
||||
" La columna %s debería tener el formato YYYY-MM-DD y es: %s \n"
|
||||
" \n"
|
||||
"Compruebe por favor la línea con referencia %s \n"
|
||||
" \n"
|
||||
"Detalles: %s"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: field:account.statement.profile,last_import_date:0
|
||||
msgid "Last Import Date"
|
||||
msgstr "Última fecha de importación"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: model:ir.model,name:account_statement_base_import.model_account_statement_profile
|
||||
msgid "Statement Profile"
|
||||
msgstr "Perfil de extracto"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/statement.py:234
|
||||
#, python-format
|
||||
msgid "Statement import error"
|
||||
msgstr "Error de importación del extracto"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:193
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Please modify the cell formatting to date format for column: %s value: %s\n"
|
||||
" Please check the line with ref: %s\n"
|
||||
" \n"
|
||||
" Detail: %s"
|
||||
msgstr ""
|
||||
"Modifique el formato de fecha para la columna %s. Valor: %s\n"
|
||||
"\n"
|
||||
"Compruebe por favor la línea con referencia: %s\n"
|
||||
" \n"
|
||||
"Detalles: %s"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:192
|
||||
#, python-format
|
||||
msgid "Date format is not valid"
|
||||
msgstr "El formato de fecha no es válido"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: field:account.statement.profile,import_type:0
|
||||
msgid "Type of import"
|
||||
msgstr "Tipo de importación"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: help:account.statement.profile,launch_import_completion:0
|
||||
msgid ""
|
||||
"Tic that box to automatically launch the completion on each imported file "
|
||||
"using this profile."
|
||||
msgstr ""
|
||||
"Marque esta casilla para lanzar automáticamente el completado en cada "
|
||||
"archivo importado usando este perfil."
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: help:credit.statement.import,balance_check:0
|
||||
msgid ""
|
||||
"Tic that box if you want OpenERP to control the start/end balance before "
|
||||
"confirming a bank statement. If don't ticked, no balance control will be "
|
||||
"done."
|
||||
msgstr ""
|
||||
"Marque esta casilla si quiere que el sistema controle el saldo inicial/final "
|
||||
"antes de confirmar un extracto bancaria. Si no está marcada, no se realizará "
|
||||
"ningún control de saldo."
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/statement.py:154
|
||||
#, python-format
|
||||
msgid "No Profile!"
|
||||
msgstr "Sin perfil"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:159
|
||||
#, python-format
|
||||
msgid "Date format is not valid."
|
||||
msgstr "El formato de fecha no es válido."
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: field:credit.statement.import,profile_id:0
|
||||
msgid "Import configuration parameter"
|
||||
msgstr "Parámetros de configuración de la importación"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: field:account.statement.profile,rec_log:0
|
||||
msgid "log"
|
||||
msgstr "registro"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: view:credit.statement.import:0
|
||||
msgid "Import Parameters Summary"
|
||||
msgstr "Resumen de parámetros de importación"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: field:credit.statement.import,balance_check:0
|
||||
msgid "Balance check"
|
||||
msgstr "Comprobar saldo"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: field:credit.statement.import,force_partner_on_bank:0
|
||||
msgid "Force partner on bank move"
|
||||
msgstr "Forzar empresa en el apunte bancario"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: field:credit.statement.import,file_name:0
|
||||
msgid "File Name"
|
||||
msgstr "Nombre del archivo"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:55
|
||||
#, python-format
|
||||
msgid "Invalid file type %s. Please use csv or xls"
|
||||
msgstr "Tipo de archivo %s no válido. Utilice por favor CSV o XLS."
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/statement.py:155
|
||||
#, python-format
|
||||
msgid "You must provide a valid profile to import a bank statement!"
|
||||
msgstr "Debe introducir un perfil válido para importar un extracto bancario"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/statement.py:83
|
||||
#, python-format
|
||||
msgid "Statement ID %s have been imported with %s lines."
|
||||
msgstr "El extracto con ID %s ha sido importado con %s líneas."
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: field:credit.statement.import,receivable_account_id:0
|
||||
msgid "Force Receivable/Payable Account"
|
||||
msgstr "Forzar cuenta a cobrar/a pagar"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:164
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:174
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:198
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:208
|
||||
#, python-format
|
||||
msgid "Missing"
|
||||
msgstr "Ausente"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: help:account.statement.profile,import_type:0
|
||||
msgid ""
|
||||
"Choose here the method by which you want to import bank statement for this "
|
||||
"profile."
|
||||
msgstr ""
|
||||
"Escoja aquí el método con el que quiere importar el extracto bancario para "
|
||||
"este perfil."
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: view:credit.statement.import:0
|
||||
msgid "Cancel"
|
||||
msgstr "Cancelar"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: help:credit.statement.import,force_partner_on_bank:0
|
||||
msgid ""
|
||||
"Tic that box if you want to use the credit insitute partner in the "
|
||||
"counterpart of the treasury/banking move."
|
||||
msgstr ""
|
||||
"Marque esta casilla si quiere usar la empresa de su institución financiera "
|
||||
"en la contrapartida del movimiento de caja/banco."
|
||||
303
account_statement_base_import/i18n/fr.po
Normal file
303
account_statement_base_import/i18n/fr.po
Normal file
@@ -0,0 +1,303 @@
|
||||
# French translation for banking-addons
|
||||
# Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014
|
||||
# This file is distributed under the same license as the banking-addons package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2014.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: banking-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2014-01-21 11:58+0000\n"
|
||||
"PO-Revision-Date: 2014-03-21 15:17+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: French <fr@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2014-05-22 06:49+0000\n"
|
||||
"X-Generator: Launchpad (build 17017)\n"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: view:credit.statement.import:0
|
||||
#: model:ir.actions.act_window,name:account_statement_base_import.statement_importer_action
|
||||
msgid "Import statement"
|
||||
msgstr "Import de relevé"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: view:account.statement.profile:0
|
||||
msgid "Historical Import Logs"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: model:ir.model,name:account_statement_base_import.model_credit_statement_import
|
||||
msgid "credit.statement.import"
|
||||
msgstr "credit.statement.import"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: field:credit.statement.import,input_statement:0
|
||||
msgid "Statement file"
|
||||
msgstr "Fichier à importer"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/statement.py:168
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Column %s you try to import is not present in the bank statement line!"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/statement.py:162
|
||||
#, python-format
|
||||
msgid "Nothing to import"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: field:credit.statement.import,journal_id:0
|
||||
msgid "Financial journal to use transaction"
|
||||
msgstr "Journal"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:102
|
||||
#, python-format
|
||||
msgid "Column %s not present in file"
|
||||
msgstr "Colonne %s non présente dans le fichier"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: view:account.statement.profile:0
|
||||
#: model:ir.ui.menu,name:account_statement_base_import.statement_importer_menu
|
||||
msgid "Import Bank Statement"
|
||||
msgstr "Importation de relevé"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:54
|
||||
#, python-format
|
||||
msgid "User Error"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/statement.py:223
|
||||
#, python-format
|
||||
msgid "The statement cannot be created: %s"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/statement.py:167
|
||||
#, python-format
|
||||
msgid "Missing column!"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/parser.py:166
|
||||
#, python-format
|
||||
msgid "No buffer file given."
|
||||
msgstr "Pas de fichier tampon donné."
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:107
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:171
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:205
|
||||
#, python-format
|
||||
msgid "Invalid data"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: field:account.statement.profile,launch_import_completion:0
|
||||
msgid "Launch completion after import"
|
||||
msgstr "Lancer l'auto-complétion après import"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: field:credit.statement.import,partner_id:0
|
||||
msgid "Credit insitute partner"
|
||||
msgstr "Organisme bancaire"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: view:account.statement.profile:0
|
||||
msgid "Import related infos"
|
||||
msgstr "Importation des informations liées"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/statement.py:163
|
||||
#, python-format
|
||||
msgid "The file is empty"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/wizard/import_statement.py:93
|
||||
#, python-format
|
||||
msgid "Please use a file with an extention"
|
||||
msgstr "Veuillez sélectionner un fichier avec une extension"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:172
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:206
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Value %s of column %s is not valid.\n"
|
||||
" Please check the line with ref %s:\n"
|
||||
" \n"
|
||||
" Detail: %s"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:29
|
||||
#: code:addons/account_statement_base_import/parser/generic_file_parser.py:31
|
||||
#, python-format
|
||||
msgid "Please install python lib xlrd"
|
||||
msgstr "Veuillez installer la bibliothèque python xlrd"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:160
|
||||
#, python-format
|
||||
msgid ""
|
||||
" It should be YYYY-MM-DD for column: %s value: %s \n"
|
||||
" \n"
|
||||
" \n"
|
||||
" Please check the line with ref: %s \n"
|
||||
" \n"
|
||||
" Detail: %s"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: field:account.statement.profile,last_import_date:0
|
||||
msgid "Last Import Date"
|
||||
msgstr "Date de dernier import"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: model:ir.model,name:account_statement_base_import.model_account_statement_profile
|
||||
msgid "Statement Profile"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/statement.py:234
|
||||
#, python-format
|
||||
msgid "Statement import error"
|
||||
msgstr "Erreur d'import de relevé"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:193
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Please modify the cell formatting to date format for column: %s value: %s\n"
|
||||
" Please check the line with ref: %s\n"
|
||||
" \n"
|
||||
" Detail: %s"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:192
|
||||
#, python-format
|
||||
msgid "Date format is not valid"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: field:account.statement.profile,import_type:0
|
||||
msgid "Type of import"
|
||||
msgstr "Type d'import"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: help:account.statement.profile,launch_import_completion:0
|
||||
msgid ""
|
||||
"Tic that box to automatically launch the completion on each imported file "
|
||||
"using this profile."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: help:credit.statement.import,balance_check:0
|
||||
msgid ""
|
||||
"Tic that box if you want OpenERP to control the start/end balance before "
|
||||
"confirming a bank statement. If don't ticked, no balance control will be "
|
||||
"done."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/statement.py:154
|
||||
#, python-format
|
||||
msgid "No Profile!"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:159
|
||||
#, python-format
|
||||
msgid "Date format is not valid."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: field:credit.statement.import,profile_id:0
|
||||
msgid "Import configuration parameter"
|
||||
msgstr "Paramètres de configuration d'import"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: field:account.statement.profile,rec_log:0
|
||||
msgid "log"
|
||||
msgstr "journal"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: view:credit.statement.import:0
|
||||
msgid "Import Parameters Summary"
|
||||
msgstr "Résumé des paramètres d'import"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: field:credit.statement.import,balance_check:0
|
||||
msgid "Balance check"
|
||||
msgstr "Vérification des soldes"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: field:credit.statement.import,force_partner_on_bank:0
|
||||
msgid "Force partner on bank move"
|
||||
msgstr "Forcer un partenaire sur la ligne du compte de banque"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: field:credit.statement.import,file_name:0
|
||||
msgid "File Name"
|
||||
msgstr "Nom du fichier"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:55
|
||||
#, python-format
|
||||
msgid "Invalid file type %s. Please use csv or xls"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/statement.py:155
|
||||
#, python-format
|
||||
msgid "You must provide a valid profile to import a bank statement!"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/statement.py:83
|
||||
#, python-format
|
||||
msgid "Statement ID %s have been imported with %s lines."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: field:credit.statement.import,receivable_account_id:0
|
||||
msgid "Force Receivable/Payable Account"
|
||||
msgstr "Forcer le compte Client/Fournisseur"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:164
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:174
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:198
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:208
|
||||
#, python-format
|
||||
msgid "Missing"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: help:account.statement.profile,import_type:0
|
||||
msgid ""
|
||||
"Choose here the method by which you want to import bank statement for this "
|
||||
"profile."
|
||||
msgstr "Choisissez la méthode d'import de relevé pour ce profil."
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: view:credit.statement.import:0
|
||||
msgid "Cancel"
|
||||
msgstr "Annulation"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: help:credit.statement.import,force_partner_on_bank:0
|
||||
msgid ""
|
||||
"Tic that box if you want to use the credit insitute partner in the "
|
||||
"counterpart of the treasury/banking move."
|
||||
msgstr ""
|
||||
25
account_statement_base_import/parser/__init__.py
Normal file
25
account_statement_base_import/parser/__init__.py
Normal file
@@ -0,0 +1,25 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Nicolas Bessi, Joel Grand-Guillaume
|
||||
# Copyright 2011-2012 Camptocamp 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/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from .parser import new_bank_statement_parser
|
||||
from .parser import BankStatementImportParser
|
||||
from . import file_parser
|
||||
from . import generic_file_parser
|
||||
203
account_statement_base_import/parser/file_parser.py
Normal file
203
account_statement_base_import/parser/file_parser.py
Normal file
@@ -0,0 +1,203 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright Camptocamp SA
|
||||
# Author Nicolas Bessi, Joel Grand-Guillaume
|
||||
# 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 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
from openerp.tools.translate import _
|
||||
from openerp.osv.orm import except_orm
|
||||
import tempfile
|
||||
import datetime
|
||||
from .parser import BankStatementImportParser
|
||||
from .parser import UnicodeDictReader
|
||||
try:
|
||||
import xlrd
|
||||
except:
|
||||
raise Exception(_('Please install python lib xlrd'))
|
||||
|
||||
|
||||
def float_or_zero(val):
|
||||
""" Conversion function used to manage
|
||||
empty string into float usecase"""
|
||||
return float(val) if val else 0.0
|
||||
|
||||
|
||||
class FileParser(BankStatementImportParser):
|
||||
"""Generic abstract class for defining parser for .csv, .xls or .xlsx file
|
||||
format.
|
||||
"""
|
||||
|
||||
def __init__(self, parse_name, ftype='csv', extra_fields=None, header=None,
|
||||
dialect=None, **kwargs):
|
||||
"""
|
||||
:param char: parse_name: The name of the parser
|
||||
:param char: ftype: extension of the file (could be csv, xls or
|
||||
xlsx)
|
||||
:param dict: extra_fields: extra fields to put into the conversion
|
||||
dict. In the format {fieldname: fieldtype}
|
||||
:param list: header : specify header fields if the csv file has no
|
||||
header
|
||||
"""
|
||||
super(FileParser, self).__init__(parse_name, **kwargs)
|
||||
if ftype in ('csv', 'xls', 'xlsx'):
|
||||
self.ftype = ftype[0:3]
|
||||
else:
|
||||
raise except_orm(
|
||||
_('User Error'),
|
||||
_('Invalid file type %s. Please use csv, xls or xlsx') % ftype)
|
||||
self.conversion_dict = extra_fields
|
||||
self.keys_to_validate = self.conversion_dict.keys()
|
||||
self.fieldnames = header
|
||||
self._datemode = 0 # used only for xls documents,
|
||||
# 0 means Windows mode (1900 based dates).
|
||||
# Set in _parse_xls, from the contents of the file
|
||||
self.dialect = dialect
|
||||
|
||||
def _custom_format(self, *args, **kwargs):
|
||||
"""No other work on data are needed in this parser."""
|
||||
return True
|
||||
|
||||
def _pre(self, *args, **kwargs):
|
||||
"""No pre-treatment needed for this parser."""
|
||||
return True
|
||||
|
||||
def _parse(self, *args, **kwargs):
|
||||
"""Launch the parsing through .csv, .xls or .xlsx depending on the
|
||||
given ftype
|
||||
"""
|
||||
res = None
|
||||
if self.ftype == 'csv':
|
||||
res = self._parse_csv()
|
||||
else:
|
||||
res = self._parse_xls()
|
||||
self.result_row_list = res
|
||||
return True
|
||||
|
||||
def _validate(self, *args, **kwargs):
|
||||
"""We check that all the key of the given file (means header) are
|
||||
present in the validation key provided. Otherwise, we raise an
|
||||
Exception. We skip the validation step if the file header is provided
|
||||
separately (in the field: fieldnames).
|
||||
"""
|
||||
if self.fieldnames is None:
|
||||
parsed_cols = self.result_row_list[0].keys()
|
||||
for col in self.keys_to_validate:
|
||||
if col not in parsed_cols:
|
||||
raise except_orm(_('Invalid data'),
|
||||
_('Column %s not present in file') % col)
|
||||
return True
|
||||
|
||||
def _post(self, *args, **kwargs):
|
||||
"""Cast row type depending on the file format .csv or .xls after
|
||||
parsing the file."""
|
||||
self.result_row_list = self._cast_rows(*args, **kwargs)
|
||||
return True
|
||||
|
||||
def _parse_csv(self):
|
||||
""":return: list of dict from csv file (line/rows)"""
|
||||
csv_file = tempfile.NamedTemporaryFile()
|
||||
csv_file.write(self.filebuffer)
|
||||
csv_file.flush()
|
||||
with open(csv_file.name, 'rU') as fobj:
|
||||
reader = UnicodeDictReader(fobj, fieldnames=self.fieldnames,
|
||||
dialect=self.dialect)
|
||||
return list(reader)
|
||||
|
||||
def _parse_xls(self):
|
||||
""":return: dict of dict from xls/xlsx file (line/rows)"""
|
||||
wb_file = tempfile.NamedTemporaryFile()
|
||||
wb_file.write(self.filebuffer)
|
||||
# We ensure that cursor is at beginig of file
|
||||
wb_file.seek(0)
|
||||
with xlrd.open_workbook(wb_file.name) as wb:
|
||||
self._datemode = wb.datemode
|
||||
sheet = wb.sheet_by_index(0)
|
||||
header = sheet.row_values(0)
|
||||
res = []
|
||||
for rownum in range(1, sheet.nrows):
|
||||
res.append(dict(zip(header, sheet.row_values(rownum))))
|
||||
return res
|
||||
|
||||
def _from_csv(self, result_set, conversion_rules):
|
||||
"""Handle the converstion from the dict and handle date format from
|
||||
an .csv file.
|
||||
"""
|
||||
for line in result_set:
|
||||
for rule in conversion_rules:
|
||||
if conversion_rules[rule] == datetime.datetime:
|
||||
try:
|
||||
date_string = line[rule].split(' ')[0]
|
||||
line[rule] = datetime.datetime.strptime(date_string,
|
||||
'%Y-%m-%d')
|
||||
except ValueError as err:
|
||||
raise except_orm(
|
||||
_("Date format is not valid."),
|
||||
_(" It should be YYYY-MM-DD for column: %s"
|
||||
" value: %s \n \n \n Please check the line with "
|
||||
"ref: %s \n \n Detail: %s") %
|
||||
(rule, line.get(rule, _('Missing')),
|
||||
line.get('ref', line), repr(err)))
|
||||
else:
|
||||
try:
|
||||
line[rule] = conversion_rules[rule](line[rule])
|
||||
except Exception as err:
|
||||
raise except_orm(
|
||||
_('Invalid data'),
|
||||
_("Value %s of column %s is not valid.\n Please "
|
||||
"check the line with ref %s:\n \n Detail: %s") %
|
||||
(line.get(rule, _('Missing')), rule,
|
||||
line.get('ref', line), repr(err)))
|
||||
return result_set
|
||||
|
||||
def _from_xls(self, result_set, conversion_rules):
|
||||
"""Handle the converstion from the dict and handle date format from
|
||||
an .csv, .xls or .xlsx file.
|
||||
"""
|
||||
for line in result_set:
|
||||
for rule in conversion_rules:
|
||||
if conversion_rules[rule] == datetime.datetime:
|
||||
try:
|
||||
t_tuple = xlrd.xldate_as_tuple(line[rule],
|
||||
self._datemode)
|
||||
line[rule] = datetime.datetime(*t_tuple)
|
||||
except Exception as err:
|
||||
raise except_orm(
|
||||
_("Date format is not valid"),
|
||||
_("Please modify the cell formatting to date "
|
||||
"format for column: %s value: %s\n Please check "
|
||||
"the line with ref: %s\n \n Detail: %s") %
|
||||
(rule, line.get(rule, _('Missing')),
|
||||
line.get('ref', line), repr(err)))
|
||||
else:
|
||||
try:
|
||||
line[rule] = conversion_rules[rule](line[rule])
|
||||
except Exception as err:
|
||||
raise except_orm(
|
||||
_('Invalid data'),
|
||||
_("Value %s of column %s is not valid.\n Please "
|
||||
"check the line with ref %s:\n \n Detail: %s") %
|
||||
(line.get(rule, _('Missing')), rule,
|
||||
line.get('ref', line), repr(err)))
|
||||
return result_set
|
||||
|
||||
def _cast_rows(self, *args, **kwargs):
|
||||
"""Convert the self.result_row_list using the self.conversion_dict
|
||||
providen. We call here _from_xls or _from_csv depending on the
|
||||
self.ftype variable.
|
||||
"""
|
||||
func = getattr(self, '_from_%s' % self.ftype)
|
||||
res = func(self.result_row_list, self.conversion_dict)
|
||||
return res
|
||||
79
account_statement_base_import/parser/generic_file_parser.py
Normal file
79
account_statement_base_import/parser/generic_file_parser.py
Normal file
@@ -0,0 +1,79 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright Camptocamp SA
|
||||
# Author Joel Grand-Guillaume
|
||||
# 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 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import datetime
|
||||
from .file_parser import FileParser
|
||||
from openerp.addons.account_statement_base_import.parser.file_parser import (
|
||||
float_or_zero
|
||||
)
|
||||
from openerp.tools import ustr
|
||||
|
||||
|
||||
class GenericFileParser(FileParser):
|
||||
"""Standard parser that use a define format in csv or xls to import into a
|
||||
bank statement. This is mostely an example of how to proceed to create a
|
||||
new parser, but will also be useful as it allow to import a basic flat
|
||||
file.
|
||||
"""
|
||||
|
||||
def __init__(self, parse_name, ftype='csv', **kwargs):
|
||||
conversion_dict = {
|
||||
'ref': ustr,
|
||||
'label': ustr,
|
||||
'date': datetime.datetime,
|
||||
'amount': float_or_zero,
|
||||
}
|
||||
super(GenericFileParser, self).__init__(
|
||||
parse_name, ftype=ftype,
|
||||
extra_fields=conversion_dict,
|
||||
**kwargs)
|
||||
|
||||
@classmethod
|
||||
def parser_for(cls, parser_name):
|
||||
"""Used by the new_bank_statement_parser class factory. Return true if
|
||||
the providen name is generic_csvxls_so
|
||||
"""
|
||||
return parser_name == 'generic_csvxls_so'
|
||||
|
||||
def get_st_line_vals(self, line, *args, **kwargs):
|
||||
"""
|
||||
This method must return a dict of vals that can be passed to create
|
||||
method of statement line in order to record it. It is the
|
||||
responsibility of every parser to give this dict of vals, so each one
|
||||
can implement his own way of recording the lines.
|
||||
:param: line: a dict of vals that represent a line of
|
||||
result_row_list
|
||||
:return: dict of values to give to the create method of statement
|
||||
line, it MUST contain at least:
|
||||
{
|
||||
'name':value,
|
||||
'date':value,
|
||||
'amount':value,
|
||||
'ref':value,
|
||||
'label':value,
|
||||
}
|
||||
"""
|
||||
return {
|
||||
'name': line.get('label', line.get('ref', '/')),
|
||||
'date': line.get('date', datetime.datetime.now().date()),
|
||||
'amount': line.get('amount', 0.0),
|
||||
'ref': line.get('ref', '/'),
|
||||
'label': line.get('label', ''),
|
||||
}
|
||||
230
account_statement_base_import/parser/parser.py
Normal file
230
account_statement_base_import/parser/parser.py
Normal file
@@ -0,0 +1,230 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Joel Grand-Guillaume
|
||||
# Copyright 2011-2012 Camptocamp 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 csv
|
||||
from datetime import datetime
|
||||
from openerp.tools.translate import _
|
||||
|
||||
|
||||
def UnicodeDictReader(utf8_data, **kwargs):
|
||||
sniffer = csv.Sniffer()
|
||||
pos = utf8_data.tell()
|
||||
sample_data = utf8_data.read(2048)
|
||||
utf8_data.seek(pos)
|
||||
if not kwargs.get('dialect'):
|
||||
dialect = sniffer.sniff(sample_data, delimiters=',;\t')
|
||||
del kwargs['dialect']
|
||||
else:
|
||||
dialect = kwargs.pop('dialect')
|
||||
csv_reader = csv.DictReader(utf8_data, dialect=dialect, **kwargs)
|
||||
for row in csv_reader:
|
||||
yield dict([(unicode(key or '', 'utf-8'),
|
||||
unicode(value or '', 'utf-8'))
|
||||
for key, value in row.iteritems()])
|
||||
|
||||
|
||||
class BankStatementImportParser(object):
|
||||
|
||||
"""
|
||||
Generic abstract class for defining parser for different files and
|
||||
format to import in a bank statement. Inherit from it to create your
|
||||
own. If your file is a .csv or .xls format, you should consider inheirt
|
||||
from the FileParser instead.
|
||||
"""
|
||||
|
||||
def __init__(self, profile, *args, **kwargs):
|
||||
# The name of the parser as it will be called
|
||||
self.parser_name = profile.import_type
|
||||
# The result as a list of row. One row per line of data in the file,
|
||||
# but not the commission one!
|
||||
self.result_row_list = None
|
||||
# The file buffer on which to work on
|
||||
self.filebuffer = None
|
||||
# The profile record to access its parameters in any parser method
|
||||
self.profile = profile
|
||||
self.balance_start = None
|
||||
self.balance_end = None
|
||||
self.statement_name = None
|
||||
self.statement_date = None
|
||||
self.support_multi_statements = False
|
||||
|
||||
@classmethod
|
||||
def parser_for(cls, parser_name):
|
||||
"""Override this method for every new parser, so that
|
||||
new_bank_statement_parser can return the good class from his name.
|
||||
"""
|
||||
return False
|
||||
|
||||
def _decode_64b_stream(self):
|
||||
"""Decode self.filebuffer in base 64 and override it"""
|
||||
self.filebuffer = base64.b64decode(self.filebuffer)
|
||||
return True
|
||||
|
||||
def _format(self, decode_base_64=True, **kwargs):
|
||||
"""Decode into base 64 if asked and Format the given filebuffer by
|
||||
calling _custom_format method.
|
||||
"""
|
||||
if decode_base_64:
|
||||
self._decode_64b_stream()
|
||||
self._custom_format(kwargs)
|
||||
return True
|
||||
|
||||
def _custom_format(self, *args, **kwargs):
|
||||
"""Implement a method in your parser to convert format, encoding and so
|
||||
on before starting to work on datas. Work on self.filebuffer
|
||||
"""
|
||||
return NotImplementedError
|
||||
|
||||
def _pre(self, *args, **kwargs):
|
||||
"""Implement a method in your parser to make a pre-treatment on datas
|
||||
before parsing them, like concatenate stuff, and so... Work on
|
||||
self.filebuffer
|
||||
"""
|
||||
return NotImplementedError
|
||||
|
||||
def _parse(self, *args, **kwargs):
|
||||
"""Implement a method in your parser to save the result of parsing
|
||||
self.filebuffer in self.result_row_list instance property.
|
||||
"""
|
||||
return NotImplementedError
|
||||
|
||||
def _validate(self, *args, **kwargs):
|
||||
"""Implement a method in your parser to validate the
|
||||
self.result_row_list instance property and raise an error if not valid.
|
||||
"""
|
||||
return NotImplementedError
|
||||
|
||||
def _post(self, *args, **kwargs):
|
||||
"""Implement a method in your parser to make some last changes on the
|
||||
result of parsing the datas, like converting dates, computing
|
||||
commission, ...
|
||||
"""
|
||||
return NotImplementedError
|
||||
|
||||
def get_st_vals(self):
|
||||
"""This method return a dict of vals that ca be passed to create method
|
||||
of statement.
|
||||
:return: dict of vals that represent additional infos for the statement
|
||||
"""
|
||||
return {
|
||||
'name': self.statement_name or '/',
|
||||
'balance_start': self.balance_start,
|
||||
'balance_end_real': self.balance_end,
|
||||
'date': self.statement_date or datetime.now()
|
||||
}
|
||||
|
||||
def get_st_line_vals(self, line, *args, **kwargs):
|
||||
"""Implement a method in your parser that must return a dict of vals
|
||||
that can be passed to create method of statement line in order to
|
||||
record it. It is the responsibility of every parser to give this dict
|
||||
of vals, so each one can implement his own way of recording the lines.
|
||||
|
||||
:param: line: a dict of vals that represent a line of result_row_list
|
||||
:return: dict of values to give to the create method of statement line,
|
||||
it MUST contain at least:
|
||||
{
|
||||
'name':value,
|
||||
'date':value,
|
||||
'amount':value,
|
||||
'ref':value,
|
||||
}
|
||||
"""
|
||||
return NotImplementedError
|
||||
|
||||
def parse(self, filebuffer, *args, **kwargs):
|
||||
"""This will be the method that will be called by wizard, button and so
|
||||
to parse a filebuffer by calling successively all the private method
|
||||
that need to be define for each parser.
|
||||
Return:
|
||||
[] of rows as {'key':value}
|
||||
|
||||
Note: The row_list must contain only value that are present in the
|
||||
account.bank.statement.line object !!!
|
||||
"""
|
||||
if filebuffer:
|
||||
self.filebuffer = filebuffer
|
||||
else:
|
||||
raise Exception(_('No buffer file given.'))
|
||||
self._format(*args, **kwargs)
|
||||
self._pre(*args, **kwargs)
|
||||
if self.support_multi_statements:
|
||||
while self._parse(*args, **kwargs):
|
||||
self._validate(*args, **kwargs)
|
||||
self._post(*args, **kwargs)
|
||||
yield self.result_row_list
|
||||
else:
|
||||
self._parse(*args, **kwargs)
|
||||
self._validate(*args, **kwargs)
|
||||
self._post(*args, **kwargs)
|
||||
yield self.result_row_list
|
||||
|
||||
|
||||
def itersubclasses(cls, _seen=None):
|
||||
"""
|
||||
itersubclasses(cls)
|
||||
|
||||
Generator over all subclasses of a given class, in depth first order.
|
||||
|
||||
>>> list(itersubclasses(int)) == [bool]
|
||||
True
|
||||
>>> class A(object): pass
|
||||
>>> class B(A): pass
|
||||
>>> class C(A): pass
|
||||
>>> class D(B,C): pass
|
||||
>>> class E(D): pass
|
||||
>>>
|
||||
>>> for cls in itersubclasses(A):
|
||||
... print(cls.__name__)
|
||||
B
|
||||
D
|
||||
E
|
||||
C
|
||||
>>> # get ALL (new-style) classes currently defined
|
||||
>>> [cls.__name__ for cls in itersubclasses(object)] #doctest: +ELLIPSIS
|
||||
['type', ...'tuple', ...]
|
||||
"""
|
||||
if not isinstance(cls, type):
|
||||
raise TypeError('itersubclasses must be called with '
|
||||
'new-style classes, not %.100r' % cls)
|
||||
if _seen is None:
|
||||
_seen = set()
|
||||
try:
|
||||
subs = cls.__subclasses__()
|
||||
except TypeError: # fails only when cls is type
|
||||
subs = cls.__subclasses__(cls)
|
||||
for sub in subs:
|
||||
if sub not in _seen:
|
||||
_seen.add(sub)
|
||||
yield sub
|
||||
for sub in itersubclasses(sub, _seen):
|
||||
yield sub
|
||||
|
||||
|
||||
def new_bank_statement_parser(profile, *args, **kwargs):
|
||||
"""Return an instance of the good parser class based on the given profile.
|
||||
|
||||
:param profile: browse_record of import profile.
|
||||
:return: class instance for given profile import type.
|
||||
"""
|
||||
for cls in itersubclasses(BankStatementImportParser):
|
||||
if cls.parser_for(profile.import_type):
|
||||
return cls(profile, *args, **kwargs)
|
||||
raise ValueError
|
||||
255
account_statement_base_import/statement.py
Normal file
255
account_statement_base_import/statement.py
Normal file
@@ -0,0 +1,255 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Joel Grand-Guillaume
|
||||
# Copyright 2011-2012 Camptocamp 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 sys
|
||||
import traceback
|
||||
from openerp.tools.translate import _
|
||||
import datetime
|
||||
from openerp.osv import fields, orm
|
||||
from .parser import new_bank_statement_parser
|
||||
from openerp.tools.config import config
|
||||
|
||||
|
||||
class AccountStatementProfil(orm.Model):
|
||||
_inherit = "account.statement.profile"
|
||||
|
||||
def _get_import_type_selection(self, cr, uid, context=None):
|
||||
"""This is the method to be inherited for adding the parser"""
|
||||
return [('generic_csvxls_so', 'Generic .csv/.xls based on SO Name')]
|
||||
|
||||
def __get_import_type_selection(self, cr, uid, context=None):
|
||||
""" Call method which can be inherited """
|
||||
return self._get_import_type_selection(cr, uid, context=context)
|
||||
|
||||
_columns = {
|
||||
'launch_import_completion': fields.boolean(
|
||||
"Launch completion after import",
|
||||
help="Tic that box to automatically launch the completion "
|
||||
"on each imported file using this profile."),
|
||||
'last_import_date': fields.datetime("Last Import Date"),
|
||||
# we remove deprecated as it floods logs in standard/warning level
|
||||
# sob...
|
||||
'rec_log': fields.text('log', readonly=True), # Deprecated
|
||||
'import_type': fields.selection(
|
||||
__get_import_type_selection,
|
||||
'Type of import',
|
||||
required=True,
|
||||
help="Choose here the method by which you want to import bank"
|
||||
"statement for this profile."),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'import_type': 'generic_csvxls_so'
|
||||
}
|
||||
|
||||
def _write_extra_statement_lines(
|
||||
self, cr, uid, parser, result_row_list, profile, statement_id,
|
||||
context):
|
||||
"""Insert extra lines after the main statement lines.
|
||||
|
||||
After the main statement lines have been created, you can override this
|
||||
method to create extra statement lines.
|
||||
|
||||
:param: browse_record of the current parser
|
||||
:param: result_row_list: [{'key':value}]
|
||||
:param: profile: browserecord of account.statement.profile
|
||||
:param: statement_id: int/long of the current importing
|
||||
statement ID
|
||||
:param: context: global context
|
||||
"""
|
||||
|
||||
def write_logs_after_import(self, cr, uid, ids, statement_id, num_lines,
|
||||
context):
|
||||
"""Write the log in the logger
|
||||
|
||||
:param int/long statement_id: ID of the concerned
|
||||
account.bank.statement
|
||||
:param int/long num_lines: Number of line that have been parsed
|
||||
:return: True
|
||||
"""
|
||||
self.message_post(
|
||||
cr, uid, ids,
|
||||
body=_('Statement ID %s have been imported with %s '
|
||||
'lines.') % (statement_id, num_lines), context=context)
|
||||
return True
|
||||
|
||||
# Deprecated remove on V8
|
||||
def prepare_statetement_lines_vals(self, *args, **kwargs):
|
||||
return self.prepare_statement_lines_vals(*args, **kwargs)
|
||||
|
||||
def prepare_statement_lines_vals(self, cr, uid, parser_vals,
|
||||
statement_id, context):
|
||||
"""Hook to build the values of a line from the parser returned values.
|
||||
At least it fullfill the statement_id. Overide it to add your own
|
||||
completion if needed.
|
||||
|
||||
:param dict of vals from parser for account.bank.statement.line
|
||||
(called by parser.get_st_line_vals)
|
||||
:param int/long statement_id: ID of the concerned
|
||||
account.bank.statement
|
||||
:return: dict of vals that will be passed to create method of
|
||||
statement line.
|
||||
"""
|
||||
statement_line_obj = self.pool['account.bank.statement.line']
|
||||
values = parser_vals
|
||||
values['statement_id'] = statement_id
|
||||
date = values.get('date')
|
||||
period_memoizer = context.get('period_memoizer')
|
||||
if not period_memoizer:
|
||||
period_memoizer = {}
|
||||
context['period_memoizer'] = period_memoizer
|
||||
if period_memoizer.get(date):
|
||||
values['period_id'] = period_memoizer[date]
|
||||
else:
|
||||
# This is awfully slow...
|
||||
periods = self.pool.get('account.period').find(
|
||||
cr, uid, dt=values.get('date'), context=context)
|
||||
values['period_id'] = periods[0]
|
||||
period_memoizer[date] = periods[0]
|
||||
values = statement_line_obj._add_missing_default_values(
|
||||
cr, uid, values, context)
|
||||
return values
|
||||
|
||||
def prepare_statement_vals(self, cr, uid, profile_id, result_row_list,
|
||||
parser, context=None):
|
||||
"""Hook to build the values of the statement from the parser and
|
||||
the profile.
|
||||
"""
|
||||
vals = {'profile_id': profile_id}
|
||||
vals.update(parser.get_st_vals())
|
||||
if vals.get('balance_start') is None:
|
||||
# Get starting balance from journal balance if parser doesn't
|
||||
# fill this data, simulating the manual flow
|
||||
statement_obj = self.pool['account.bank.statement']
|
||||
profile = self.browse(cr, uid, profile_id, context=context)
|
||||
temp = statement_obj.onchange_journal_id(
|
||||
cr, uid, None, profile.journal_id.id, context=context)
|
||||
vals['balance_start'] = temp['value'].get('balance_start', False)
|
||||
return vals
|
||||
|
||||
def multi_statement_import(self, cr, uid, ids, profile_id, file_stream,
|
||||
ftype="csv", context=None):
|
||||
"""Create multiple bank statements from values given by the parser for
|
||||
the given profile.
|
||||
|
||||
:param int/long profile_id: ID of the profile used to import the file
|
||||
:param filebuffer file_stream: binary of the providen file
|
||||
:param char: ftype represent the file exstension (csv by default)
|
||||
:return: list: list of ids of the created account.bank.statemênt
|
||||
"""
|
||||
prof_obj = self.pool['account.statement.profile']
|
||||
if not profile_id:
|
||||
raise orm.except_orm(
|
||||
_("No Profile!"),
|
||||
_("You must provide a valid profile to import a bank "
|
||||
"statement!"))
|
||||
prof = prof_obj.browse(cr, uid, profile_id, context=context)
|
||||
parser = new_bank_statement_parser(prof, ftype=ftype)
|
||||
res = []
|
||||
for result_row_list in parser.parse(file_stream):
|
||||
statement_id = self._statement_import(
|
||||
cr, uid, ids, prof, parser, file_stream, ftype=ftype,
|
||||
context=context)
|
||||
res.append(statement_id)
|
||||
return res
|
||||
|
||||
def _statement_import(self, cr, uid, ids, prof, parser, file_stream,
|
||||
ftype="csv", context=None):
|
||||
"""Create a bank statement with the given profile and parser. It will
|
||||
fullfill the bank statement with the values of the file providen, but
|
||||
will not complete data (like finding the partner, or the right
|
||||
account). This will be done in a second step with the completion rules.
|
||||
|
||||
:param prof : The profile used to import the file
|
||||
:param parser: the parser
|
||||
:param filebuffer file_stream: binary of the providen file
|
||||
:param char: ftype represent the file exstension (csv by default)
|
||||
:return: ID of the created account.bank.statemênt
|
||||
"""
|
||||
statement_obj = self.pool['account.bank.statement']
|
||||
statement_line_obj = self.pool['account.bank.statement.line']
|
||||
attachment_obj = self.pool['ir.attachment']
|
||||
result_row_list = parser.result_row_list
|
||||
# Check all key are present in account.bank.statement.line!!
|
||||
if not result_row_list:
|
||||
raise orm.except_orm(_("Nothing to import"),
|
||||
_("The file is empty"))
|
||||
parsed_cols = parser.get_st_line_vals(result_row_list[0]).keys()
|
||||
for col in parsed_cols:
|
||||
if col not in statement_line_obj._columns:
|
||||
raise orm.except_orm(
|
||||
_("Missing column!"),
|
||||
_("Column %s you try to import is not present in the bank "
|
||||
"statement line!") % col)
|
||||
statement_vals = self.prepare_statement_vals(
|
||||
cr, uid, prof.id, result_row_list, parser, context)
|
||||
statement_id = statement_obj.create(
|
||||
cr, uid, statement_vals, context=context)
|
||||
try:
|
||||
# Record every line in the bank statement
|
||||
statement_store = []
|
||||
for line in result_row_list:
|
||||
parser_vals = parser.get_st_line_vals(line)
|
||||
values = self.prepare_statement_lines_vals(
|
||||
cr, uid, parser_vals, statement_id,
|
||||
context)
|
||||
statement_store.append(values)
|
||||
# Hack to bypass ORM poor perfomance. Sob...
|
||||
statement_line_obj._insert_lines(
|
||||
cr, uid, statement_store, context=context)
|
||||
self._write_extra_statement_lines(
|
||||
cr, uid, parser, result_row_list, prof, statement_id, context)
|
||||
# Trigger store field computation if someone has better idea
|
||||
start_bal = statement_obj.read(
|
||||
cr, uid, statement_id, ['balance_start'], context=context)
|
||||
start_bal = start_bal['balance_start']
|
||||
statement_obj.write(
|
||||
cr, uid, [statement_id], {'balance_start': start_bal})
|
||||
attachment_data = {
|
||||
'name': 'statement file',
|
||||
'datas': file_stream,
|
||||
'datas_fname': "%s.%s" % (datetime.datetime.now().date(),
|
||||
ftype),
|
||||
'res_model': 'account.bank.statement',
|
||||
'res_id': statement_id,
|
||||
}
|
||||
attachment_obj.create(cr, uid, attachment_data, context=context)
|
||||
# If user ask to launch completion at end of import, do it!
|
||||
if prof.launch_import_completion:
|
||||
statement_obj.button_auto_completion(
|
||||
cr, uid, [statement_id], context)
|
||||
# Write the needed log infos on profile
|
||||
self.write_logs_after_import(cr, uid, prof.id,
|
||||
statement_id,
|
||||
len(result_row_list),
|
||||
context)
|
||||
except Exception:
|
||||
error_type, error_value, trbk = sys.exc_info()
|
||||
st = "Error: %s\nDescription: %s\nTraceback:" % (
|
||||
error_type.__name__, error_value)
|
||||
st += ''.join(traceback.format_tb(trbk, 30))
|
||||
# TODO we should catch correctly the exception with a python
|
||||
# Exception and only re-catch some special exception.
|
||||
# For now we avoid re-catching error in debug mode
|
||||
if config['debug_mode']:
|
||||
raise
|
||||
raise orm.except_orm(_("Statement import error"),
|
||||
_("The statement cannot be created: %s") % st)
|
||||
return statement_id
|
||||
45
account_statement_base_import/statement_view.xml
Normal file
45
account_statement_base_import/statement_view.xml
Normal file
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
|
||||
<record id="statement_importer_view_form" model="ir.ui.view">
|
||||
<field name="name">account.statement.profile.view</field>
|
||||
<field name="model">account.statement.profile</field>
|
||||
<field name="inherit_id" ref="account_statement_ext.statement_importer_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="bank_statement_prefix" position="after">
|
||||
<separator colspan="4" string="Import related infos"/>
|
||||
<field name="launch_import_completion"/>
|
||||
<field name="last_import_date"/>
|
||||
<field name="import_type"/>
|
||||
<button name="%(account_statement_base_import.statement_importer_action)d"
|
||||
string="Import Bank Statement"
|
||||
type="action" icon="gtk-ok"
|
||||
colspan = "2"/>
|
||||
<group attrs="{'invisible': [('rec_log', '=', False)]}">
|
||||
<separator colspan="4" string="Historical Import Logs"/>
|
||||
<field name="rec_log" colspan="4" nolabel="1" />
|
||||
</group>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="bank_statement_view_form" model="ir.ui.view">
|
||||
<field name="name">account_bank_statement.bank_statement.view_form</field>
|
||||
<field name="model">account.bank.statement</field>
|
||||
<field name="inherit_id" ref="account_statement_base_completion.bank_statement_view_form" />
|
||||
<field eval="20" name="priority"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='line_ids']/form//field[@name='account_id']" position="attributes">
|
||||
<attribute name="attrs">{'required': [('already_completed','=', True)]}</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='line_ids']/tree//field[@name='account_id']" position="attributes">
|
||||
<attribute name="attrs">{'required': [('already_completed','=', True)]}</attribute>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
27
account_statement_base_import/tests/__init__.py
Normal file
27
account_statement_base_import/tests/__init__.py
Normal file
@@ -0,0 +1,27 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
#
|
||||
# Authors: Laurent Mignon
|
||||
# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu)
|
||||
# All Rights Reserved
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
#
|
||||
|
||||
from . import test_base_import
|
||||
|
||||
checks = [
|
||||
test_base_import
|
||||
]
|
||||
110
account_statement_base_import/tests/test_base_import.py
Normal file
110
account_statement_base_import/tests/test_base_import.py
Normal file
@@ -0,0 +1,110 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
#
|
||||
# Authors: Laurent Mignon
|
||||
# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu)
|
||||
# All Rights Reserved
|
||||
#
|
||||
# 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 inspect
|
||||
import os
|
||||
from openerp.tests import common
|
||||
|
||||
|
||||
class TestCodaImport(common.TransactionCase):
|
||||
|
||||
def prepare(self):
|
||||
self.company_a = self.browse_ref('base.main_company')
|
||||
self.profile_obj = self.registry("account.statement.profile")
|
||||
self.account_bank_statement_obj = self.registry(
|
||||
"account.bank.statement")
|
||||
# create the 2009 fiscal year since imported coda file reference
|
||||
# statement lines in 2009
|
||||
self.fiscalyear_id = self._create_fiscalyear("2011", self.company_a.id)
|
||||
self.account_id = self.ref("account.a_recv")
|
||||
self.journal_id = self.ref("account.bank_journal")
|
||||
self.import_wizard_obj = self.registry('credit.statement.import')
|
||||
self.profile_id = self.profile_obj.create(self.cr, self.uid, {
|
||||
"name": "BASE_PROFILE",
|
||||
"commission_account_id": self.account_id,
|
||||
"journal_id": self.journal_id,
|
||||
"import_type": "generic_csvxls_so"})
|
||||
|
||||
def _create_fiscalyear(self, year, company_id):
|
||||
fiscalyear_obj = self.registry("account.fiscalyear")
|
||||
fiscalyear_id = fiscalyear_obj.create(self.cr, self.uid, {
|
||||
"name": year,
|
||||
"code": year,
|
||||
"date_start": year + "-01-01",
|
||||
"date_stop": year + "-12-31",
|
||||
"company_id": company_id
|
||||
})
|
||||
fiscalyear_obj.create_period3(self.cr, self.uid, [fiscalyear_id])
|
||||
return fiscalyear_id
|
||||
|
||||
def _filename_to_abs_filename(self, file_name):
|
||||
dir_name = os.path.dirname(inspect.getfile(self.__class__))
|
||||
return os.path.join(dir_name, file_name)
|
||||
|
||||
def _import_file(self, file_name):
|
||||
""" import a file using the wizard
|
||||
return the create account.bank.statement object
|
||||
"""
|
||||
with open(file_name) as f:
|
||||
content = f.read()
|
||||
wizard_id = self.import_wizard_obj.create(self.cr, self.uid, {
|
||||
"profile_id": self.profile_id,
|
||||
'input_statement': base64.b64encode(content),
|
||||
'file_name': os.path.basename(file_name),
|
||||
})
|
||||
res = self.import_wizard_obj.import_statement(
|
||||
self.cr, self.uid, wizard_id)
|
||||
statement_id = self.account_bank_statement_obj.search(
|
||||
self.cr, self.uid, eval(res['domain']))
|
||||
return self.account_bank_statement_obj.browse(
|
||||
self.cr, self.uid, statement_id)[0]
|
||||
|
||||
def test_simple_xls(self):
|
||||
"""Test import from xls
|
||||
"""
|
||||
self.prepare()
|
||||
file_name = self._filename_to_abs_filename(
|
||||
os.path.join("..", "data", "statement.xls"))
|
||||
statement = self._import_file(file_name)
|
||||
self._validate_imported_satement(statement)
|
||||
|
||||
def test_simple_csv(self):
|
||||
"""Test import from csv
|
||||
"""
|
||||
self.prepare()
|
||||
file_name = self._filename_to_abs_filename(
|
||||
os.path.join("..", "data", "statement.csv"))
|
||||
statement = self._import_file(file_name)
|
||||
self._validate_imported_satement(statement)
|
||||
|
||||
def _validate_imported_satement(self, statement):
|
||||
self.assertEqual("/", statement.name)
|
||||
self.assertEqual(0.0, statement.balance_start)
|
||||
self.assertEqual(0.0, statement.balance_end_real)
|
||||
self.assertEqual(3, len(statement.line_ids))
|
||||
self.assertTrue(statement.account_id)
|
||||
st_line_obj = statement.line_ids[1]
|
||||
# common infos
|
||||
self.assertEqual(st_line_obj.ref, "51065326")
|
||||
self.assertEqual(st_line_obj.date, "2011-03-02")
|
||||
self.assertEqual(st_line_obj.amount, 189.0)
|
||||
self.assertEqual(st_line_obj.name, "label b")
|
||||
20
account_statement_base_import/wizard/__init__.py
Normal file
20
account_statement_base_import/wizard/__init__.py
Normal file
@@ -0,0 +1,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author Nicolas Bessi, Joel Grand-Guillaume. Copyright Camptocamp SA
|
||||
#
|
||||
# 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 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
from . import import_statement
|
||||
120
account_statement_base_import/wizard/import_statement.py
Normal file
120
account_statement_base_import/wizard/import_statement.py
Normal file
@@ -0,0 +1,120 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Nicolas Bessi, Joel Grand-Guillaume
|
||||
# Copyright 2011-2012 Camptocamp 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/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
"""
|
||||
Wizard to import financial institute date in bank statement
|
||||
"""
|
||||
|
||||
from openerp.osv import orm, fields
|
||||
|
||||
from openerp.tools.translate import _
|
||||
import os
|
||||
|
||||
|
||||
class CreditPartnerStatementImporter(orm.TransientModel):
|
||||
_name = "credit.statement.import"
|
||||
|
||||
def default_get(self, cr, uid, fields, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
res = {}
|
||||
if (context.get('active_model', False) ==
|
||||
'account.statement.profile' and
|
||||
context.get('active_ids', False)):
|
||||
ids = context['active_ids']
|
||||
assert len(
|
||||
ids) == 1, 'You cannot use this on more than one profile !'
|
||||
res['profile_id'] = ids[0]
|
||||
other_vals = self.onchange_profile_id(
|
||||
cr, uid, [], res['profile_id'], context=context)
|
||||
res.update(other_vals.get('value', {}))
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
'profile_id': fields.many2one('account.statement.profile',
|
||||
'Import configuration parameter',
|
||||
required=True),
|
||||
'input_statement': fields.binary('Statement file', required=True),
|
||||
'partner_id': fields.many2one('res.partner',
|
||||
'Credit insitute partner'),
|
||||
'journal_id': fields.many2one('account.journal',
|
||||
'Financial journal to use transaction'),
|
||||
'file_name': fields.char('File Name', size=128),
|
||||
'receivable_account_id': fields.many2one(
|
||||
'account.account', 'Force Receivable/Payable Account'),
|
||||
'force_partner_on_bank': fields.boolean(
|
||||
'Force partner on bank move',
|
||||
help="Tic that box if you want to use the credit insitute partner "
|
||||
"in the counterpart of the treasury/banking move."),
|
||||
'balance_check': fields.boolean(
|
||||
'Balance check',
|
||||
help="Tic that box if you want OpenERP to control the "
|
||||
"start/end balance before confirming a bank statement. "
|
||||
"If don't ticked, no balance control will be done."),
|
||||
}
|
||||
|
||||
def onchange_profile_id(self, cr, uid, ids, profile_id, context=None):
|
||||
res = {}
|
||||
if profile_id:
|
||||
c = self.pool["account.statement.profile"].browse(
|
||||
cr, uid, profile_id, context=context)
|
||||
res = {'value':
|
||||
{'partner_id': c.partner_id and c.partner_id.id or False,
|
||||
'journal_id': c.journal_id and c.journal_id.id or False,
|
||||
'receivable_account_id': c.receivable_account_id.id,
|
||||
'force_partner_on_bank': c.force_partner_on_bank,
|
||||
'balance_check': c.balance_check,
|
||||
}
|
||||
}
|
||||
return res
|
||||
|
||||
def _check_extension(self, filename):
|
||||
(__, ftype) = os.path.splitext(filename)
|
||||
if not ftype:
|
||||
# We do not use osv exception we do not want to have it logged
|
||||
raise Exception(_('Please use a file with an extention'))
|
||||
return ftype
|
||||
|
||||
def import_statement(self, cr, uid, req_id, context=None):
|
||||
"""This Function import credit card agency statement"""
|
||||
context = context or {}
|
||||
if isinstance(req_id, list):
|
||||
req_id = req_id[0]
|
||||
importer = self.browse(cr, uid, req_id, context)
|
||||
ftype = self._check_extension(importer.file_name)
|
||||
context['file_name'] = importer.file_name
|
||||
sid = self.pool.get(
|
||||
'account.statement.profile').multi_statement_import(
|
||||
cr,
|
||||
uid,
|
||||
False,
|
||||
importer.profile_id.id,
|
||||
importer.input_statement,
|
||||
ftype.replace('.', ''),
|
||||
context=context
|
||||
)
|
||||
model_obj = self.pool.get('ir.model.data')
|
||||
action_obj = self.pool.get('ir.actions.act_window')
|
||||
action_id = model_obj.get_object_reference(
|
||||
cr, uid, 'account', 'action_bank_statement_tree')[1]
|
||||
res = action_obj.read(cr, uid, action_id)
|
||||
res['domain'] = res['domain'][:-1] + ",('id', 'in', %s)]" % sid
|
||||
return res
|
||||
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<record id="statement_importer_view" model="ir.ui.view">
|
||||
<field name="name">credit.statement.import.config.view</field>
|
||||
<field name="model">credit.statement.import</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Import statement">
|
||||
<group colspan="4" >
|
||||
<field name="profile_id" on_change="onchange_profile_id(profile_id)"/>
|
||||
<field name="input_statement" filename="file_name" colspan="2"/>
|
||||
<field name="file_name" colspan="2" invisible="1"/>
|
||||
<separator string="Import Parameters Summary" colspan="4"/>
|
||||
<field name="partner_id" readonly="1"/>
|
||||
<field name="journal_id" readonly="1"/>
|
||||
<field name="receivable_account_id" readonly="1"/>
|
||||
<field name="force_partner_on_bank" readonly="1"/>
|
||||
<field name="balance_check" readonly="1"/>
|
||||
</group>
|
||||
<separator string="" colspan="4"/>
|
||||
<group colspan="4" col="6">
|
||||
<button icon="gtk-cancel" special="cancel" string="Cancel"/>
|
||||
<button icon="gtk-ok" name="import_statement" string="Import statement" type="object"/>
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="statement_importer_action" model="ir.actions.act_window">
|
||||
<field name="name">Import statement</field>
|
||||
<field name="res_model">credit.statement.import</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="view_id" ref="statement_importer_view"/>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
<menuitem id="statement_importer_menu" name="Import Bank Statement" action="statement_importer_action" parent="account.menu_finance_bank_and_cash"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
Reference in New Issue
Block a user