diff --git a/.coveragerc b/.coveragerc
index f0fda4fa..d25f247d 100644
--- a/.coveragerc
+++ b/.coveragerc
@@ -3,6 +3,7 @@ include =
*/bank-statement-reconcile/*
omit =
+ */test/*
*/tests/*
*__init__.py
diff --git a/__unported__/account_advanced_reconcile/__init__.py b/__unported__/account_advanced_reconcile/__init__.py
index af0e2c47..e1a57902 100644
--- a/__unported__/account_advanced_reconcile/__init__.py
+++ b/__unported__/account_advanced_reconcile/__init__.py
@@ -20,7 +20,6 @@
#
##############################################################################
-import easy_reconcile
-import base_advanced_reconciliation
-import advanced_reconciliation
-import res_config # noqa
+from . import easy_reconcile
+from . import base_advanced_reconciliation
+from . import advanced_reconciliation
diff --git a/__unported__/account_advanced_reconcile/__openerp__.py b/__unported__/account_advanced_reconcile/__openerp__.py
index 064345fd..b5d0acfd 100644
--- a/__unported__/account_advanced_reconcile/__openerp__.py
+++ b/__unported__/account_advanced_reconcile/__openerp__.py
@@ -64,8 +64,8 @@ The base class to find the reconciliations is built to be as efficient as
possible.
So basically, if you have an invoice with 3 payments (one per month), the first
-month, it will partial reconcile the debit move line with the first payment, the
-second month, it will partial reconcile the debit move line with 2 first
+month, it will partial reconcile the debit move line with the first payment,
+the second month, it will partial reconcile the debit move line with 2 first
payments, the third month, it will make the full reconciliation.
This module is perfectly adapted for E-Commerce business where a big volume of
@@ -75,7 +75,7 @@ many offices.
""",
'website': 'http://www.camptocamp.com',
'data': ['easy_reconcile_view.xml',
- 'res_config_view.xml'],
+ ],
'test': [],
'images': [],
'installable': False,
diff --git a/__unported__/account_advanced_reconcile/base_advanced_reconciliation.py b/__unported__/account_advanced_reconcile/base_advanced_reconciliation.py
index e6f8ced9..a9fe439c 100644
--- a/__unported__/account_advanced_reconcile/base_advanced_reconciliation.py
+++ b/__unported__/account_advanced_reconcile/base_advanced_reconciliation.py
@@ -23,10 +23,8 @@ import logging
from itertools import product
from openerp.osv import orm
-from openerp import pooler
from openerp.tools.translate import _
-
_logger = logging.getLogger(__name__)
@@ -188,7 +186,8 @@ class easy_reconcile_advanced(orm.AbstractModel):
If all the matchers match for a move line and an opposite move line,
they are candidate for a reconciliation.
"""
- opp_matchers = self._opposite_matchers(cr, uid, rec, opposite_move_line,
+ opp_matchers = self._opposite_matchers(cr, uid, rec,
+ opposite_move_line,
context=context)
for matcher in matchers:
try:
@@ -222,29 +221,10 @@ class easy_reconcile_advanced(orm.AbstractModel):
cr, uid, rec, move_line, op, matchers, context=context)]
def _action_rec(self, cr, uid, rec, context=None):
- # we use a new cursor to be able to commit the reconciliation
- # often. We have to create it here and not later to avoid problems
- # where the new cursor sees the lines as reconciles but the old one
- # does not.
- if context is None:
- context = {}
- ctx = context.copy()
- ctx['commit_every'] = (
- rec.journal_id.company_id.reconciliation_commit_every
- )
- if ctx['commit_every']:
- new_cr = pooler.get_db(cr.dbname).cursor()
- else:
- new_cr = cr
- try:
- credit_lines = self._query_credit(new_cr, uid, rec, context=ctx)
- debit_lines = self._query_debit(new_cr, uid, rec, context=ctx)
- result = self._rec_auto_lines_advanced(
- new_cr, uid, rec, credit_lines, debit_lines, context=ctx)
- finally:
- if ctx['commit_every']:
- new_cr.commit()
- new_cr.close()
+ credit_lines = self._query_credit(cr, uid, rec, context=context)
+ debit_lines = self._query_debit(cr, uid, rec, context=context)
+ result = self._rec_auto_lines_advanced(
+ cr, uid, rec, credit_lines, debit_lines, context=context)
return result
def _skip_line(self, cr, uid, rec, move_line, context=None):
diff --git a/__unported__/account_advanced_reconcile_bank_statement/__init__.py b/__unported__/account_advanced_reconcile_bank_statement/__init__.py
new file mode 100644
index 00000000..0f9a7e4c
--- /dev/null
+++ b/__unported__/account_advanced_reconcile_bank_statement/__init__.py
@@ -0,0 +1,23 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Author: Matthieu Dietrich
+# Copyright 2014 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 .
+#
+##############################################################################
+
+from . import easy_reconcile
+from . import advanced_reconciliation
diff --git a/__unported__/account_advanced_reconcile_bank_statement/__openerp__.py b/__unported__/account_advanced_reconcile_bank_statement/__openerp__.py
new file mode 100644
index 00000000..cd62e051
--- /dev/null
+++ b/__unported__/account_advanced_reconcile_bank_statement/__openerp__.py
@@ -0,0 +1,44 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Author: Matthieu Dietrich
+# Copyright 2014 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 .
+#
+##############################################################################
+
+{'name': 'Advanced Reconcile Bank Statement',
+ 'description': """
+Advanced reconciliation method for the module account_advanced_reconcile
+========================================================================
+Reconcile rules with bank statement name.
+
+This will reconcile multiple credit move lines (bank statements) with
+all the lines from a specific bank statement, debit or credit (to also
+reconcile the commission with credit card imports).
+
+""",
+ 'version': '1.0.0',
+ 'author': 'Camptocamp',
+ 'category': 'Finance',
+ 'website': 'http://www.camptocamp.com',
+ 'depends': ['account_advanced_reconcile'],
+ 'data': ['easy_reconcile_view.xml'],
+ 'demo': [],
+ 'test': [],
+ 'auto_install': False,
+ 'installable': True,
+ 'images': []
+ }
diff --git a/__unported__/account_advanced_reconcile_bank_statement/advanced_reconciliation.py b/__unported__/account_advanced_reconcile_bank_statement/advanced_reconciliation.py
new file mode 100644
index 00000000..2eb77cbc
--- /dev/null
+++ b/__unported__/account_advanced_reconcile_bank_statement/advanced_reconciliation.py
@@ -0,0 +1,81 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Author: Matthieu Dietrich. Copyright 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 .
+#
+##############################################################################
+
+from openerp.osv import orm
+
+
+class easy_reconcile_advanced_bank_statement(orm.TransientModel):
+
+ _name = 'easy.reconcile.advanced.bank_statement'
+ _inherit = 'easy.reconcile.advanced'
+
+ def _base_columns(self, rec):
+ """ Mandatory columns for move lines queries
+ An extra column aliased as ``key`` should be defined
+ in each query."""
+ aml_cols = super(easy_reconcile_advanced_bank_statement, self).\
+ _base_columns(rec)
+ aml_cols += ['account_move_line.statement_id',
+ 'account_bank_statement.name as statement_name',
+ ]
+ return aml_cols
+
+ def _from(self, rec, *args, **kwargs):
+ result = super(easy_reconcile_advanced_bank_statement, self).\
+ _from(rec, *args, **kwargs)
+ result = result + (
+ " INNER JOIN account_bank_statement "
+ "ON account_bank_statement.id = account_move_line.statement_id "
+ )
+ return result
+
+ def _skip_line(self, cr, uid, rec, move_line, context=None):
+ """
+ When True is returned on some conditions, the credit move line
+ will be skipped for reconciliation. Can be inherited to
+ skip on some conditions. ie: ref or partner_id is empty.
+ """
+ result = super(easy_reconcile_advanced_bank_statement, self).\
+ _skip_line(cr, uid, rec, move_line, context=context)
+ if result:
+ return result
+ return not (move_line.get('ref') and
+ move_line.get('partner_id'))
+
+ def _matchers(self, cr, uid, rec, move_line, context=None):
+ return (('partner_id', move_line['partner_id']),
+ ('ref', move_line['ref'].lower().strip()))
+
+ def _opposite_matchers(self, cr, uid, rec, move_line, context=None):
+ yield ('partner_id', move_line['partner_id'])
+ yield ('ref',
+ (move_line['statement_name'] or '').lower().strip())
+
+ # Re-defined for this particular rule; since the commission line is a
+ # credit line inside of the target statement, it should also be considered
+ # as an opposite to be reconciled.
+ # And also, given some are refunds, debit lines can be "credit".
+ def _action_rec(self, cr, uid, rec, context=None):
+ credit_lines = self._query_credit(cr, uid, rec, context=context)
+ debit_lines = self._query_debit(cr, uid, rec, context=context)
+ return self._rec_auto_lines_advanced(cr, uid, rec,
+ credit_lines + debit_lines,
+ credit_lines + debit_lines,
+ context=context)
diff --git a/__unported__/account_advanced_reconcile_bank_statement/easy_reconcile.py b/__unported__/account_advanced_reconcile_bank_statement/easy_reconcile.py
new file mode 100644
index 00000000..53adbbb0
--- /dev/null
+++ b/__unported__/account_advanced_reconcile_bank_statement/easy_reconcile.py
@@ -0,0 +1,36 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Author: Matthieu Dietrich
+# Copyright 2014 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 .
+#
+##############################################################################
+
+from openerp.osv import orm
+
+
+class account_easy_reconcile_method(orm.Model):
+
+ _inherit = 'account.easy.reconcile.method'
+
+ def _get_all_rec_method(self, cr, uid, context=None):
+ methods = super(account_easy_reconcile_method, self).\
+ _get_all_rec_method(cr, uid, context=context)
+ methods += [
+ ('easy.reconcile.advanced.bank_statement',
+ 'Advanced. Partner and Bank Statement'),
+ ]
+ return methods
diff --git a/__unported__/account_advanced_reconcile_bank_statement/easy_reconcile_view.xml b/__unported__/account_advanced_reconcile_bank_statement/easy_reconcile_view.xml
new file mode 100644
index 00000000..72c0ad68
--- /dev/null
+++ b/__unported__/account_advanced_reconcile_bank_statement/easy_reconcile_view.xml
@@ -0,0 +1,19 @@
+
+
+
+
+ account.easy.reconcile.form
+ account.easy.reconcile
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/__unported__/account_advanced_reconcile_bank_statement/i18n/account_advanced_reconcile_bank_statement.po b/__unported__/account_advanced_reconcile_bank_statement/i18n/account_advanced_reconcile_bank_statement.po
new file mode 100644
index 00000000..5ede7195
--- /dev/null
+++ b/__unported__/account_advanced_reconcile_bank_statement/i18n/account_advanced_reconcile_bank_statement.po
@@ -0,0 +1,107 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * account_advanced_reconcile_bank_statement
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2014-05-27 08:36+0000\n"
+"PO-Revision-Date: 2014-05-27 08:36+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_advanced_reconcile_bank_statement
+#: field:easy.reconcile.advanced.bank_statement,filter:0
+#: model:ir.model.fields,field_description:account_advanced_reconcile_bank_statement.field_easy_reconcile_advanced_bank_statement_filter
+msgid "Filter"
+msgstr ""
+
+#. module: account_advanced_reconcile_bank_statement
+#: field:easy.reconcile.advanced.bank_statement,account_id:0
+#: model:ir.model.fields,field_description:account_advanced_reconcile_bank_statement.field_easy_reconcile_advanced_bank_statement_account_id
+msgid "Account"
+msgstr ""
+
+#. module: account_advanced_reconcile_bank_statement
+#: field:easy.reconcile.advanced.bank_statement,partner_ids:0
+#: model:ir.model.fields,field_description:account_advanced_reconcile_bank_statement.field_easy_reconcile_advanced_bank_statement_partner_ids
+msgid "Restrict on partners"
+msgstr ""
+
+#. module: account_advanced_reconcile_bank_statement
+#: code:_description:0
+#: model:ir.model,name:account_advanced_reconcile_bank_statement.model_easy_reconcile_advanced_bank_statement
+#, python-format
+msgid "easy.reconcile.advanced.bank_statement"
+msgstr ""
+
+#. module: account_advanced_reconcile_bank_statement
+#: view:account.easy.reconcile:0
+msgid "Match multiple debit vs multiple credit entries. Allow partial reconciliation. The lines should have the partner, the credit entry reference is matched vs the debit entry bank statement name."
+msgstr ""
+
+#. module: account_advanced_reconcile_bank_statement
+#: field:easy.reconcile.advanced.bank_statement,journal_id:0
+#: model:ir.model.fields,field_description:account_advanced_reconcile_bank_statement.field_easy_reconcile_advanced_bank_statement_journal_id
+msgid "Journal"
+msgstr ""
+
+#. module: account_advanced_reconcile_bank_statement
+#: field:easy.reconcile.advanced.bank_statement,account_profit_id:0
+#: model:ir.model.fields,field_description:account_advanced_reconcile_bank_statement.field_easy_reconcile_advanced_bank_statement_account_profit_id
+msgid "Account Profit"
+msgstr ""
+
+#. module: account_advanced_reconcile_bank_statement
+#: field:easy.reconcile.advanced.bank_statement,analytic_account_id:0
+#: model:ir.model.fields,field_description:account_advanced_reconcile_bank_statement.field_easy_reconcile_advanced_bank_statement_analytic_account_id
+msgid "Analytic Account"
+msgstr ""
+
+#. module: account_advanced_reconcile_bank_statement
+#: code:_description:0
+#: model:ir.model,name:account_advanced_reconcile_bank_statement.model_account_easy_reconcile_method
+#, python-format
+msgid "reconcile method for account_easy_reconcile"
+msgstr ""
+
+#. module: account_advanced_reconcile_bank_statement
+#: field:easy.reconcile.advanced.bank_statement,date_base_on:0
+#: model:ir.model.fields,field_description:account_advanced_reconcile_bank_statement.field_easy_reconcile_advanced_bank_statement_date_base_on
+msgid "Date of reconciliation"
+msgstr ""
+
+#. module: account_advanced_reconcile_bank_statement
+#: help:easy.reconcile.advanced.bank_statement,analytic_account_id:0
+msgid "Analytic account for the write-off"
+msgstr ""
+
+#. module: account_advanced_reconcile_bank_statement
+#: view:account.easy.reconcile:0
+msgid "Advanced. Partner and Bank Statement"
+msgstr ""
+
+#. module: account_advanced_reconcile_bank_statement
+#: code:_description:0
+#: model:ir.model,name:account_advanced_reconcile_bank_statement.model_easy_reconcile_advanced
+#, python-format
+msgid "easy.reconcile.advanced"
+msgstr ""
+
+#. module: account_advanced_reconcile_bank_statement
+#: field:easy.reconcile.advanced.bank_statement,account_lost_id:0
+#: model:ir.model.fields,field_description:account_advanced_reconcile_bank_statement.field_easy_reconcile_advanced_bank_statement_account_lost_id
+msgid "Account Lost"
+msgstr ""
+
+#. module: account_advanced_reconcile_bank_statement
+#: field:easy.reconcile.advanced.bank_statement,write_off:0
+#: model:ir.model.fields,field_description:account_advanced_reconcile_bank_statement.field_easy_reconcile_advanced_bank_statement_write_off
+msgid "Write off allowed"
+msgstr ""
+
diff --git a/__unported__/account_advanced_reconcile_bank_statement/i18n/fr.po b/__unported__/account_advanced_reconcile_bank_statement/i18n/fr.po
new file mode 100644
index 00000000..63124f07
--- /dev/null
+++ b/__unported__/account_advanced_reconcile_bank_statement/i18n/fr.po
@@ -0,0 +1,103 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * account_advanced_reconcile_bank_statement
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2014-05-27 08:36+0000\n"
+"PO-Revision-Date: 2014-05-27 08:36+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_advanced_reconcile_bank_statement
+#: field:easy.reconcile.advanced.bank_statement,filter:0
+#: model:ir.model.fields,field_description:account_advanced_reconcile_bank_statement.field_easy_reconcile_advanced_bank_statement_filter
+msgid "Filter"
+msgstr "Filtre"
+
+#. module: account_advanced_reconcile_bank_statement
+#: field:easy.reconcile.advanced.bank_statement,account_id:0
+#: model:ir.model.fields,field_description:account_advanced_reconcile_bank_statement.field_easy_reconcile_advanced_bank_statement_account_id
+msgid "Account"
+msgstr "Compte"
+
+#. module: account_advanced_reconcile_bank_statement
+#: field:easy.reconcile.advanced.bank_statement,partner_ids:0
+#: model:ir.model.fields,field_description:account_advanced_reconcile_bank_statement.field_easy_reconcile_advanced_bank_statement_partner_ids
+msgid "Restrict on partners"
+msgstr "Restriction sur les partenaires"
+
+#. module: account_advanced_reconcile_bank_statement
+#: code:_description:0
+#: model:ir.model,name:account_advanced_reconcile_bank_statement.model_easy_reconcile_advanced_bank_statement
+#, python-format
+msgid "easy.reconcile.advanced.bank_statement"
+msgstr "easy.reconcile.advanced.bank_statement"
+
+#. module: account_advanced_reconcile_bank_statement
+#: view:account.easy.reconcile:0
+msgid ""
+"Match multiple debit vs multiple credit entries. Allow partial "
+"reconciliation. The lines should have the partner, the credit entry "
+"reference is matched vs the debit entry bank statement name."
+msgstr ""
+"Le lettrage peut s'effectuer sur plusieurs écritures de débit et crédit. Le "
+"lettrage partiel est autorisé. Les écritures doivent avoir le même "
+"partenaire et la référence sur les écritures de crédit doit se retrouver
+"dans le nom du relevé bancaire des écritures de débit."
+
+#. module: account_advanced_reconcile_bank_statement
+#: field:easy.reconcile.advanced.bank_statement,journal_id:0
+#: model:ir.model.fields,field_description:account_advanced_reconcile_bank_statement.field_easy_reconcile_advanced_bank_statement_journal_id
+msgid "Journal"
+msgstr "Journal"
+
+#. module: account_advanced_reconcile_bank_statement
+#: field:easy.reconcile.advanced.bank_statement,account_profit_id:0
+#: model:ir.model.fields,field_description:account_advanced_reconcile_bank_statement.field_easy_reconcile_advanced_bank_statement_account_profit_id
+msgid "Account Profit"
+msgstr "Compte de produit"
+
+#. module: account_advanced_reconcile_bank_statement
+#: code:_description:0
+#: model:ir.model,name:account_advanced_reconcile_bank_statement.model_account_easy_reconcile_method
+#, python-format
+msgid "reconcile method for account_easy_reconcile"
+msgstr "Méthode de lettrage pour le module account_easy_reconcile"
+
+#. module: account_advanced_reconcile_bank_statement
+#: field:easy.reconcile.advanced.bank_statement,date_base_on:0
+#: model:ir.model.fields,field_description:account_advanced_reconcile_bank_statement.field_easy_reconcile_advanced_bank_statement_date_base_on
+msgid "Date of reconciliation"
+msgstr "Date de lettrage"
+
+#. module: account_advanced_reconcile_bank_statement
+#: view:account.easy.reconcile:0
+msgid "Advanced. Partner and Bank Statement"
+msgstr "Avancé. Partenaire et Relevé Bancaire"
+
+#. module: account_advanced_reconcile_bank_statement
+#: code:_description:0
+#: model:ir.model,name:account_advanced_reconcile_bank_statement.model_easy_reconcile_advanced
+#, python-format
+msgid "easy.reconcile.advanced"
+msgstr "easy.reconcile.advanced"
+
+#. module: account_advanced_reconcile_bank_statement
+#: field:easy.reconcile.advanced.bank_statement,account_lost_id:0
+#: model:ir.model.fields,field_description:account_advanced_reconcile_bank_statement.field_easy_reconcile_advanced_bank_statement_account_lost_id
+msgid "Account Lost"
+msgstr "Compte de charge"
+
+#. module: account_advanced_reconcile_bank_statement
+#: field:easy.reconcile.advanced.bank_statement,write_off:0
+#: model:ir.model.fields,field_description:account_advanced_reconcile_bank_statement.field_easy_reconcile_advanced_bank_statement_write_off
+msgid "Write off allowed"
+msgstr "Ecart autorisé"
+
diff --git a/__unported__/account_advanced_reconcile_transaction_ref/base_advanced_reconciliation.py b/__unported__/account_advanced_reconcile_transaction_ref/base_advanced_reconciliation.py
index c5feb2ac..240df83d 100644
--- a/__unported__/account_advanced_reconcile_transaction_ref/base_advanced_reconciliation.py
+++ b/__unported__/account_advanced_reconcile_transaction_ref/base_advanced_reconciliation.py
@@ -30,16 +30,6 @@ class EasyReconcileAdvanced(orm.AbstractModel):
""" Mandatory columns for move lines queries
An extra column aliased as ``key`` should be defined
in each query."""
- aml_cols = (
- 'id',
- 'debit',
- 'credit',
- 'date',
- 'period_id',
- 'ref',
- 'name',
- 'partner_id',
- 'account_id',
- 'move_id',
- 'transaction_ref')
- return ["account_move_line.%s" % col for col in aml_cols]
+ aml_cols = super(EasyReconcileAdvanced, self)._base_columns(rec)
+ aml_cols.append('account_move_line.transaction_ref')
+ return aml_cols
diff --git a/__unported__/account_easy_reconcile/__init__.py b/__unported__/account_easy_reconcile/__init__.py
index b648751f..0b0a2b53 100755
--- a/__unported__/account_easy_reconcile/__init__.py
+++ b/__unported__/account_easy_reconcile/__init__.py
@@ -19,7 +19,8 @@
#
##############################################################################
-import easy_reconcile
-import base_reconciliation
-import simple_reconciliation
-import easy_reconcile_history
+from . import easy_reconcile
+from . import base_reconciliation
+from . import simple_reconciliation
+from . import easy_reconcile_history
+from . import res_config
diff --git a/__unported__/account_easy_reconcile/__openerp__.py b/__unported__/account_easy_reconcile/__openerp__.py
index aa81e8eb..187e2983 100755
--- a/__unported__/account_easy_reconcile/__openerp__.py
+++ b/__unported__/account_easy_reconcile/__openerp__.py
@@ -58,7 +58,9 @@ allows multiple lines and partial.
"data": ["easy_reconcile.xml",
"easy_reconcile_history_view.xml",
"security/ir_rule.xml",
- "security/ir.model.access.csv"],
+ "security/ir.model.access.csv",
+ "res_config_view.xml",
+ ],
'license': 'AGPL-3',
"auto_install": False,
'installable': False,
diff --git a/__unported__/account_easy_reconcile/base_reconciliation.py b/__unported__/account_easy_reconcile/base_reconciliation.py
index 6145720a..35ce4920 100644
--- a/__unported__/account_easy_reconcile/base_reconciliation.py
+++ b/__unported__/account_easy_reconcile/base_reconciliation.py
@@ -71,6 +71,7 @@ class EasyReconcileBase(orm.AbstractModel):
'name',
'partner_id',
'account_id',
+ 'reconcile_partial_id',
'move_id')
return ["account_move_line.%s" % col for col in aml_cols]
@@ -78,10 +79,15 @@ class EasyReconcileBase(orm.AbstractModel):
return "SELECT %s" % ', '.join(self._base_columns(rec))
def _from(self, rec, *args, **kwargs):
- return "FROM account_move_line"
+ return ("FROM account_move_line "
+ "LEFT OUTER JOIN account_move_reconcile ON "
+ "(account_move_line.reconcile_partial_id "
+ "= account_move_reconcile.id)"
+ )
def _where(self, rec, *args, **kwargs):
where = ("WHERE account_move_line.account_id = %s "
+ "AND COALESCE(account_move_reconcile.type,'') <> 'manual' "
"AND account_move_line.reconcile_id IS NULL ")
# it would be great to use dict for params
# but as we use _where_calc in _get_filter
@@ -177,7 +183,7 @@ class EasyReconcileBase(orm.AbstractModel):
cr, uid, rec, lines, rec.date_base_on, context=context)
rec_ctx = dict(context, date_p=date)
if below_writeoff:
- if sum_credit < sum_debit:
+ if sum_credit > sum_debit:
writeoff_account_id = rec.account_profit_id.id
else:
writeoff_account_id = rec.account_lost_id.id
@@ -195,10 +201,42 @@ class EasyReconcileBase(orm.AbstractModel):
context=rec_ctx)
return True, True
elif allow_partial:
+ # Check if the group of move lines was already partially
+ # reconciled and if all the lines were the same, in such
+ # case, just skip the group and consider it as partially
+ # reconciled (no change).
+ if lines:
+ existing_partial_id = lines[0]['reconcile_partial_id']
+ if existing_partial_id:
+ partial_line_ids = set(ml_obj.search(
+ cr, uid,
+ [('reconcile_partial_id', '=', existing_partial_id)],
+ context=context))
+ if set(line_ids) == partial_line_ids:
+ return True, False
+
+ # We need to give a writeoff_acc_id
+ # in case we have a multi currency lines
+ # to reconcile.
+ # If amount in currency is equal between
+ # lines to reconcile
+ # it will do a full reconcile instead of a partial reconcile
+ # and make a write-off for exchange
+ if sum_credit > sum_debit:
+ writeoff_account_id = rec.income_exchange_account_id.id
+ else:
+ writeoff_account_id = rec.expense_exchange_account_id.id
+ period_id = self.pool['account.period'].find(
+ cr, uid, dt=date, context=context)[0]
+ if rec.analytic_account_id:
+ rec_ctx['analytic_id'] = rec.analytic_account_id.id
ml_obj.reconcile_partial(
cr, uid,
line_ids,
type='manual',
+ writeoff_acc_id=writeoff_account_id,
+ writeoff_period_id=period_id,
+ writeoff_journal_id=rec.journal_id.id,
context=rec_ctx)
return True, False
return False, False
diff --git a/__unported__/account_easy_reconcile/easy_reconcile.py b/__unported__/account_easy_reconcile/easy_reconcile.py
index 99ed960f..89af1759 100644
--- a/__unported__/account_easy_reconcile/easy_reconcile.py
+++ b/__unported__/account_easy_reconcile/easy_reconcile.py
@@ -19,8 +19,14 @@
#
##############################################################################
+from datetime import datetime
from openerp.osv import fields, orm
+from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
from openerp.tools.translate import _
+from openerp import pooler
+
+import logging
+_logger = logging.getLogger(__name__)
class EasyReconcileOptions(orm.AbstractModel):
@@ -60,6 +66,11 @@ class EasyReconcileOptions(orm.AbstractModel):
'analytic_account_id': fields.many2one(
'account.analytic.account', 'Analytic Account',
help="Analytic account for the write-off"),
+ 'income_exchange_account_id': fields.many2one(
+ 'account.account', 'Gain Exchange Rate Account'),
+ 'expense_exchange_account_id': fields.many2one(
+ 'account.account', 'Loss Exchange Rate Account'),
+
}
_defaults = {
@@ -131,6 +142,7 @@ class AccountEasyReconcileMethod(orm.Model):
class AccountEasyReconcile(orm.Model):
_name = 'account.easy.reconcile'
+ _inherit = ['mail.thread']
_description = 'account easy reconcile'
def _get_total_unrec(self, cr, uid, ids, name, arg, context=None):
@@ -159,11 +171,16 @@ class AccountEasyReconcile(orm.Model):
def _last_history(self, cr, uid, ids, name, args, context=None):
result = {}
- for history in self.browse(cr, uid, ids, context=context):
- result[history.id] = False
- if history.history_ids:
- # history is sorted by date desc
- result[history.id] = history.history_ids[0].id
+ # do a search() for retrieving the latest history line,
+ # as a read() will badly split the list of ids with 'date desc'
+ # and return the wrong result.
+ history_obj = self.pool['easy.reconcile.history']
+ for reconcile_id in ids:
+ last_history = history_obj.search(
+ cr, uid, [('easy_reconcile_id', '=', reconcile_id)],
+ limit=1, order='date desc', context=context
+ )
+ result[reconcile_id] = last_history[0] if last_history else False
return result
_columns = {
@@ -202,13 +219,19 @@ class AccountEasyReconcile(orm.Model):
rec_method.account_profit_id.id),
'analytic_account_id': (rec_method.analytic_account_id and
rec_method.analytic_account_id.id),
+ 'income_exchange_account_id':
+ (rec_method.income_exchange_account_id and
+ rec_method.income_exchange_account_id.id),
+ 'expense_exchange_account_id':
+ (rec_method.income_exchange_account_id and
+ rec_method.income_exchange_account_id.id),
'journal_id': (rec_method.journal_id and
rec_method.journal_id.id),
'date_base_on': rec_method.date_base_on,
'filter': rec_method.filter}
def run_reconcile(self, cr, uid, ids, context=None):
- def find_reconcile_ids(fieldname, move_line_ids):
+ def find_reconcile_ids(cr, fieldname, move_line_ids):
if not move_line_ids:
return []
sql = ("SELECT DISTINCT " + fieldname +
@@ -219,41 +242,75 @@ class AccountEasyReconcile(orm.Model):
res = cr.fetchall()
return [row[0] for row in res]
+ # we use a new cursor to be able to commit the reconciliation
+ # often. We have to create it here and not later to avoid problems
+ # where the new cursor sees the lines as reconciles but the old one
+ # does not.
+ if context is None:
+ context = {}
+
for rec in self.browse(cr, uid, ids, context=context):
- all_ml_rec_ids = []
- all_ml_partial_ids = []
+ ctx = context.copy()
+ ctx['commit_every'] = (
+ rec.account.company_id.reconciliation_commit_every
+ )
+ if ctx['commit_every']:
+ new_cr = pooler.get_db(cr.dbname).cursor()
+ else:
+ new_cr = cr
+ try:
+ all_ml_rec_ids = []
+ all_ml_partial_ids = []
- for method in rec.reconcile_method:
- rec_model = self.pool.get(method.name)
- auto_rec_id = rec_model.create(
- cr, uid,
- self._prepare_run_transient(
- cr, uid, method, context=context),
- context=context)
+ for method in rec.reconcile_method:
+ rec_model = self.pool.get(method.name)
+ auto_rec_id = rec_model.create(
+ new_cr, uid,
+ self._prepare_run_transient(
+ new_cr, uid, method, context=context),
+ context=context)
- ml_rec_ids, ml_partial_ids = rec_model.automatic_reconcile(
- cr, uid, auto_rec_id, context=context)
+ ml_rec_ids, ml_partial_ids = rec_model.automatic_reconcile(
+ new_cr, uid, auto_rec_id, context=ctx)
- all_ml_rec_ids += ml_rec_ids
- all_ml_partial_ids += ml_partial_ids
+ all_ml_rec_ids += ml_rec_ids
+ all_ml_partial_ids += ml_partial_ids
- reconcile_ids = find_reconcile_ids(
- 'reconcile_id', all_ml_rec_ids)
- partial_ids = find_reconcile_ids(
- 'reconcile_partial_id', all_ml_partial_ids)
+ reconcile_ids = find_reconcile_ids(
+ new_cr, 'reconcile_id', all_ml_rec_ids)
+ partial_ids = find_reconcile_ids(
+ new_cr, 'reconcile_partial_id', all_ml_partial_ids)
- self.pool.get('easy.reconcile.history').create(
- cr,
- uid,
- {'easy_reconcile_id': rec.id,
- 'date': fields.datetime.now(),
- 'reconcile_ids': [(4, rid) for rid in reconcile_ids],
- 'reconcile_partial_ids': [(4, rid) for rid in partial_ids]},
- context=context)
+ self.pool.get('easy.reconcile.history').create(new_cr, uid, {
+ 'easy_reconcile_id': rec.id,
+ 'date': fields.datetime.now(),
+ 'reconcile_ids': [(4, rid) for rid in reconcile_ids],
+ 'reconcile_partial_ids': [(4, rid) for rid in partial_ids],
+ }, context=context)
+ except Exception as e:
+ # In case of error, we log it in the mail thread, log the
+ # stack trace and create an empty history line; otherwise,
+ # the cron will just loop on this reconcile task.
+ _logger.exception("The reconcile task %s had an exception: %s",
+ rec.name, e.value)
+ message = "There was an error during reconciliation : %s" \
+ % e.value
+ self.message_post(cr, uid, rec.id,
+ body=message, context=context)
+ self.pool.get('easy.reconcile.history').create(new_cr, uid, {
+ 'easy_reconcile_id': rec.id,
+ 'date': fields.datetime.now(),
+ 'reconcile_ids': [],
+ 'reconcile_partial_ids': [],
+ })
+ finally:
+ if ctx['commit_every']:
+ new_cr.commit()
+ new_cr.close()
return True
def _no_history(self, cr, uid, rec, context=None):
- """ Raise an `osv.except_osv` error, supposed to
+ """ Raise an `orm.except_orm` error, supposed to
be called when there is no history on the reconciliation
task.
"""
@@ -333,3 +390,30 @@ class AccountEasyReconcile(orm.Model):
if not rec.last_history:
self._no_history(cr, uid, rec, context=context)
return rec.last_history.open_partial()
+
+ def run_scheduler(self, cr, uid, run_all=None, context=None):
+ """ Launch the reconcile with the oldest run
+ This function is mostly here to be used with cron task
+
+ :param run_all: if set it will ingore lookup and launch
+ all reconciliation
+ :returns: True in case of success or raises an exception
+
+ """
+ def _get_date(reconcile):
+ if reconcile.last_history.date:
+ return datetime.strptime(reconcile.last_history.date,
+ DEFAULT_SERVER_DATETIME_FORMAT)
+ else:
+ return datetime.min
+
+ ids = self.search(cr, uid, [], context=context)
+ assert ids, "No easy reconcile available"
+ if run_all:
+ self.run_reconcile(cr, uid, ids, context=context)
+ return True
+ reconciles = self.browse(cr, uid, ids, context=context)
+ reconciles.sort(key=_get_date)
+ older = reconciles[0]
+ self.run_reconcile(cr, uid, [older.id], context=context)
+ return True
diff --git a/__unported__/account_easy_reconcile/easy_reconcile.xml b/__unported__/account_easy_reconcile/easy_reconcile.xml
index 1fb27a10..076bd3b3 100644
--- a/__unported__/account_easy_reconcile/easy_reconcile.xml
+++ b/__unported__/account_easy_reconcile/easy_reconcile.xml
@@ -71,6 +71,10 @@ The lines should have the same amount (with the write-off) and the same referenc
+
+
+
+
@@ -129,6 +133,8 @@ The lines should have the same amount (with the write-off) and the same referenc
+
+
@@ -147,6 +153,8 @@ The lines should have the same amount (with the write-off) and the same referenc
+
+
@@ -161,4 +169,22 @@ The lines should have the same amount (with the write-off) and the same referenc
parent="account.periodical_processing_reconciliation"/>
+
+
+
+
+ Do Automatic Reconciliations
+
+
+ 3
+ hours
+ -1
+
+
+
+
+
+
+
+
diff --git a/__unported__/account_easy_reconcile/easy_reconcile_history.py b/__unported__/account_easy_reconcile/easy_reconcile_history.py
index 67581cb7..d73c0033 100644
--- a/__unported__/account_easy_reconcile/easy_reconcile_history.py
+++ b/__unported__/account_easy_reconcile/easy_reconcile_history.py
@@ -53,7 +53,7 @@ class EasyReconcileHistory(orm.Model):
_columns = {
'easy_reconcile_id': fields.many2one(
'account.easy.reconcile', 'Reconcile Profile', readonly=True),
- 'date': fields.datetime('Run date', readonly=True),
+ 'date': fields.datetime('Run date', readonly=True, required=True),
'reconcile_ids': fields.many2many(
'account.move.reconcile',
'account_move_reconcile_history_rel',
@@ -62,28 +62,27 @@ class EasyReconcileHistory(orm.Model):
'account.move.reconcile',
'account_move_reconcile_history_partial_rel',
string='Partial Reconciliations', readonly=True),
- 'reconcile_line_ids':
- fields.function(
+ 'reconcile_line_ids': fields.function(
_reconcile_line_ids,
string='Reconciled Items',
type='many2many',
relation='account.move.line',
readonly=True,
multi='lines'),
- 'partial_line_ids':
- fields.function(
- _reconcile_line_ids,
- string='Partially Reconciled Items',
- type='many2many',
- relation='account.move.line',
- readonly=True,
- multi='lines'),
- 'company_id': fields.related('easy_reconcile_id', 'company_id',
- relation='res.company',
- type='many2one',
- string='Company',
- store=True,
- readonly=True),
+ 'partial_line_ids': fields.function(
+ _reconcile_line_ids,
+ string='Partially Reconciled Items',
+ type='many2many',
+ relation='account.move.line',
+ readonly=True,
+ multi='lines'),
+ 'company_id': fields.related(
+ 'easy_reconcile_id', 'company_id',
+ relation='res.company',
+ type='many2one',
+ string='Company',
+ store=True,
+ readonly=True),
}
diff --git a/__unported__/account_easy_reconcile/i18n/account_easy_reconcile.pot b/__unported__/account_easy_reconcile/i18n/account_easy_reconcile.pot
index 4f878273..598b81ea 100644
--- a/__unported__/account_easy_reconcile/i18n/account_easy_reconcile.pot
+++ b/__unported__/account_easy_reconcile/i18n/account_easy_reconcile.pot
@@ -404,3 +404,24 @@ msgstr ""
msgid "account easy reconcile"
msgstr ""
+#. module: account_easy_reconcile
+#: field:account.easy.reconcile.method,expense_exchange_account_id:0
+#: field:easy.reconcile.base,expense_exchange_account_id:0
+#: field:easy.reconcile.options,expense_exchange_account_id:0
+#: field:easy.reconcile.simple,expense_exchange_account_id:0
+#: field:easy.reconcile.simple.name,expense_exchange_account_id:0
+#: field:easy.reconcile.simple.partner,expense_exchange_account_id:0
+#: field:easy.reconcile.simple.reference,expense_exchange_account_id:0
+msgid "Loss Exchange Rate Account"
+msgstr ""
+
+#. module: account_easy_reconcile
+#: field:account.easy.reconcile.method,income_exchange_account_id:0
+#: field:easy.reconcile.base,income_exchange_account_id:0
+#: field:easy.reconcile.options,income_exchange_account_id:0
+#: field:easy.reconcile.simple,income_exchange_account_id:0
+#: field:easy.reconcile.simple.name,income_exchange_account_id:0
+#: field:easy.reconcile.simple.partner,income_exchange_account_id:0
+#: field:easy.reconcile.simple.reference,income_exchange_account_id:0
+msgid "Gain Exchange Rate Account"
+msgstr ""
diff --git a/__unported__/account_easy_reconcile/i18n/fr.po b/__unported__/account_easy_reconcile/i18n/fr.po
index 431f2c0b..957765d4 100644
--- a/__unported__/account_easy_reconcile/i18n/fr.po
+++ b/__unported__/account_easy_reconcile/i18n/fr.po
@@ -427,3 +427,25 @@ msgstr "easy.reconcile.simple.reference"
#: model:ir.model,name:account_easy_reconcile.model_account_easy_reconcile
msgid "account easy reconcile"
msgstr "Lettrage automatisé"
+
+#. module: account_easy_reconcile
+#: field:account.easy.reconcile.method,expense_exchange_account_id:0
+#: field:easy.reconcile.base,expense_exchange_account_id:0
+#: field:easy.reconcile.options,expense_exchange_account_id:0
+#: field:easy.reconcile.simple,expense_exchange_account_id:0
+#: field:easy.reconcile.simple.name,expense_exchange_account_id:0
+#: field:easy.reconcile.simple.partner,expense_exchange_account_id:0
+#: field:easy.reconcile.simple.reference,expense_exchange_account_id:0
+msgid "Loss Exchange Rate Account"
+msgstr "Compte de perte de change"
+
+#. module: account_easy_reconcile
+#: field:account.easy.reconcile.method,income_exchange_account_id:0
+#: field:easy.reconcile.base,income_exchange_account_id:0
+#: field:easy.reconcile.options,income_exchange_account_id:0
+#: field:easy.reconcile.simple,income_exchange_account_id:0
+#: field:easy.reconcile.simple.name,income_exchange_account_id:0
+#: field:easy.reconcile.simple.partner,income_exchange_account_id:0
+#: field:easy.reconcile.simple.reference,income_exchange_account_id:0
+msgid "Gain Exchange Rate Account"
+msgstr "Compte de gain de change"
diff --git a/__unported__/account_easy_reconcile/res_config.py b/__unported__/account_easy_reconcile/res_config.py
new file mode 100644
index 00000000..cb827ab3
--- /dev/null
+++ b/__unported__/account_easy_reconcile/res_config.py
@@ -0,0 +1,59 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Author: Leonardo Pistone
+# Copyright 2014 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 .
+#
+##############################################################################
+
+from openerp.osv import orm, fields
+
+
+class AccountConfigSettings(orm.TransientModel):
+ _inherit = 'account.config.settings'
+
+ _columns = {
+ 'reconciliation_commit_every': fields.related(
+ 'company_id',
+ 'reconciliation_commit_every',
+ type='integer',
+ string='How often to commit when performing automatic '
+ 'reconciliation.',
+ help="""Leave zero to commit only at the end of the process."""),
+ }
+
+ def onchange_company_id(self, cr, uid, ids, company_id, context=None):
+ company_obj = self.pool['res.company']
+
+ result = super(AccountConfigSettings, self).onchange_company_id(
+ cr, uid, ids, company_id, context=None)
+
+ if company_id:
+ company = company_obj.browse(cr, uid, company_id, context=context)
+ result['value']['reconciliation_commit_every'] = (
+ company.reconciliation_commit_every
+ )
+ return result
+
+
+class Company(orm.Model):
+ _inherit = "res.company"
+ _columns = {
+ 'reconciliation_commit_every': fields.integer(
+ string='How often to commit when performing automatic '
+ 'reconciliation.',
+ help="""Leave zero to commit only at the end of the process."""),
+ }
diff --git a/__unported__/account_easy_reconcile/res_config_view.xml b/__unported__/account_easy_reconcile/res_config_view.xml
new file mode 100644
index 00000000..8badc32e
--- /dev/null
+++ b/__unported__/account_easy_reconcile/res_config_view.xml
@@ -0,0 +1,24 @@
+
+
+
+
+ account settings
+ account.config.settings
+
+
+
+
+
+
+