mirror of
https://github.com/OCA/account-reconcile.git
synced 2025-01-20 12:27:39 +02:00
Merge pull request #137 from mdietrichc2c/9.0-account-transaction-base-import
[9.0] account move base import
This commit is contained in:
@@ -34,6 +34,7 @@ install:
|
||||
- git clone --depth=1 https://github.com/OCA/maintainer-quality-tools.git ${HOME}/maintainer-quality-tools
|
||||
- export PATH=${HOME}/maintainer-quality-tools/travis:${PATH}
|
||||
- travis_install_nightly
|
||||
- pip install xlrd
|
||||
|
||||
script:
|
||||
- travis_run_tests
|
||||
|
||||
57
account_move_bankaccount_import/README.rst
Normal file
57
account_move_bankaccount_import/README.rst
Normal file
@@ -0,0 +1,57 @@
|
||||
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
|
||||
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
|
||||
:alt: License: AGPL-3
|
||||
|
||||
=================================================
|
||||
Journal Entry completion from bank account number
|
||||
=================================================
|
||||
|
||||
This module extends the functionality of account_move_base_import
|
||||
to add a completion method based on the partner bank account number
|
||||
provided by the bank/office.
|
||||
|
||||
Completion will look in the partner with that bank account number
|
||||
to match the partner, then it will fill in the journal item with
|
||||
it to ease the reconciliation.
|
||||
|
||||
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
|
||||
:alt: Try me on Runbot
|
||||
:target: https://runbot.odoo-community.org/runbot/98/9.0
|
||||
|
||||
Bug Tracker
|
||||
===========
|
||||
|
||||
Bugs are tracked on `GitHub Issues
|
||||
<https://github.com/OCA/bank-statement-reconcile/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
|
||||
=======
|
||||
|
||||
Images
|
||||
------
|
||||
|
||||
* Odoo Community Association: `Icon <https://github.com/OCA/maintainer-tools/blob/master/template/module/static/description/icon.svg>`_.
|
||||
|
||||
Contributors
|
||||
------------
|
||||
|
||||
* Laurent Mignon <laurent.mignon@acsone.eu>
|
||||
* Matthieu Dietrich <matthieu.dietrich@gmail.com>
|
||||
|
||||
Maintainer
|
||||
----------
|
||||
|
||||
.. image:: https://odoo-community.org/logo.png
|
||||
:alt: Odoo Community Association
|
||||
:target: https://odoo-community.org
|
||||
|
||||
This module is maintained by the OCA.
|
||||
|
||||
OCA, or the Odoo Community Association, is a nonprofit organization whose
|
||||
mission is to support the collaborative development of Odoo features and
|
||||
promote its widespread use.
|
||||
|
||||
To contribute to this module, please visit https://odoo-community.org.
|
||||
5
account_move_bankaccount_import/__init__.py
Normal file
5
account_move_bankaccount_import/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2013 ACSONE SA/NV
|
||||
# © 2016 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||
from . import models
|
||||
23
account_move_bankaccount_import/__openerp__.py
Normal file
23
account_move_bankaccount_import/__openerp__.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2013 ACSONE SA/NV
|
||||
# © 2016 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||
{
|
||||
'name': "Journal Entry completion from bank account number",
|
||||
'version': '9.0.1.0.0',
|
||||
'author': "ACSONE SA/NV,Odoo Community Association (OCA)",
|
||||
'maintainer': 'ACSONE SA/NV',
|
||||
'category': 'Finance',
|
||||
'complexity': 'normal',
|
||||
'depends': [
|
||||
'account_move_base_import',
|
||||
],
|
||||
'website': 'http://www.acsone.eu',
|
||||
'data': [
|
||||
"data/completion_rule_data.xml",
|
||||
],
|
||||
'demo': [],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
'license': 'AGPL-3',
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo noupdate="1">
|
||||
|
||||
<record id="bank_statement_completion_rule_10" model="account.move.completion.rule">
|
||||
<field name="name">Match from bank account number (Normal or IBAN))</field>
|
||||
<field name="sequence">10</field>
|
||||
<field name="function_to_call">get_from_bank_account</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -17,18 +17,18 @@ msgstr ""
|
||||
"X-Launchpad-Export-Date: 2014-06-06 06:36+0000\n"
|
||||
"X-Generator: Launchpad (build 17031)\n"
|
||||
|
||||
#. module: account_statement_bankaccount_completion
|
||||
#. module: account_move_bankaccount_import
|
||||
#: help:account.bank.statement.line,partner_acc_number:0
|
||||
msgid "Account number of the partner"
|
||||
msgstr "Número de cuenta de la empresa"
|
||||
|
||||
#. module: account_statement_bankaccount_completion
|
||||
#: model:ir.model,name:account_statement_bankaccount_completion.model_account_bank_statement_line
|
||||
#. module: account_move_bankaccount_import
|
||||
#: model:ir.model,name:account_move_bankaccount_import.model_account_bank_statement_line
|
||||
msgid "Bank Statement Line"
|
||||
msgstr "Línea de extracto bancario"
|
||||
|
||||
#. module: account_statement_bankaccount_completion
|
||||
#: code:addons/account_statement_bankaccount_completion/statement.py:68
|
||||
#. module: account_move_bankaccount_import
|
||||
#: code:addons/account_move_bankaccount_import/statement.py:68
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Line named \"%s\" (Ref:%s) was matched by more than one partner for account "
|
||||
@@ -37,12 +37,12 @@ msgstr ""
|
||||
"La línea llamada \"%s\" (Ref: %s) fue casada con más de una empresa al "
|
||||
"buscar el nº de cuenta \"%s\"."
|
||||
|
||||
#. module: account_statement_bankaccount_completion
|
||||
#. module: account_move_bankaccount_import
|
||||
#: field:account.bank.statement.line,partner_acc_number:0
|
||||
msgid "Account Number"
|
||||
msgstr "Número de cuenta"
|
||||
|
||||
#. module: account_statement_bankaccount_completion
|
||||
#: model:ir.model,name:account_statement_bankaccount_completion.model_account_statement_completion_rule
|
||||
#. module: account_move_bankaccount_import
|
||||
#: model:ir.model,name:account_move_bankaccount_import.model_account_statement_completion_rule
|
||||
msgid "account.statement.completion.rule"
|
||||
msgstr "account.statement.completion.rule"
|
||||
@@ -17,30 +17,30 @@ msgstr ""
|
||||
"X-Launchpad-Export-Date: 2014-06-20 06:09+0000\n"
|
||||
"X-Generator: Launchpad (build 17058)\n"
|
||||
|
||||
#. module: account_statement_bankaccount_completion
|
||||
#. module: account_move_bankaccount_import
|
||||
#: help:account.bank.statement.line,partner_acc_number:0
|
||||
msgid "Account number of the partner"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_bankaccount_completion
|
||||
#: model:ir.model,name:account_statement_bankaccount_completion.model_account_bank_statement_line
|
||||
#. module: account_move_bankaccount_import
|
||||
#: model:ir.model,name:account_move_bankaccount_import.model_account_bank_statement_line
|
||||
msgid "Bank Statement Line"
|
||||
msgstr "Ligne de relevé bancaire"
|
||||
|
||||
#. module: account_statement_bankaccount_completion
|
||||
#: code:addons/account_statement_bankaccount_completion/statement.py:68
|
||||
#. module: account_move_bankaccount_import
|
||||
#: code:addons/account_move_bankaccount_import/statement.py:68
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Line named \"%s\" (Ref:%s) was matched by more than one partner for account "
|
||||
"number \"%s\"."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_bankaccount_completion
|
||||
#. module: account_move_bankaccount_import
|
||||
#: field:account.bank.statement.line,partner_acc_number:0
|
||||
msgid "Account Number"
|
||||
msgstr "Numéro de compte"
|
||||
|
||||
#. module: account_statement_bankaccount_completion
|
||||
#: model:ir.model,name:account_statement_bankaccount_completion.model_account_statement_completion_rule
|
||||
#. module: account_move_bankaccount_import
|
||||
#: model:ir.model,name:account_move_bankaccount_import.model_account_statement_completion_rule
|
||||
msgid "account.statement.completion.rule"
|
||||
msgstr ""
|
||||
6
account_move_bankaccount_import/models/__init__.py
Normal file
6
account_move_bankaccount_import/models/__init__.py
Normal file
@@ -0,0 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2013 ACSONE SA/NV
|
||||
# © 2016 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||
from . import account_move
|
||||
from . import res_partner_bank
|
||||
57
account_move_bankaccount_import/models/account_move.py
Normal file
57
account_move_bankaccount_import/models/account_move.py
Normal file
@@ -0,0 +1,57 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2013 ACSONE SA/NV
|
||||
# © 2016 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||
from openerp import _, fields, models
|
||||
from openerp.addons.account_move_base_import.models.account_move \
|
||||
import ErrorTooManyPartner
|
||||
|
||||
|
||||
class AccountMoveCompletionRule(models.Model):
|
||||
"""Add a rule based on transaction ID"""
|
||||
|
||||
_inherit = "account.move.completion.rule"
|
||||
|
||||
function_to_call = fields.Selection(
|
||||
selection_add=[
|
||||
('get_from_bank_account',
|
||||
'From bank account number (Normal or IBAN)')
|
||||
])
|
||||
|
||||
def get_from_bank_account(self, line):
|
||||
"""
|
||||
Match the partner based on the partner account number field
|
||||
Then, call the generic st_line method to complete other values.
|
||||
:param dict st_line: read of the concerned account.bank.statement.line
|
||||
:return:
|
||||
A dict of value that can be passed directly to the write method of
|
||||
the statement line or {}
|
||||
{'partner_id': value,
|
||||
'account_id' : value,
|
||||
...}
|
||||
"""
|
||||
partner_acc_number = line.partner_acc_number
|
||||
if not partner_acc_number:
|
||||
return {}
|
||||
res = {}
|
||||
res_bank_obj = self.env['res.partner.bank']
|
||||
banks = res_bank_obj.search_by_acc_number(partner_acc_number)
|
||||
if len(banks) > 1:
|
||||
raise ErrorTooManyPartner(_('Line named "%s" was matched '
|
||||
'by more than one partner for account '
|
||||
'number "%s".') %
|
||||
(line.name,
|
||||
partner_acc_number))
|
||||
if len(banks) == 1:
|
||||
partner = banks[0].partner_id
|
||||
res['partner_id'] = partner.id
|
||||
return res
|
||||
|
||||
|
||||
class AccountMoveLine(models.Model):
|
||||
_inherit = "account.move.line"
|
||||
|
||||
partner_acc_number = fields.Char(
|
||||
string='Account Number',
|
||||
size=64,
|
||||
help="Account number of the partner")
|
||||
34
account_move_bankaccount_import/models/res_partner_bank.py
Normal file
34
account_move_bankaccount_import/models/res_partner_bank.py
Normal file
@@ -0,0 +1,34 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2013 ACSONE SA/NV
|
||||
# © 2016 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||
from openerp import api, models
|
||||
|
||||
|
||||
class ResPartnerBank(models.Model):
|
||||
_inherit = 'res.partner.bank'
|
||||
|
||||
@api.multi
|
||||
def search_by_acc_number(self, acc_number):
|
||||
'''
|
||||
Try to find the Account Number using a 'like' operator to avoid
|
||||
problems with the input mask used to store the value.
|
||||
'''
|
||||
# first try with an exact match
|
||||
banks = self.search([('acc_number', '=', acc_number)])
|
||||
if banks:
|
||||
return banks
|
||||
|
||||
self.env.cr.execute("""
|
||||
SELECT
|
||||
id
|
||||
FROM
|
||||
res_partner_bank
|
||||
WHERE
|
||||
regexp_replace(acc_number,'([^[:alnum:]])', '','g')
|
||||
ilike
|
||||
regexp_replace(%s,'([^[:alnum:]])', '','g')
|
||||
""", (acc_number,))
|
||||
# apply security constraints by using the orm
|
||||
return self.search(
|
||||
[('id', 'in', [r[0] for r in self.env.cr.fetchall()])])
|
||||
5
account_move_bankaccount_import/tests/__init__.py
Normal file
5
account_move_bankaccount_import/tests/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2013 ACSONE SA/NV
|
||||
# © 2016 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||
from . import test_bankaccount_completion
|
||||
@@ -0,0 +1,93 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2013 ACSONE SA/NV
|
||||
# © 2016 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||
from openerp.tests import common
|
||||
from openerp import fields, tools
|
||||
from openerp.modules import get_module_resource
|
||||
|
||||
ACC_NUMBER = " BE38 7330 4038 5372 "
|
||||
|
||||
|
||||
class BankAccountCompletion(common.TransactionCase):
|
||||
|
||||
def setUp(self):
|
||||
super(BankAccountCompletion, self).setUp()
|
||||
tools.convert_file(self.cr, 'account',
|
||||
get_module_resource('account', 'test',
|
||||
'account_minimal_test.xml'),
|
||||
{}, 'init', False, 'test')
|
||||
self.account_move_obj = self.env["account.move"]
|
||||
self.account_move_line_obj = \
|
||||
self.env["account.move.line"].with_context(
|
||||
check_move_validity=False
|
||||
)
|
||||
self.company_a = self.browse_ref('base.main_company')
|
||||
self.completion_rule_id = \
|
||||
self.ref('account_move_bankaccount_import.'
|
||||
'bank_statement_completion_rule_10')
|
||||
self.journal = self.browse_ref("account.bank_journal")
|
||||
self.partner = self.browse_ref('base.main_partner')
|
||||
self.account_id = self.ref("account.a_recv")
|
||||
|
||||
# Create the profile
|
||||
self.journal.write({
|
||||
'used_for_completion': True,
|
||||
'rule_ids': [(6, 0, [self.completion_rule_id])]
|
||||
})
|
||||
# Create a bank statement
|
||||
self.move = self.account_move_obj.create({
|
||||
"date": fields.Date.today(),
|
||||
"journal_id": self.journal.id
|
||||
})
|
||||
|
||||
# Add a bank account number to the partner
|
||||
self.res_partner_bank_obj = self.env['res.partner.bank']
|
||||
vals = {"state": "bank",
|
||||
"company_id": self.company_a.id,
|
||||
"partner_id": self.partner.id,
|
||||
"acc_number": ACC_NUMBER,
|
||||
"footer": True,
|
||||
"bank_name": "Reserve",
|
||||
}
|
||||
self.partner_bank = self.res_partner_bank_obj.create(vals)
|
||||
|
||||
def test_00(self):
|
||||
"""Test complete partner_id from bank account number
|
||||
Test the automatic completion of the partner_id based on the account
|
||||
number associated to the statement line
|
||||
"""
|
||||
for bank_acc_number in [ACC_NUMBER, ACC_NUMBER.replace(" ", ""),
|
||||
ACC_NUMBER.replace(" ", "-")]:
|
||||
# check the completion for well formatted and not well
|
||||
# formatted account number
|
||||
self.partner_bank.write({"acc_number": bank_acc_number})
|
||||
for acc_number in [ACC_NUMBER, ACC_NUMBER.replace(" ", ""),
|
||||
ACC_NUMBER.replace(" ", "-"),
|
||||
" BE38-7330 4038-5372 "]:
|
||||
self.move_line = self.account_move_line_obj.create({
|
||||
'account_id': self.account_id,
|
||||
'credit': 1000.0,
|
||||
'name': 'EXT001',
|
||||
'move_id': self.move.id,
|
||||
'partner_acc_number': acc_number
|
||||
})
|
||||
self.assertFalse(
|
||||
self.move_line.partner_id,
|
||||
'Partner_id must be blank before completion')
|
||||
self.move.button_auto_completion()
|
||||
self.assertEquals(
|
||||
self.partner, self.move_line.partner_id,
|
||||
"Missing expected partner id after completion")
|
||||
|
||||
self.move_line = self.account_move_line_obj.create({
|
||||
'account_id': self.account_id,
|
||||
'credit': 1000.0,
|
||||
'name': 'EXT001',
|
||||
'move_id': self.move.id,
|
||||
'partner_acc_number': 'BE38a7330.4038-5372.',
|
||||
})
|
||||
self.assertFalse(self.move_line.partner_id,
|
||||
'Partner_id must be blank before completion')
|
||||
self.move.button_auto_completion()
|
||||
self.assertFalse(self.move_line.partner_id)
|
||||
103
account_move_base_import/README.rst
Normal file
103
account_move_base_import/README.rst
Normal file
@@ -0,0 +1,103 @@
|
||||
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
|
||||
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
|
||||
:alt: License: AGPL-3
|
||||
|
||||
========================
|
||||
Account move base import
|
||||
========================
|
||||
|
||||
This module is a grouping of 7.0/8.0 modules, used to import accounting files
|
||||
and completing them automatically:
|
||||
|
||||
* account_statement_base_completion
|
||||
* account_statement_base_import
|
||||
* account_statement_commission
|
||||
* account_statement_ext
|
||||
|
||||
The main change is that, in order to import financial data, this information
|
||||
is now imported directly as a Journal Entry.
|
||||
|
||||
Most of the information present in the "statement profile" is now located in
|
||||
the account journal (with 2 boolean parameters which allows to use
|
||||
this journal for importation and/or auto-completion).
|
||||
|
||||
Financial data can be imported using a standard .csv or .xls file (you'll find
|
||||
it in the 'data' folder). It respects the journal to pass the entries.
|
||||
|
||||
This module can handle a commission taken by the payment office and has the
|
||||
following format:
|
||||
* __date__: date of the payment
|
||||
* __amount__: amount paid in the currency of the journal used in the
|
||||
importation
|
||||
* __label__: the comunication given by the payment office, used as
|
||||
communication in the generated entries.
|
||||
|
||||
Another column which can be used is __commission_amount__, representing
|
||||
the amount for the commission taken by line.
|
||||
|
||||
Afterwards, the goal is to populate the journal items with information that
|
||||
the bank or office gave you. For this, completion rules can be specified by
|
||||
journal.
|
||||
|
||||
Some basic rules are provided in this module:
|
||||
|
||||
1) Match from statement line label (based on partner field 'Bank Statement
|
||||
Label')
|
||||
2) Match from statement line label (based on partner name)
|
||||
3) Match from statement line label (based on Invoice reference)
|
||||
|
||||
Feel free to extend either the importation method, the completion method, or
|
||||
both.
|
||||
|
||||
|
||||
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
|
||||
:alt: Try me on Runbot
|
||||
:target: https://runbot.odoo-community.org/runbot/{repo_id}/{branch}
|
||||
|
||||
.. repo_id is available in https://github.com/OCA/maintainer-tools/blob/master/tools/repos_with_ids.txt
|
||||
.. branch is "8.0" for example
|
||||
|
||||
Known issues / Roadmap
|
||||
======================
|
||||
|
||||
* As for now, the module does not handle multicurrency imports.
|
||||
|
||||
Bug Tracker
|
||||
===========
|
||||
|
||||
Bugs are tracked on `GitHub Issues
|
||||
<https://github.com/OCA/bank-statement-reconcile/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
|
||||
=======
|
||||
|
||||
Images
|
||||
------
|
||||
|
||||
* Odoo Community Association: `Icon <https://github.com/OCA/maintainer-tools/blob/master/template/module/static/description/icon.svg>`_.
|
||||
|
||||
Contributors
|
||||
------------
|
||||
|
||||
* Joël Grand-Guillaume <joel.grandguillaume@camptocamp.com>
|
||||
* Nicolas Bessi <nicolas.bessi@camptocamp.com>
|
||||
* Laurent Mignon <laurent.mignon@acsone.eu>
|
||||
* Sébastien Beau <sebastien.beau@akretion.com>
|
||||
* Matthieu Dietrich <matthieu.dietrich@camptocamp.com>
|
||||
|
||||
Maintainer
|
||||
----------
|
||||
|
||||
.. image:: https://odoo-community.org/logo.png
|
||||
:alt: Odoo Community Association
|
||||
:target: https://odoo-community.org
|
||||
|
||||
This module is maintained by the OCA.
|
||||
|
||||
OCA, or the Odoo Community Association, is a nonprofit organization whose
|
||||
mission is to support the collaborative development of Odoo features and
|
||||
promote its widespread use.
|
||||
|
||||
To contribute to this module, please visit https://odoo-community.org.
|
||||
9
account_move_base_import/__init__.py
Normal file
9
account_move_base_import/__init__.py
Normal file
@@ -0,0 +1,9 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2011 Akretion
|
||||
# © 2011-2016 Camptocamp SA
|
||||
# © 2013 Savoir-faire Linux
|
||||
# © 2014 ACSONE SA/NV
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||
from . import parser
|
||||
from . import wizard
|
||||
from . import models
|
||||
32
account_move_base_import/__openerp__.py
Normal file
32
account_move_base_import/__openerp__.py
Normal file
@@ -0,0 +1,32 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2011 Akretion
|
||||
# © 2011-2016 Camptocamp SA
|
||||
# © 2013 Savoir-faire Linux
|
||||
# © 2014 ACSONE SA/NV
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||
{
|
||||
'name': "Journal Entry base import",
|
||||
'version': '9.0.1.0.0',
|
||||
'author': "Akretion,Camptocamp,Odoo Community Association (OCA)",
|
||||
'category': 'Finance',
|
||||
'depends': ['account'],
|
||||
'website': 'http://www.camptocamp.com',
|
||||
'data': [
|
||||
"security/ir.model.access.csv",
|
||||
"data/completion_rule_data.xml",
|
||||
"wizard/import_statement_view.xml",
|
||||
"views/account_move_view.xml",
|
||||
"views/journal_view.xml",
|
||||
"views/partner_view.xml",
|
||||
],
|
||||
'test': [
|
||||
'test/partner.yml',
|
||||
'test/invoice.yml',
|
||||
'test/supplier_invoice.yml',
|
||||
'test/refund.yml',
|
||||
'test/completion_test.yml'
|
||||
],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
'license': 'AGPL-3',
|
||||
}
|
||||
28
account_move_base_import/data/completion_rule_data.xml
Normal file
28
account_move_base_import/data/completion_rule_data.xml
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo noupdate="1">
|
||||
|
||||
<record id="bank_statement_completion_rule_2" model="account.move.completion.rule">
|
||||
<field name="name">Match from line label (based on partner field 'Bank Statement Label')</field>
|
||||
<field name="sequence">60</field>
|
||||
<field name="function_to_call">get_from_name_and_partner_field</field>
|
||||
</record>
|
||||
|
||||
<record id="bank_statement_completion_rule_3" model="account.move.completion.rule">
|
||||
<field name="name">Match from line label (based on partner name)</field>
|
||||
<field name="sequence">70</field>
|
||||
<field name="function_to_call">get_from_name_and_partner_name</field>
|
||||
</record>
|
||||
|
||||
<record id="bank_statement_completion_rule_4" model="account.move.completion.rule">
|
||||
<field name="name">Match from line label (based on Invoice number)</field>
|
||||
<field name="sequence">40</field>
|
||||
<field name="function_to_call">get_from_name_and_invoice</field>
|
||||
</record>
|
||||
|
||||
<record id="bank_statement_completion_rule_5" model="account.move.completion.rule">
|
||||
<field name="name">Match from line label (based on Invoice Supplier number)</field>
|
||||
<field name="sequence">45</field>
|
||||
<field name="function_to_call">get_from_name_and_supplier_invoice</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
4
account_move_base_import/data/statement.csv
Normal file
4
account_move_base_import/data/statement.csv
Normal file
@@ -0,0 +1,4 @@
|
||||
"date";"amount";"commission_amount";"label"
|
||||
2011-03-07 13:45:14;118.4;-11.84;"label a"
|
||||
2011-03-02 13:45:14;189;-15.12;"label b"
|
||||
2011-03-02 17:45:14;189;-15.12;"label c"
|
||||
|
BIN
account_move_base_import/data/statement.xls
Normal file
BIN
account_move_base_import/data/statement.xls
Normal file
Binary file not shown.
@@ -17,29 +17,29 @@ msgstr ""
|
||||
"X-Launchpad-Export-Date: 2014-06-06 06:36+0000\n"
|
||||
"X-Generator: Launchpad (build 17031)\n"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#. module: account_move_base_import
|
||||
#: view:credit.statement.import:0
|
||||
#: model:ir.actions.act_window,name:account_statement_base_import.statement_importer_action
|
||||
#: model:ir.actions.act_window,name:account_move_base_import.statement_importer_action
|
||||
msgid "Import statement"
|
||||
msgstr "Importar extracto"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#. module: account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: model:ir.model,name:account_move_base_import.model_credit_statement_import
|
||||
msgid "credit.statement.import"
|
||||
msgstr "credit.statement.import"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#. module: account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_base_import/statement.py:168
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Column %s you try to import is not present in the bank statement line!"
|
||||
@@ -47,91 +47,91 @@ 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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_base_import/statement.py:162
|
||||
#, python-format
|
||||
msgid "Nothing to import"
|
||||
msgstr "Nada que importar"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#. module: account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: view:account.statement.profile:0
|
||||
#: model:ir.ui.menu,name:account_statement_base_import.statement_importer_menu
|
||||
#: model:ir.ui.menu,name:account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_base_import/parser/file_parser.py:107
|
||||
#: code:addons/account_move_base_import/parser/file_parser.py:171
|
||||
#: code:addons/account_move_base_import/parser/file_parser.py:205
|
||||
#, python-format
|
||||
msgid "Invalid data"
|
||||
msgstr "Datos inválidos"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#. module: account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: field:credit.statement.import,partner_id:0
|
||||
msgid "Credit insitute partner"
|
||||
msgstr "Empresa para el agente financiero"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#. module: account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_base_import/parser/file_parser.py:172
|
||||
#: code:addons/account_move_base_import/parser/file_parser.py:206
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Value %s of column %s is not valid.\n"
|
||||
@@ -145,15 +145,15 @@ msgstr ""
|
||||
" \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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_base_import/parser/file_parser.py:29
|
||||
#: code:addons/account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_base_import/parser/file_parser.py:160
|
||||
#, python-format
|
||||
msgid ""
|
||||
" It should be YYYY-MM-DD for column: %s value: %s \n"
|
||||
@@ -169,24 +169,24 @@ msgstr ""
|
||||
" \n"
|
||||
"Detalles: %s"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#. module: account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: model:ir.model,name:account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_base_import/parser/file_parser.py:193
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Please modify the cell formatting to date format for column: %s value: %s\n"
|
||||
@@ -200,18 +200,18 @@ msgstr ""
|
||||
" \n"
|
||||
"Detalles: %s"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:192
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: field:account.statement.profile,import_type:0
|
||||
msgid "Type of import"
|
||||
msgstr "Tipo de importación"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#. module: account_move_base_import
|
||||
#: help:account.statement.profile,launch_import_completion:0
|
||||
msgid ""
|
||||
"Tic that box to automatically launch the completion on each imported file "
|
||||
@@ -220,7 +220,7 @@ msgstr ""
|
||||
"Marque esta casilla para lanzar automáticamente el completado en cada "
|
||||
"archivo importado usando este perfil."
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#. module: account_move_base_import
|
||||
#: help:credit.statement.import,balance_check:0
|
||||
msgid ""
|
||||
"Tic that box if you want OpenERP to control the start/end balance before "
|
||||
@@ -231,81 +231,81 @@ msgstr ""
|
||||
"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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_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
|
||||
#. module: account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: field:account.statement.profile,rec_log:0
|
||||
msgid "log"
|
||||
msgstr "registro"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#. module: account_move_base_import
|
||||
#: view:credit.statement.import:0
|
||||
msgid "Import Parameters Summary"
|
||||
msgstr "Resumen de parámetros de importación"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#. module: account_move_base_import
|
||||
#: field:credit.statement.import,balance_check:0
|
||||
msgid "Balance check"
|
||||
msgstr "Comprobar saldo"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#. module: account_move_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
|
||||
#. module: account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_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
|
||||
#. module: account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_base_import/parser/file_parser.py:164
|
||||
#: code:addons/account_move_base_import/parser/file_parser.py:174
|
||||
#: code:addons/account_move_base_import/parser/file_parser.py:198
|
||||
#: code:addons/account_move_base_import/parser/file_parser.py:208
|
||||
#, python-format
|
||||
msgid "Missing"
|
||||
msgstr "Ausente"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#. module: account_move_base_import
|
||||
#: help:account.statement.profile,import_type:0
|
||||
msgid ""
|
||||
"Choose here the method by which you want to import bank statement for this "
|
||||
@@ -314,12 +314,12 @@ msgstr ""
|
||||
"Escoja aquí el método con el que quiere importar el extracto bancario para "
|
||||
"este perfil."
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#. module: account_move_base_import
|
||||
#: view:credit.statement.import:0
|
||||
msgid "Cancel"
|
||||
msgstr "Cancelar"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#. module: account_move_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 "
|
||||
@@ -17,119 +17,119 @@ msgstr ""
|
||||
"X-Launchpad-Export-Date: 2014-05-22 06:49+0000\n"
|
||||
"X-Generator: Launchpad (build 17017)\n"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#. module: account_move_base_import
|
||||
#: view:credit.statement.import:0
|
||||
#: model:ir.actions.act_window,name:account_statement_base_import.statement_importer_action
|
||||
#: model:ir.actions.act_window,name:account_move_base_import.statement_importer_action
|
||||
msgid "Import statement"
|
||||
msgstr "Import de relevé"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#. module: account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: model:ir.model,name:account_move_base_import.model_credit_statement_import
|
||||
msgid "credit.statement.import"
|
||||
msgstr "credit.statement.import"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#. module: account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_base_import/statement.py:162
|
||||
#, python-format
|
||||
msgid "Nothing to import"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#. module: account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: view:account.statement.profile:0
|
||||
#: model:ir.ui.menu,name:account_statement_base_import.statement_importer_menu
|
||||
#: model:ir.ui.menu,name:account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_base_import/parser/file_parser.py:107
|
||||
#: code:addons/account_move_base_import/parser/file_parser.py:171
|
||||
#: code:addons/account_move_base_import/parser/file_parser.py:205
|
||||
#, python-format
|
||||
msgid "Invalid data"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#. module: account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: field:credit.statement.import,partner_id:0
|
||||
msgid "Credit insitute partner"
|
||||
msgstr "Organisme bancaire"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#. module: account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_base_import/parser/file_parser.py:172
|
||||
#: code:addons/account_move_base_import/parser/file_parser.py:206
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Value %s of column %s is not valid.\n"
|
||||
@@ -138,15 +138,15 @@ msgid ""
|
||||
" 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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_base_import/parser/file_parser.py:29
|
||||
#: code:addons/account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_base_import/parser/file_parser.py:160
|
||||
#, python-format
|
||||
msgid ""
|
||||
" It should be YYYY-MM-DD for column: %s value: %s \n"
|
||||
@@ -157,24 +157,24 @@ msgid ""
|
||||
" Detail: %s"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#. module: account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: model:ir.model,name:account_move_base_import.model_account_statement_profile
|
||||
msgid "Statement Profile"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/statement.py:234
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_base_import/parser/file_parser.py:193
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Please modify the cell formatting to date format for column: %s value: %s\n"
|
||||
@@ -183,25 +183,25 @@ msgid ""
|
||||
" Detail: %s"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/parser/file_parser.py:192
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_base_import/parser/file_parser.py:192
|
||||
#, python-format
|
||||
msgid "Date format is not valid"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#. module: account_move_base_import
|
||||
#: field:account.statement.profile,import_type:0
|
||||
msgid "Type of import"
|
||||
msgstr "Type d'import"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#. module: account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: help:credit.statement.import,balance_check:0
|
||||
msgid ""
|
||||
"Tic that box if you want OpenERP to control the start/end balance before "
|
||||
@@ -209,93 +209,93 @@ msgid ""
|
||||
"done."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#: code:addons/account_statement_base_import/statement.py:154
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_base_import/parser/file_parser.py:159
|
||||
#, python-format
|
||||
msgid "Date format is not valid."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#. module: account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: field:account.statement.profile,rec_log:0
|
||||
msgid "log"
|
||||
msgstr "journal"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#. module: account_move_base_import
|
||||
#: view:credit.statement.import:0
|
||||
msgid "Import Parameters Summary"
|
||||
msgstr "Résumé des paramètres d'import"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#. module: account_move_base_import
|
||||
#: field:credit.statement.import,balance_check:0
|
||||
msgid "Balance check"
|
||||
msgstr "Vérification des soldes"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#. module: account_move_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
|
||||
#. module: account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_base_import/statement.py:83
|
||||
#, python-format
|
||||
msgid "Statement ID %s have been imported with %s lines."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#. module: account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: code:addons/account_move_base_import/parser/file_parser.py:164
|
||||
#: code:addons/account_move_base_import/parser/file_parser.py:174
|
||||
#: code:addons/account_move_base_import/parser/file_parser.py:198
|
||||
#: code:addons/account_move_base_import/parser/file_parser.py:208
|
||||
#, python-format
|
||||
msgid "Missing"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#. module: account_move_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
|
||||
#. module: account_move_base_import
|
||||
#: view:credit.statement.import:0
|
||||
msgid "Cancel"
|
||||
msgstr "Annulation"
|
||||
|
||||
#. module: account_statement_base_import
|
||||
#. module: account_move_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 "
|
||||
9
account_move_base_import/models/__init__.py
Normal file
9
account_move_base_import/models/__init__.py
Normal file
@@ -0,0 +1,9 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2011 Akretion
|
||||
# © 2011-2016 Camptocamp SA
|
||||
# © 2013 Savoir-faire Linux
|
||||
# © 2014 ACSONE SA/NV
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||
from . import account_journal
|
||||
from . import account_move
|
||||
from . import partner
|
||||
334
account_move_base_import/models/account_journal.py
Normal file
334
account_move_base_import/models/account_journal.py
Normal file
@@ -0,0 +1,334 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2011 Akretion
|
||||
# © 2011-2016 Camptocamp SA
|
||||
# © 2013 Savoir-faire Linux
|
||||
# © 2014 ACSONE SA/NV
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||
import sys
|
||||
import traceback
|
||||
import os
|
||||
from openerp import _, api, fields, models
|
||||
from ..parser.parser import new_move_parser
|
||||
from openerp.exceptions import UserError, ValidationError
|
||||
from operator import attrgetter
|
||||
|
||||
|
||||
class AccountJournal(models.Model):
|
||||
_name = 'account.journal'
|
||||
_inherit = ['account.journal', 'mail.thread']
|
||||
|
||||
used_for_import = fields.Boolean(
|
||||
string="Journal used for import")
|
||||
|
||||
commission_account_id = fields.Many2one(
|
||||
comodel_name='account.account',
|
||||
string='Commission account')
|
||||
|
||||
import_type = fields.Selection(
|
||||
[('generic_csvxls_so', 'Generic .csv/.xls based on SO Name')],
|
||||
string='Type of import',
|
||||
default='generic_csvxls_so',
|
||||
required=True,
|
||||
help="Choose here the method by which you want to import account "
|
||||
"moves for this journal.")
|
||||
|
||||
last_import_date = fields.Datetime(
|
||||
string="Last Import Date")
|
||||
|
||||
partner_id = fields.Many2one(
|
||||
comodel_name='res.partner',
|
||||
string='Bank/Payment Office partner',
|
||||
help="Put a partner if you want to have it on the commission move "
|
||||
"(and optionaly on the counterpart of the intermediate/"
|
||||
"banking move if you tick the corresponding checkbox).")
|
||||
|
||||
receivable_account_id = fields.Many2one(
|
||||
comodel_name='account.account',
|
||||
string='Receivable/Payable Account',
|
||||
help="Choose a receivable/payable account to use as the default "
|
||||
"debit/credit account.")
|
||||
|
||||
used_for_completion = fields.Boolean(
|
||||
string="Journal used for completion")
|
||||
|
||||
rule_ids = fields.Many2many(
|
||||
comodel_name='account.move.completion.rule',
|
||||
string='Auto-completion rules',
|
||||
relation='account_journal_completion_rule_rel')
|
||||
|
||||
launch_import_completion = fields.Boolean(
|
||||
string="Launch completion after import",
|
||||
help="Tic that box to automatically launch the completion "
|
||||
"on each imported file using this journal.")
|
||||
|
||||
create_counterpart = fields.Boolean(
|
||||
string="Create Counterpart",
|
||||
help="Tick that box to automatically create the move counterpart",
|
||||
default=True)
|
||||
|
||||
split_counterpart = fields.Boolean(
|
||||
string="Split Counterpart",
|
||||
help="Two counterparts will be automatically created : one for "
|
||||
"the refunds and one for the payments")
|
||||
|
||||
def _get_rules(self):
|
||||
# We need to respect the sequence order
|
||||
return sorted(self.rule_ids, key=attrgetter('sequence'))
|
||||
|
||||
def _find_values_from_rules(self, calls, line):
|
||||
"""This method will execute all related rules, in their sequence order,
|
||||
to retrieve all the values returned by the first rules that will match.
|
||||
:param calls: list of lookup function name available in rules
|
||||
:param dict line: read of the concerned account.bank.statement.line
|
||||
:return:
|
||||
A dict of value that can be passed directly to the write method of
|
||||
the statement line or {}
|
||||
{'partner_id': value,
|
||||
'account_id: value,
|
||||
...}
|
||||
"""
|
||||
if not calls:
|
||||
calls = self._get_rules()
|
||||
rule_obj = self.env['account.move.completion.rule']
|
||||
for call in calls:
|
||||
method_to_call = getattr(rule_obj, call.function_to_call)
|
||||
result = method_to_call(line)
|
||||
if result:
|
||||
result['already_completed'] = True
|
||||
return result
|
||||
return None
|
||||
|
||||
@api.multi
|
||||
def _prepare_counterpart_line(self, move, amount, date):
|
||||
if amount > 0.0:
|
||||
account_id = self.default_debit_account_id.id
|
||||
credit = 0.0
|
||||
debit = amount
|
||||
else:
|
||||
account_id = self.default_credit_account_id.id
|
||||
credit = -amount
|
||||
debit = 0.0
|
||||
counterpart_values = {
|
||||
'name': _('/'),
|
||||
'date_maturity': date,
|
||||
'credit': credit,
|
||||
'debit': debit,
|
||||
'partner_id': self.partner_id.id,
|
||||
'move_id': move.id,
|
||||
'account_id': account_id,
|
||||
'already_completed': True,
|
||||
'journal_id': self.id,
|
||||
'company_id': self.company_id.id,
|
||||
'currency_id': self.currency_id.id,
|
||||
'company_currency_id': self.company_id.currency_id.id,
|
||||
'amount_residual': amount,
|
||||
}
|
||||
return counterpart_values
|
||||
|
||||
@api.multi
|
||||
def _create_counterpart(self, parser, move):
|
||||
move_line_obj = self.env['account.move.line']
|
||||
refund = 0.0
|
||||
payment = 0.0
|
||||
transfer_lines = []
|
||||
for move_line in move.line_ids:
|
||||
refund -= move_line.debit
|
||||
payment += move_line.credit
|
||||
if self.split_counterpart:
|
||||
if refund:
|
||||
transfer_lines.append(refund)
|
||||
if payment:
|
||||
transfer_lines.append(payment)
|
||||
else:
|
||||
total_amount = refund + payment
|
||||
if total_amount:
|
||||
transfer_lines.append(total_amount)
|
||||
counterpart_date = parser.get_move_vals().get('date') or \
|
||||
fields.Date.today()
|
||||
transfer_line_count = len(transfer_lines)
|
||||
check_move_validity = False
|
||||
for amount in transfer_lines:
|
||||
transfer_line_count -= 1
|
||||
if not transfer_line_count:
|
||||
check_move_validity = True
|
||||
vals = self._prepare_counterpart_line(move, amount,
|
||||
counterpart_date)
|
||||
move_line_obj.with_context(
|
||||
check_move_validity=check_move_validity
|
||||
).create(vals)
|
||||
|
||||
@api.multi
|
||||
def _write_extra_move_lines(self, parser, move):
|
||||
"""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
|
||||
"""
|
||||
move_line_obj = self.env['account.move.line']
|
||||
global_commission_amount = 0
|
||||
for row in parser.result_row_list:
|
||||
global_commission_amount += float(
|
||||
row.get('commission_amount', '0.0'))
|
||||
partner_id = self.partner_id.id
|
||||
# Commission line
|
||||
if global_commission_amount > 0.0:
|
||||
raise UserError(_('Commission amount should not be positive.'))
|
||||
elif global_commission_amount < 0.0:
|
||||
if not self.commission_account_id:
|
||||
raise UserError(
|
||||
_('No commission account is set on the journal.'))
|
||||
else:
|
||||
commission_account_id = self.commission_account_id.id
|
||||
comm_values = {
|
||||
'name': _('Commission line'),
|
||||
'date_maturity': parser.get_move_vals().get('date') or
|
||||
fields.Date.today(),
|
||||
'debit': -global_commission_amount,
|
||||
'partner_id': partner_id,
|
||||
'move_id': move.id,
|
||||
'account_id': commission_account_id,
|
||||
'already_completed': True,
|
||||
}
|
||||
move_line_obj.with_context(
|
||||
check_move_validity=False
|
||||
).create(comm_values)
|
||||
|
||||
@api.multi
|
||||
def write_logs_after_import(self, move, num_lines):
|
||||
"""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(
|
||||
body=_('Move %s have been imported with %s '
|
||||
'lines.') % (move.name, num_lines))
|
||||
return True
|
||||
|
||||
def prepare_move_line_vals(self, parser_vals, move):
|
||||
"""Hook to build the values of a line from the parser returned values.
|
||||
At least it fullfill the basic values. 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.
|
||||
"""
|
||||
move_line_obj = self.env['account.move.line']
|
||||
values = parser_vals
|
||||
values['company_id'] = self.company_id.id
|
||||
values['currency_id'] = self.currency_id.id
|
||||
values['company_currency_id'] = self.company_id.currency_id.id
|
||||
values['journal_id'] = self.id
|
||||
values['move_id'] = move.id
|
||||
if not values.get('account_id', False):
|
||||
values['account_id'] = self.receivable_account_id.id
|
||||
values = move_line_obj._add_missing_default_values(values)
|
||||
return values
|
||||
|
||||
def prepare_move_vals(self, result_row_list, parser):
|
||||
"""Hook to build the values of the statement from the parser and
|
||||
the profile.
|
||||
"""
|
||||
vals = {'journal_id': self.id,
|
||||
'currency_id': self.currency_id.id}
|
||||
vals.update(parser.get_move_vals())
|
||||
return vals
|
||||
|
||||
def multi_move_import(self, file_stream, ftype="csv"):
|
||||
"""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
|
||||
"""
|
||||
filename = self._context.get('file_name', None)
|
||||
if filename:
|
||||
(filename, __) = os.path.splitext(filename)
|
||||
parser = new_move_parser(self, ftype=ftype, move_ref=filename)
|
||||
res = self.env['account.move']
|
||||
for result_row_list in parser.parse(file_stream):
|
||||
move = self._move_import(parser, file_stream, ftype=ftype)
|
||||
res |= move
|
||||
return res
|
||||
|
||||
def _move_import(self, parser, file_stream, ftype="csv"):
|
||||
"""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
|
||||
"""
|
||||
move_obj = self.env['account.move']
|
||||
move_line_obj = self.env['account.move.line']
|
||||
attachment_obj = self.env['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 UserError(_("Nothing to import: "
|
||||
"The file is empty"))
|
||||
parsed_cols = parser.get_move_line_vals(result_row_list[0]).keys()
|
||||
for col in parsed_cols:
|
||||
if col not in move_line_obj._columns:
|
||||
raise UserError(
|
||||
_("Missing column! Column %s you try to import is not "
|
||||
"present in the bank statement line!") % col)
|
||||
move_vals = self.prepare_move_vals(result_row_list, parser)
|
||||
move = move_obj.create(move_vals)
|
||||
try:
|
||||
# Record every line in the bank statement
|
||||
move_store = []
|
||||
for line in result_row_list:
|
||||
parser_vals = parser.get_move_line_vals(line)
|
||||
values = self.prepare_move_line_vals(parser_vals, move)
|
||||
move_store.append(values)
|
||||
# Hack to bypass ORM poor perfomance. Sob...
|
||||
move_line_obj._insert_lines(move_store)
|
||||
self.env.invalidate_all()
|
||||
self._write_extra_move_lines(parser, move)
|
||||
if self.create_counterpart:
|
||||
self._create_counterpart(parser, move)
|
||||
attachment_data = {
|
||||
'name': 'statement file',
|
||||
'datas': file_stream,
|
||||
'datas_fname': "%s.%s" % (fields.Date.today(), ftype),
|
||||
'res_model': 'account.move',
|
||||
'res_id': move.id,
|
||||
}
|
||||
attachment_obj.create(attachment_data)
|
||||
# If user ask to launch completion at end of import, do it!
|
||||
if self.launch_import_completion:
|
||||
move.button_auto_completion()
|
||||
# Write the needed log infos on profile
|
||||
self.write_logs_after_import(move, len(result_row_list))
|
||||
except UserError:
|
||||
# "Clean" exception, raise as such
|
||||
raise
|
||||
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))
|
||||
raise ValidationError(
|
||||
_("Statement import error"
|
||||
"The statement cannot be created: %s") % st)
|
||||
return move
|
||||
407
account_move_base_import/models/account_move.py
Normal file
407
account_move_base_import/models/account_move.py
Normal file
@@ -0,0 +1,407 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2011 Akretion
|
||||
# © 2011-2016 Camptocamp SA
|
||||
# © 2013 Savoir-faire Linux
|
||||
# © 2014 ACSONE SA/NV
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||
import traceback
|
||||
import sys
|
||||
import logging
|
||||
|
||||
import psycopg2
|
||||
|
||||
from openerp import _, api, fields, models
|
||||
from openerp.exceptions import ValidationError
|
||||
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ErrorTooManyPartner(Exception):
|
||||
""" New Exception definition that is raised when more than one partner is
|
||||
matched by the completion rule.
|
||||
"""
|
||||
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
|
||||
def __str__(self):
|
||||
return repr(self.value)
|
||||
|
||||
def __repr__(self):
|
||||
return repr(self.value)
|
||||
|
||||
|
||||
class AccountMoveCompletionRule(models.Model):
|
||||
"""This will represent all the completion method that we can have to
|
||||
fullfill the bank statement lines. You'll be able to extend them in you own
|
||||
module and choose those to apply for every statement profile.
|
||||
The goal of a rule is to fullfill at least the partner of the line, but
|
||||
if possible also the reference because we'll use it in the reconciliation
|
||||
process. The reference should contain the invoice number or the SO number
|
||||
or any reference that will be matched by the invoice accounting move.
|
||||
"""
|
||||
_name = "account.move.completion.rule"
|
||||
_order = "sequence asc"
|
||||
|
||||
sequence = fields.Integer(
|
||||
string='Sequence',
|
||||
help="Lower means parsed first.")
|
||||
name = fields.Char(
|
||||
string='Name')
|
||||
journal_ids = fields.Many2many(
|
||||
comodel_name='account.journal',
|
||||
relation='account_journal_completion_rule_rel',
|
||||
string='Related journals')
|
||||
function_to_call = fields.Selection([
|
||||
('get_from_name_and_invoice',
|
||||
'From line name (based on customer invoice number)'),
|
||||
('get_from_name_and_supplier_invoice',
|
||||
'From line name (based on supplier invoice number)'),
|
||||
('get_from_name_and_partner_field',
|
||||
'From line name (based on partner field)'),
|
||||
('get_from_name_and_partner_name',
|
||||
'From line name (based on partner name)')
|
||||
], string='Method')
|
||||
|
||||
def _find_invoice(self, line, inv_type):
|
||||
"""Find invoice related to statement line"""
|
||||
inv_obj = self.env['account.invoice']
|
||||
if inv_type == 'supplier':
|
||||
type_domain = ('in_invoice', 'in_refund')
|
||||
number_field = 'reference'
|
||||
elif inv_type == 'customer':
|
||||
type_domain = ('out_invoice', 'out_refund')
|
||||
number_field = 'number'
|
||||
else:
|
||||
raise ValidationError(
|
||||
_('Invalid invoice type for completion: %') % inv_type)
|
||||
|
||||
invoices = inv_obj.search([(number_field, '=', line.name.strip()),
|
||||
('type', 'in', type_domain)])
|
||||
if invoices:
|
||||
if len(invoices) == 1:
|
||||
return invoices
|
||||
else:
|
||||
raise ErrorTooManyPartner(
|
||||
_('Line named "%s" was matched by more than one '
|
||||
'partner while looking on %s invoices') %
|
||||
(line.name, inv_type))
|
||||
return False
|
||||
|
||||
def _from_invoice(self, line, inv_type):
|
||||
"""Populate statement line values"""
|
||||
if inv_type not in ('supplier', 'customer'):
|
||||
raise ValidationError(
|
||||
_('Invalid invoice type for completion: %') %
|
||||
inv_type)
|
||||
res = {}
|
||||
invoice = self._find_invoice(line, inv_type)
|
||||
if invoice:
|
||||
partner_id = invoice.commercial_partner_id.id
|
||||
res = {'partner_id': partner_id,
|
||||
'account_id': invoice.account_id.id}
|
||||
return res
|
||||
|
||||
# Should be private but data are initialised with no update XML
|
||||
def get_from_name_and_supplier_invoice(self, line):
|
||||
"""Match the partner based on the invoice number and the reference of
|
||||
the statement line. Then, call the generic get_values_for_line method
|
||||
to complete other values. If more than one partner matched, raise the
|
||||
ErrorTooManyPartner error.
|
||||
|
||||
:param dict line: read of the concerned account.bank.statement.line
|
||||
:return:
|
||||
A dict of value that can be passed directly to the write method of
|
||||
the statement line or {}
|
||||
{'partner_id': value,
|
||||
'account_id': value,
|
||||
...}
|
||||
"""
|
||||
return self._from_invoice(line, 'supplier')
|
||||
|
||||
# Should be private but data are initialised with no update XML
|
||||
def get_from_name_and_invoice(self, line):
|
||||
"""Match the partner based on the invoice number and the reference of
|
||||
the statement line. Then, call the generic get_values_for_line method
|
||||
to complete other values. If more than one partner matched, raise the
|
||||
ErrorTooManyPartner error.
|
||||
|
||||
:param dict line: read of the concerned account.bank.statement.line
|
||||
:return:
|
||||
A dict of value that can be passed directly to the write method of
|
||||
the statement line or {}
|
||||
{'partner_id': value,
|
||||
'account_id': value,
|
||||
...}
|
||||
"""
|
||||
return self._from_invoice(line, 'customer')
|
||||
|
||||
# Should be private but data are initialised with no update XML
|
||||
def get_from_name_and_partner_field(self, line):
|
||||
"""
|
||||
Match the partner based on the label field of the statement line and
|
||||
the text defined in the 'bank_statement_label' field of the partner.
|
||||
Remember that we can have values separated with ; Then, call the
|
||||
generic get_values_for_line method to complete other values. If more
|
||||
than one partner matched, raise the ErrorTooManyPartner error.
|
||||
|
||||
:param dict line: read of the concerned account.bank.statement.line
|
||||
:return:
|
||||
A dict of value that can be passed directly to the write method of
|
||||
the statement line or {}
|
||||
{'partner_id': value,
|
||||
'account_id': value,
|
||||
|
||||
...}
|
||||
"""
|
||||
res = {}
|
||||
partner_obj = self.env['res.partner']
|
||||
or_regex = ".*;? *%s *;?.*" % line.name
|
||||
sql = ("SELECT id from res_partner"
|
||||
" WHERE bank_statement_label ~* %s")
|
||||
self.env.cr.execute(sql, (or_regex, ))
|
||||
partner_ids = self.env.cr.fetchall()
|
||||
partners = partner_obj.browse([x[0] for x in partner_ids])
|
||||
if partners:
|
||||
if len(partners) > 1:
|
||||
msg = (_('Line named "%s" was matched by more than '
|
||||
'one partner while looking on partner label: %s') %
|
||||
(line.name,
|
||||
','.join([x.name for x in partners])))
|
||||
raise ErrorTooManyPartner(msg)
|
||||
res['partner_id'] = partners[0].id
|
||||
return res
|
||||
|
||||
def get_from_name_and_partner_name(self, line):
|
||||
"""Match the partner based on the label field of the statement line and
|
||||
the name of the partner. Then, call the generic get_values_for_line
|
||||
method to complete other values. If more than one partner matched,
|
||||
raise the ErrorTooManyPartner error.
|
||||
|
||||
:param dict st_line: read of the concerned account.bank.statement.line
|
||||
:return:
|
||||
A dict of value that can be passed directly to the write method of
|
||||
the statement line or {}
|
||||
{'partner_id': value,
|
||||
'account_id': value,
|
||||
|
||||
...}
|
||||
"""
|
||||
res = {}
|
||||
# The regexp_replace() escapes the name to avoid false positive
|
||||
# example: 'John J. Doe (No 1)' is escaped to 'John J\. Doe \(No 1\)'
|
||||
# See http://stackoverflow.com/a/400316/1504003 for a list of
|
||||
# chars to escape. Postgres is POSIX-ARE, compatible with
|
||||
# POSIX-ERE excepted that '\' must be escaped inside brackets according
|
||||
# to:
|
||||
# http://www.postgresql.org/docs/9.0/static/functions-matching.html
|
||||
# in chapter 9.7.3.6. Limits and Compatibility
|
||||
sql = r"""
|
||||
SELECT id FROM (
|
||||
SELECT id,
|
||||
regexp_matches(%s,
|
||||
regexp_replace(name,'([\.\^\$\*\+\?\(\)\[\{\\\|])', %s,
|
||||
'g'), 'i') AS name_match
|
||||
FROM res_partner)
|
||||
AS res_partner_matcher
|
||||
WHERE name_match IS NOT NULL"""
|
||||
self.env.cr.execute(sql, (line.name, r"\\\1"))
|
||||
result = self.env.cr.fetchall()
|
||||
if result:
|
||||
if len(result) > 1:
|
||||
raise ErrorTooManyPartner(
|
||||
_('Line named "%s" was matched by more than one '
|
||||
'partner while looking on partner by name') %
|
||||
line.name)
|
||||
res['partner_id'] = result[0][0]
|
||||
return res
|
||||
|
||||
|
||||
class AccountMoveLine(models.Model):
|
||||
"""
|
||||
Add sparse field on the statement line to allow to store all the bank infos
|
||||
that are given by a bank/office. You can then add you own in your module.
|
||||
The idea here is to store all bank/office infos in the
|
||||
additionnal_bank_fields serialized field when importing the file. If many
|
||||
values, add a tab in the bank statement line to store your specific one.
|
||||
Have a look in account_move_base_import module to see how we've done
|
||||
it.
|
||||
"""
|
||||
_inherit = "account.move.line"
|
||||
_order = "already_completed desc, date asc"
|
||||
|
||||
already_completed = fields.Boolean(
|
||||
string="Auto-Completed",
|
||||
default=False,
|
||||
help="When this checkbox is ticked, the auto-completion "
|
||||
"process/button will ignore this line.")
|
||||
|
||||
def _get_line_values_from_rules(self, rules):
|
||||
"""We'll try to find out the values related to the line based on rules
|
||||
setted on the profile.. We will ignore line for which already_completed
|
||||
is ticked.
|
||||
|
||||
:return:
|
||||
A dict of dict value that can be passed directly to the write
|
||||
method of the statement line or {}. The first dict has statement
|
||||
line ID as a key: {117009: {'partner_id': 100997,
|
||||
'account_id': 489L}}
|
||||
"""
|
||||
journal_obj = self.env['account.journal']
|
||||
for line in self:
|
||||
if not line.already_completed:
|
||||
# Ask the rule
|
||||
vals = journal_obj._find_values_from_rules(rules, line)
|
||||
if vals:
|
||||
vals['id'] = line['id']
|
||||
return vals
|
||||
return {}
|
||||
|
||||
def _get_available_columns(self, move_store):
|
||||
"""Return writeable by SQL columns"""
|
||||
model_cols = self._columns
|
||||
avail = [
|
||||
k for k, col in model_cols.iteritems() if not hasattr(col, '_fnct')
|
||||
]
|
||||
keys = [k for k in move_store[0].keys() if k in avail]
|
||||
keys.sort()
|
||||
return keys
|
||||
|
||||
def _prepare_insert(self, move, cols):
|
||||
""" Apply column formating to prepare data for SQL inserting
|
||||
Return a copy of statement
|
||||
"""
|
||||
move_copy = move
|
||||
for k, col in move_copy.iteritems():
|
||||
if k in cols:
|
||||
move_copy[k] = self._columns[k]._symbol_set[1](col)
|
||||
return move_copy
|
||||
|
||||
def _prepare_manyinsert(self, move_store, cols):
|
||||
""" Apply column formating to prepare multiple SQL inserts
|
||||
Return a copy of statement_store
|
||||
"""
|
||||
values = []
|
||||
for move in move_store:
|
||||
values.append(self._prepare_insert(move, cols))
|
||||
return values
|
||||
|
||||
def _insert_lines(self, move_store):
|
||||
""" Do raw insert into database because ORM is awfully slow
|
||||
when doing batch write. It is a shame that batch function
|
||||
does not exist"""
|
||||
self.check_access_rule('create')
|
||||
self.check_access_rights('create', raise_exception=True)
|
||||
cols = self._get_available_columns(move_store)
|
||||
move_store = self._prepare_manyinsert(move_store, cols)
|
||||
tmp_vals = (', '.join(cols), ', '.join(['%%(%s)s' % i for i in cols]))
|
||||
sql = "INSERT INTO account_move_line (%s) " \
|
||||
"VALUES (%s);" % tmp_vals
|
||||
try:
|
||||
self.env.cr.executemany(sql, tuple(move_store))
|
||||
except psycopg2.Error as sql_err:
|
||||
self.env.cr.rollback()
|
||||
raise ValidationError(_("ORM bypass error"),
|
||||
sql_err.pgerror)
|
||||
|
||||
def _update_line(self, vals):
|
||||
""" Do raw update into database because ORM is awfully slow
|
||||
when cheking security.
|
||||
"""
|
||||
cols = self._get_available_columns([vals])
|
||||
vals = self._prepare_insert(vals, cols)
|
||||
tmp_vals = (', '.join(['%s = %%(%s)s' % (i, i) for i in cols]))
|
||||
sql = "UPDATE account_move_line " \
|
||||
"SET %s where id = %%(id)s;" % tmp_vals
|
||||
try:
|
||||
self.env.cr.execute(sql, vals)
|
||||
except psycopg2.Error as sql_err:
|
||||
self.env.cr.rollback()
|
||||
raise ValidationError(_("ORM bypass error"),
|
||||
sql_err.pgerror)
|
||||
|
||||
|
||||
class AccountMove(models.Model):
|
||||
"""We add a basic button and stuff to support the auto-completion
|
||||
of the bank statement once line have been imported or manually fullfill.
|
||||
"""
|
||||
_name = 'account.move'
|
||||
_inherit = ['account.move', 'mail.thread']
|
||||
|
||||
used_for_completion = fields.Boolean(
|
||||
related='journal_id.used_for_completion',
|
||||
readonly=True)
|
||||
completion_logs = fields.Text(string='Completion Log', readonly=True)
|
||||
|
||||
def write_completion_log(self, error_msg, number_imported):
|
||||
"""Write the log in the completion_logs field of the bank statement to
|
||||
let the user know what have been done. This is an append mode, so we
|
||||
don't overwrite what already recoded.
|
||||
|
||||
:param int/long stat_id: ID of the account.bank.statement
|
||||
:param char error_msg: Message to add
|
||||
:number_imported int/long: Number of lines that have been completed
|
||||
:return True
|
||||
"""
|
||||
user_name = self.env.user.name
|
||||
number_line = len(self.line_ids)
|
||||
log = self.completion_logs or ""
|
||||
completion_date = fields.Datetime.now()
|
||||
message = (_("%s Account Move %s has %s/%s lines completed by "
|
||||
"%s \n%s\n%s\n") % (completion_date, self.name,
|
||||
number_imported, number_line,
|
||||
user_name, error_msg, log))
|
||||
self.write({'completion_logs': message})
|
||||
|
||||
body = (_('Statement ID %s auto-completed for %s/%s lines completed') %
|
||||
(self.name, number_imported, number_line)),
|
||||
self.message_post(body=body)
|
||||
return True
|
||||
|
||||
@api.multi
|
||||
def button_auto_completion(self):
|
||||
"""Complete line with values given by rules and tic the
|
||||
already_completed checkbox so we won't compute them again unless the
|
||||
user untick them!
|
||||
"""
|
||||
move_line_obj = self.env['account.move.line']
|
||||
compl_lines = 0
|
||||
move_line_obj.check_access_rule('create')
|
||||
move_line_obj.check_access_rights('create', raise_exception=True)
|
||||
for move in self:
|
||||
msg_lines = []
|
||||
journal = move.journal_id
|
||||
rules = journal._get_rules()
|
||||
res = False
|
||||
for line in move.line_ids:
|
||||
try:
|
||||
res = line._get_line_values_from_rules(rules)
|
||||
if res:
|
||||
compl_lines += 1
|
||||
except ErrorTooManyPartner, exc:
|
||||
msg_lines.append(repr(exc))
|
||||
except Exception, exc:
|
||||
msg_lines.append(repr(exc))
|
||||
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))
|
||||
_logger.error(st)
|
||||
if res:
|
||||
try:
|
||||
move_line_obj._update_line(res)
|
||||
except Exception as exc:
|
||||
msg_lines.append(repr(exc))
|
||||
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))
|
||||
_logger.error(st)
|
||||
# we can commit as it is not needed to be atomic
|
||||
# commiting here adds a nice perfo boost
|
||||
if not compl_lines % 500:
|
||||
self.env.cr.commit()
|
||||
msg = u'\n'.join(msg_lines)
|
||||
self.write_completion_log(msg, compl_lines)
|
||||
return True
|
||||
22
account_move_base_import/models/partner.py
Normal file
22
account_move_base_import/models/partner.py
Normal file
@@ -0,0 +1,22 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2011 Akretion
|
||||
# © 2011-2016 Camptocamp SA
|
||||
# © 2013 Savoir-faire Linux
|
||||
# © 2014 ACSONE SA/NV
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||
from openerp import fields, models
|
||||
|
||||
|
||||
class ResPartner(models.Model):
|
||||
"""Add a bank label on the partner so that we can use it to match
|
||||
this partner when we found this in a statement line.
|
||||
"""
|
||||
_inherit = 'res.partner'
|
||||
|
||||
bank_statement_label = fields.Char(
|
||||
string='Bank Statement Label',
|
||||
help="Enter the various label found on your bank statement "
|
||||
"separated by a ; If one of this label is include in the "
|
||||
"bank statement line, the partner will be automatically "
|
||||
"filled (as long as you use this method/rules in your "
|
||||
"statement profile).")
|
||||
10
account_move_base_import/parser/__init__.py
Normal file
10
account_move_base_import/parser/__init__.py
Normal file
@@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2011 Akretion
|
||||
# © 2011-2016 Camptocamp SA
|
||||
# © 2013 Savoir-faire Linux
|
||||
# © 2014 ACSONE SA/NV
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||
from .parser import new_move_parser
|
||||
from .parser import AccountMoveImportParser
|
||||
from . import file_parser
|
||||
from . import generic_file_parser
|
||||
@@ -1,28 +1,14 @@
|
||||
# -*- 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/>.
|
||||
#
|
||||
##############################################################################
|
||||
# © 2011 Akretion
|
||||
# © 2011-2016 Camptocamp SA
|
||||
# © 2013 Savoir-faire Linux
|
||||
# © 2014 ACSONE SA/NV
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||
from openerp.tools.translate import _
|
||||
from openerp.osv.orm import except_orm
|
||||
from openerp.exceptions import UserError
|
||||
import tempfile
|
||||
import datetime
|
||||
from .parser import BankStatementImportParser
|
||||
from .parser import UnicodeDictReader
|
||||
from .parser import AccountMoveImportParser, UnicodeDictReader
|
||||
try:
|
||||
import xlrd
|
||||
except:
|
||||
@@ -35,13 +21,13 @@ def float_or_zero(val):
|
||||
return float(val) if val else 0.0
|
||||
|
||||
|
||||
class FileParser(BankStatementImportParser):
|
||||
class FileParser(AccountMoveImportParser):
|
||||
"""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):
|
||||
def __init__(self, journal, ftype='csv', extra_fields=None, header=None,
|
||||
dialect=None, move_ref=None, **kwargs):
|
||||
"""
|
||||
:param char: parse_name: The name of the parser
|
||||
:param char: ftype: extension of the file (could be csv, xls or
|
||||
@@ -51,12 +37,11 @@ class FileParser(BankStatementImportParser):
|
||||
:param list: header : specify header fields if the csv file has no
|
||||
header
|
||||
"""
|
||||
super(FileParser, self).__init__(parse_name, **kwargs)
|
||||
super(FileParser, self).__init__(journal, **kwargs)
|
||||
if ftype in ('csv', 'xls', 'xlsx'):
|
||||
self.ftype = ftype[0:3]
|
||||
else:
|
||||
raise except_orm(
|
||||
_('User Error'),
|
||||
raise UserError(
|
||||
_('Invalid file type %s. Please use csv, xls or xlsx') % ftype)
|
||||
self.conversion_dict = extra_fields
|
||||
self.keys_to_validate = self.conversion_dict.keys()
|
||||
@@ -65,6 +50,7 @@ class FileParser(BankStatementImportParser):
|
||||
# 0 means Windows mode (1900 based dates).
|
||||
# Set in _parse_xls, from the contents of the file
|
||||
self.dialect = dialect
|
||||
self.move_ref = move_ref
|
||||
|
||||
def _custom_format(self, *args, **kwargs):
|
||||
"""No other work on data are needed in this parser."""
|
||||
@@ -96,8 +82,7 @@ class FileParser(BankStatementImportParser):
|
||||
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)
|
||||
raise UserError(_('Column %s not present in file') % col)
|
||||
return True
|
||||
|
||||
def _post(self, *args, **kwargs):
|
||||
@@ -143,9 +128,9 @@ class FileParser(BankStatementImportParser):
|
||||
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"
|
||||
raise UserError(
|
||||
_("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')),
|
||||
@@ -154,8 +139,7 @@ class FileParser(BankStatementImportParser):
|
||||
try:
|
||||
line[rule] = conversion_rules[rule](line[rule])
|
||||
except Exception as err:
|
||||
raise except_orm(
|
||||
_('Invalid data'),
|
||||
raise UserError(
|
||||
_("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,
|
||||
@@ -174,9 +158,9 @@ class FileParser(BankStatementImportParser):
|
||||
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 "
|
||||
raise UserError(
|
||||
_("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')),
|
||||
@@ -185,8 +169,7 @@ class FileParser(BankStatementImportParser):
|
||||
try:
|
||||
line[rule] = conversion_rules[rule](line[rule])
|
||||
except Exception as err:
|
||||
raise except_orm(
|
||||
_('Invalid data'),
|
||||
raise UserError(
|
||||
_("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,
|
||||
82
account_move_base_import/parser/generic_file_parser.py
Normal file
82
account_move_base_import/parser/generic_file_parser.py
Normal file
@@ -0,0 +1,82 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2011 Akretion
|
||||
# © 2011-2016 Camptocamp SA
|
||||
# © 2013 Savoir-faire Linux
|
||||
# © 2014 ACSONE SA/NV
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||
import datetime
|
||||
from .file_parser import FileParser
|
||||
from openerp.addons.account_move_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, journal, ftype='csv', **kwargs):
|
||||
conversion_dict = {
|
||||
'label': ustr,
|
||||
'date': datetime.datetime,
|
||||
'amount': float_or_zero,
|
||||
}
|
||||
# set self.env for later ORM searches
|
||||
self.env = journal.env
|
||||
super(GenericFileParser, self).__init__(
|
||||
journal, 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_move_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_maturity':value,
|
||||
'credit':value,
|
||||
'debit':value
|
||||
}
|
||||
"""
|
||||
account_obj = self.env['account.account']
|
||||
partner_obj = self.env['res.partner']
|
||||
account_id = False
|
||||
partner_id = False
|
||||
|
||||
if line.get('account'):
|
||||
accounts = account_obj.search([('code', '=', line['account'])])
|
||||
if len(accounts) == 1:
|
||||
account_id = accounts[0].id
|
||||
|
||||
if line.get('partner'):
|
||||
partners = partner_obj.search([('name', '=', line['partner'])])
|
||||
if len(partners) == 1:
|
||||
partner_id = partners[0].id
|
||||
|
||||
amount = line.get('amount', 0.0)
|
||||
return {
|
||||
'name': line.get('label', '/'),
|
||||
'date_maturity': line.get('date', datetime.datetime.now().date()),
|
||||
'credit': amount > 0.0 and amount or 0.0,
|
||||
'debit': amount < 0.0 and -amount or 0.0,
|
||||
'account_id': account_id,
|
||||
'partner_id': partner_id,
|
||||
}
|
||||
@@ -1,27 +1,12 @@
|
||||
# -*- 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/>.
|
||||
#
|
||||
##############################################################################
|
||||
# © 2011 Akretion
|
||||
# © 2011-2016 Camptocamp SA
|
||||
# © 2013 Savoir-faire Linux
|
||||
# © 2014 ACSONE SA/NV
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||
import base64
|
||||
import csv
|
||||
from datetime import datetime
|
||||
from openerp.tools.translate import _
|
||||
from openerp import _, fields
|
||||
|
||||
|
||||
def UnicodeDictReader(utf8_data, **kwargs):
|
||||
@@ -41,7 +26,7 @@ def UnicodeDictReader(utf8_data, **kwargs):
|
||||
for key, value in row.iteritems()])
|
||||
|
||||
|
||||
class BankStatementImportParser(object):
|
||||
class AccountMoveImportParser(object):
|
||||
|
||||
"""
|
||||
Generic abstract class for defining parser for different files and
|
||||
@@ -50,21 +35,20 @@ class BankStatementImportParser(object):
|
||||
from the FileParser instead.
|
||||
"""
|
||||
|
||||
def __init__(self, profile, *args, **kwargs):
|
||||
def __init__(self, journal, *args, **kwargs):
|
||||
# The name of the parser as it will be called
|
||||
self.parser_name = profile.import_type
|
||||
self.parser_name = journal.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
|
||||
self.journal = journal
|
||||
self.move_date = None
|
||||
self.move_name = None
|
||||
self.move_ref = None
|
||||
self.support_multi_moves = None
|
||||
|
||||
@classmethod
|
||||
def parser_for(cls, parser_name):
|
||||
@@ -119,19 +103,18 @@ class BankStatementImportParser(object):
|
||||
"""
|
||||
return NotImplementedError
|
||||
|
||||
def get_st_vals(self):
|
||||
def get_move_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()
|
||||
'name': self.move_name or '/',
|
||||
'date': self.move_date or fields.Datetime.now(),
|
||||
'ref': self.move_ref or '/'
|
||||
}
|
||||
|
||||
def get_st_line_vals(self, line, *args, **kwargs):
|
||||
def get_move_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
|
||||
@@ -165,7 +148,7 @@ class BankStatementImportParser(object):
|
||||
raise Exception(_('No buffer file given.'))
|
||||
self._format(*args, **kwargs)
|
||||
self._pre(*args, **kwargs)
|
||||
if self.support_multi_statements:
|
||||
if self.support_multi_moves:
|
||||
while self._parse(*args, **kwargs):
|
||||
self._validate(*args, **kwargs)
|
||||
self._post(*args, **kwargs)
|
||||
@@ -218,13 +201,13 @@ def itersubclasses(cls, _seen=None):
|
||||
yield sub
|
||||
|
||||
|
||||
def new_bank_statement_parser(profile, *args, **kwargs):
|
||||
def new_move_parser(journal, *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)
|
||||
for cls in itersubclasses(AccountMoveImportParser):
|
||||
if cls.parser_for(journal.import_type):
|
||||
return cls(journal, *args, **kwargs)
|
||||
raise ValueError
|
||||
3
account_move_base_import/security/ir.model.access.csv
Normal file
3
account_move_base_import/security/ir.model.access.csv
Normal file
@@ -0,0 +1,3 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_account_bank_st_cmpl_user,account.move.completion.rule.user,model_account_move_completion_rule,account.group_account_user,1,0,0,0
|
||||
access_account_bank_st_cmpl_manager,account.move.completion.rule.manager,model_account_move_completion_rule,account.group_account_manager,1,1,1,1
|
||||
|
122
account_move_base_import/test/completion_test.yml
Normal file
122
account_move_base_import/test/completion_test.yml
Normal file
@@ -0,0 +1,122 @@
|
||||
-
|
||||
In order to test the banking framework, I first need to create a journal
|
||||
-
|
||||
!record {model: account.journal, id: account.bank_journal}:
|
||||
used_for_completion: True
|
||||
rule_ids:
|
||||
- bank_statement_completion_rule_4
|
||||
- bank_statement_completion_rule_2
|
||||
- bank_statement_completion_rule_3
|
||||
- bank_statement_completion_rule_5
|
||||
-
|
||||
Now I create a statement. I create statment lines separately because I need
|
||||
to find each one by XML id
|
||||
-
|
||||
!record {model: account.move, id: move_test1}:
|
||||
name: Move 2
|
||||
journal_id: account.bank_journal
|
||||
company_id: base.main_company
|
||||
-
|
||||
I create a move line for a CI
|
||||
-
|
||||
!record {model: account.move.line, id: move_line_ci}:
|
||||
name: \
|
||||
account_id: account.a_sale
|
||||
move_id: move_test1
|
||||
date_maturity: '2013-12-20'
|
||||
credit: 0.0
|
||||
-
|
||||
I create a move line for a SI
|
||||
-
|
||||
!record {model: account.move.line, id: move_line_si}:
|
||||
name: \
|
||||
account_id: account.a_expense
|
||||
move_id: move_test1
|
||||
date_maturity: '2013-12-19'
|
||||
debit: 0.0
|
||||
-
|
||||
I create a move line for a CR
|
||||
-
|
||||
!record {model: account.move.line, id: move_line_cr}:
|
||||
name: \
|
||||
account_id: account.a_expense
|
||||
move_id: move_test1
|
||||
date_maturity: '2013-12-19'
|
||||
debit: 0.0
|
||||
-
|
||||
I create a move line for the Partner Name
|
||||
-
|
||||
!record {model: account.move.line, id: move_line_partner_name}:
|
||||
name: Test autocompletion based on Partner Name Camptocamp
|
||||
account_id: account.a_sale
|
||||
move_id: move_test1
|
||||
date_maturity: '2013-12-17'
|
||||
credit: 0.0
|
||||
-
|
||||
I create a move line for the Partner Label
|
||||
-
|
||||
!record {model: account.move.line, id: move_line_partner_label}:
|
||||
name: XXX66Z
|
||||
account_id: account.a_sale
|
||||
move_id: move_test1
|
||||
date_maturity: '2013-12-24'
|
||||
debit: 0.0
|
||||
-
|
||||
and add the correct name
|
||||
-
|
||||
!python {model: account.move.line}: |
|
||||
import datetime as dt
|
||||
context['check_move_validity'] = False
|
||||
model.write(cr, uid, [ref('move_line_ci')],
|
||||
{'name': dt.date.today().strftime('TBNK/%Y/0001'),
|
||||
'credit': 210.0},
|
||||
context)
|
||||
model.write(cr, uid, [ref('move_line_si')],
|
||||
{'name': 'T2S12345',
|
||||
'debit': 65.0},
|
||||
context)
|
||||
model.write(cr, uid, [ref('move_line_cr')],
|
||||
{'name': dt.date.today().strftime('RTEXJ/%Y/0001'),
|
||||
'debit': 210.0},
|
||||
context)
|
||||
model.write(cr, uid, [ref('move_line_partner_name')],
|
||||
{'credit': 600.0},
|
||||
context)
|
||||
model.write(cr, uid, [ref('move_line_partner_label')],
|
||||
{'debit': 932.4},
|
||||
context)
|
||||
-
|
||||
I run the auto complete
|
||||
-
|
||||
!python {model: account.move}: |
|
||||
result = self.button_auto_completion(cr, uid, [ref("move_test1")])
|
||||
-
|
||||
Now I can check that all is nice and shiny, line 1. I expect the Customer
|
||||
Invoice Number to be recognised.
|
||||
I Use _ref, because ref conflicts with the field ref of the statement line
|
||||
-
|
||||
!assert {model: account.move.line, id: move_line_ci, string: Check completion by CI number}:
|
||||
- partner_id.id == _ref("base.res_partner_12")
|
||||
-
|
||||
Line 2. I expect the Supplier invoice number to be recognised. The supplier
|
||||
invoice was created by the account module demo data, and we confirmed it
|
||||
here.
|
||||
-
|
||||
!assert {model: account.move.line, id: move_line_si, string: Check completion by SI number}:
|
||||
- partner_id.id == _ref("base.res_partner_12")
|
||||
-
|
||||
Line 3. I expect the Customer refund number to be recognised. It should be
|
||||
the commercial partner, and not the regular partner.
|
||||
-
|
||||
!assert {model: account.move.line, id: move_line_cr, string: Check completion by CR number and commercial partner}:
|
||||
- partner_id.id == _ref("base.res_partner_12")
|
||||
-
|
||||
Line 4. I check that the partner name has been recognised.
|
||||
-
|
||||
!assert {model: account.move.line, id: move_line_partner_name, string: Check completion by partner name}:
|
||||
- partner_id.name == 'Camptocamp'
|
||||
-
|
||||
Line 5. I check that the partner special label has been recognised.
|
||||
-
|
||||
!assert {model: account.move.line, id: move_line_partner_label, string: Check completion by partner label}:
|
||||
- partner_id.id == _ref("base.res_partner_4")
|
||||
42
account_move_base_import/test/invoice.yml
Normal file
42
account_move_base_import/test/invoice.yml
Normal file
@@ -0,0 +1,42 @@
|
||||
-
|
||||
I import account minimal data
|
||||
-
|
||||
!python {model: account.invoice}: |
|
||||
openerp.tools.convert_file(cr,
|
||||
'account',
|
||||
openerp.modules.get_module_resource(
|
||||
'account',
|
||||
'test',
|
||||
'account_minimal_test.xml'),
|
||||
{}, 'init', False, 'test')
|
||||
-
|
||||
I create a customer Invoice to be found by the completion.
|
||||
-
|
||||
!record {model: account.invoice, id: invoice_for_completion_1}:
|
||||
company_id: base.main_company
|
||||
currency_id: base.EUR
|
||||
invoice_line_ids:
|
||||
- name: '[PCSC234] PC Assemble SC234'
|
||||
price_unit: 210.0
|
||||
quantity: 1.0
|
||||
product_id: product.product_product_3
|
||||
uom_id: product.product_uom_unit
|
||||
journal_id: account.bank_journal
|
||||
partner_id: base.res_partner_12
|
||||
reference_type: none
|
||||
-
|
||||
I confirm the Invoice
|
||||
-
|
||||
!workflow {model: account.invoice, action: invoice_open, ref: invoice_for_completion_1}
|
||||
-
|
||||
I check that the invoice state is "Open"
|
||||
-
|
||||
!assert {model: account.invoice, id: invoice_for_completion_1}:
|
||||
- state == 'open'
|
||||
-
|
||||
I check that it is given the number "TBNK/%Y/0001"
|
||||
-
|
||||
!python {model: account.invoice}: |
|
||||
import datetime as dt
|
||||
invoice = model.browse(cr, uid, ref('invoice_for_completion_1'), context)
|
||||
assert invoice.number == dt.date.today().strftime('TBNK/%Y/0001')
|
||||
@@ -1,5 +1,5 @@
|
||||
-
|
||||
I fill in the field Bank Statement Label in a Partner
|
||||
-
|
||||
!record {model: res.partner, id: base.res_partner_6}:
|
||||
!record {model: res.partner, id: base.res_partner_4}:
|
||||
bank_statement_label: XXX66Z
|
||||
@@ -12,17 +12,14 @@
|
||||
I create a customer refund to be found by the completion.
|
||||
-
|
||||
!record {model: account.invoice, id: refund_for_completion_1}:
|
||||
account_id: account.a_pay
|
||||
company_id: base.main_company
|
||||
currency_id: base.EUR
|
||||
internal_number: CR0001
|
||||
invoice_line:
|
||||
- account_id: account.a_expense
|
||||
name: '[PCSC234] PC Assemble SC234'
|
||||
invoice_line_ids:
|
||||
- name: '[PCSC234] PC Assemble SC234'
|
||||
price_unit: 210.0
|
||||
quantity: 1.0
|
||||
product_id: product.product_product_3
|
||||
uos_id: product.product_uom_unit
|
||||
uom_id: product.product_uom_unit
|
||||
journal_id: account.expenses_journal
|
||||
partner_id: res_partner_12_child
|
||||
type: 'out_refund'
|
||||
@@ -37,7 +34,9 @@
|
||||
!assert {model: account.invoice, id: refund_for_completion_1}:
|
||||
- state == 'open'
|
||||
-
|
||||
I check that it is given the number "CR0001"
|
||||
I check that it is given the number "RTEXJ/%Y/0001"
|
||||
-
|
||||
!assert {model: account.invoice, id: refund_for_completion_1, string: Check CI number}:
|
||||
- number == 'CR0001'
|
||||
!python {model: account.invoice}: |
|
||||
import datetime as dt
|
||||
invoice = model.browse(cr, uid, ref('refund_for_completion_1'), context)
|
||||
assert invoice.number == dt.date.today().strftime('RTEXJ/%Y/0001')
|
||||
@@ -1,3 +1,14 @@
|
||||
-
|
||||
I import account minimal data
|
||||
-
|
||||
!python {model: account.invoice}: |
|
||||
openerp.tools.convert_file(cr,
|
||||
'account',
|
||||
openerp.modules.get_module_resource(
|
||||
'account',
|
||||
'demo',
|
||||
'account_invoice_demo.yml'),
|
||||
{}, 'init', False, 'test')
|
||||
-
|
||||
I check that my invoice is a supplier invoice
|
||||
-
|
||||
@@ -8,7 +19,7 @@
|
||||
-
|
||||
!python {model: account.invoice}: |
|
||||
self.write(cr, uid, ref('account.demo_invoice_0'), {
|
||||
'supplier_invoice_number': 'T2S12345'
|
||||
'reference': 'T2S12345'
|
||||
})
|
||||
-
|
||||
I check a second time that my invoice is still a supplier invoice
|
||||
@@ -23,7 +34,7 @@
|
||||
I check that the supplier number is there
|
||||
-
|
||||
!assert {model: account.invoice, id: account.demo_invoice_0, string: Check supplier number}:
|
||||
- supplier_invoice_number == 'T2S12345'
|
||||
- reference == 'T2S12345'
|
||||
-
|
||||
I check a third time that my invoice is still a supplier invoice
|
||||
-
|
||||
8
account_move_base_import/tests/__init__.py
Normal file
8
account_move_base_import/tests/__init__.py
Normal file
@@ -0,0 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2011 Akretion
|
||||
# © 2011-2016 Camptocamp SA
|
||||
# © 2013 Savoir-faire Linux
|
||||
# © 2014 ACSONE SA/NV
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||
from . import test_base_completion
|
||||
from . import test_base_import
|
||||
95
account_move_base_import/tests/test_base_completion.py
Normal file
95
account_move_base_import/tests/test_base_completion.py
Normal file
@@ -0,0 +1,95 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2011 Akretion
|
||||
# © 2011-2016 Camptocamp SA
|
||||
# © 2013 Savoir-faire Linux
|
||||
# © 2014 ACSONE SA/NV
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||
from openerp import fields, tools
|
||||
from openerp.modules import get_module_resource
|
||||
from openerp.tests import common
|
||||
from collections import namedtuple
|
||||
|
||||
name_completion_case = namedtuple(
|
||||
"name_completion_case", ["partner_name", "line_label", "should_match"])
|
||||
NAMES_COMPLETION_CASES = [
|
||||
name_completion_case("Acsone", "Line for Acsone SA", True),
|
||||
name_completion_case("Acsone", "Line for Acsone", True),
|
||||
name_completion_case("Acsone", "Acsone for line", True),
|
||||
name_completion_case("acsone", "Acsone for line", True),
|
||||
name_completion_case("Acsone SA", "Line for Acsone SA test", True),
|
||||
name_completion_case("Ac..ne", "Acsone for line", False),
|
||||
name_completion_case("é@|r{}", "Acsone é@|r{} for line", True),
|
||||
name_completion_case("Acsone", "A..one for line", False),
|
||||
name_completion_case("A.one SA", "A.one SA for line", True),
|
||||
name_completion_case(
|
||||
"Acsone SA", "Line for Acsone ([^a-zA-Z0-9 -]) SA test", False),
|
||||
name_completion_case(
|
||||
"Acsone ([^a-zA-Z0-9 -]) SA", "Line for Acsone ([^a-zA-Z0-9 -]) SA "
|
||||
"test", True),
|
||||
name_completion_case(
|
||||
r"Acsone (.^$*+?()[{\| -]\) SA", r"Line for Acsone (.^$*+?()[{\| -]\) "
|
||||
r"SA test", True),
|
||||
name_completion_case("Acšone SA", "Line for Acšone SA test", True),
|
||||
]
|
||||
|
||||
|
||||
class BaseCompletion(common.TransactionCase):
|
||||
|
||||
def setUp(self):
|
||||
super(BaseCompletion, self).setUp()
|
||||
tools.convert_file(self.cr, 'account',
|
||||
get_module_resource('account', 'test',
|
||||
'account_minimal_test.xml'),
|
||||
{}, 'init', False, 'test')
|
||||
self.account_move_obj = self.env["account.move"]
|
||||
self.account_move_line_obj = \
|
||||
self.env["account.move.line"]
|
||||
self.company_a = self.browse_ref('base.main_company')
|
||||
self.journal = self.browse_ref("account.bank_journal")
|
||||
self.partner = self.browse_ref("base.res_partner_12")
|
||||
self.account_id = self.ref("account.a_recv")
|
||||
|
||||
def test_name_completion(self):
|
||||
"""Test complete partner_id from statement line label
|
||||
Test the automatic completion of the partner_id based if the name of
|
||||
the partner appears in the statement line label
|
||||
"""
|
||||
self.completion_rule_id = self.ref(
|
||||
'account_move_base_import.bank_statement_completion_rule_3')
|
||||
# Create the profile
|
||||
self.journal.write({
|
||||
'used_for_completion': True,
|
||||
'rule_ids': [(6, 0, [self.completion_rule_id])]
|
||||
})
|
||||
# Create a bank statement
|
||||
self.move = self.account_move_obj.create({
|
||||
"date": fields.Date.today(),
|
||||
"journal_id": self.journal.id
|
||||
})
|
||||
|
||||
for case in NAMES_COMPLETION_CASES:
|
||||
self.partner.write({'name': case.partner_name})
|
||||
self.move_line = self.account_move_line_obj.with_context(
|
||||
check_move_validity=False
|
||||
).create({
|
||||
'account_id': self.account_id,
|
||||
'credit': 1000.0,
|
||||
'name': case.line_label,
|
||||
'move_id': self.move.id,
|
||||
})
|
||||
self.assertFalse(
|
||||
self.move_line.partner_id,
|
||||
"Partner_id must be blank before completion")
|
||||
self.move.button_auto_completion()
|
||||
if case.should_match:
|
||||
self.assertEquals(
|
||||
self.partner, self.move_line.partner_id,
|
||||
"Missing expected partner id after completion "
|
||||
"(partner_name: %s, line_name: %s)" %
|
||||
(case.partner_name, case.line_label))
|
||||
else:
|
||||
self.assertNotEquals(
|
||||
self.partner, self.move_line.partner_id,
|
||||
"Partner id should be empty after completion "
|
||||
"(partner_name: %s, line_name: %s)"
|
||||
% (case.partner_name, case.line_label))
|
||||
82
account_move_base_import/tests/test_base_import.py
Normal file
82
account_move_base_import/tests/test_base_import.py
Normal file
@@ -0,0 +1,82 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2011 Akretion
|
||||
# © 2011-2016 Camptocamp SA
|
||||
# © 2013 Savoir-faire Linux
|
||||
# © 2014 ACSONE SA/NV
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||
import base64
|
||||
import inspect
|
||||
import os
|
||||
from operator import attrgetter
|
||||
from openerp.tests import common
|
||||
from openerp import tools
|
||||
from openerp.modules import get_module_resource
|
||||
|
||||
|
||||
class TestCodaImport(common.TransactionCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestCodaImport, self).setUp()
|
||||
self.company_a = self.browse_ref('base.main_company')
|
||||
tools.convert_file(self.cr, 'account',
|
||||
get_module_resource('account', 'test',
|
||||
'account_minimal_test.xml'),
|
||||
{}, 'init', False, 'test')
|
||||
self.account_move_obj = self.env["account.move"]
|
||||
self.account_move_line_obj = self.env["account.move.line"]
|
||||
self.account_id = self.ref("account.a_recv")
|
||||
self.journal = self.browse_ref("account.bank_journal")
|
||||
self.import_wizard_obj = self.env['credit.statement.import']
|
||||
self.partner = self.browse_ref("base.res_partner_12")
|
||||
self.journal.write({
|
||||
'used_for_import': True,
|
||||
"import_type": "generic_csvxls_so",
|
||||
'partner_id': self.partner.id,
|
||||
'commission_account_id': self.account_id,
|
||||
'receivable_account_id': self.account_id,
|
||||
'create_counterpart': True,
|
||||
})
|
||||
|
||||
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()
|
||||
self.wizard = self.import_wizard_obj.create({
|
||||
"journal_id": self.journal.id,
|
||||
'input_statement': base64.b64encode(content),
|
||||
'file_name': os.path.basename(file_name),
|
||||
})
|
||||
res = self.wizard.import_statement()
|
||||
return self.account_move_obj.browse(res['res_id'])
|
||||
|
||||
def test_simple_xls(self):
|
||||
"""Test import from xls
|
||||
"""
|
||||
file_name = self._filename_to_abs_filename(
|
||||
os.path.join("..", "data", "statement.xls"))
|
||||
move = self._import_file(file_name)
|
||||
self._validate_imported_move(move)
|
||||
|
||||
def test_simple_csv(self):
|
||||
"""Test import from csv
|
||||
"""
|
||||
file_name = self._filename_to_abs_filename(
|
||||
os.path.join("..", "data", "statement.csv"))
|
||||
move = self._import_file(file_name)
|
||||
self._validate_imported_move(move)
|
||||
|
||||
def _validate_imported_move(self, move):
|
||||
self.assertEqual("/", move.name)
|
||||
self.assertEqual(5, len(move.line_ids))
|
||||
move_line = sorted(move.line_ids,
|
||||
key=attrgetter('date_maturity'))[2]
|
||||
# common infos
|
||||
self.assertEqual(move_line.date_maturity, "2011-03-07")
|
||||
self.assertEqual(move_line.credit, 118.4)
|
||||
self.assertEqual(move_line.name, "label a")
|
||||
67
account_move_base_import/views/account_move_view.xml
Normal file
67
account_move_base_import/views/account_move_view.xml
Normal file
@@ -0,0 +1,67 @@
|
||||
<odoo>
|
||||
<record id="view_move_importer_form" model="ir.ui.view">
|
||||
<field name="name">account.move.view</field>
|
||||
<field name="model">account.move</field>
|
||||
<field name="inherit_id" ref="account.view_move_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="journal_id" position="after">
|
||||
<field name="used_for_completion" invisible="1"/>
|
||||
</field>
|
||||
<button name="button_cancel" position="after">
|
||||
<button name="button_auto_completion"
|
||||
string="Auto Completion"
|
||||
type="object"
|
||||
class="oe_highlight"
|
||||
groups="account.group_account_invoice"
|
||||
attrs="{'invisible': ['|', ('used_for_completion','=',False), ('state','not in', ['draft'])]}"/>
|
||||
</button>
|
||||
<xpath expr="//field[@name='line_ids']/tree/field[@name='credit']" position="after">
|
||||
<field name="already_completed"/>
|
||||
</xpath>
|
||||
<xpath expr="/form/sheet/notebook" position="inside">
|
||||
<page string="Completion Logs" attrs="{'invisible':[('completion_logs','=',False)]}">
|
||||
<field name="completion_logs" colspan="4" nolabel="1"/>
|
||||
</page>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="move_completion_rule_view_form" model="ir.ui.view">
|
||||
<field name="name">account.move.completion.rule.view</field>
|
||||
<field name="model">account.move.completion.rule</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Move Completion Rule">
|
||||
<group>
|
||||
<field name="sequence"/>
|
||||
<field name="name" select="1" />
|
||||
<field name="function_to_call"/>
|
||||
</group>
|
||||
<separator colspan="4" string="Related Profiles"/>
|
||||
<field name="journal_ids" nolabel="1" colspan="4"/>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="move_completion_rule_view_tree" model="ir.ui.view">
|
||||
<field name="name">account.move.completion.rule.view</field>
|
||||
<field name="model">account.move.completion.rule</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Move Completion Rule">
|
||||
<field name="sequence"/>
|
||||
<field name="name" select="1" />
|
||||
<field name="journal_ids" />
|
||||
<field name="function_to_call"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_move_completion_rule_tree" model="ir.actions.act_window">
|
||||
<field name="name">Move Completion Rule</field>
|
||||
<field name="res_model">account.move.completion.rule</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
</record>
|
||||
|
||||
<menuitem string="Move Completion Rule" action="action_move_completion_rule_tree"
|
||||
id="menu_action_move_completion_rule_tree_menu" parent="account.account_management_menu"/>
|
||||
</odoo>
|
||||
44
account_move_base_import/views/journal_view.xml
Normal file
44
account_move_base_import/views/journal_view.xml
Normal file
@@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="journal_importer_view_form" model="ir.ui.view">
|
||||
<field name="name">account.journal.view</field>
|
||||
<field name="model">account.journal</field>
|
||||
<field name="inherit_id" ref="account.view_account_journal_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="loss_account_id" position="after">
|
||||
<field name="used_for_import"/>
|
||||
<field name="used_for_completion"/>
|
||||
</field>
|
||||
<notebook position="inside">
|
||||
<page string="Import related infos" attrs="{'invisible': [('used_for_import', '=', False)]}">
|
||||
<group>
|
||||
<field name="launch_import_completion" attrs="{'invisible': ['|',
|
||||
('used_for_import', '=', False),
|
||||
('used_for_completion', '=', False)]}"/>
|
||||
<field name="last_import_date" readonly="1"/>
|
||||
<field name="import_type" attrs="{'required': [('used_for_import', '=', True)]}"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="commission_account_id"/>
|
||||
<field name="receivable_account_id" attrs="{'required': [('used_for_import', '=', True)]}"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="create_counterpart"/>
|
||||
<field name="split_counterpart" attrs="{'invisible': [('create_counterpart', '=', False)]}"/>
|
||||
</group>
|
||||
<group>
|
||||
<button name="%(account_move_base_import.move_importer_action)d"
|
||||
string="Import batch file"
|
||||
type="action" icon="gtk-ok"
|
||||
colspan = "2"/>
|
||||
</group>
|
||||
</page>
|
||||
<page string="Auto-Completion related infos" attrs="{'invisible': [('used_for_completion', '=', False)]}">
|
||||
<group>
|
||||
<separator colspan="4" string="Auto-Completion Rules"/>
|
||||
<field name="rule_ids" colspan="4" nolabel="1"/>
|
||||
</group>
|
||||
</page>
|
||||
</notebook>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
15
account_move_base_import/views/partner_view.xml
Normal file
15
account_move_base_import/views/partner_view.xml
Normal file
@@ -0,0 +1,15 @@
|
||||
<odoo>
|
||||
|
||||
<record id="bk_view_partner_form" model="ir.ui.view">
|
||||
<field name="name">account_bank_statement_import.view.partner.form</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="priority">20</field>
|
||||
<field name="inherit_id" ref="account.view_partner_property_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="property_account_payable_id" position="after">
|
||||
<field name="bank_statement_label"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
7
account_move_base_import/wizard/__init__.py
Normal file
7
account_move_base_import/wizard/__init__.py
Normal file
@@ -0,0 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2011 Akretion
|
||||
# © 2011-2016 Camptocamp SA
|
||||
# © 2013 Savoir-faire Linux
|
||||
# © 2014 ACSONE SA/NV
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||
from . import import_statement
|
||||
91
account_move_base_import/wizard/import_statement.py
Normal file
91
account_move_base_import/wizard/import_statement.py
Normal file
@@ -0,0 +1,91 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2011 Akretion
|
||||
# © 2011-2016 Camptocamp SA
|
||||
# © 2013 Savoir-faire Linux
|
||||
# © 2014 ACSONE SA/NV
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||
"""
|
||||
Wizard to import financial institute date in bank statement
|
||||
"""
|
||||
|
||||
from openerp import _, api, fields, models
|
||||
import os
|
||||
|
||||
|
||||
class CreditPartnerStatementImporter(models.TransientModel):
|
||||
_name = "credit.statement.import"
|
||||
|
||||
@api.model
|
||||
def default_get(self, fields):
|
||||
ctx = self._context
|
||||
res = {}
|
||||
if (ctx.get('active_model', False) == 'account.journal' and
|
||||
ctx.get('active_ids', False)):
|
||||
ids = ctx['active_ids']
|
||||
assert len(ids) == 1, \
|
||||
'You cannot use this on more than one journal !'
|
||||
res['journal_id'] = ids[0]
|
||||
values = self.onchange_journal_id(res['journal_id'])
|
||||
res.update(values.get('value', {}))
|
||||
return res
|
||||
|
||||
journal_id = fields.Many2one(
|
||||
comodel_name='account.journal',
|
||||
string='Import configuration parameter',
|
||||
required=True)
|
||||
input_statement = fields.Binary(
|
||||
string='Statement file',
|
||||
required=True)
|
||||
partner_id = fields.Many2one(
|
||||
comodel_name='res.partner',
|
||||
string='Credit institute partner')
|
||||
file_name = fields.Char()
|
||||
receivable_account_id = fields.Many2one(
|
||||
comodel_name='account.account',
|
||||
string='Force Receivable/Payable Account')
|
||||
commission_account_id = fields.Many2one(
|
||||
comodel_name='account.account',
|
||||
string='Commission account')
|
||||
|
||||
@api.multi
|
||||
def onchange_journal_id(self, journal_id):
|
||||
if journal_id:
|
||||
journal = self.env['account.journal'].browse(journal_id)
|
||||
return {
|
||||
'value': {
|
||||
'partner_id': journal.partner_id.id,
|
||||
'receivable_account_id': journal.receivable_account_id.id,
|
||||
'commission_account_id': journal.commission_account_id.id,
|
||||
}
|
||||
}
|
||||
|
||||
@api.multi
|
||||
def _check_extension(self):
|
||||
self.ensure_one()
|
||||
(__, ftype) = os.path.splitext(self.file_name)
|
||||
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 extension'))
|
||||
return ftype
|
||||
|
||||
@api.multi
|
||||
def import_statement(self):
|
||||
"""This Function import credit card agency statement"""
|
||||
moves = self.env['account.move']
|
||||
for importer in self:
|
||||
journal = importer.journal_id
|
||||
ftype = importer._check_extension()
|
||||
moves |= journal.with_context(
|
||||
file_name=importer.file_name).multi_move_import(
|
||||
importer.input_statement,
|
||||
ftype.replace('.', '')
|
||||
)
|
||||
xmlid = ('account', 'action_move_journal_line')
|
||||
action = self.env['ir.actions.act_window'].for_xml_id(*xmlid)
|
||||
if len(moves) > 1:
|
||||
action['domain'] = [('id', 'in', moves.ids)]
|
||||
else:
|
||||
ref = self.env.ref('account.view_move_form')
|
||||
action['views'] = [(ref.id, 'form')]
|
||||
action['res_id'] = moves.id if moves else False
|
||||
return action
|
||||
35
account_move_base_import/wizard/import_statement_view.xml
Normal file
35
account_move_base_import/wizard/import_statement_view.xml
Normal file
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="move_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 move">
|
||||
<group colspan="4" >
|
||||
<field name="journal_id" on_change="onchange_journal_id(journal_id)" domain="[('used_for_import', '=', True)]"/>
|
||||
<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="receivable_account_id" readonly="1"/>
|
||||
<field name="commission_account_id" readonly="1"/>
|
||||
</group>
|
||||
<footer>
|
||||
<button icon="gtk-ok" name="import_statement" string="Import file" type="object" class="oe_highlight"/>
|
||||
<button icon="gtk-cancel" special="cancel" string="Cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="move_importer_action" model="ir.actions.act_window">
|
||||
<field name="name">Import Batch File</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="move_importer_view"/>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
<menuitem id="move_importer_menu" name="Import Batch File" action="move_importer_action" parent="account.menu_finance_entries"/>
|
||||
</odoo>
|
||||
55
account_move_so_import/README.rst
Normal file
55
account_move_so_import/README.rst
Normal file
@@ -0,0 +1,55 @@
|
||||
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
|
||||
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
|
||||
:alt: License: AGPL-3
|
||||
|
||||
===================================
|
||||
Journal Entry Sale Order completion
|
||||
===================================
|
||||
|
||||
This module extends the functionality of account_move_base_import
|
||||
to add support for completion rules based on Sale Orders. This was initially
|
||||
part of the module account_statement_base_completion, but is now separate to
|
||||
keep dependencies separate.
|
||||
|
||||
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
|
||||
:alt: Try me on Runbot
|
||||
:target: https://runbot.odoo-community.org/runbot/98/9.0
|
||||
|
||||
Bug Tracker
|
||||
===========
|
||||
|
||||
Bugs are tracked on `GitHub Issues
|
||||
<https://github.com/OCA/bank-statement-reconcile/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
|
||||
=======
|
||||
|
||||
Images
|
||||
------
|
||||
|
||||
* Odoo Community Association: `Icon <https://github.com/OCA/maintainer-tools/blob/master/template/module/static/description/icon.svg>`_.
|
||||
|
||||
Contributors
|
||||
------------
|
||||
|
||||
* Joël Grand-Guillaume <joel.grandguillaume@camptocamp.com>
|
||||
* Leonardo Pistone <leonardo.pistone@camptocamp.com>
|
||||
* Matthieu Dietrich <matthieu.dietrich@camptocamp.com>
|
||||
|
||||
Maintainer
|
||||
----------
|
||||
|
||||
.. image:: https://odoo-community.org/logo.png
|
||||
:alt: Odoo Community Association
|
||||
:target: https://odoo-community.org
|
||||
|
||||
This module is maintained by the OCA.
|
||||
|
||||
OCA, or the Odoo Community Association, is a nonprofit organization whose
|
||||
mission is to support the collaborative development of Odoo features and
|
||||
promote its widespread use.
|
||||
|
||||
To contribute to this module, please visit https://odoo-community.org.
|
||||
4
account_move_so_import/__init__.py
Normal file
4
account_move_so_import/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2011-2016 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||
from . import models
|
||||
22
account_move_so_import/__openerp__.py
Normal file
22
account_move_so_import/__openerp__.py
Normal file
@@ -0,0 +1,22 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2011-2016 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||
{
|
||||
'name': "Journal Entry Sale Order completion",
|
||||
'version': '9.0.1.0.0',
|
||||
'author': "Camptocamp,Odoo Community Association (OCA)",
|
||||
'maintainer': 'Camptocamp',
|
||||
'category': 'Finance',
|
||||
'complexity': 'easy',
|
||||
'depends': ['account_move_base_import', 'sale'],
|
||||
'website': 'http://www.camptocamp.com',
|
||||
'data': [
|
||||
'data/completion_rule_data.xml',
|
||||
],
|
||||
'test': [
|
||||
'test/completion_so_test.yml'],
|
||||
'installable': True,
|
||||
'images': [],
|
||||
'auto_install': False,
|
||||
'license': 'AGPL-3',
|
||||
}
|
||||
10
account_move_so_import/data/completion_rule_data.xml
Normal file
10
account_move_so_import/data/completion_rule_data.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo noupdate="1">
|
||||
|
||||
<record id="bank_statement_completion_rule_1" model="account.move.completion.rule">
|
||||
<field name="name">Match from line name (based on SO number)</field>
|
||||
<field name="sequence">50</field>
|
||||
<field name="function_to_call">get_from_name_and_so</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -17,8 +17,8 @@ msgstr ""
|
||||
"X-Launchpad-Export-Date: 2014-06-06 06:36+0000\n"
|
||||
"X-Generator: Launchpad (build 17031)\n"
|
||||
|
||||
#. module: account_statement_so_completion
|
||||
#: code:addons/account_statement_so_completion/statement.py:77
|
||||
#. module: account_move_so_import
|
||||
#: code:addons/account_move_so_import/statement.py:77
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Line named \"%s\" (Ref:%s) was matched by more than one partner while "
|
||||
@@ -27,7 +27,7 @@ msgstr ""
|
||||
"La línea llamada \"%s\" (Ref: %s) se casó con más de una empresa al buscar "
|
||||
"por referencia de pedido."
|
||||
|
||||
#. module: account_statement_so_completion
|
||||
#: model:ir.model,name:account_statement_so_completion.model_account_statement_completion_rule
|
||||
#. module: account_move_so_import
|
||||
#: model:ir.model,name:account_move_so_import.model_account_statement_completion_rule
|
||||
msgid "account.statement.completion.rule"
|
||||
msgstr "account.statement.completion.rule"
|
||||
4
account_move_so_import/models/__init__.py
Normal file
4
account_move_so_import/models/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2011-2016 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||
from . import account_move
|
||||
48
account_move_so_import/models/account_move.py
Normal file
48
account_move_so_import/models/account_move.py
Normal file
@@ -0,0 +1,48 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2011-2016 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||
from openerp import _, fields, models
|
||||
from openerp.addons.account_move_base_import.models.account_move \
|
||||
import ErrorTooManyPartner
|
||||
|
||||
|
||||
class AccountMoveCompletionRule(models.Model):
|
||||
|
||||
_name = "account.move.completion.rule"
|
||||
_inherit = "account.move.completion.rule"
|
||||
|
||||
function_to_call = fields.Selection(
|
||||
selection_add=[
|
||||
('get_from_name_and_so', 'From line name (based on SO number)')
|
||||
])
|
||||
|
||||
# Should be private but data are initialised with no update XML
|
||||
def get_from_name_and_so(self, line):
|
||||
"""
|
||||
Match the partner based on the SO number and the reference of the
|
||||
statement line. Then, call the generic get_values_for_line method to
|
||||
complete other values. If more than one partner matched, raise the
|
||||
ErrorTooManyPartner error.
|
||||
|
||||
:param int/long st_line: read of the concerned
|
||||
account.bank.statement.line
|
||||
|
||||
:return:
|
||||
A dict of value that can be passed directly to the write method of
|
||||
the statement line or {}
|
||||
{'partner_id': value,
|
||||
'account_id': value,
|
||||
|
||||
...}
|
||||
"""
|
||||
res = {}
|
||||
so_obj = self.env['sale.order']
|
||||
orders = so_obj.search([('name', '=', line.name)])
|
||||
if len(orders) > 1:
|
||||
raise ErrorTooManyPartner(
|
||||
_('Line named "%s" was matched by more '
|
||||
'than one partner while looking on SO by ref.') %
|
||||
line.name)
|
||||
if len(orders) == 1:
|
||||
res['partner_id'] = orders[0].partner_id.id
|
||||
return res
|
||||
59
account_move_so_import/test/completion_so_test.yml
Normal file
59
account_move_so_import/test/completion_so_test.yml
Normal file
@@ -0,0 +1,59 @@
|
||||
-
|
||||
I import account minimal data
|
||||
-
|
||||
!python {model: account.invoice}: |
|
||||
openerp.tools.convert_file(cr,
|
||||
'account',
|
||||
openerp.modules.get_module_resource(
|
||||
'account',
|
||||
'test',
|
||||
'account_minimal_test.xml'),
|
||||
{}, 'init', False, 'test')
|
||||
-
|
||||
In order to test the banking framework for Sale Orders, I first need to
|
||||
create a profile
|
||||
-
|
||||
!record {model: account.journal, id: account.bank_journal}:
|
||||
used_for_completion: True
|
||||
rule_ids:
|
||||
- account_move_base_import.bank_statement_completion_rule_4
|
||||
- account_move_base_import.bank_statement_completion_rule_5
|
||||
- account_move_base_import.bank_statement_completion_rule_2
|
||||
- account_move_base_import.bank_statement_completion_rule_3
|
||||
- bank_statement_completion_rule_1
|
||||
-
|
||||
Now I create a statement. I create statment lines separately because I need
|
||||
to find each one by XML id
|
||||
-
|
||||
!record {model: account.move, id: move_test_sale1}:
|
||||
name: Statement for SO
|
||||
journal_id: account.bank_journal
|
||||
company_id: base.main_company
|
||||
-
|
||||
I create a move line for a SO
|
||||
-
|
||||
!record {model: account.move.line, id: move_line_so}:
|
||||
name: SO007
|
||||
account_id: account.a_sale
|
||||
move_id: move_test_sale1
|
||||
date_maturity: '2013-12-20'
|
||||
credit: 0.0
|
||||
-
|
||||
and add the correct name
|
||||
-
|
||||
!python {model: account.move.line}: |
|
||||
context['check_move_validity'] = False
|
||||
model.write(cr, uid, [ref('move_line_so')],
|
||||
{'credit': 14981.0},
|
||||
context)
|
||||
-
|
||||
I run the auto complete
|
||||
-
|
||||
!python {model: account.move}: |
|
||||
result = self.button_auto_completion(cr, uid, [ref("move_test_sale1")])
|
||||
-
|
||||
Now I can check that all is nice and shiny, line 1. I expect the Sale Order
|
||||
Number to be recognised.
|
||||
-
|
||||
!assert {model: account.move.line, id: move_line_so, string: Check completion by SO number}:
|
||||
- partner_id.name == u'China Export'
|
||||
54
account_move_transactionid_import/README.rst
Normal file
54
account_move_transactionid_import/README.rst
Normal file
@@ -0,0 +1,54 @@
|
||||
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
|
||||
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
|
||||
:alt: License: AGPL-3
|
||||
|
||||
===================================
|
||||
Journal Entry transaction ID import
|
||||
===================================
|
||||
|
||||
This module extends the functionality of
|
||||
account_move_base_import, in order to add both importation
|
||||
and auto-completion for the "transaction_ref" field added in
|
||||
base_transaction_id.
|
||||
|
||||
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
|
||||
:alt: Try me on Runbot
|
||||
:target: https://runbot.odoo-community.org/runbot/98/9.0
|
||||
|
||||
Bug Tracker
|
||||
===========
|
||||
|
||||
Bugs are tracked on `GitHub Issues
|
||||
<https://github.com/OCA/bank-statement-reconcile/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
|
||||
=======
|
||||
|
||||
Images
|
||||
------
|
||||
|
||||
* Odoo Community Association: `Icon <https://github.com/OCA/maintainer-tools/blob/master/template/module/static/description/icon.svg>`_.
|
||||
|
||||
Contributors
|
||||
------------
|
||||
|
||||
* Joël Grand-Guillaume <joel.grandguillaume@camptocamp.com>
|
||||
* Matthieu Dietrich <matthieu.dietrich@camptocamp.com>
|
||||
|
||||
Maintainer
|
||||
----------
|
||||
|
||||
.. image:: https://odoo-community.org/logo.png
|
||||
:alt: Odoo Community Association
|
||||
:target: https://odoo-community.org
|
||||
|
||||
This module is maintained by the OCA.
|
||||
|
||||
OCA, or the Odoo Community Association, is a nonprofit organization whose
|
||||
mission is to support the collaborative development of Odoo features and
|
||||
promote its widespread use.
|
||||
|
||||
To contribute to this module, please visit https://odoo-community.org.
|
||||
5
account_move_transactionid_import/__init__.py
Normal file
5
account_move_transactionid_import/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2011-2016 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||
from . import parser
|
||||
from . import models
|
||||
28
account_move_transactionid_import/__openerp__.py
Normal file
28
account_move_transactionid_import/__openerp__.py
Normal file
@@ -0,0 +1,28 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2011-2016 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||
{
|
||||
'name': "Journal Entry transactionID import",
|
||||
'version': '9.0.1.0.0',
|
||||
'author': "Camptocamp,Odoo Community Association (OCA)",
|
||||
'maintainer': 'Camptocamp',
|
||||
'category': 'Finance',
|
||||
'complexity': 'normal',
|
||||
'depends': [
|
||||
'account_move_base_import',
|
||||
'base_transaction_id'
|
||||
],
|
||||
'data': [
|
||||
'data/completion_rule_data.xml'
|
||||
],
|
||||
'test': [
|
||||
'test/sale.yml',
|
||||
'test/completion_transactionid_test.yml',
|
||||
'test/invoice.yml',
|
||||
'test/completion_invoice_transactionid_test.yml',
|
||||
],
|
||||
'website': 'http://www.camptocamp.com',
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
'license': 'AGPL-3',
|
||||
}
|
||||
@@ -1,18 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
<odoo noupdate="1">
|
||||
|
||||
<record id="bank_statement_completion_rule_4" model="account.statement.completion.rule">
|
||||
<record id="bank_statement_completion_rule_4" model="account.move.completion.rule">
|
||||
<field name="name">Match from Sales Order using transaction ID</field>
|
||||
<field name="sequence">30</field>
|
||||
<field name="function_to_call">get_from_transaction_id_and_so</field>
|
||||
</record>
|
||||
|
||||
<record id="bank_statement_completion_rule_trans_id_invoice" model="account.statement.completion.rule">
|
||||
<record id="bank_statement_completion_rule_trans_id_invoice" model="account.move.completion.rule">
|
||||
<field name="name">Match from Invoice using transaction ID</field>
|
||||
<field name="sequence">40</field>
|
||||
<field name="function_to_call">get_from_transaction_id_and_invoice</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
</odoo>
|
||||
BIN
account_move_transactionid_import/data/statement.xls
Normal file
BIN
account_move_transactionid_import/data/statement.xls
Normal file
Binary file not shown.
@@ -1,5 +1,6 @@
|
||||
# Translation of OpenERP Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * account_statement_transactionid_import
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
@@ -15,7 +16,12 @@ msgstr ""
|
||||
"Plural-Forms: \n"
|
||||
|
||||
#. module: account_statement_transactionid_import
|
||||
#: model:ir.model,name:account_statement_transactionid_import.model_account_statement_profile
|
||||
msgid "Statement Profile"
|
||||
#: code:addons/account_statement_transactionid_import/account_move.py:65
|
||||
#, python-format
|
||||
msgid "Line named \"%s\" was matched by more than one partner."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_transactionid_import
|
||||
#: model:ir.model,name:account_statement_transactionid_import.model_account_move_completion_rule
|
||||
msgid "account.move.completion.rule"
|
||||
msgstr ""
|
||||
@@ -17,7 +17,13 @@ msgstr ""
|
||||
"X-Launchpad-Export-Date: 2014-06-06 06:36+0000\n"
|
||||
"X-Generator: Launchpad (build 17031)\n"
|
||||
|
||||
#. module: account_statement_transactionid_import
|
||||
#: model:ir.model,name:account_statement_transactionid_import.model_account_statement_profile
|
||||
msgid "Statement Profile"
|
||||
msgstr "Perfil de extracto"
|
||||
#. module: account_move_transactionid_import
|
||||
#: code:addons/account_move_transactionid_import/account_move.py:65
|
||||
#, python-format
|
||||
msgid "Line named \"%s\" (Ref:%s) was matched by more than one partner."
|
||||
msgstr "La línea llamada \"%s\" (Ref: %s) se casó con más de una empresa."
|
||||
|
||||
#. module: account_move_transactionid_import
|
||||
#: model:ir.model,name:account_move_transactionid_import.model_account_move_completion_rule
|
||||
msgid "account.move.completion.rule"
|
||||
msgstr "account.move.completion.rule"
|
||||
5
account_move_transactionid_import/models/__init__.py
Normal file
5
account_move_transactionid_import/models/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2011-2016 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||
from . import account_journal
|
||||
from . import account_move
|
||||
14
account_move_transactionid_import/models/account_journal.py
Normal file
14
account_move_transactionid_import/models/account_journal.py
Normal file
@@ -0,0 +1,14 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2011-2016 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||
from openerp import fields, models
|
||||
|
||||
|
||||
class AccountJournal(models.Model):
|
||||
_inherit = "account.journal"
|
||||
|
||||
import_type = fields.Selection(
|
||||
selection_add=[
|
||||
('generic_csvxls_transaction',
|
||||
'Generic .csv/.xls based on SO transaction ID')
|
||||
])
|
||||
75
account_move_transactionid_import/models/account_move.py
Normal file
75
account_move_transactionid_import/models/account_move.py
Normal file
@@ -0,0 +1,75 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2011-2016 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||
from openerp import _, fields, models
|
||||
from openerp.addons.account_move_base_import.models.account_move import \
|
||||
ErrorTooManyPartner
|
||||
|
||||
|
||||
class AccountMoveCompletionRule(models.Model):
|
||||
"""Add a rule based on transaction ID"""
|
||||
|
||||
_inherit = "account.move.completion.rule"
|
||||
|
||||
function_to_call = fields.Selection(
|
||||
selection_add=[
|
||||
('get_from_transaction_id_and_so',
|
||||
'Match Sales Order using transaction ID'),
|
||||
('get_from_transaction_id_and_invoice',
|
||||
'Match Invoice using transaction ID')
|
||||
])
|
||||
|
||||
def get_from_transaction_id_and_so(self, line):
|
||||
"""
|
||||
Match the partner based on the transaction ID field of the SO.
|
||||
Then, call the generic st_line method to complete other values.
|
||||
In that case, we always fullfill the reference of the line with the SO
|
||||
name.
|
||||
:param dict st_line: read of the concerned account.bank.statement.line
|
||||
:return:
|
||||
A dict of value that can be passed directly to the write method of
|
||||
the statement line or {}
|
||||
{'partner_id': value,
|
||||
'account_id' : value,
|
||||
...}
|
||||
"""
|
||||
res = {}
|
||||
so_obj = self.env['sale.order']
|
||||
sales = so_obj.search([('transaction_id', '=', line.transaction_ref)])
|
||||
if len(sales) > 1:
|
||||
raise ErrorTooManyPartner(
|
||||
_('Line named "%s" was matched by more than '
|
||||
'one partner.') % line.name)
|
||||
if len(sales) == 1:
|
||||
sale = sales[0]
|
||||
res['partner_id'] = sale.partner_id.id
|
||||
return res
|
||||
|
||||
def get_from_transaction_id_and_invoice(self, line):
|
||||
"""Match the partner based on the transaction ID field of the invoice.
|
||||
Then, call the generic st_line method to complete other values.
|
||||
|
||||
In that case, we always fullfill the reference of the line with the
|
||||
invoice name.
|
||||
|
||||
:param dict st_line: read of the concerned account.bank.statement.line
|
||||
:return:
|
||||
A dict of value that can be passed directly to the write method of
|
||||
the statement line or {}
|
||||
{'partner_id': value,
|
||||
'account_id' : value,
|
||||
...}
|
||||
"""
|
||||
res = {}
|
||||
invoice_obj = self.env['account.invoice']
|
||||
invoices = invoice_obj.search(
|
||||
[('transaction_id', '=', line.transaction_ref)])
|
||||
if len(invoices) > 1:
|
||||
raise ErrorTooManyPartner(
|
||||
_('Line named "%s" was matched by more than '
|
||||
'one partner.') % line.name)
|
||||
elif len(invoices) == 1:
|
||||
invoice = invoices[0]
|
||||
res['partner_id'] = invoice.commercial_partner_id.id
|
||||
res['account_id'] = invoice.account_id.id
|
||||
return res
|
||||
4
account_move_transactionid_import/parser/__init__.py
Normal file
4
account_move_transactionid_import/parser/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2011-2016 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||
from . import transactionid_file_parser
|
||||
@@ -1,25 +1,9 @@
|
||||
# -*- 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/>.
|
||||
#
|
||||
##############################################################################
|
||||
# © 2011-2016 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||
import datetime
|
||||
from openerp.tools import ustr
|
||||
from account_statement_base_import.parser.file_parser import (
|
||||
from openerp.addons.account_move_base_import.parser.file_parser import (
|
||||
FileParser, float_or_zero
|
||||
)
|
||||
|
||||
@@ -44,6 +28,7 @@ class TransactionIDFileParser(FileParser):
|
||||
'label': ustr,
|
||||
'date': datetime.datetime,
|
||||
'amount': float_or_zero,
|
||||
'commission_amount': float_or_zero,
|
||||
}
|
||||
super(TransactionIDFileParser, self).__init__(
|
||||
profile, extra_fields=conversion_dict, ftype=ftype, header=header,
|
||||
@@ -56,7 +41,7 @@ class TransactionIDFileParser(FileParser):
|
||||
"""
|
||||
return parser_name == 'generic_csvxls_transaction'
|
||||
|
||||
def get_st_line_vals(self, line, *args, **kwargs):
|
||||
def get_move_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
|
||||
@@ -76,12 +61,11 @@ class TransactionIDFileParser(FileParser):
|
||||
In this generic parser, the commission is given for every line, so we
|
||||
store it for each one.
|
||||
"""
|
||||
amount = line.get('amount', 0.0)
|
||||
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('transaction_id', '/'),
|
||||
'label': line.get('label', ''),
|
||||
'transaction_id': line.get('transaction_id', '/'),
|
||||
'commission_amount': line.get('commission_amount', 0.0)
|
||||
'name': line.get('label', '/'),
|
||||
'date_maturity': line.get('date', datetime.datetime.now().date()),
|
||||
'credit': amount > 0.0 and amount or 0.0,
|
||||
'debit': amount < 0.0 and amount or 0.0,
|
||||
'transaction_ref': line.get('transaction_id', '/'),
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
-
|
||||
In order to test the banking framework, I first need to create a journal
|
||||
-
|
||||
!record {model: account.journal, id: account.bank_journal}:
|
||||
used_for_completion: True
|
||||
rule_ids:
|
||||
- bank_statement_completion_rule_trans_id_invoice
|
||||
-
|
||||
Now I create a move. I create statment lines separately because I need
|
||||
to find each one by XML id
|
||||
-
|
||||
!record {model: account.move, id: move_invoice_transactionid_test1}:
|
||||
name: Move with transaction ID
|
||||
journal_id: account.bank_journal
|
||||
company_id: base.main_company
|
||||
-
|
||||
I create a move line for a SO with transaction ID
|
||||
-
|
||||
!record {model: account.move.line, id: move_line_invoice_transactionid}:
|
||||
name: Test autocompletion based on invoice with transaction ID
|
||||
account_id: account.a_sale
|
||||
move_id: move_invoice_transactionid_test1
|
||||
transaction_ref: XXX77Z
|
||||
date_maturity: !eval time.strftime('%Y-%m-%d')
|
||||
credit: 0.0
|
||||
-
|
||||
and add the correct amount
|
||||
-
|
||||
!python {model: account.move.line}: |
|
||||
context['check_move_validity'] = False
|
||||
model.write(cr, uid, [ref('move_line_invoice_transactionid')],
|
||||
{'credit': 450.0},
|
||||
context)
|
||||
-
|
||||
I run the auto complete
|
||||
-
|
||||
!python {model: account.move}: |
|
||||
result = self.button_auto_completion(cr, uid, [ref("move_invoice_transactionid_test1")])
|
||||
-
|
||||
Now I can check that all is nice and shiny, line 1. I expect the invoice has been
|
||||
recognised from the transaction ID.
|
||||
-
|
||||
!assert {model: account.move.line, id: move_line_invoice_transactionid, string: Check completion by Invoice transaction ID}:
|
||||
- partner_id.name == u'Agrolait'
|
||||
@@ -0,0 +1,48 @@
|
||||
-
|
||||
In order to test the banking framework, I first need to create a journal
|
||||
-
|
||||
!record {model: account.journal, id: account.bank_journal}:
|
||||
used_for_completion: True
|
||||
rule_ids:
|
||||
- bank_statement_completion_rule_4
|
||||
- account_move_base_import.bank_statement_completion_rule_4
|
||||
- account_move_base_import.bank_statement_completion_rule_5
|
||||
- account_move_base_import.bank_statement_completion_rule_2
|
||||
- account_move_base_import.bank_statement_completion_rule_3
|
||||
-
|
||||
Now I create a move. I create statment lines separately because I need
|
||||
to find each one by XML id
|
||||
-
|
||||
!record {model: account.move, id: move_transactionid_test1}:
|
||||
name: Move with transaction ID
|
||||
journal_id: account.bank_journal
|
||||
company_id: base.main_company
|
||||
-
|
||||
I create a move line for a SO with transaction ID
|
||||
-
|
||||
!record {model: account.move.line, id: move_line_transactionid}:
|
||||
name: Test autocompletion based on SO with transaction ID
|
||||
account_id: account.a_sale
|
||||
move_id: move_transactionid_test1
|
||||
transaction_ref: XXX66Z
|
||||
date_maturity: !eval "'%s-01-06' %(datetime.now().year)"
|
||||
credit: 0.0
|
||||
-
|
||||
and add the correct amount
|
||||
-
|
||||
!python {model: account.move.line}: |
|
||||
context['check_move_validity'] = False
|
||||
model.write(cr, uid, [ref('move_line_transactionid')],
|
||||
{'credit': 118.4},
|
||||
context)
|
||||
-
|
||||
I run the auto complete
|
||||
-
|
||||
!python {model: account.move}: |
|
||||
result = self.button_auto_completion(cr, uid, [ref("move_transactionid_test1")])
|
||||
-
|
||||
Now I can check that all is nice and shiny, line 1. I expect the SO has been
|
||||
recognised from the transaction ID.
|
||||
-
|
||||
!assert {model: account.move.line, id: move_line_transactionid, string: Check completion by SO transaction ID}:
|
||||
- partner_id.name == u'Agrolait'
|
||||
25
account_move_transactionid_import/test/invoice.yml
Normal file
25
account_move_transactionid_import/test/invoice.yml
Normal file
@@ -0,0 +1,25 @@
|
||||
-
|
||||
I create a new invoice with transaction ID
|
||||
-
|
||||
!record {model: account.invoice, id: invoice_with_transaction_id}:
|
||||
company_id: base.main_company
|
||||
currency_id: base.EUR
|
||||
partner_id: base.res_partner_2
|
||||
transaction_id: XXX77Z
|
||||
invoice_line_ids:
|
||||
- name: '[PCSC234] PC Assemble SC234'
|
||||
price_unit: 450.0
|
||||
quantity: 1.0
|
||||
product_id: product.product_product_3
|
||||
uom_id: product.product_uom_unit
|
||||
journal_id: account.bank_journal
|
||||
reference_type: none
|
||||
-
|
||||
I confirm the Invoice
|
||||
-
|
||||
!workflow {model: account.invoice, action: invoice_open, ref: invoice_with_transaction_id}
|
||||
-
|
||||
I check that the invoice state is "Open"
|
||||
-
|
||||
!assert {model: account.invoice, id: invoice_with_transaction_id}:
|
||||
- state == 'open'
|
||||
21
account_move_transactionid_import/test/sale.yml
Normal file
21
account_move_transactionid_import/test/sale.yml
Normal file
@@ -0,0 +1,21 @@
|
||||
-
|
||||
I import account minimal data
|
||||
-
|
||||
!python {model: account.invoice}: |
|
||||
openerp.tools.convert_file(cr,
|
||||
'account',
|
||||
openerp.modules.get_module_resource(
|
||||
'account',
|
||||
'test',
|
||||
'account_minimal_test.xml'),
|
||||
{}, 'init', False, 'test')
|
||||
-
|
||||
I create a new Sale Order with transaction ID
|
||||
-
|
||||
!record {model: sale.order, id: so_with_transaction_id}:
|
||||
partner_id: base.res_partner_2
|
||||
note: Invoice after delivery
|
||||
transaction_id: XXX66Z
|
||||
order_line:
|
||||
- product_id: product.product_product_7
|
||||
product_uom_qty: 8
|
||||
@@ -1,22 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
#
|
||||
# Author: Laurent Mignon
|
||||
# Copyright 2013 'ACSONE SA/NV'
|
||||
#
|
||||
# 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 statement
|
||||
from . import res_partner_bank
|
||||
@@ -1,48 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
#
|
||||
# Author: Laurent Mignon
|
||||
# Copyright 2013 'ACSONE SA/NV'
|
||||
#
|
||||
# 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 completion from bank account number",
|
||||
'version': '1.0.1',
|
||||
'author': "ACSONE SA/NV,Odoo Community Association (OCA)",
|
||||
'maintainer': 'ACSONE SA/NV',
|
||||
'category': 'Finance',
|
||||
'complexity': 'normal',
|
||||
'depends': [
|
||||
'account_statement_base_completion',
|
||||
],
|
||||
'description': """
|
||||
Add a completion method based on the partner bank account number
|
||||
provided by the bank/office.
|
||||
|
||||
Completion will look in the partner with that bank account number
|
||||
to match the partner, then it will fill in the bank statement line
|
||||
with it to ease the reconciliation.
|
||||
|
||||
""",
|
||||
'website': 'http://www.acsone.eu',
|
||||
'data': [
|
||||
"data.xml",
|
||||
],
|
||||
'demo': [],
|
||||
'installable': False,
|
||||
'auto_install': False,
|
||||
'license': 'AGPL-3',
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
|
||||
<record id="bank_statement_completion_rule_10" model="account.statement.completion.rule">
|
||||
<field name="name">Match from bank account number (Normal or IBAN))</field>
|
||||
<field name="sequence">10</field>
|
||||
<field name="function_to_call">get_from_bank_account</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -1,52 +0,0 @@
|
||||
#
|
||||
# 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 openerp.osv.orm import Model
|
||||
|
||||
|
||||
class res_partner_bank(Model):
|
||||
_inherit = 'res.partner.bank'
|
||||
|
||||
def search_by_acc_number(self, cr, uid, acc_number, context=None):
|
||||
'''
|
||||
Try to find the Account Number using a 'like' operator to avoid
|
||||
problems with the input mask used to store the value.
|
||||
'''
|
||||
# first try with an exact match
|
||||
ids = self.search(cr,
|
||||
uid,
|
||||
[('acc_number', '=', acc_number)],
|
||||
context=context)
|
||||
if ids:
|
||||
return ids
|
||||
|
||||
cr.execute("""
|
||||
SELECT
|
||||
id
|
||||
FROM
|
||||
res_partner_bank
|
||||
WHERE
|
||||
regexp_replace(acc_number,'([^[:alnum:]])', '','g')
|
||||
ilike
|
||||
regexp_replace(%s,'([^[:alnum:]])', '','g')
|
||||
""", (acc_number,))
|
||||
# apply security constraints by using the orm
|
||||
return self.search(cr, uid,
|
||||
[('id', 'in', [r[0] for r in cr.fetchall()])],
|
||||
context=context)
|
||||
@@ -1,98 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
#
|
||||
# Author: Laurent Mignon
|
||||
# Copyright 2013 'ACSONE SA/NV'
|
||||
#
|
||||
# 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 openerp.tools.translate import _
|
||||
from openerp.osv.orm import Model
|
||||
from openerp.osv import fields
|
||||
from openerp.addons.account_statement_base_completion.statement \
|
||||
import ErrorTooManyPartner
|
||||
|
||||
|
||||
class AccountStatementCompletionRule(Model):
|
||||
"""Add a rule based on transaction ID"""
|
||||
|
||||
_inherit = "account.statement.completion.rule"
|
||||
|
||||
def _get_functions(self, cr, uid, context=None):
|
||||
res = super(AccountStatementCompletionRule, self)._get_functions(
|
||||
cr, uid, context=context)
|
||||
res.append(('get_from_bank_account',
|
||||
'From bank account number (Normal or IBAN)'))
|
||||
return res
|
||||
|
||||
def get_from_bank_account(self, cr, uid, st_line, context=None):
|
||||
"""
|
||||
Match the partner based on the partner account number field
|
||||
Then, call the generic st_line method to complete other values.
|
||||
:param dict st_line: read of the concerned account.bank.statement.line
|
||||
:return:
|
||||
A dict of value that can be passed directly to the write method of
|
||||
the statement line or {}
|
||||
{'partner_id': value,
|
||||
'account_id' : value,
|
||||
...}
|
||||
"""
|
||||
partner_acc_number = st_line['partner_acc_number']
|
||||
if not partner_acc_number:
|
||||
return {}
|
||||
st_obj = self.pool['account.bank.statement.line']
|
||||
res = {}
|
||||
res_bank_obj = self.pool['res.partner.bank']
|
||||
ids = res_bank_obj.search_by_acc_number(cr,
|
||||
uid,
|
||||
partner_acc_number,
|
||||
context=context)
|
||||
if len(ids) > 1:
|
||||
raise ErrorTooManyPartner(_('Line named "%s" (Ref:%s) was matched '
|
||||
'by more than one partner for account '
|
||||
'number "%s".') %
|
||||
(st_line['name'],
|
||||
st_line['ref'],
|
||||
partner_acc_number))
|
||||
if len(ids) == 1:
|
||||
partner = res_bank_obj.browse(cr,
|
||||
uid,
|
||||
ids[0],
|
||||
context=context).partner_id
|
||||
res['partner_id'] = partner.id
|
||||
st_vals = st_obj.get_values_for_line(
|
||||
cr, uid, profile_id=st_line['profile_id'],
|
||||
master_account_id=st_line['master_account_id'],
|
||||
partner_id=res.get('partner_id', False),
|
||||
line_type=st_line['type'],
|
||||
amount=st_line['amount'] if st_line['amount'] else 0.0,
|
||||
context=context)
|
||||
res.update(st_vals)
|
||||
return res
|
||||
|
||||
|
||||
class AccountStatementLine(Model):
|
||||
_inherit = "account.bank.statement.line"
|
||||
|
||||
_columns = {
|
||||
'partner_acc_number': fields.sparse(
|
||||
type='char',
|
||||
string='Account Number',
|
||||
size=64,
|
||||
serialization_field='additionnal_bank_fields',
|
||||
help="Account number of the partner"),
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
#
|
||||
# Authors: Laurent Mignon
|
||||
# Copyright (c) 2013 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_bankaccount_completion
|
||||
|
||||
checks = [
|
||||
test_bankaccount_completion
|
||||
]
|
||||
@@ -1,123 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
#
|
||||
# Authors: Laurent Mignon
|
||||
# Copyright (c) 2013 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 openerp.tests import common
|
||||
import time
|
||||
|
||||
ACC_NUMBER = " BE38 7330 4038 5372 "
|
||||
|
||||
|
||||
class bankaccount_completion(common.TransactionCase):
|
||||
|
||||
def setUp(self):
|
||||
super(bankaccount_completion, self).setUp()
|
||||
self.company_a = self.browse_ref('base.main_company')
|
||||
self.profile_obj = self.registry("account.statement.profile")
|
||||
self.acc_bk_stmt = self.registry("account.bank.statement")
|
||||
self.st_line_obj = self.registry("account.bank.statement.line")
|
||||
self.completion_rule_id = \
|
||||
self.ref('account_statement_bankaccount_completion.'
|
||||
'bank_statement_completion_rule_10')
|
||||
self.journal_id = self.ref("account.bank_journal")
|
||||
self.partner_id = self.ref('base.main_partner')
|
||||
self.account_id = self.ref("account.a_recv")
|
||||
|
||||
# Create the profile
|
||||
self.profile_id = self.profile_obj.create(self.cr, self.uid, {
|
||||
"name": "TEST",
|
||||
"commission_account_id": self.account_id,
|
||||
"journal_id": self.journal_id,
|
||||
"rule_ids": [(6, 0, [self.completion_rule_id])]})
|
||||
# Create a bank statement
|
||||
vals = {"balance_end_real": 0.0,
|
||||
"balance_start": 0.0,
|
||||
"date": time.strftime('%Y-%m-%d'),
|
||||
"journal_id": self.journal_id,
|
||||
"profile_id": self.profile_id,
|
||||
}
|
||||
self.statement_id = self.acc_bk_stmt.create(self.cr,
|
||||
self.uid,
|
||||
vals)
|
||||
|
||||
# Add a bank account number to the partner
|
||||
self.res_partner_bank_obj = self.registry('res.partner.bank')
|
||||
vals = {"state": "bank",
|
||||
"company_id": self.company_a.id,
|
||||
"partner_id": self.partner_id,
|
||||
"acc_number": ACC_NUMBER,
|
||||
"footer": True,
|
||||
"bank_name": "Reserve",
|
||||
}
|
||||
self.res_partner_bank_id = self.res_partner_bank_obj.create(self.cr,
|
||||
self.uid,
|
||||
vals)
|
||||
|
||||
def test_00(self):
|
||||
"""Test complete partner_id from bank account number
|
||||
Test the automatic completion of the partner_id based on the account
|
||||
number associated to the statement line
|
||||
"""
|
||||
for bank_acc_number in [ACC_NUMBER, ACC_NUMBER.replace(" ", ""),
|
||||
ACC_NUMBER.replace(" ", "-")]:
|
||||
# check the completion for well formatted and not well
|
||||
# formatted account number
|
||||
self.res_partner_bank_obj.write(self.cr,
|
||||
self.uid,
|
||||
self.res_partner_bank_id,
|
||||
{"acc_number": bank_acc_number}
|
||||
)
|
||||
for acc_number in [ACC_NUMBER, ACC_NUMBER.replace(" ", ""),
|
||||
ACC_NUMBER.replace(" ", "-"),
|
||||
" BE38-7330 4038-5372 "]:
|
||||
vals = {'amount': 1000.0,
|
||||
'name': 'EXT001',
|
||||
'ref': 'My ref',
|
||||
'statement_id': self.statement_id,
|
||||
'partner_acc_number': acc_number
|
||||
}
|
||||
line_id = self.st_line_obj.create(self.cr, self.uid, vals)
|
||||
line = self.st_line_obj.browse(self.cr, self.uid, line_id)
|
||||
self.assertFalse(line.partner_id,
|
||||
'Partner_id must be blank before completion')
|
||||
statement_obj = self.acc_bk_stmt.browse(self.cr,
|
||||
self.uid,
|
||||
self.statement_id)
|
||||
statement_obj.button_auto_completion()
|
||||
line = self.st_line_obj.browse(self.cr, self.uid, line_id)
|
||||
self.assertEquals(self.partner_id, line.partner_id['id'],
|
||||
'Missing expected partner id after '
|
||||
'completion')
|
||||
vals = {'amount': 1000.0,
|
||||
'name': 'EXT001',
|
||||
'ref': 'My ref',
|
||||
'statement_id': self.statement_id,
|
||||
'partner_acc_number': 'BE38a7330.4038-5372.',
|
||||
}
|
||||
line_id = self.st_line_obj.create(self.cr, self.uid, vals)
|
||||
line = self.st_line_obj.browse(self.cr, self.uid, line_id)
|
||||
self.assertFalse(line.partner_id,
|
||||
'Partner_id must be blank before completion')
|
||||
statement_obj = self.acc_bk_stmt.browse(self.cr,
|
||||
self.uid,
|
||||
self.statement_id)
|
||||
statement_obj.button_auto_completion()
|
||||
line = self.st_line_obj.browse(self.cr, self.uid, line_id)
|
||||
self.assertFalse(line.partner_id.id)
|
||||
@@ -1,23 +0,0 @@
|
||||
# -*- 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 partner
|
||||
from . import statement
|
||||
@@ -1,87 +0,0 @@
|
||||
# -*- 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 completion",
|
||||
'version': '1.0.3',
|
||||
'author': "Camptocamp,Odoo Community Association (OCA)",
|
||||
'maintainer': 'Camptocamp',
|
||||
'category': 'Finance',
|
||||
'complexity': 'normal',
|
||||
'depends': ['account_statement_ext',
|
||||
'account_report_company'],
|
||||
'description': """
|
||||
The goal of this module is to improve the basic bank statement, help dealing
|
||||
with huge volume of reconciliation by providing basic rules to identify the
|
||||
partner of a bank statement line.
|
||||
Each bank statement profile can have its own rules to be applied according to
|
||||
a sequence order.
|
||||
|
||||
Some basic rules are provided in this module:
|
||||
|
||||
1) Match from statement line label (based on partner field 'Bank Statement
|
||||
Label')
|
||||
2) Match from statement line label (based on partner name)
|
||||
3) Match from statement line reference (based on Invoice number)
|
||||
|
||||
You can easily override this module and add your own rules in your own one.
|
||||
The basic rules only fill in the partner, but you can use them to fill in
|
||||
any value of the line (in the future, we will add a rule to automatically
|
||||
match and reconcile the line).
|
||||
|
||||
It adds as well a label on the bank statement line (on which the pre-define
|
||||
rules can match) and a char field on the partner called 'Bank Statement
|
||||
Label'. Using the pre-define rules, you will be able to match various
|
||||
labels for a partner.
|
||||
|
||||
The reference of the line is always used by the reconciliation process. We're
|
||||
supposed to copy there (or write manually) the matching string. This can be:
|
||||
the order Number or an invoice number, or anything that will be found in the
|
||||
invoice accounting entry part to make the match.
|
||||
|
||||
You can use it with our account_advanced_reconcile module to automatize the
|
||||
reconciliation process.
|
||||
|
||||
|
||||
TODO: The rules that look for invoices to find out the partner should take
|
||||
back the payable / receivable account from there directly instead of
|
||||
retrieving it from partner properties!
|
||||
""",
|
||||
'website': 'http://www.camptocamp.com',
|
||||
'data': [
|
||||
'statement_view.xml',
|
||||
'partner_view.xml',
|
||||
'data.xml',
|
||||
'security/ir.model.access.csv',
|
||||
],
|
||||
'demo': [],
|
||||
'test': [
|
||||
'test/partner.yml',
|
||||
'test/invoice.yml',
|
||||
'test/supplier_invoice.yml',
|
||||
'test/refund.yml',
|
||||
'test/completion_test.yml'
|
||||
],
|
||||
'installable': False,
|
||||
'images': [],
|
||||
'auto_install': False,
|
||||
'license': 'AGPL-3',
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
|
||||
<record id="bank_statement_completion_rule_2" model="account.statement.completion.rule">
|
||||
<field name="name">Match from line label (based on partner field 'Bank Statement Label')</field>
|
||||
<field name="sequence">60</field>
|
||||
<field name="function_to_call">get_from_label_and_partner_field</field>
|
||||
</record>
|
||||
|
||||
<record id="bank_statement_completion_rule_3" model="account.statement.completion.rule">
|
||||
<field name="name">Match from line label (based on partner name)</field>
|
||||
<field name="sequence">70</field>
|
||||
<field name="function_to_call">get_from_label_and_partner_name</field>
|
||||
</record>
|
||||
|
||||
<record id="bank_statement_completion_rule_4" model="account.statement.completion.rule">
|
||||
<field name="name">Match from line reference (based on Invoice number)</field>
|
||||
<field name="sequence">40</field>
|
||||
<field name="function_to_call">get_from_ref_and_invoice</field>
|
||||
</record>
|
||||
|
||||
<record id="bank_statement_completion_rule_5" model="account.statement.completion.rule">
|
||||
<field name="name">Match from line reference (based on Invoice Supplier number)</field>
|
||||
<field name="sequence">45</field>
|
||||
<field name="function_to_call">get_from_ref_and_supplier_invoice</field>
|
||||
</record>
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -1,216 +0,0 @@
|
||||
# Abkhazian 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:57+0000\n"
|
||||
"PO-Revision-Date: 2014-04-02 23:04+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Abkhazian <ab@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_completion
|
||||
#: view:account.statement.completion.rule:0
|
||||
msgid "Related Profiles"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: help:account.bank.statement.line,label:0
|
||||
msgid ""
|
||||
"Generic field to store a label given from the bank/office on which we can "
|
||||
"base the default/standard providen rule."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: code:addons/account_statement_base_completion/statement.py:169
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Line named \"%s\" (Ref:%s) was matched by more than one partner while "
|
||||
"looking on %s invoices"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: field:account.bank.statement,completion_logs:0
|
||||
msgid "Completion Log"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: field:account.bank.statement.line,label:0
|
||||
msgid "Label"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: model:ir.model,name:account_statement_base_completion.model_account_bank_statement
|
||||
msgid "Bank Statement"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: field:account.statement.completion.rule,function_to_call:0
|
||||
msgid "Method"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: code:addons/account_statement_base_completion/statement.py:326
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Line named \"%s\" (Ref:%s) was matched by more than one partner while "
|
||||
"looking on partner by name"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: code:addons/account_statement_base_completion/statement.py:504
|
||||
#, python-format
|
||||
msgid "Statement ID %s auto-completed for %s lines completed"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: code:addons/account_statement_base_completion/statement.py:500
|
||||
#, python-format
|
||||
msgid ""
|
||||
"%s Bank Statement ID %s has %s lines completed by %s \n"
|
||||
"%s\n"
|
||||
"%s\n"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: model:ir.model,name:account_statement_base_completion.model_account_bank_statement_line
|
||||
msgid "Bank Statement Line"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: field:account.bank.statement.line,additionnal_bank_fields:0
|
||||
msgid "Additionnal infos from bank"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: view:account.statement.profile:0
|
||||
msgid "Auto-Completion Rules"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: view:account.bank.statement:0
|
||||
msgid "Importation related infos"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: code:addons/account_statement_base_completion/statement.py:159
|
||||
#: code:addons/account_statement_base_completion/statement.py:179
|
||||
#, python-format
|
||||
msgid "Invalid invoice type for completion: %"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: field:account.statement.completion.rule,name:0
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: model:ir.model,name:account_statement_base_completion.model_account_statement_profile
|
||||
msgid "Statement Profile"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: view:account.bank.statement:0
|
||||
msgid "Auto Completion"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: view:account.statement.completion.rule:0
|
||||
#: model:ir.actions.act_window,name:account_statement_base_completion.action_st_completion_rule_tree
|
||||
#: model:ir.ui.menu,name:account_statement_base_completion.menu_action_st_completion_rule_tree_menu
|
||||
msgid "Statement Completion Rule"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: model:ir.model,name:account_statement_base_completion.model_account_statement_completion_rule
|
||||
msgid "account.statement.completion.rule"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: help:account.bank.statement.line,additionnal_bank_fields:0
|
||||
msgid ""
|
||||
"Used by completion and import system. Adds every field that is present in "
|
||||
"your bank/office statement file"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: field:account.statement.completion.rule,profile_ids:0
|
||||
#: field:account.statement.profile,rule_ids:0
|
||||
msgid "Related statement profiles"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: code:addons/account_statement_base_completion/statement.py:158
|
||||
#: code:addons/account_statement_base_completion/statement.py:178
|
||||
#, python-format
|
||||
msgid "System error"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: field:account.bank.statement.line,already_completed:0
|
||||
msgid "Auto-Completed"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: code:addons/account_statement_base_completion/statement.py:448
|
||||
#: code:addons/account_statement_base_completion/statement.py:466
|
||||
#, python-format
|
||||
msgid "ORM bypass error"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: field:account.statement.completion.rule,sequence:0
|
||||
msgid "Sequence"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: code:addons/account_statement_base_completion/statement.py:280
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Line named \"%s\" (Ref:%s) was matched by more than one partner while "
|
||||
"looking on partner label: %s"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: help:account.statement.completion.rule,sequence:0
|
||||
msgid "Lower means parsed first."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: field:res.partner,bank_statement_label:0
|
||||
msgid "Bank Statement Label"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: help:account.bank.statement.line,already_completed:0
|
||||
msgid ""
|
||||
"When this checkbox is ticked, the auto-completion process/button will ignore "
|
||||
"this line."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: help:res.partner,bank_statement_label:0
|
||||
msgid ""
|
||||
"Enter the various label found on your bank statement separated by a ; If "
|
||||
" one of this label is include in the bank statement line, the "
|
||||
"partner will be automatically filled (as long as you use "
|
||||
"this method/rules in your statement profile)."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: model:ir.model,name:account_statement_base_completion.model_res_partner
|
||||
msgid "Partner"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: view:account.bank.statement:0
|
||||
msgid "Completion Logs"
|
||||
msgstr ""
|
||||
@@ -1,199 +0,0 @@
|
||||
# Translation of OpenERP Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * account_statement_base_completion
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: OpenERP Server 7.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2014-01-21 11:57+0000\n"
|
||||
"PO-Revision-Date: 2014-01-21 11:57+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_completion
|
||||
#: view:account.statement.completion.rule:0
|
||||
msgid "Related Profiles"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: help:account.bank.statement.line,label:0
|
||||
msgid "Generic field to store a label given from the bank/office on which we can base the default/standard providen rule."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: code:addons/account_statement_base_completion/statement.py:169
|
||||
#, python-format
|
||||
msgid "Line named \"%s\" (Ref:%s) was matched by more than one partner while looking on %s invoices"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: field:account.bank.statement,completion_logs:0
|
||||
msgid "Completion Log"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: field:account.bank.statement.line,label:0
|
||||
msgid "Label"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: model:ir.model,name:account_statement_base_completion.model_account_bank_statement
|
||||
msgid "Bank Statement"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: field:account.statement.completion.rule,function_to_call:0
|
||||
msgid "Method"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: code:addons/account_statement_base_completion/statement.py:326
|
||||
#, python-format
|
||||
msgid "Line named \"%s\" (Ref:%s) was matched by more than one partner while looking on partner by name"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: code:addons/account_statement_base_completion/statement.py:504
|
||||
#, python-format
|
||||
msgid "Statement ID %s auto-completed for %s lines completed"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: code:addons/account_statement_base_completion/statement.py:500
|
||||
#, python-format
|
||||
msgid "%s Bank Statement ID %s has %s lines completed by %s \n"
|
||||
"%s\n"
|
||||
"%s\n"
|
||||
""
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: model:ir.model,name:account_statement_base_completion.model_account_bank_statement_line
|
||||
msgid "Bank Statement Line"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: field:account.bank.statement.line,additionnal_bank_fields:0
|
||||
msgid "Additionnal infos from bank"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: view:account.statement.profile:0
|
||||
msgid "Auto-Completion Rules"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: view:account.bank.statement:0
|
||||
msgid "Importation related infos"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: code:addons/account_statement_base_completion/statement.py:159
|
||||
#: code:addons/account_statement_base_completion/statement.py:179
|
||||
#, python-format
|
||||
msgid "Invalid invoice type for completion: %"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: field:account.statement.completion.rule,name:0
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: model:ir.model,name:account_statement_base_completion.model_account_statement_profile
|
||||
msgid "Statement Profile"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: view:account.bank.statement:0
|
||||
msgid "Auto Completion"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: view:account.statement.completion.rule:0
|
||||
#: model:ir.actions.act_window,name:account_statement_base_completion.action_st_completion_rule_tree
|
||||
#: model:ir.ui.menu,name:account_statement_base_completion.menu_action_st_completion_rule_tree_menu
|
||||
msgid "Statement Completion Rule"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: model:ir.model,name:account_statement_base_completion.model_account_statement_completion_rule
|
||||
msgid "account.statement.completion.rule"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: help:account.bank.statement.line,additionnal_bank_fields:0
|
||||
msgid "Used by completion and import system. Adds every field that is present in your bank/office statement file"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: field:account.statement.completion.rule,profile_ids:0
|
||||
#: field:account.statement.profile,rule_ids:0
|
||||
msgid "Related statement profiles"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: code:addons/account_statement_base_completion/statement.py:158
|
||||
#: code:addons/account_statement_base_completion/statement.py:178
|
||||
#, python-format
|
||||
msgid "System error"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: field:account.bank.statement.line,already_completed:0
|
||||
msgid "Auto-Completed"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: code:addons/account_statement_base_completion/statement.py:448
|
||||
#: code:addons/account_statement_base_completion/statement.py:466
|
||||
#, python-format
|
||||
msgid "ORM bypass error"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: field:account.statement.completion.rule,sequence:0
|
||||
msgid "Sequence"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: code:addons/account_statement_base_completion/statement.py:280
|
||||
#, python-format
|
||||
msgid "Line named \"%s\" (Ref:%s) was matched by more than one partner while looking on partner label: %s"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: help:account.statement.completion.rule,sequence:0
|
||||
msgid "Lower means parsed first."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: field:res.partner,bank_statement_label:0
|
||||
msgid "Bank Statement Label"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: help:account.bank.statement.line,already_completed:0
|
||||
msgid "When this checkbox is ticked, the auto-completion process/button will ignore this line."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: help:res.partner,bank_statement_label:0
|
||||
msgid "Enter the various label found on your bank statement separated by a ; If one of this label is include in the bank statement line, the partner will be automatically filled (as long as you use this method/rules in your statement profile)."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: model:ir.model,name:account_statement_base_completion.model_res_partner
|
||||
msgid "Partner"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: view:account.bank.statement:0
|
||||
msgid "Completion Logs"
|
||||
msgstr ""
|
||||
|
||||
@@ -1,235 +0,0 @@
|
||||
# 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:57+0000\n"
|
||||
"PO-Revision-Date: 2014-06-05 22:02+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_completion
|
||||
#: view:account.statement.completion.rule:0
|
||||
msgid "Related Profiles"
|
||||
msgstr "Perfiles relacionados"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: help:account.bank.statement.line,label:0
|
||||
msgid ""
|
||||
"Generic field to store a label given from the bank/office on which we can "
|
||||
"base the default/standard providen rule."
|
||||
msgstr ""
|
||||
"Campo genérico para almacenar una etiqueta dad por el banco/entidad en la "
|
||||
"que podemos basar la regla provista por defecto."
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: code:addons/account_statement_base_completion/statement.py:169
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Line named \"%s\" (Ref:%s) was matched by more than one partner while "
|
||||
"looking on %s invoices"
|
||||
msgstr ""
|
||||
"La línea llamada \"%s\" (Ref: %s) fue casada con más de una empresa al "
|
||||
"buscar en las facturas %s"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: field:account.bank.statement,completion_logs:0
|
||||
msgid "Completion Log"
|
||||
msgstr "Registro de completado"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: field:account.bank.statement.line,label:0
|
||||
msgid "Label"
|
||||
msgstr "Etiqueta"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: model:ir.model,name:account_statement_base_completion.model_account_bank_statement
|
||||
msgid "Bank Statement"
|
||||
msgstr "Extracto bancario"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: field:account.statement.completion.rule,function_to_call:0
|
||||
msgid "Method"
|
||||
msgstr "Método"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: code:addons/account_statement_base_completion/statement.py:326
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Line named \"%s\" (Ref:%s) was matched by more than one partner while "
|
||||
"looking on partner by name"
|
||||
msgstr ""
|
||||
"La línea llamada \"%s\" (Ref: %s) fue casada con más de una empresa al "
|
||||
"buscar por nombre de empresa"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: code:addons/account_statement_base_completion/statement.py:504
|
||||
#, python-format
|
||||
msgid "Statement ID %s auto-completed for %s lines completed"
|
||||
msgstr "Se han auto-completado para el extracto con ID %s %s líneas"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: code:addons/account_statement_base_completion/statement.py:500
|
||||
#, python-format
|
||||
msgid ""
|
||||
"%s Bank Statement ID %s has %s lines completed by %s \n"
|
||||
"%s\n"
|
||||
"%s\n"
|
||||
msgstr ""
|
||||
"%s El extracto bancario con ID %s tiene %s líneas completadas por %s \n"
|
||||
"%s\n"
|
||||
"%s\n"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: model:ir.model,name:account_statement_base_completion.model_account_bank_statement_line
|
||||
msgid "Bank Statement Line"
|
||||
msgstr "Línea del extracto bancario"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: field:account.bank.statement.line,additionnal_bank_fields:0
|
||||
msgid "Additionnal infos from bank"
|
||||
msgstr "Información adicional del banco"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: view:account.statement.profile:0
|
||||
msgid "Auto-Completion Rules"
|
||||
msgstr "Reglas de auto-completado"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: view:account.bank.statement:0
|
||||
msgid "Importation related infos"
|
||||
msgstr "Información relacionada con la importación"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: code:addons/account_statement_base_completion/statement.py:159
|
||||
#: code:addons/account_statement_base_completion/statement.py:179
|
||||
#, python-format
|
||||
msgid "Invalid invoice type for completion: %"
|
||||
msgstr "Tipo de factura no válida para completado: %s"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: field:account.statement.completion.rule,name:0
|
||||
msgid "Name"
|
||||
msgstr "Nombre"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: model:ir.model,name:account_statement_base_completion.model_account_statement_profile
|
||||
msgid "Statement Profile"
|
||||
msgstr "Perfil de extracto"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: view:account.bank.statement:0
|
||||
msgid "Auto Completion"
|
||||
msgstr "Auto completado"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: view:account.statement.completion.rule:0
|
||||
#: model:ir.actions.act_window,name:account_statement_base_completion.action_st_completion_rule_tree
|
||||
#: model:ir.ui.menu,name:account_statement_base_completion.menu_action_st_completion_rule_tree_menu
|
||||
msgid "Statement Completion Rule"
|
||||
msgstr "Regla de completado del extracto"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: model:ir.model,name:account_statement_base_completion.model_account_statement_completion_rule
|
||||
msgid "account.statement.completion.rule"
|
||||
msgstr "account.statement.completion.rule"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: help:account.bank.statement.line,additionnal_bank_fields:0
|
||||
msgid ""
|
||||
"Used by completion and import system. Adds every field that is present in "
|
||||
"your bank/office statement file"
|
||||
msgstr ""
|
||||
"Usado por el sistema de importación y completado. Añade cada campo que está "
|
||||
"presente en su archivo de extracto del banco/entidad"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: field:account.statement.completion.rule,profile_ids:0
|
||||
#: field:account.statement.profile,rule_ids:0
|
||||
msgid "Related statement profiles"
|
||||
msgstr "Perfiles de extractos relacionados"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: code:addons/account_statement_base_completion/statement.py:158
|
||||
#: code:addons/account_statement_base_completion/statement.py:178
|
||||
#, python-format
|
||||
msgid "System error"
|
||||
msgstr "Error de sistema"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: field:account.bank.statement.line,already_completed:0
|
||||
msgid "Auto-Completed"
|
||||
msgstr "Auto-completado"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: code:addons/account_statement_base_completion/statement.py:448
|
||||
#: code:addons/account_statement_base_completion/statement.py:466
|
||||
#, python-format
|
||||
msgid "ORM bypass error"
|
||||
msgstr "Error al saltar el ORM"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: field:account.statement.completion.rule,sequence:0
|
||||
msgid "Sequence"
|
||||
msgstr "Secuencia"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: code:addons/account_statement_base_completion/statement.py:280
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Line named \"%s\" (Ref:%s) was matched by more than one partner while "
|
||||
"looking on partner label: %s"
|
||||
msgstr ""
|
||||
"La línea llamada \"%s\" (Ref: %s) fue casada con más de una empresa al "
|
||||
"buscar por la etiqueta de empresa: %s"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: help:account.statement.completion.rule,sequence:0
|
||||
msgid "Lower means parsed first."
|
||||
msgstr "Más bajo significa reconocido primero."
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: field:res.partner,bank_statement_label:0
|
||||
msgid "Bank Statement Label"
|
||||
msgstr "Etiqueta del extracto bancario"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: help:account.bank.statement.line,already_completed:0
|
||||
msgid ""
|
||||
"When this checkbox is ticked, the auto-completion process/button will ignore "
|
||||
"this line."
|
||||
msgstr ""
|
||||
"Cuando la casilla está marcada, el proceso de auto-completado/botón será "
|
||||
"ignorado para esta línea."
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: help:res.partner,bank_statement_label:0
|
||||
msgid ""
|
||||
"Enter the various label found on your bank statement separated by a ; If "
|
||||
" one of this label is include in the bank statement line, the "
|
||||
"partner will be automatically filled (as long as you use "
|
||||
"this method/rules in your statement profile)."
|
||||
msgstr ""
|
||||
"Introduzca los diversos tipos de etiqueta encontrados en el extracto "
|
||||
"bancario, separados por un ;. Si una de estas etiquetas está incluida en la "
|
||||
"línea del extracto bancario, la empresa será rellenada automáticamente "
|
||||
"(mientras use este método/reglas en el perfil de extracto)."
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: model:ir.model,name:account_statement_base_completion.model_res_partner
|
||||
msgid "Partner"
|
||||
msgstr "Empresa"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: view:account.bank.statement:0
|
||||
msgid "Completion Logs"
|
||||
msgstr "Registro de completado"
|
||||
@@ -1,223 +0,0 @@
|
||||
# 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:57+0000\n"
|
||||
"PO-Revision-Date: 2014-06-19 13:54+0000\n"
|
||||
"Last-Translator: Joël Grand-Guillaume @ camptocamp "
|
||||
"<joel.grandguillaume@camptocamp.com>\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-06-20 06:09+0000\n"
|
||||
"X-Generator: Launchpad (build 17058)\n"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: view:account.statement.completion.rule:0
|
||||
msgid "Related Profiles"
|
||||
msgstr "Profils liés"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: help:account.bank.statement.line,label:0
|
||||
msgid ""
|
||||
"Generic field to store a label given from the bank/office on which we can "
|
||||
"base the default/standard providen rule."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: code:addons/account_statement_base_completion/statement.py:169
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Line named \"%s\" (Ref:%s) was matched by more than one partner while "
|
||||
"looking on %s invoices"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: field:account.bank.statement,completion_logs:0
|
||||
msgid "Completion Log"
|
||||
msgstr "Journal des complétions"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: field:account.bank.statement.line,label:0
|
||||
msgid "Label"
|
||||
msgstr "Libellé"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: model:ir.model,name:account_statement_base_completion.model_account_bank_statement
|
||||
msgid "Bank Statement"
|
||||
msgstr "Relevé bancaire"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: field:account.statement.completion.rule,function_to_call:0
|
||||
msgid "Method"
|
||||
msgstr "Méthode"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: code:addons/account_statement_base_completion/statement.py:326
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Line named \"%s\" (Ref:%s) was matched by more than one partner while "
|
||||
"looking on partner by name"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: code:addons/account_statement_base_completion/statement.py:504
|
||||
#, python-format
|
||||
msgid "Statement ID %s auto-completed for %s lines completed"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: code:addons/account_statement_base_completion/statement.py:500
|
||||
#, python-format
|
||||
msgid ""
|
||||
"%s Bank Statement ID %s has %s lines completed by %s \n"
|
||||
"%s\n"
|
||||
"%s\n"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: model:ir.model,name:account_statement_base_completion.model_account_bank_statement_line
|
||||
msgid "Bank Statement Line"
|
||||
msgstr "Ligne de relevé bancaire"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: field:account.bank.statement.line,additionnal_bank_fields:0
|
||||
msgid "Additionnal infos from bank"
|
||||
msgstr "Informations additionnelles de la banque"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: view:account.statement.profile:0
|
||||
msgid "Auto-Completion Rules"
|
||||
msgstr "Règles d'auto-complétion"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: view:account.bank.statement:0
|
||||
msgid "Importation related infos"
|
||||
msgstr "Importation des informations liées"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: code:addons/account_statement_base_completion/statement.py:159
|
||||
#: code:addons/account_statement_base_completion/statement.py:179
|
||||
#, python-format
|
||||
msgid "Invalid invoice type for completion: %"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: field:account.statement.completion.rule,name:0
|
||||
msgid "Name"
|
||||
msgstr "Nom"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: model:ir.model,name:account_statement_base_completion.model_account_statement_profile
|
||||
msgid "Statement Profile"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: view:account.bank.statement:0
|
||||
msgid "Auto Completion"
|
||||
msgstr "Auto-complétion"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: view:account.statement.completion.rule:0
|
||||
#: model:ir.actions.act_window,name:account_statement_base_completion.action_st_completion_rule_tree
|
||||
#: model:ir.ui.menu,name:account_statement_base_completion.menu_action_st_completion_rule_tree_menu
|
||||
msgid "Statement Completion Rule"
|
||||
msgstr "Règle d'auto-complétion du relevé"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: model:ir.model,name:account_statement_base_completion.model_account_statement_completion_rule
|
||||
msgid "account.statement.completion.rule"
|
||||
msgstr "account.statement.completion.rule"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: help:account.bank.statement.line,additionnal_bank_fields:0
|
||||
msgid ""
|
||||
"Used by completion and import system. Adds every field that is present in "
|
||||
"your bank/office statement file"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: field:account.statement.completion.rule,profile_ids:0
|
||||
#: field:account.statement.profile,rule_ids:0
|
||||
msgid "Related statement profiles"
|
||||
msgstr "Profils liés"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: code:addons/account_statement_base_completion/statement.py:158
|
||||
#: code:addons/account_statement_base_completion/statement.py:178
|
||||
#, python-format
|
||||
msgid "System error"
|
||||
msgstr "Erreur système"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: field:account.bank.statement.line,already_completed:0
|
||||
msgid "Auto-Completed"
|
||||
msgstr "Auto-Complété"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: code:addons/account_statement_base_completion/statement.py:448
|
||||
#: code:addons/account_statement_base_completion/statement.py:466
|
||||
#, python-format
|
||||
msgid "ORM bypass error"
|
||||
msgstr "Erreur de bypass de l'ORM"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: field:account.statement.completion.rule,sequence:0
|
||||
msgid "Sequence"
|
||||
msgstr "Séquence"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: code:addons/account_statement_base_completion/statement.py:280
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Line named \"%s\" (Ref:%s) was matched by more than one partner while "
|
||||
"looking on partner label: %s"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: help:account.statement.completion.rule,sequence:0
|
||||
msgid "Lower means parsed first."
|
||||
msgstr "Plus petite séquence analysée en premier."
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: field:res.partner,bank_statement_label:0
|
||||
msgid "Bank Statement Label"
|
||||
msgstr "Description de relevé bancaire"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: help:account.bank.statement.line,already_completed:0
|
||||
msgid ""
|
||||
"When this checkbox is ticked, the auto-completion process/button will ignore "
|
||||
"this line."
|
||||
msgstr ""
|
||||
"Les lignes cochées seront ignorées lorsque vous cliquez sur le bouton auto-"
|
||||
"complétion"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: help:res.partner,bank_statement_label:0
|
||||
msgid ""
|
||||
"Enter the various label found on your bank statement separated by a ; If "
|
||||
" one of this label is include in the bank statement line, the "
|
||||
"partner will be automatically filled (as long as you use "
|
||||
"this method/rules in your statement profile)."
|
||||
msgstr ""
|
||||
"Entrez les différentes descriptions/informations sur votre relevé bancaire "
|
||||
"séparées par un ';' Si l'une d'entre elles figure dans la ligne du "
|
||||
"relevé, le partenaire correspondant sera automatiquement retrouvé "
|
||||
"(à condition d'utiliser un règle de lettrage dans le profil)."
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: model:ir.model,name:account_statement_base_completion.model_res_partner
|
||||
msgid "Partner"
|
||||
msgstr "Partenaire"
|
||||
|
||||
#. module: account_statement_base_completion
|
||||
#: view:account.bank.statement:0
|
||||
msgid "Completion Logs"
|
||||
msgstr "Journaux d'auto-complétion"
|
||||
@@ -1,39 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##########################################################################
|
||||
#
|
||||
# Copyright (C) 2011 Akretion & Camptocamp
|
||||
# Author : Sébastien BEAU, Joel Grand-Guillaume
|
||||
#
|
||||
# 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 openerp.osv import orm, fields
|
||||
|
||||
|
||||
class ResPartner(orm.Model):
|
||||
"""Add a bank label on the partner so that we can use it to match
|
||||
this partner when we found this in a statement line.
|
||||
"""
|
||||
_inherit = 'res.partner'
|
||||
|
||||
_columns = {
|
||||
'bank_statement_label': fields.char(
|
||||
'Bank Statement Label', size=100,
|
||||
help="Enter the various label found on your bank statement "
|
||||
"separated by a ; If one of this label is include in the "
|
||||
"bank statement line, the partner will be automatically "
|
||||
"filled (as long as you use this method/rules in your "
|
||||
"statement profile)."),
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="bk_view_partner_form" model="ir.ui.view">
|
||||
<field name="name">account_bank_statement_import.view.partner.form</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="priority">20</field>
|
||||
<field name="inherit_id" ref="account.view_partner_property_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="property_account_payable" position="after">
|
||||
<field name="bank_statement_label"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -1,3 +0,0 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_account_bank_st_cmpl_user,account.statement.completion.rule,model_account_statement_completion_rule,account.group_account_user,1,0,0,0
|
||||
access_account_bank_st_cmpl_manager,account.statement.completion.rule,model_account_statement_completion_rule,account.group_account_manager,1,1,1,1
|
||||
|
@@ -1,654 +0,0 @@
|
||||
# -*- 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/>.
|
||||
#
|
||||
##############################################################################
|
||||
# TODO replace customer supplier by package constant
|
||||
import traceback
|
||||
import sys
|
||||
import logging
|
||||
import simplejson
|
||||
import inspect
|
||||
import datetime
|
||||
|
||||
import psycopg2
|
||||
|
||||
from collections import defaultdict
|
||||
import re
|
||||
from openerp.tools.translate import _
|
||||
from openerp.osv import orm, fields
|
||||
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
|
||||
from operator import attrgetter
|
||||
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ErrorTooManyPartner(Exception):
|
||||
""" New Exception definition that is raised when more than one partner is
|
||||
matched by the completion rule.
|
||||
"""
|
||||
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
|
||||
def __str__(self):
|
||||
return repr(self.value)
|
||||
|
||||
def __repr__(self):
|
||||
return repr(self.value)
|
||||
|
||||
|
||||
class AccountStatementProfil(orm.Model):
|
||||
"""Extend the class to add rules per profile that will match at least the
|
||||
partner, but it could also be used to match other values as well.
|
||||
"""
|
||||
_inherit = "account.statement.profile"
|
||||
|
||||
_columns = {
|
||||
# @Akretion: For now, we don't implement this features, but this would
|
||||
# probably be there: 'auto_completion': fields.text('Auto Completion'),
|
||||
# 'transferts_account_id':fields.many2one('account.account',
|
||||
# 'Transferts Account'),
|
||||
# => You can implement it in a module easily, we design it with your
|
||||
# needs in mind as well!
|
||||
|
||||
'rule_ids': fields.many2many(
|
||||
'account.statement.completion.rule',
|
||||
string='Related statement profiles',
|
||||
rel='as_rul_st_prof_rel'),
|
||||
}
|
||||
|
||||
def _get_rules(self, cr, uid, profile, context=None):
|
||||
if isinstance(profile, (int, long)):
|
||||
prof = self.browse(cr, uid, profile, context=context)
|
||||
else:
|
||||
prof = profile
|
||||
# We need to respect the sequence order
|
||||
return sorted(prof.rule_ids, key=attrgetter('sequence'))
|
||||
|
||||
def _find_values_from_rules(self, cr, uid, calls, line, context=None):
|
||||
"""This method will execute all related rules, in their sequence order,
|
||||
to retrieve all the values returned by the first rules that will match.
|
||||
:param calls: list of lookup function name available in rules
|
||||
:param dict line: read of the concerned account.bank.statement.line
|
||||
:return:
|
||||
A dict of value that can be passed directly to the write method of
|
||||
the statement line or {}
|
||||
{'partner_id': value,
|
||||
'account_id: value,
|
||||
|
||||
...}
|
||||
"""
|
||||
if not calls:
|
||||
calls = self._get_rules(
|
||||
cr, uid, line['profile_id'], context=context)
|
||||
rule_obj = self.pool.get('account.statement.completion.rule')
|
||||
for call in calls:
|
||||
method_to_call = getattr(rule_obj, call.function_to_call)
|
||||
if len(inspect.getargspec(method_to_call).args) == 6:
|
||||
result = method_to_call(cr, uid, call.id, line, context)
|
||||
else:
|
||||
result = method_to_call(cr, uid, line, context)
|
||||
if result:
|
||||
result['already_completed'] = True
|
||||
return result
|
||||
return None
|
||||
|
||||
|
||||
class AccountStatementCompletionRule(orm.Model):
|
||||
"""This will represent all the completion method that we can have to
|
||||
fullfill the bank statement lines. You'll be able to extend them in you own
|
||||
module and choose those to apply for every statement profile.
|
||||
The goal of a rule is to fullfill at least the partner of the line, but
|
||||
if possible also the reference because we'll use it in the reconciliation
|
||||
process. The reference should contain the invoice number or the SO number
|
||||
or any reference that will be matched by the invoice accounting move.
|
||||
"""
|
||||
_name = "account.statement.completion.rule"
|
||||
_order = "sequence asc"
|
||||
|
||||
def _get_functions(self, cr, uid, context=None):
|
||||
"""List of available methods for rules.
|
||||
|
||||
Override this to add you own."""
|
||||
return [
|
||||
('get_from_ref_and_invoice',
|
||||
'From line reference (based on customer invoice number)'),
|
||||
('get_from_ref_and_supplier_invoice',
|
||||
'From line reference (based on supplier invoice number)'),
|
||||
('get_from_label_and_partner_field',
|
||||
'From line label (based on partner field)'),
|
||||
('get_from_label_and_partner_name',
|
||||
'From line label (based on partner name)')
|
||||
]
|
||||
|
||||
def __get_functions(self, cr, uid, context=None):
|
||||
""" Call method which can be inherited """
|
||||
return self._get_functions(cr, uid, context=context)
|
||||
|
||||
_columns = {
|
||||
'sequence': fields.integer('Sequence',
|
||||
help="Lower means parsed first."),
|
||||
'name': fields.char('Name', size=128),
|
||||
'profile_ids': fields.many2many(
|
||||
'account.statement.profile',
|
||||
rel='as_rul_st_prof_rel',
|
||||
string='Related statement profiles'),
|
||||
'function_to_call': fields.selection(__get_functions, 'Method'),
|
||||
}
|
||||
|
||||
def _find_invoice(self, cr, uid, st_line, inv_type, context=None):
|
||||
"""Find invoice related to statement line"""
|
||||
inv_obj = self.pool.get('account.invoice')
|
||||
if inv_type == 'supplier':
|
||||
type_domain = ('in_invoice', 'in_refund')
|
||||
number_field = 'supplier_invoice_number'
|
||||
elif inv_type == 'customer':
|
||||
type_domain = ('out_invoice', 'out_refund')
|
||||
number_field = 'number'
|
||||
else:
|
||||
raise orm.except_orm(
|
||||
_('System error'),
|
||||
_('Invalid invoice type for completion: %') % inv_type)
|
||||
|
||||
inv_id = inv_obj.search(cr, uid,
|
||||
[(number_field, '=', st_line['ref'].strip()),
|
||||
('type', 'in', type_domain)],
|
||||
context=context)
|
||||
if inv_id:
|
||||
if len(inv_id) == 1:
|
||||
inv = inv_obj.browse(cr, uid, inv_id[0], context=context)
|
||||
else:
|
||||
raise ErrorTooManyPartner(
|
||||
_('Line named "%s" (Ref:%s) was matched by more than one '
|
||||
'partner while looking on %s invoices') %
|
||||
(st_line['name'], st_line['ref'], inv_type))
|
||||
return inv
|
||||
return False
|
||||
|
||||
def _from_invoice(self, cr, uid, line, inv_type, context):
|
||||
"""Populate statement line values"""
|
||||
if inv_type not in ('supplier', 'customer'):
|
||||
raise orm.except_orm(_('System error'),
|
||||
_('Invalid invoice type for completion: %') %
|
||||
inv_type)
|
||||
res = {}
|
||||
inv = self._find_invoice(cr, uid, line, inv_type, context=context)
|
||||
if inv:
|
||||
partner_id = inv.commercial_partner_id.id
|
||||
res = {'partner_id': partner_id,
|
||||
'account_id': inv.account_id.id,
|
||||
'type': inv_type}
|
||||
override_acc = line['master_account_id']
|
||||
if override_acc:
|
||||
res['account_id'] = override_acc
|
||||
return res
|
||||
|
||||
# Should be private but data are initialised with no update XML
|
||||
def get_from_ref_and_supplier_invoice(self, cr, uid, line, context=None):
|
||||
"""Match the partner based on the invoice supplier invoice number and
|
||||
the reference of the statement line. Then, call the generic
|
||||
get_values_for_line method to complete other values. If more than one
|
||||
partner matched, raise the ErrorTooManyPartner error.
|
||||
|
||||
:param dict line: read of the concerned account.bank.statement.line
|
||||
:return:
|
||||
A dict of value that can be passed directly to the write method of
|
||||
the statement line or {}
|
||||
{'partner_id': value,
|
||||
'account_id': value,
|
||||
|
||||
...}
|
||||
"""
|
||||
return self._from_invoice(cr, uid, line, 'supplier', context=context)
|
||||
|
||||
# Should be private but data are initialised with no update XML
|
||||
def get_from_ref_and_invoice(self, cr, uid, line, context=None):
|
||||
"""Match the partner based on the invoice number and the reference of
|
||||
the statement line. Then, call the generic get_values_for_line method
|
||||
to complete other values. If more than one partner matched, raise the
|
||||
ErrorTooManyPartner error.
|
||||
|
||||
:param dict line: read of the concerned account.bank.statement.line
|
||||
:return:
|
||||
A dict of value that can be passed directly to the write method of
|
||||
the statement line or {}
|
||||
{'partner_id': value,
|
||||
'account_id': value,
|
||||
...}
|
||||
"""
|
||||
return self._from_invoice(cr, uid, line, 'customer', context=context)
|
||||
|
||||
# Should be private but data are initialised with no update XML
|
||||
def get_from_label_and_partner_field(self, cr, uid, st_line, context=None):
|
||||
"""
|
||||
Match the partner based on the label field of the statement line and
|
||||
the text defined in the 'bank_statement_label' field of the partner.
|
||||
Remember that we can have values separated with ; Then, call the
|
||||
generic get_values_for_line method to complete other values. If more
|
||||
than one partner matched, raise the ErrorTooManyPartner error.
|
||||
|
||||
:param dict st_line: read of the concerned account.bank.statement.line
|
||||
:return:
|
||||
A dict of value that can be passed directly to the write method of
|
||||
the statement line or {}
|
||||
{'partner_id': value,
|
||||
'account_id': value,
|
||||
|
||||
...}
|
||||
"""
|
||||
partner_obj = self.pool['res.partner']
|
||||
st_obj = self.pool.get('account.bank.statement.line')
|
||||
res = {}
|
||||
# As we have to iterate on each partner for each line,
|
||||
# we memoize the pair to avoid
|
||||
# to redo computation for each line.
|
||||
# Following code can be done by a single SQL query
|
||||
# but this option is not really maintanable
|
||||
if not context.get('label_memoizer'):
|
||||
context['label_memoizer'] = defaultdict(list)
|
||||
partner_ids = partner_obj.search(
|
||||
cr, uid, [('bank_statement_label', '!=', False)],
|
||||
context=context)
|
||||
line_ids = context.get('line_ids', [])
|
||||
for partner in partner_obj.browse(cr, uid, partner_ids,
|
||||
context=context):
|
||||
vals = '|'.join(
|
||||
re.escape(x.strip())
|
||||
for x in partner.bank_statement_label.split(';'))
|
||||
or_regex = ".*%s.*" % vals
|
||||
sql = ("SELECT id from account_bank_statement_line"
|
||||
" WHERE id in %s"
|
||||
" AND name ~* %s")
|
||||
cr.execute(sql, (line_ids, or_regex))
|
||||
pairs = cr.fetchall()
|
||||
for pair in pairs:
|
||||
context['label_memoizer'][pair[0]].append(partner)
|
||||
if st_line['id'] in context['label_memoizer']:
|
||||
found_partner = context['label_memoizer'][st_line['id']]
|
||||
if len(found_partner) > 1:
|
||||
msg = (_('Line named "%s" (Ref:%s) was matched by more than '
|
||||
'one partner while looking on partner label: %s') %
|
||||
(st_line['name'], st_line['ref'],
|
||||
','.join([x.name for x in found_partner])))
|
||||
raise ErrorTooManyPartner(msg)
|
||||
res['partner_id'] = found_partner[0].id
|
||||
st_vals = st_obj.get_values_for_line(
|
||||
cr, uid, profile_id=st_line['profile_id'],
|
||||
master_account_id=st_line['master_account_id'],
|
||||
partner_id=found_partner[0].id, line_type=False,
|
||||
amount=st_line['amount'] if st_line['amount'] else 0.0,
|
||||
context=context)
|
||||
res.update(st_vals)
|
||||
return res
|
||||
|
||||
def get_from_label_and_partner_name(self, cr, uid, st_line, context=None):
|
||||
"""Match the partner based on the label field of the statement line and
|
||||
the name of the partner. Then, call the generic get_values_for_line
|
||||
method to complete other values. If more than one partner matched,
|
||||
raise the ErrorTooManyPartner error.
|
||||
|
||||
:param dict st_line: read of the concerned account.bank.statement.line
|
||||
:return:
|
||||
A dict of value that can be passed directly to the write method of
|
||||
the statement line or {}
|
||||
{'partner_id': value,
|
||||
'account_id': value,
|
||||
|
||||
...}
|
||||
"""
|
||||
res = {}
|
||||
# We memoize allowed partner
|
||||
if not context.get('partner_memoizer'):
|
||||
context['partner_memoizer'] = tuple(
|
||||
self.pool['res.partner'].search(cr, uid, []))
|
||||
if not context['partner_memoizer']:
|
||||
return res
|
||||
st_obj = self.pool.get('account.bank.statement.line')
|
||||
# The regexp_replace() escapes the name to avoid false positive
|
||||
# example: 'John J. Doe (No 1)' is escaped to 'John J\. Doe \(No 1\)'
|
||||
# See http://stackoverflow.com/a/400316/1504003 for a list of
|
||||
# chars to escape. Postgres is POSIX-ARE, compatible with
|
||||
# POSIX-ERE excepted that '\' must be escaped inside brackets according
|
||||
# to:
|
||||
# http://www.postgresql.org/docs/9.0/static/functions-matching.html
|
||||
# in chapter 9.7.3.6. Limits and Compatibility
|
||||
sql = r"""
|
||||
SELECT id FROM (
|
||||
SELECT id,
|
||||
regexp_matches(%s,
|
||||
regexp_replace(name,'([\.\^\$\*\+\?\(\)\[\{\\\|])', %s,
|
||||
'g'), 'i') AS name_match
|
||||
FROM res_partner
|
||||
WHERE id IN %s)
|
||||
AS res_patner_matcher
|
||||
WHERE name_match IS NOT NULL"""
|
||||
cr.execute(
|
||||
sql, (st_line['name'], r"\\\1", context['partner_memoizer']))
|
||||
result = cr.fetchall()
|
||||
if not result:
|
||||
return res
|
||||
if len(result) > 1:
|
||||
raise ErrorTooManyPartner(
|
||||
_('Line named "%s" (Ref:%s) was matched by more than one '
|
||||
'partner while looking on partner by name') %
|
||||
(st_line['name'], st_line['ref']))
|
||||
res['partner_id'] = result[0][0]
|
||||
st_vals = st_obj.get_values_for_line(
|
||||
cr, uid, profile_id=st_line['profile_id'],
|
||||
master_account_id=st_line['master_account_id'],
|
||||
partner_id=res['partner_id'], line_type=False,
|
||||
amount=st_line['amount'] if st_line['amount'] else 0.0,
|
||||
context=context)
|
||||
res.update(st_vals)
|
||||
return res
|
||||
|
||||
|
||||
class AccountStatement(orm.Model):
|
||||
_inherit = "account.bank.statement"
|
||||
|
||||
def button_confirm_bank(self, cr, uid, ids, context=None):
|
||||
line_obj = self.pool['account.bank.statement.line']
|
||||
for stat_id in ids:
|
||||
line_without_account = line_obj.search(cr, uid, [
|
||||
['statement_id', '=', stat_id],
|
||||
['account_id', '=', False],
|
||||
], context=context)
|
||||
if line_without_account:
|
||||
stat = self.browse(cr, uid, stat_id, context=context)
|
||||
raise orm.except_orm(
|
||||
_('User error'),
|
||||
_('You should fill all account on the line of the'
|
||||
' statement %s') % stat.name)
|
||||
return super(AccountStatement, self).button_confirm_bank(
|
||||
cr, uid, ids, context=context)
|
||||
|
||||
|
||||
class AccountStatementLine(orm.Model):
|
||||
"""
|
||||
Add sparse field on the statement line to allow to store all the bank infos
|
||||
that are given by a bank/office. You can then add you own in your module.
|
||||
The idea here is to store all bank/office infos in the
|
||||
additionnal_bank_fields serialized field when importing the file. If many
|
||||
values, add a tab in the bank statement line to store your specific one.
|
||||
Have a look in account_statement_base_import module to see how we've done
|
||||
it.
|
||||
"""
|
||||
_inherit = "account.bank.statement.line"
|
||||
_order = "already_completed desc, date asc"
|
||||
|
||||
_columns = {
|
||||
'additionnal_bank_fields': fields.serialized(
|
||||
'Additionnal infos from bank',
|
||||
help="Used by completion and import system. Adds every field that "
|
||||
"is present in your bank/office statement file"),
|
||||
'label': fields.sparse(
|
||||
type='char',
|
||||
string='Label',
|
||||
serialization_field='additionnal_bank_fields',
|
||||
help="Generic field to store a label given from the "
|
||||
"bank/office on which we can base the default/standard "
|
||||
"providen rule."),
|
||||
'already_completed': fields.boolean(
|
||||
"Auto-Completed",
|
||||
help="When this checkbox is ticked, the auto-completion "
|
||||
"process/button will ignore this line."),
|
||||
# Set account_id field as optional by removing required option.
|
||||
'account_id': fields.many2one('account.account', 'Account'),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'already_completed': False,
|
||||
}
|
||||
|
||||
def _get_line_values_from_rules(self, cr, uid, line, rules, context=None):
|
||||
"""We'll try to find out the values related to the line based on rules
|
||||
setted on the profile.. We will ignore line for which already_completed
|
||||
is ticked.
|
||||
|
||||
:return:
|
||||
A dict of dict value that can be passed directly to the write
|
||||
method of the statement line or {}. The first dict has statement
|
||||
line ID as a key: {117009: {'partner_id': 100997,
|
||||
'account_id': 489L}}
|
||||
"""
|
||||
profile_obj = self.pool['account.statement.profile']
|
||||
if line.get('already_completed'):
|
||||
return {}
|
||||
# Ask the rule
|
||||
vals = profile_obj._find_values_from_rules(
|
||||
cr, uid, rules, line, context)
|
||||
if vals:
|
||||
vals['id'] = line['id']
|
||||
return vals
|
||||
return {}
|
||||
|
||||
def _get_available_columns(self, statement_store,
|
||||
include_serializable=False):
|
||||
"""Return writeable by SQL columns"""
|
||||
statement_line_obj = self.pool['account.bank.statement.line']
|
||||
model_cols = statement_line_obj._columns
|
||||
avail = [
|
||||
k for k, col in model_cols.iteritems() if not hasattr(col, '_fnct')
|
||||
]
|
||||
keys = [k for k in statement_store[0].keys() if k in avail]
|
||||
# add sparse fields..
|
||||
if include_serializable:
|
||||
for k, col in model_cols.iteritems():
|
||||
if k in statement_store[0].keys() and \
|
||||
isinstance(col, fields.sparse) and \
|
||||
col.serialization_field not in keys and \
|
||||
col._type == 'char':
|
||||
keys.append(col.serialization_field)
|
||||
keys.sort()
|
||||
return keys
|
||||
|
||||
def _prepare_insert(self, statement, cols):
|
||||
""" Apply column formating to prepare data for SQL inserting
|
||||
Return a copy of statement
|
||||
"""
|
||||
st_copy = statement
|
||||
for k, col in st_copy.iteritems():
|
||||
if k in cols:
|
||||
st_copy[k] = self._columns[k]._symbol_set[1](col)
|
||||
return st_copy
|
||||
|
||||
def _prepare_manyinsert(self, statement_store, cols):
|
||||
""" Apply column formating to prepare multiple SQL inserts
|
||||
Return a copy of statement_store
|
||||
"""
|
||||
values = []
|
||||
for statement in statement_store:
|
||||
values.append(self._prepare_insert(statement, cols))
|
||||
return values
|
||||
|
||||
def _serialize_sparse_fields(self, cols, statement_store):
|
||||
""" Serialize sparse fields values in the target serialized field
|
||||
Return a copy of statement_store
|
||||
"""
|
||||
statement_line_obj = self.pool['account.bank.statement.line']
|
||||
model_cols = statement_line_obj._columns
|
||||
sparse_fields = dict(
|
||||
[(k, col) for k, col in model_cols.iteritems() if isinstance(
|
||||
col, fields.sparse) and col._type == 'char'])
|
||||
values = []
|
||||
for statement in statement_store:
|
||||
to_json_k = set()
|
||||
st_copy = statement.copy()
|
||||
for k, col in sparse_fields.iteritems():
|
||||
if k in st_copy:
|
||||
to_json_k.add(col.serialization_field)
|
||||
serialized = st_copy.setdefault(
|
||||
col.serialization_field, {})
|
||||
serialized[k] = st_copy[k]
|
||||
for k in to_json_k:
|
||||
st_copy[k] = simplejson.dumps(st_copy[k])
|
||||
values.append(st_copy)
|
||||
return values
|
||||
|
||||
def _insert_lines(self, cr, uid, statement_store, context=None):
|
||||
""" Do raw insert into database because ORM is awfully slow
|
||||
when doing batch write. It is a shame that batch function
|
||||
does not exist"""
|
||||
statement_line_obj = self.pool['account.bank.statement.line']
|
||||
statement_line_obj.check_access_rule(cr, uid, [], 'create')
|
||||
statement_line_obj.check_access_rights(
|
||||
cr, uid, 'create', raise_exception=True)
|
||||
cols = self._get_available_columns(
|
||||
statement_store, include_serializable=True)
|
||||
statement_store = self._prepare_manyinsert(statement_store, cols)
|
||||
tmp_vals = (', '.join(cols), ', '.join(['%%(%s)s' % i for i in cols]))
|
||||
sql = "INSERT INTO account_bank_statement_line (%s) " \
|
||||
"VALUES (%s);" % tmp_vals
|
||||
try:
|
||||
cr.executemany(
|
||||
sql, tuple(self._serialize_sparse_fields(cols,
|
||||
statement_store)))
|
||||
except psycopg2.Error as sql_err:
|
||||
cr.rollback()
|
||||
raise orm.except_orm(_("ORM bypass error"),
|
||||
sql_err.pgerror)
|
||||
|
||||
def _update_line(self, cr, uid, vals, context=None):
|
||||
""" Do raw update into database because ORM is awfully slow
|
||||
when cheking security.
|
||||
TODO / WARM: sparse fields are skipped by the method. IOW, if your
|
||||
completion rule update an sparse field, the updated value will never
|
||||
be stored in the database. It would be safer to call the update method
|
||||
from the ORM for records updating this kind of fields.
|
||||
"""
|
||||
cols = self._get_available_columns([vals])
|
||||
vals = self._prepare_insert(vals, cols)
|
||||
tmp_vals = (', '.join(['%s = %%(%s)s' % (i, i) for i in cols]))
|
||||
sql = "UPDATE account_bank_statement_line " \
|
||||
"SET %s where id = %%(id)s;" % tmp_vals
|
||||
try:
|
||||
cr.execute(sql, vals)
|
||||
except psycopg2.Error as sql_err:
|
||||
cr.rollback()
|
||||
raise orm.except_orm(_("ORM bypass error"),
|
||||
sql_err.pgerror)
|
||||
|
||||
|
||||
class AccountBankStatement(orm.Model):
|
||||
"""We add a basic button and stuff to support the auto-completion
|
||||
of the bank statement once line have been imported or manually fullfill.
|
||||
"""
|
||||
_inherit = "account.bank.statement"
|
||||
|
||||
_columns = {
|
||||
'completion_logs': fields.text('Completion Log', readonly=True),
|
||||
}
|
||||
|
||||
def write_completion_log(self, cr, uid, stat_id, error_msg,
|
||||
number_imported, context=None):
|
||||
"""Write the log in the completion_logs field of the bank statement to
|
||||
let the user know what have been done. This is an append mode, so we
|
||||
don't overwrite what already recoded.
|
||||
|
||||
:param int/long stat_id: ID of the account.bank.statement
|
||||
:param char error_msg: Message to add
|
||||
:number_imported int/long: Number of lines that have been completed
|
||||
:return True
|
||||
"""
|
||||
user_name = self.pool.get('res.users').read(
|
||||
cr, uid, uid, ['name'], context=context)['name']
|
||||
statement = self.browse(cr, uid, stat_id, context=context)
|
||||
number_line = len(statement.line_ids)
|
||||
log = self.read(cr, uid, stat_id, ['completion_logs'],
|
||||
context=context)['completion_logs']
|
||||
log = log if log else ""
|
||||
completion_date = datetime.datetime.now().strftime(
|
||||
DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
message = (_("%s Bank Statement ID %s has %s/%s lines completed by "
|
||||
"%s \n%s\n%s\n") % (completion_date, stat_id,
|
||||
number_imported, number_line,
|
||||
user_name, error_msg, log))
|
||||
self.write(
|
||||
cr, uid, [stat_id], {'completion_logs': message}, context=context)
|
||||
|
||||
body = (_('Statement ID %s auto-completed for %s/%s lines completed') %
|
||||
(stat_id, number_imported, number_line)),
|
||||
self.message_post(cr, uid, [stat_id], body=body, context=context)
|
||||
return True
|
||||
|
||||
def button_auto_completion(self, cr, uid, ids, context=None):
|
||||
"""Complete line with values given by rules and tic the
|
||||
already_completed checkbox so we won't compute them again unless the
|
||||
user untick them!
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
stat_line_obj = self.pool['account.bank.statement.line']
|
||||
profile_obj = self.pool.get('account.statement.profile')
|
||||
compl_lines = 0
|
||||
stat_line_obj.check_access_rule(cr, uid, [], 'create')
|
||||
stat_line_obj.check_access_rights(
|
||||
cr, uid, 'create', raise_exception=True)
|
||||
for stat in self.browse(cr, uid, ids, context=context):
|
||||
msg_lines = []
|
||||
ctx = context.copy()
|
||||
ctx['line_ids'] = tuple((x.id for x in stat.line_ids))
|
||||
b_profile = stat.profile_id
|
||||
rules = profile_obj._get_rules(cr, uid, b_profile, context=context)
|
||||
# Only for perfo even it gains almost nothing
|
||||
profile_id = b_profile.id
|
||||
master_account_id = b_profile.receivable_account_id
|
||||
master_account_id = master_account_id.id if \
|
||||
master_account_id else False
|
||||
res = False
|
||||
for line in stat_line_obj.read(cr, uid, ctx['line_ids']):
|
||||
try:
|
||||
# performance trick
|
||||
line['master_account_id'] = master_account_id
|
||||
line['profile_id'] = profile_id
|
||||
res = stat_line_obj._get_line_values_from_rules(
|
||||
cr, uid, line, rules, context=ctx)
|
||||
if res:
|
||||
compl_lines += 1
|
||||
except ErrorTooManyPartner, exc:
|
||||
msg_lines.append(repr(exc))
|
||||
except Exception, exc:
|
||||
msg_lines.append(repr(exc))
|
||||
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))
|
||||
_logger.error(st)
|
||||
if res:
|
||||
# stat_line_obj.write(cr, uid, [line.id], vals,
|
||||
# context=ctx)
|
||||
try:
|
||||
stat_line_obj._update_line(
|
||||
cr, uid, res, context=context)
|
||||
except Exception as exc:
|
||||
msg_lines.append(repr(exc))
|
||||
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))
|
||||
_logger.error(st)
|
||||
# we can commit as it is not needed to be atomic
|
||||
# commiting here adds a nice perfo boost
|
||||
if not compl_lines % 500:
|
||||
cr.commit()
|
||||
msg = u'\n'.join(msg_lines)
|
||||
self.write_completion_log(cr, uid, stat.id,
|
||||
msg, compl_lines, context=context)
|
||||
return True
|
||||
@@ -1,99 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="bank_statement_view_form" model="ir.ui.view">
|
||||
<field name="name">account_bank_statement_import_base.bank_statement.view_form</field>
|
||||
<field name="model">account.bank.statement</field>
|
||||
<field name="inherit_id" ref="account.view_bank_statement_form" />
|
||||
<field eval="16" name="priority"/>
|
||||
<field name="arch" type="xml">
|
||||
<data>
|
||||
<xpath expr="/form/sheet/notebook/page/field[@name='line_ids']/form/group/field[@name='sequence']" position="after">
|
||||
<separator colspan="4" string="Importation related infos"/>
|
||||
<field name="label" />
|
||||
<field name="already_completed" />
|
||||
</xpath>
|
||||
|
||||
<!-- <xpath expr="/form/group[2]" position="attributes">
|
||||
<attribute name="col">10</attribute>
|
||||
</xpath> -->
|
||||
|
||||
<button name="button_confirm_bank" position="before">
|
||||
<button name="button_auto_completion" string="Auto Completion" states='draft,open' type="object" class="oe_highlight" icon="gtk-execute"/>
|
||||
</button>
|
||||
|
||||
<xpath expr="/form/sheet/notebook/page[@string='Transactions']" position="after">
|
||||
<page string="Completion Logs" attrs="{'invisible':[('completion_logs','=',False)]}">
|
||||
<field name="completion_logs" colspan="4" nolabel="1" attrs="{'invisible':[('completion_logs','=',False)]}"/>
|
||||
</page>
|
||||
</xpath>
|
||||
|
||||
</data>
|
||||
</field>
|
||||
</record>
|
||||
<record id="bank_statement_view_form2" model="ir.ui.view">
|
||||
<field name="name">account_bank_statement_import_base.bank_statement.auto_cmpl</field>
|
||||
<field name="model">account.bank.statement</field>
|
||||
<field name="inherit_id" ref="account.view_bank_statement_form" />
|
||||
<field name="arch" type="xml">
|
||||
<data>
|
||||
<xpath expr="/form/sheet/notebook/page/field[@name='line_ids']/tree/field[@name='amount']" position="after">
|
||||
<field name="already_completed" />
|
||||
</xpath>
|
||||
</data>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="statement_rules_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="Auto-Completion Rules"/>
|
||||
<field name="rule_ids" colspan="4" nolabel="1"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="statement_st_completion_rule_view_form" model="ir.ui.view">
|
||||
<field name="name">account.statement.completion.rule.view</field>
|
||||
<field name="model">account.statement.completion.rule</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Statement Completion Rule">
|
||||
<field name="sequence"/>
|
||||
<field name="name" select="1" />
|
||||
<field name="function_to_call"/>
|
||||
<separator colspan="4" string="Related Profiles"/>
|
||||
<field name="profile_ids" nolabel="1" colspan="4"/>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="statement_st_completion_rule_view_tree" model="ir.ui.view">
|
||||
<field name="name">account.statement.completion.rule.view</field>
|
||||
<field name="model">account.statement.completion.rule</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Statement Completion Rule">
|
||||
<field name="sequence"/>
|
||||
<field name="name" select="1" />
|
||||
<field name="profile_ids" />
|
||||
<field name="function_to_call"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record id="action_st_completion_rule_tree" model="ir.actions.act_window">
|
||||
<field name="name">Statement Completion Rule</field>
|
||||
<field name="res_model">account.statement.completion.rule</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
</record>
|
||||
|
||||
<menuitem string="Statement Completion Rule" action="action_st_completion_rule_tree"
|
||||
id="menu_action_st_completion_rule_tree_menu" parent="account.menu_configuration_misc"
|
||||
sequence="30"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -1,102 +0,0 @@
|
||||
-
|
||||
In order to test the banking framework, I first need to create a profile
|
||||
-
|
||||
!record {model: account.statement.profile, id: profile_test1}:
|
||||
name: Bank EUR Profile
|
||||
journal_id: account.bank_journal
|
||||
commission_account_id: account.a_expense
|
||||
company_id: base.main_company
|
||||
balance_check: True
|
||||
rule_ids:
|
||||
- bank_statement_completion_rule_4
|
||||
- bank_statement_completion_rule_5
|
||||
- bank_statement_completion_rule_2
|
||||
- bank_statement_completion_rule_3
|
||||
-
|
||||
Now I create a statement. I create statment lines separately because I need
|
||||
to find each one by XML id
|
||||
-
|
||||
!record {model: account.bank.statement, id: statement_test1}:
|
||||
name: Statement 2
|
||||
profile_id: profile_test1
|
||||
company_id: base.main_company
|
||||
-
|
||||
I create a statement line for a CI
|
||||
-
|
||||
!record {model: account.bank.statement.line, id: statement_line_ci}:
|
||||
name: Test autocompletion based on Customer Invoice Number
|
||||
statement_id: statement_test1
|
||||
ref: CI0001
|
||||
date: '2013-12-20'
|
||||
amount: 210.0
|
||||
-
|
||||
I create a statement line for a SI
|
||||
-
|
||||
!record {model: account.bank.statement.line, id: statement_line_si}:
|
||||
name: Test autocompletion based on Supplier Invoice Number
|
||||
statement_id: statement_test1
|
||||
ref: T2S12345
|
||||
date: '2013-12-19'
|
||||
amount: -65.0
|
||||
-
|
||||
I create a statement line for a CR
|
||||
-
|
||||
!record {model: account.bank.statement.line, id: statement_line_cr}:
|
||||
name: Test autocompletion based on Customer Refund Number
|
||||
statement_id: statement_test1
|
||||
ref: CR0001
|
||||
date: '2013-12-19'
|
||||
amount: -210.0
|
||||
-
|
||||
I create a statement line for the Partner Name
|
||||
-
|
||||
!record {model: account.bank.statement.line, id: statement_line_partner_name}:
|
||||
name: Test autocompletion based on Partner Name Vauxoo
|
||||
statement_id: statement_test1
|
||||
ref: /
|
||||
date: '2013-12-17'
|
||||
amount: 600.0
|
||||
-
|
||||
I create a statement line for the Partner Label
|
||||
-
|
||||
!record {model: account.bank.statement.line, id: statement_line_partner_label}:
|
||||
name: test autocompletion based on text (XXX66Z) matching with partner form information (note that Ref does not exist)
|
||||
statement_id: statement_test1
|
||||
ref: ZU788
|
||||
date: '2013-12-24'
|
||||
amount: -932.4
|
||||
-
|
||||
I run the auto complete
|
||||
-
|
||||
!python {model: account.bank.statement}: |
|
||||
result = self.button_auto_completion(cr, uid, [ref("statement_test1")])
|
||||
-
|
||||
Now I can check that all is nice and shiny, line 1. I expect the Customer
|
||||
Invoice Number to be recognised.
|
||||
I Use _ref, because ref conflicts with the field ref of the statement line
|
||||
-
|
||||
!assert {model: account.bank.statement.line, id: statement_line_ci, string: Check completion by CI number}:
|
||||
- partner_id.id == _ref("base.res_partner_12")
|
||||
-
|
||||
Line 2. I expect the Supplier invoice number to be recognised. The supplier
|
||||
invoice was created by the account module demo data, and we confirmed it
|
||||
here.
|
||||
-
|
||||
!assert {model: account.bank.statement.line, id: statement_line_si, string: Check completion by SI number}:
|
||||
- partner_id.id == _ref("base.res_partner_17")
|
||||
-
|
||||
Line 3. I expect the Customer refund number to be recognised. It should be
|
||||
the commercial partner, and not the regular partner.
|
||||
-
|
||||
!assert {model: account.bank.statement.line, id: statement_line_cr, string: Check completion by CR number and commercial partner}:
|
||||
- partner_id.id == _ref("base.res_partner_12")
|
||||
-
|
||||
Line 4. I check that the partner name has been recognised.
|
||||
-
|
||||
!assert {model: account.bank.statement.line, id: statement_line_partner_name, string: Check completion by partner name}:
|
||||
- partner_id.name == 'Vauxoo'
|
||||
-
|
||||
Line 5. I check that the partner special label has been recognised.
|
||||
-
|
||||
!assert {model: account.bank.statement.line, id: statement_line_partner_label, string: Check completion by partner label}:
|
||||
- partner_id.id == _ref("base.res_partner_6")
|
||||
@@ -1,32 +0,0 @@
|
||||
-
|
||||
I create a customer Invoice to be found by the completion.
|
||||
-
|
||||
!record {model: account.invoice, id: invoice_for_completion_1}:
|
||||
account_id: account.a_recv
|
||||
company_id: base.main_company
|
||||
currency_id: base.EUR
|
||||
internal_number: CI0001
|
||||
invoice_line:
|
||||
- account_id: account.a_sale
|
||||
name: '[PCSC234] PC Assemble SC234'
|
||||
price_unit: 210.0
|
||||
quantity: 1.0
|
||||
product_id: product.product_product_3
|
||||
uos_id: product.product_uom_unit
|
||||
journal_id: account.bank_journal
|
||||
partner_id: base.res_partner_12
|
||||
reference_type: none
|
||||
-
|
||||
I confirm the Invoice
|
||||
-
|
||||
!workflow {model: account.invoice, action: invoice_open, ref: invoice_for_completion_1}
|
||||
-
|
||||
I check that the invoice state is "Open"
|
||||
-
|
||||
!assert {model: account.invoice, id: invoice_for_completion_1}:
|
||||
- state == 'open'
|
||||
-
|
||||
I check that it is given the number "CI0001"
|
||||
-
|
||||
!assert {model: account.invoice, id: invoice_for_completion_1, string: Check CI number}:
|
||||
- number == 'CI0001'
|
||||
@@ -1,27 +0,0 @@
|
||||
# -*- 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_completion
|
||||
|
||||
checks = [
|
||||
test_base_completion
|
||||
]
|
||||
@@ -1,122 +0,0 @@
|
||||
# -*- 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 openerp.tests import common
|
||||
import time
|
||||
from collections import namedtuple
|
||||
|
||||
name_completion_case = namedtuple(
|
||||
"name_completion_case", ["partner_name", "line_label", "should_match"])
|
||||
NAMES_COMPLETION_CASES = [
|
||||
name_completion_case("Acsone", "Line for Acsone SA", True),
|
||||
name_completion_case("Acsone", "Line for Acsone", True),
|
||||
name_completion_case("Acsone", "Acsone for line", True),
|
||||
name_completion_case("acsone", "Acsone for line", True),
|
||||
name_completion_case("Acsone SA", "Line for Acsone SA test", True),
|
||||
name_completion_case("Ac..ne", "Acsone for line", False),
|
||||
name_completion_case("é@|r{}", "Acsone é@|r{} for line", True),
|
||||
name_completion_case("Acsone", "A..one for line", False),
|
||||
name_completion_case("A.one SA", "A.one SA for line", True),
|
||||
name_completion_case(
|
||||
"Acsone SA", "Line for Acsone ([^a-zA-Z0-9 -]) SA test", False),
|
||||
name_completion_case(
|
||||
"Acsone ([^a-zA-Z0-9 -]) SA", "Line for Acsone ([^a-zA-Z0-9 -]) SA "
|
||||
"test", True),
|
||||
name_completion_case(
|
||||
r"Acsone (.^$*+?()[{\| -]\) SA", r"Line for Acsone (.^$*+?()[{\| -]\) "
|
||||
r"SA test", True),
|
||||
name_completion_case("Acšone SA", "Line for Acšone SA test", True),
|
||||
]
|
||||
|
||||
|
||||
class base_completion(common.TransactionCase):
|
||||
|
||||
def setUp(self):
|
||||
super(base_completion, self).setUp()
|
||||
self.company_a = self.browse_ref('base.main_company')
|
||||
self.profile_obj = self.registry("account.statement.profile")
|
||||
self.partner_obj = self.registry("res.partner")
|
||||
self.account_bank_statement_obj = self.registry(
|
||||
"account.bank.statement")
|
||||
self.account_bank_statement_line_obj = self.registry(
|
||||
"account.bank.statement.line")
|
||||
self.journal_id = self.ref("account.bank_journal")
|
||||
self.partner_id = self.ref('base.main_partner')
|
||||
self.account_id = self.ref("account.a_recv")
|
||||
self.partner_id = self.ref("base.res_partner_12")
|
||||
|
||||
def test_name_completion(self):
|
||||
"""Test complete partner_id from statement line label
|
||||
Test the automatic completion of the partner_id based if the name of
|
||||
the partner appears in the statement line label
|
||||
"""
|
||||
self.completion_rule_id = self.ref(
|
||||
'account_statement_base_completion.'
|
||||
'bank_statement_completion_rule_3')
|
||||
# Create the profile
|
||||
self.profile_id = self.profile_obj.create(self.cr, self.uid, {
|
||||
"name": "TEST",
|
||||
"commission_account_id": self.account_id,
|
||||
"journal_id": self.journal_id,
|
||||
"rule_ids": [(6, 0, [self.completion_rule_id])]})
|
||||
# Create a bank statement
|
||||
self.statement_id = self.account_bank_statement_obj.create(
|
||||
self.cr, self.uid, {
|
||||
"balance_end_real": 0.0,
|
||||
"balance_start": 0.0,
|
||||
"date": time.strftime('%Y-%m-%d'),
|
||||
"journal_id": self.journal_id,
|
||||
"profile_id": self.profile_id
|
||||
})
|
||||
|
||||
for case in NAMES_COMPLETION_CASES:
|
||||
self.partner_obj.write(
|
||||
self.cr, self.uid, self.partner_id, {'name': case.partner_name}
|
||||
)
|
||||
statement_line_id = self.account_bank_statement_line_obj.create(
|
||||
self.cr, self.uid, {
|
||||
'amount': 1000.0,
|
||||
'name': case.line_label,
|
||||
'ref': 'My ref',
|
||||
'statement_id': self.statement_id,
|
||||
})
|
||||
statement_line = self.account_bank_statement_line_obj.browse(
|
||||
self.cr, self.uid, statement_line_id)
|
||||
self.assertFalse(
|
||||
statement_line.partner_id,
|
||||
"Partner_id must be blank before completion")
|
||||
statement_obj = self.account_bank_statement_obj.browse(
|
||||
self.cr, self.uid, self.statement_id)
|
||||
statement_obj.button_auto_completion()
|
||||
statement_line = self.account_bank_statement_line_obj.browse(
|
||||
self.cr, self.uid, statement_line_id)
|
||||
if case.should_match:
|
||||
self.assertEquals(
|
||||
self.partner_id, statement_line.partner_id['id'],
|
||||
"Missing expected partner id after completion "
|
||||
"(partner_name: %s, line_name: %s)" %
|
||||
(case.partner_name, case.line_label))
|
||||
else:
|
||||
self.assertNotEquals(
|
||||
self.partner_id, statement_line.partner_id['id'],
|
||||
"Partner id should be empty after completion "
|
||||
"(partner_name: %s, line_name: %s)"
|
||||
% (case.partner_name, case.line_label))
|
||||
@@ -1,23 +0,0 @@
|
||||
# -*- 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
|
||||
@@ -1,73 +0,0 @@
|
||||
# -*- 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',
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
"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"
|
||||
|
Binary file not shown.
@@ -1,25 +0,0 @@
|
||||
# -*- 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
|
||||
@@ -1,79 +0,0 @@
|
||||
# -*- 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', ''),
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user