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 + + + + + + + + + + + diff --git a/__unported__/account_statement_bankaccount_completion/__init__.py b/__unported__/account_statement_bankaccount_completion/__init__.py index 133223b9..cac9a795 100644 --- a/__unported__/account_statement_bankaccount_completion/__init__.py +++ b/__unported__/account_statement_bankaccount_completion/__init__.py @@ -18,4 +18,5 @@ # along with this program. If not, see . # # -import statement +from . import statement +from . import res_partner_bank diff --git a/__unported__/account_statement_bankaccount_completion/res_partner_bank.py b/__unported__/account_statement_bankaccount_completion/res_partner_bank.py new file mode 100644 index 00000000..ea826f96 --- /dev/null +++ b/__unported__/account_statement_bankaccount_completion/res_partner_bank.py @@ -0,0 +1,52 @@ +# +# 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 . +# +# +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) diff --git a/__unported__/account_statement_bankaccount_completion/statement.py b/__unported__/account_statement_bankaccount_completion/statement.py index 4525f183..3c40204f 100644 --- a/__unported__/account_statement_bankaccount_completion/statement.py +++ b/__unported__/account_statement_bankaccount_completion/statement.py @@ -23,8 +23,8 @@ 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 +from openerp.addons.account_statement_base_completion.statement \ + import ErrorTooManyPartner class AccountStatementCompletionRule(Model): @@ -54,21 +54,25 @@ class AccountStatementCompletionRule(Model): partner_acc_number = st_line['partner_acc_number'] if not partner_acc_number: return {} - st_obj = self.pool.get('account.bank.statement.line') + st_obj = self.pool['account.bank.statement.line'] res = {} - res_bank_obj = self.pool.get('res.partner.bank') - ids = res_bank_obj.search(cr, - uid, - [('acc_number', '=', partner_acc_number)], - context=context) + 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)) + 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 + 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'], diff --git a/__unported__/account_statement_bankaccount_completion/tests/test_bankaccount_completion.py b/__unported__/account_statement_bankaccount_completion/tests/test_bankaccount_completion.py index 123ef3e3..bef61969 100644 --- a/__unported__/account_statement_bankaccount_completion/tests/test_bankaccount_completion.py +++ b/__unported__/account_statement_bankaccount_completion/tests/test_bankaccount_completion.py @@ -22,81 +22,102 @@ from openerp.tests import common import time -ACC_NUMBER = "BE38733040385372" +ACC_NUMBER = " BE38 7330 4038 5372 " class bankaccount_completion(common.TransactionCase): - def prepare(self): + 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.st_obj = self.registry("account.bank.statement") + 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.registry("ir.model.data").get_object_reference( - self.cr, self. uid, "account", "bank_journal")[1] + 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.account_id = self.registry("ir.model.data").get_object_reference( - self.cr, self.uid, "account", "a_recv")[1] - self.journal_id = self.registry("ir.model.data").get_object_reference( - self.cr, self. uid, "account", "bank_journal")[1] 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 the completion rule - # Create a bank statement - self.statement_id = self.st_obj.create( - self.cr, self.uid, { - "balance_end_real": 0.0, + 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 - }) - - # Create bank a statement line - self.statement_line_id = self.st_line_obj.create(self.cr, self.uid, { - 'amount': 1000.0, - 'name': 'EXT001', - 'ref': 'My ref', - 'statement_id': self.statement_id, - 'partner_acc_number': ACC_NUMBER - }) + "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 - res_bank_obj = self.registry('res.partner.bank') - res_bank_obj.create(self.cr, self.uid, { - "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_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 + number associated to the statement line """ - self.prepare() - statement_line = self.st_line_obj.browse(self.cr, self.uid, - self.statement_line_id) - # before import, the - self.assertFalse( - statement_line.partner_id, - "Partner_id must be blank before completion") - statement_obj = self.st_obj.browse(self.cr, self.uid, self.statement_id) - statement_obj.button_auto_completion() - statement_line = self.st_line_obj.browse(self.cr, self.uid, - self.statement_line_id) - self.assertEquals(self.partner_id, statement_line.partner_id[ - 'id'], "Missing expected partner id after completion") + 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) diff --git a/__unported__/account_statement_base_completion/__openerp__.py b/__unported__/account_statement_base_completion/__openerp__.py index aebf6ceb..dc8adfaf 100644 --- a/__unported__/account_statement_base_completion/__openerp__.py +++ b/__unported__/account_statement_base_completion/__openerp__.py @@ -26,13 +26,14 @@ 'maintainer': 'Camptocamp', 'category': 'Finance', 'complexity': 'normal', - 'depends': ['account_statement_ext'], + '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. + 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: @@ -41,15 +42,15 @@ 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). + 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. + 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: @@ -59,9 +60,10 @@ 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 ! + + 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': [ @@ -75,6 +77,7 @@ 'test/partner.yml', 'test/invoice.yml', 'test/supplier_invoice.yml', + 'test/refund.yml', 'test/completion_test.yml' ], 'installable': False, diff --git a/__unported__/account_statement_base_completion/i18n/fr.po b/__unported__/account_statement_base_completion/i18n/fr.po index c707856e..f5443fa3 100644 --- a/__unported__/account_statement_base_completion/i18n/fr.po +++ b/__unported__/account_statement_base_completion/i18n/fr.po @@ -158,7 +158,7 @@ msgstr "Erreur système" #. module: account_statement_base_completion #: field:account.bank.statement.line,already_completed:0 msgid "Auto-Completed" -msgstr "Auto-Completé" +msgstr "Auto-Complété" #. module: account_statement_base_completion #: code:addons/account_statement_base_completion/statement.py:448 @@ -170,7 +170,7 @@ msgstr "Erreur de bypass de l'ORM" #. module: account_statement_base_completion #: field:account.statement.completion.rule,sequence:0 msgid "Sequence" -msgstr "Séquence" +msgstr "Séquence" #. module: account_statement_base_completion #: code:addons/account_statement_base_completion/statement.py:280 @@ -210,7 +210,7 @@ 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é " -"(A condition d'utiliser un règle de lettrage dans le profil)." +"(à 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 diff --git a/__unported__/account_statement_base_completion/partner.py b/__unported__/account_statement_base_completion/partner.py index 2670d8aa..3f371c78 100644 --- a/__unported__/account_statement_base_completion/partner.py +++ b/__unported__/account_statement_base_completion/partner.py @@ -32,8 +32,8 @@ class ResPartner(orm.Model): '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)."), + "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)."), } diff --git a/__unported__/account_statement_base_completion/statement.py b/__unported__/account_statement_base_completion/statement.py index ba1771f5..12bf2d31 100644 --- a/__unported__/account_statement_base_completion/statement.py +++ b/__unported__/account_statement_base_completion/statement.py @@ -124,7 +124,9 @@ class AccountStatementCompletionRule(orm.Model): _order = "sequence asc" def _get_functions(self, cr, uid, context=None): - """List of available methods for rules. Override this to add you own.""" + """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)'), @@ -189,13 +191,7 @@ class AccountStatementCompletionRule(orm.Model): res = {} inv = self._find_invoice(cr, uid, line, inv_type, context=context) if inv: - # FIXME use only commercial_partner_id of invoice in 7.1 - # this is for backward compatibility in 7.0 before - # the refactoring of res.partner - if hasattr(inv, 'commercial_partner_id'): - partner_id = inv.commercial_partner_id.id - else: - partner_id = inv.partner_id.id + partner_id = inv.commercial_partner_id.id res = {'partner_id': partner_id, 'account_id': inv.account_id.id, 'type': inv_type} @@ -225,8 +221,8 @@ class AccountStatementCompletionRule(orm.Model): # 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 + 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 @@ -242,11 +238,11 @@ class AccountStatementCompletionRule(orm.Model): # 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. + 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: @@ -303,10 +299,10 @@ class AccountStatementCompletionRule(orm.Model): 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. + """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: @@ -333,7 +329,7 @@ class AccountStatementCompletionRule(orm.Model): # to: # http://www.postgresql.org/docs/9.0/static/functions-matching.html # in chapter 9.7.3.6. Limits and Compatibility - sql = """ + sql = r""" SELECT id FROM ( SELECT id, regexp_matches(%s, @@ -386,9 +382,9 @@ class AccountStatement(orm.Model): 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 + 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 @@ -449,7 +445,8 @@ class AccountStatementLine(orm.Model): 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')] + 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: @@ -635,7 +632,8 @@ class AccountBankStatement(orm.Model): st += ''.join(traceback.format_tb(trbk, 30)) _logger.error(st) if res: - # stat_line_obj.write(cr, uid, [line.id], vals, context=ctx) + # stat_line_obj.write(cr, uid, [line.id], vals, + # context=ctx) try: stat_line_obj._update_line( cr, uid, res, context=context) diff --git a/__unported__/account_statement_base_completion/test/completion_test.yml b/__unported__/account_statement_base_completion/test/completion_test.yml index 5b87a959..5f5cdbad 100644 --- a/__unported__/account_statement_base_completion/test/completion_test.yml +++ b/__unported__/account_statement_base_completion/test/completion_test.yml @@ -38,6 +38,15 @@ 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 - @@ -76,12 +85,18 @@ !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 check that the partner name has been recognised. + 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 4. I check that the partner special label has been recognised. + 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") diff --git a/__unported__/account_statement_base_completion/test/refund.yml b/__unported__/account_statement_base_completion/test/refund.yml new file mode 100644 index 00000000..f8c07909 --- /dev/null +++ b/__unported__/account_statement_base_completion/test/refund.yml @@ -0,0 +1,43 @@ +- + I create a "child" partner, to use in the invoice + (and have a different commercial_partner_id than itself) +- + !record {model: res.partner, id: res_partner_12_child}: + name: Child Partner + supplier: False + customer: True + is_company: False + parent_id: base.res_partner_12 +- + 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' + price_unit: 210.0 + quantity: 1.0 + product_id: product.product_product_3 + uos_id: product.product_uom_unit + journal_id: account.expenses_journal + partner_id: res_partner_12_child + type: 'out_refund' + reference_type: none +- + I confirm the refund +- + !workflow {model: account.invoice, action: invoice_open, ref: refund_for_completion_1} +- + I check that the refund state is "Open" +- + !assert {model: account.invoice, id: refund_for_completion_1}: + - state == 'open' +- + I check that it is given the number "CR0001" +- + !assert {model: account.invoice, id: refund_for_completion_1, string: Check CI number}: + - number == 'CR0001' diff --git a/__unported__/account_statement_base_completion/tests/test_base_completion.py b/__unported__/account_statement_base_completion/tests/test_base_completion.py index acbabbb0..9fd9adb5 100644 --- a/__unported__/account_statement_base_completion/tests/test_base_completion.py +++ b/__unported__/account_statement_base_completion/tests/test_base_completion.py @@ -65,8 +65,8 @@ class base_completion(common.TransactionCase): 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 + 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.' @@ -89,7 +89,8 @@ class base_completion(common.TransactionCase): for case in NAMES_COMPLETION_CASES: self.partner_obj.write( - self.cr, self.uid, self.partner_id, {'name': case.partner_name}) + 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, @@ -116,5 +117,6 @@ class base_completion(common.TransactionCase): 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)) + "Partner id should be empty after completion " + "(partner_name: %s, line_name: %s)" + % (case.partner_name, case.line_label)) diff --git a/__unported__/account_statement_base_import/__init__.py b/__unported__/account_statement_base_import/__init__.py index 7c864205..2fe60a3e 100644 --- a/__unported__/account_statement_base_import/__init__.py +++ b/__unported__/account_statement_base_import/__init__.py @@ -18,6 +18,6 @@ # along with this program. If not, see . # ############################################################################## -import parser -import wizard -import statement +from . import parser +from . import wizard +from . import statement diff --git a/__unported__/account_statement_base_import/__openerp__.py b/__unported__/account_statement_base_import/__openerp__.py index 224d470f..c3ba2bcc 100644 --- a/__unported__/account_statement_base_import/__openerp__.py +++ b/__unported__/account_statement_base_import/__openerp__.py @@ -57,8 +57,8 @@ 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. + 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': [ diff --git a/__unported__/account_statement_base_import/parser/__init__.py b/__unported__/account_statement_base_import/parser/__init__.py index c802d6b1..cb73080b 100644 --- a/__unported__/account_statement_base_import/parser/__init__.py +++ b/__unported__/account_statement_base_import/parser/__init__.py @@ -19,7 +19,7 @@ # ############################################################################## -from parser import new_bank_statement_parser -from parser import BankStatementImportParser -import file_parser -import generic_file_parser +from .parser import new_bank_statement_parser +from .parser import BankStatementImportParser +from . import file_parser +from . import generic_file_parser diff --git a/__unported__/account_statement_base_import/parser/file_parser.py b/__unported__/account_statement_base_import/parser/file_parser.py index e7d050a6..706e0b2d 100644 --- a/__unported__/account_statement_base_import/parser/file_parser.py +++ b/__unported__/account_statement_base_import/parser/file_parser.py @@ -21,8 +21,8 @@ from openerp.tools.translate import _ from openerp.osv.orm import except_orm import tempfile import datetime -from parser import BankStatementImportParser -from parser import UnicodeDictReader +from .parser import BankStatementImportParser +from .parser import UnicodeDictReader try: import xlrd except: @@ -41,12 +41,12 @@ class FileParser(BankStatementImportParser): """ def __init__(self, parse_name, ftype='csv', extra_fields=None, header=None, - **kwargs): + dialect=None, **kwargs): """ :param char: parse_name: The name of the parser :param char: ftype: extension of the file (could be csv, xls or xlsx) - :param dict: extra_fields: extra fields to add to the conversion + :param dict: extra_fields: extra fields to put into the conversion dict. In the format {fieldname: fieldtype} :param list: header : specify header fields if the csv file has no header @@ -58,19 +58,13 @@ class FileParser(BankStatementImportParser): raise except_orm( _('User Error'), _('Invalid file type %s. Please use csv, xls or xlsx') % ftype) - self.conversion_dict = { - 'ref': unicode, - 'label': unicode, - 'date': datetime.datetime, - 'amount': float_or_zero, - } - if extra_fields: - self.conversion_dict.update(extra_fields) + self.conversion_dict = extra_fields self.keys_to_validate = self.conversion_dict.keys() self.fieldnames = header self._datemode = 0 # used only for xls documents, # 0 means Windows mode (1900 based dates). # Set in _parse_xls, from the contents of the file + self.dialect = dialect def _custom_format(self, *args, **kwargs): """No other work on data are needed in this parser.""" @@ -118,7 +112,8 @@ class FileParser(BankStatementImportParser): csv_file.write(self.filebuffer) csv_file.flush() with open(csv_file.name, 'rU') as fobj: - reader = UnicodeDictReader(fobj, fieldnames=self.fieldnames) + reader = UnicodeDictReader(fobj, fieldnames=self.fieldnames, + dialect=self.dialect) return list(reader) def _parse_xls(self): @@ -181,9 +176,9 @@ class FileParser(BankStatementImportParser): except Exception as err: raise except_orm( _("Date format is not valid"), - _("Please modify the cell formatting to date format" - " for column: %s value: %s\n Please check the " - "line with ref: %s\n \n Detail: %s") % + _("Please modify the cell formatting to date " + "format for column: %s value: %s\n Please check " + "the line with ref: %s\n \n Detail: %s") % (rule, line.get(rule, _('Missing')), line.get('ref', line), repr(err))) else: diff --git a/__unported__/account_statement_base_import/parser/generic_file_parser.py b/__unported__/account_statement_base_import/parser/generic_file_parser.py index 710c5595..47e98445 100644 --- a/__unported__/account_statement_base_import/parser/generic_file_parser.py +++ b/__unported__/account_statement_base_import/parser/generic_file_parser.py @@ -19,18 +19,31 @@ ############################################################################## import datetime -from file_parser import FileParser +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. + 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, **kwargs) + parse_name, ftype=ftype, + extra_fields=conversion_dict, + **kwargs) @classmethod def parser_for(cls, parser_name): @@ -42,9 +55,9 @@ class GenericFileParser(FileParser): 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. + 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 diff --git a/__unported__/account_statement_base_import/parser/parser.py b/__unported__/account_statement_base_import/parser/parser.py index 6a9be611..999be4b0 100644 --- a/__unported__/account_statement_base_import/parser/parser.py +++ b/__unported__/account_statement_base_import/parser/parser.py @@ -29,11 +29,16 @@ def UnicodeDictReader(utf8_data, **kwargs): pos = utf8_data.tell() sample_data = utf8_data.read(2048) utf8_data.seek(pos) - dialect = sniffer.sniff(sample_data, delimiters=',;\t') + if not kwargs.get('dialect'): + dialect = sniffer.sniff(sample_data, delimiters=',;\t') + del kwargs['dialect'] + else: + dialect = kwargs.pop('dialect') csv_reader = csv.DictReader(utf8_data, dialect=dialect, **kwargs) for row in csv_reader: - yield dict([(key, unicode(value, 'utf-8')) for key, value in - row.iteritems()]) + yield dict([(unicode(key or '', 'utf-8'), + unicode(value or '', 'utf-8')) + for key, value in row.iteritems()]) class BankStatementImportParser(object): @@ -48,8 +53,8 @@ class BankStatementImportParser(object): def __init__(self, profile, *args, **kwargs): # The name of the parser as it will be called self.parser_name = profile.import_type - # The result as a list of row. One row per line of data in the file, but - # not the commission one ! + # 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 @@ -128,9 +133,9 @@ class BankStatementImportParser(object): def get_st_line_vals(self, line, *args, **kwargs): """Implement a method in your parser that must return a dict of vals - that can be passed to create method of statement line in order to record - it. It is the responsibility of every parser to give this dict of vals, - so each one can implement his own way of recording the lines. + 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, diff --git a/__unported__/account_statement_base_import/statement.py b/__unported__/account_statement_base_import/statement.py index 2bacb45c..83e250f3 100644 --- a/__unported__/account_statement_base_import/statement.py +++ b/__unported__/account_statement_base_import/statement.py @@ -23,7 +23,7 @@ import traceback from openerp.tools.translate import _ import datetime from openerp.osv import fields, orm -from parser import new_bank_statement_parser +from .parser import new_bank_statement_parser from openerp.tools.config import config @@ -74,13 +74,13 @@ class AccountStatementProfil(orm.Model): statement ID :param: context: global context """ - pass def write_logs_after_import(self, cr, uid, ids, statement_id, num_lines, context): """Write the log in the logger - :param int/long statement_id: ID of the concerned account.bank.statement + :param int/long statement_id: ID of the concerned + account.bank.statement :param int/long num_lines: Number of line that have been parsed :return: True """ @@ -102,7 +102,8 @@ class AccountStatementProfil(orm.Model): :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 + :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. """ @@ -133,7 +134,7 @@ class AccountStatementProfil(orm.Model): """ vals = {'profile_id': profile_id} vals.update(parser.get_st_vals()) - if not vals.get('balance_start'): + if vals.get('balance_start') is None: # Get starting balance from journal balance if parser doesn't # fill this data, simulating the manual flow statement_obj = self.pool['account.bank.statement'] @@ -173,8 +174,8 @@ class AccountStatementProfil(orm.Model): ftype="csv", context=None): """Create a bank statement with the given profile and parser. It will fullfill the bank statement with the values of the file providen, but - will not complete data (like finding the partner, or the right account). - This will be done in a second step with the completion rules. + 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 diff --git a/__unported__/account_statement_base_import/wizard/__init__.py b/__unported__/account_statement_base_import/wizard/__init__.py index 5dbd2b0c..888026df 100644 --- a/__unported__/account_statement_base_import/wizard/__init__.py +++ b/__unported__/account_statement_base_import/wizard/__init__.py @@ -17,4 +17,4 @@ # along with this program. If not, see . # ############################################################################## -import import_statement +from . import import_statement diff --git a/__unported__/account_statement_cancel_line/__init__.py b/__unported__/account_statement_cancel_line/__init__.py index 153ef95a..9ec2ed82 100644 --- a/__unported__/account_statement_cancel_line/__init__.py +++ b/__unported__/account_statement_cancel_line/__init__.py @@ -20,6 +20,6 @@ ############################################################################### """Account Statement Cancel Line.""" -import statement # noqa -import statement_line # noqa -import wizard # noqa +from . import statement # noqa +from . import statement_line # noqa +from . import wizard # noqa diff --git a/__unported__/account_statement_cancel_line/test/cancel_line.yml b/__unported__/account_statement_cancel_line/test/cancel_line.yml index 032ab054..579f1e79 100644 --- a/__unported__/account_statement_cancel_line/test/cancel_line.yml +++ b/__unported__/account_statement_cancel_line/test/cancel_line.yml @@ -22,7 +22,7 @@ name: line1 statement_id: statement_test ref: ref1 - date: '2014-01-20' + date: !eval "'%s-01-20' %(datetime.now().year)" amount: 100.0 - I create a second statement line @@ -31,7 +31,7 @@ name: line2 statement_id: statement_test ref: ref2 - date: '2014-01-25' + date: !eval "'%s-01-25' %(datetime.now().year)" amount: 200.0 - I check that the state of the statement is "Draft" diff --git a/__unported__/account_statement_cancel_line/test/confirm_statement_no_double_moves.yml b/__unported__/account_statement_cancel_line/test/confirm_statement_no_double_moves.yml index 0fa66bb3..cb649977 100644 --- a/__unported__/account_statement_cancel_line/test/confirm_statement_no_double_moves.yml +++ b/__unported__/account_statement_cancel_line/test/confirm_statement_no_double_moves.yml @@ -23,7 +23,7 @@ name: line11 statement_id: statement_test_10 ref: ref11 - date: '2014-01-20' + date: !eval "'%s-01-20' %(datetime.now().year)" amount: 100.0 - I create a second statement line @@ -32,7 +32,7 @@ name: line12 statement_id: statement_test_10 ref: ref12 - date: '2014-01-25' + date: !eval "'%s-01-25' %(datetime.now().year)" amount: 200.0 - Now I confirm only the first statement line diff --git a/__unported__/account_statement_cancel_line/test/test_confirm_last_line_balance_check.yml b/__unported__/account_statement_cancel_line/test/test_confirm_last_line_balance_check.yml index 8afc5a81..47c90f4b 100644 --- a/__unported__/account_statement_cancel_line/test/test_confirm_last_line_balance_check.yml +++ b/__unported__/account_statement_cancel_line/test/test_confirm_last_line_balance_check.yml @@ -25,7 +25,7 @@ name: line1 statement_id: statement_test3 ref: line1 - date: '2014-01-20' + date: !eval "'%s-01-20' %(datetime.now().year)" amount: 10.0 - Now I confirm the statement line. That should not pass the balance check diff --git a/__unported__/account_statement_cancel_line/test/test_confirm_last_line_no_balance_check.yml b/__unported__/account_statement_cancel_line/test/test_confirm_last_line_no_balance_check.yml index fb6cd3ec..6ae7ac61 100644 --- a/__unported__/account_statement_cancel_line/test/test_confirm_last_line_no_balance_check.yml +++ b/__unported__/account_statement_cancel_line/test/test_confirm_last_line_no_balance_check.yml @@ -25,7 +25,7 @@ name: line1 statement_id: statement_test4 ref: line1 - date: '2014-01-20' + date: !eval "'%s-01-20' %(datetime.now().year)" amount: 10.0 - Now I confirm the statement line diff --git a/__unported__/account_statement_cancel_line/wizard/__init__.py b/__unported__/account_statement_cancel_line/wizard/__init__.py index 49b74d3f..89af38cf 100644 --- a/__unported__/account_statement_cancel_line/wizard/__init__.py +++ b/__unported__/account_statement_cancel_line/wizard/__init__.py @@ -20,5 +20,5 @@ ############################################################################### """Wizard for asking the confirmation when some move is reconciled.""" -import cancel_statement # noqa -import cancel_statement_line # noqa +from . import cancel_statement # noqa +from . import cancel_statement_line # noqa diff --git a/__unported__/account_statement_commission/__init__.py b/__unported__/account_statement_commission/__init__.py index 5ba29072..65fff538 100644 --- a/__unported__/account_statement_commission/__init__.py +++ b/__unported__/account_statement_commission/__init__.py @@ -19,4 +19,4 @@ # along with this program. If not, see . # ############################################################################## -import commission +from . import commission diff --git a/__unported__/account_statement_commission/__openerp__.py b/__unported__/account_statement_commission/__openerp__.py index dd07e606..791e53ca 100644 --- a/__unported__/account_statement_commission/__openerp__.py +++ b/__unported__/account_statement_commission/__openerp__.py @@ -31,9 +31,9 @@ 'account_statement_base_import' ], 'description': """ -This module brings commission support to bank statement imports. It computes the -sum of a commission field on each transaction and creates a statement entry for -it. +This module brings commission support to bank statement imports. It computes +the sum of a commission field on each transaction and creates a statement +entry for it. """, 'website': 'http://www.camptocamp.com', 'data': [ diff --git a/__unported__/account_statement_commission/commission.py b/__unported__/account_statement_commission/commission.py index cba22bcf..7690b790 100644 --- a/__unported__/account_statement_commission/commission.py +++ b/__unported__/account_statement_commission/commission.py @@ -24,7 +24,8 @@ class AccountStatementProfil(orm.Model): commission_analytic_id = profile.commission_analytic_id.id comm_values = { 'name': 'IN ' + _('Commission line'), - 'date': parser.get_st_vals().get('date') or datetime.datetime.now(), + 'date': parser.get_st_vals().get('date') or + datetime.datetime.now(), 'amount': global_commission_amount, 'partner_id': partner_id, 'type': 'general', @@ -32,8 +33,8 @@ class AccountStatementProfil(orm.Model): 'account_id': commission_account_id, 'ref': 'commission', 'analytic_account_id': commission_analytic_id, - # !! We set the already_completed so auto-completion will not update - # those values! + # !! We set the already_completed so auto-completion will not + # update those values! 'already_completed': True, } st_obj = self.pool['account.bank.statement.line'] diff --git a/__unported__/account_statement_completion_label/statement.py b/__unported__/account_statement_completion_label/statement.py index aef6cb36..1f9d5bc1 100644 --- a/__unported__/account_statement_completion_label/statement.py +++ b/__unported__/account_statement_completion_label/statement.py @@ -92,7 +92,7 @@ class AccountStatementCompletionRule(orm.Model): ON st_l.statement_id = s.id WHERE - st_l.name ~* l.label + (st_l.name ~* l.label OR st_l.ref ~* l.label) AND l.profile_id = s.profile_id AND @@ -125,8 +125,8 @@ class AccountStatementLabel(orm.Model): 'label': fields.char('Bank Statement Label', size=100), 'account_id': fields.many2one('account.account', 'Account', required=True, - help='Account corresponding to the label ' - 'for a given partner'), + help='Account corresponding to the ' + 'label for a given partner'), 'company_id': fields.related('account_id', 'company_id', type='many2one', relation='res.company', diff --git a/__unported__/account_statement_ext/__init__.py b/__unported__/account_statement_ext/__init__.py index 7bf22aa2..5e15fac6 100644 --- a/__unported__/account_statement_ext/__init__.py +++ b/__unported__/account_statement_ext/__init__.py @@ -19,7 +19,7 @@ # ############################################################################## -import statement -import report -import account -import voucher +from . import statement +from . import report +from . import account +from . import voucher diff --git a/__unported__/account_statement_ext/__openerp__.py b/__unported__/account_statement_ext/__openerp__.py index e5e686f8..be69f14d 100644 --- a/__unported__/account_statement_ext/__openerp__.py +++ b/__unported__/account_statement_ext/__openerp__.py @@ -45,8 +45,8 @@ Features: 1) Improve the bank statement: allows to define profiles (for each Office or - Bank). The bank statement will then generate the entries based on some criteria - chosen in the selected profile. You can setup on the profile: + Bank). The bank statement will then generate the entries based on some + criteria chosen in the selected profile. You can setup on the profile: - the journal to use - use balance check or not diff --git a/__unported__/account_statement_ext/report/__init__.py b/__unported__/account_statement_ext/report/__init__.py index 14b13013..29a4bdaf 100644 --- a/__unported__/account_statement_ext/report/__init__.py +++ b/__unported__/account_statement_ext/report/__init__.py @@ -23,4 +23,4 @@ # ############################################################################## -import bank_statement_report +from . import bank_statement_report diff --git a/__unported__/account_statement_ext/statement.py b/__unported__/account_statement_ext/statement.py index 68d2eb72..748db07e 100644 --- a/__unported__/account_statement_ext/statement.py +++ b/__unported__/account_statement_ext/statement.py @@ -19,7 +19,7 @@ # ############################################################################## import openerp.addons.account.account_bank_statement as stat_mod -from openerp.osv import fields, orm +from openerp.osv import fields, orm, osv from openerp.tools.translate import _ @@ -52,8 +52,8 @@ class AccountStatementProfile(orm.Model): 'name': fields.char('Name', required=True), 'sequence': fields.integer( 'Sequence', - help="Gives a sequence in lists, the first profile will be used as " - "default"), + help="Gives a sequence in lists, the first profile will be used " + "as default"), 'partner_id': fields.many2one( 'res.partner', 'Bank/Payment Office partner', @@ -144,7 +144,8 @@ class AccountBankStatement(orm.Model): profile_obj = self.pool['account.statement.profile'] user = user_obj.browse(cr, uid, uid, context=context) profile_ids = profile_obj.search( - cr, uid, [('company_id', '=', user.company_id.id)], context=context) + cr, uid, [('company_id', '=', user.company_id.id)], context=context + ) return profile_ids[0] if profile_ids else False def _get_statement_from_profile(self, cr, uid, profile_ids, context=None): @@ -304,7 +305,8 @@ class AccountBankStatement(orm.Model): line if different from the statement line account ID :param int/long analytic_id: ID of analytic account to put on the move line - :param int/long partner_id: ID of the partner to put on the move line + :param int/long partner_id: ID of the partner to put on the move + line :return: dict of value to create() the account.move.line """ if context is None: @@ -420,7 +422,7 @@ class AccountBankStatement(orm.Model): self.create_move_from_st_line( cr, uid, st_line.id, company_currency_id, st_line_number, context) - except orm.except_orm, exc: + except (orm.except_orm, osv.except_osv) as exc: msg = "Line ID %s with ref %s had following error: %s" % ( st_line.id, st_line.ref, exc.value) errors_stack.append(msg) @@ -445,7 +447,7 @@ class AccountBankStatement(orm.Model): def get_account_for_counterpart(self, cr, uid, amount, account_receivable, account_payable): """For backward compatibility.""" - account_id, type = self.get_account_and_type_for_counterpart( + account_id, account_type = self.get_account_and_type_for_counterpart( cr, uid, amount, account_receivable, account_payable) return account_id @@ -496,10 +498,10 @@ class AccountBankStatement(orm.Model): self, cr, uid, amount, account_receivable, account_payable, partner_id=False): """ - Give the amount, payable and receivable account (that can be found using - get_default_pay_receiv_accounts method) and receive the one to use. This - method should be use when there is no other way to know which one to - take. The rules are: + Give the amount, payable and receivable account (that can be found + using get_default_pay_receiv_accounts method) and receive the one to + use. This method should be use when there is no other way to know which + one to take. The rules are: - If the customer checkbox is checked on the found partner, type and account will be customer and receivable - If the supplier checkbox is checked on the found partner, type and @@ -606,7 +608,7 @@ class AccountBankStatementLine(orm.Model): local_context['account_period_prefer_normal'] = True try: periods = period_obj.find(cr, uid, dt=date, context=local_context) - except orm.except_orm: + except (orm.except_orm, osv.except_osv): # if no period defined, we are certainly at installation time return False return periods and periods[0] or False @@ -617,7 +619,8 @@ class AccountBankStatementLine(orm.Model): _columns = { # Set them as required + 64 char instead of 32 'ref': fields.char('Reference', size=64, required=True), - 'period_id': fields.many2one('account.period', 'Period', required=True), + 'period_id': fields.many2one( + 'account.period', 'Period', required=True), } _defaults = { 'period_id': _get_period, @@ -732,8 +735,8 @@ class AccountBankStatementLine(orm.Model): 'voucher_id': False}} return {'value': {'type': line_type}} - def onchange_type(self, cr, uid, line_id, partner_id, line_type, profile_id, - context=None): + def onchange_type(self, cr, uid, line_id, partner_id, line_type, + profile_id, context=None): """Keep the same features as in standard and call super. If an account is returned, call the method to compute line values. """ diff --git a/__unported__/account_statement_ext_point_of_sale/point_of_sale.py b/__unported__/account_statement_ext_point_of_sale/point_of_sale.py index 6460b0a7..d929ab0e 100644 --- a/__unported__/account_statement_ext_point_of_sale/point_of_sale.py +++ b/__unported__/account_statement_ext_point_of_sale/point_of_sale.py @@ -82,7 +82,8 @@ if not hasattr(std_pos_session, '_prepare_bank_statement'): cr, uid, [('type', '=', 'cash')], context=context) if not cashids: cashids = journal_proxy.search( - cr, uid, [('journal_user', '=', True)], context=context) + cr, uid, [('journal_user', '=', True)], + context=context) jobj.write( cr, uid, [pos_config.id], {'journal_ids': [(6, 0, cashids)]}) pos_config = jobj.browse(cr, uid, config_id, context=context) diff --git a/__unported__/account_statement_ofx_import/__init__.py b/__unported__/account_statement_ofx_import/__init__.py index 19462c05..71e18ac5 100644 --- a/__unported__/account_statement_ofx_import/__init__.py +++ b/__unported__/account_statement_ofx_import/__init__.py @@ -18,5 +18,5 @@ # along with this program. If not, see . # ############################################################################## -import statement -import parser +from . import statement +from . import parser diff --git a/__unported__/account_statement_one_move/statement.py b/__unported__/account_statement_one_move/statement.py index 2e60964b..73e46c12 100644 --- a/__unported__/account_statement_one_move/statement.py +++ b/__unported__/account_statement_one_move/statement.py @@ -63,7 +63,8 @@ class AccountBankStatement(orm.Model): }) return res - def create_move_from_st_line(self, cr, uid, st_line_id, company_currency_id, + def create_move_from_st_line(self, cr, uid, st_line_id, + company_currency_id, st_line_number, context=None): if context is None: context = {} diff --git a/__unported__/account_statement_regex_account_completion/statement.py b/__unported__/account_statement_regex_account_completion/statement.py index 6a232b02..cc697de0 100644 --- a/__unported__/account_statement_regex_account_completion/statement.py +++ b/__unported__/account_statement_regex_account_completion/statement.py @@ -54,7 +54,7 @@ class AccountStatementCompletionRule(Model): string="Account to set"), } - def set_account(self, cr, uid, id, st_line, context=None): + def set_account(self, cr, uid, account_id, st_line, context=None): """ If line name match regex, update account_id Then, call the generic st_line method to complete other values. @@ -69,7 +69,7 @@ class AccountStatementCompletionRule(Model): name = st_line['name'] res = {} if name: - rule = self.browse(cr, uid, id, context=context) + rule = self.browse(cr, uid, account_id, context=context) if re.match(rule.regex, name): res['account_id'] = rule.account_id.id return res diff --git a/__unported__/account_statement_regex_account_completion/tests/test_regex_account_completion.py b/__unported__/account_statement_regex_account_completion/tests/test_regex_account_completion.py index ea3af52c..faac8a86 100644 --- a/__unported__/account_statement_regex_account_completion/tests/test_regex_account_completion.py +++ b/__unported__/account_statement_regex_account_completion/tests/test_regex_account_completion.py @@ -87,12 +87,14 @@ class test_regex_account_completion(common.TransactionCase): """Test the automatic completion on account """ self.prepare() - statement_obj = self.st_obj.browse(self.cr, self.uid, self.statement_id) + statement_obj = self.st_obj.browse( + self.cr, self.uid, self.statement_id) statement_obj.button_auto_completion() statement_line1 = self.st_line_obj.browse( self.cr, self.uid, self.statement_line1_id) self.assertEquals(self.account_id, statement_line1.account_id.id, - "The account should be the account of the completion") + "The account should be the account of the completion" + ) statement_line2 = self.st_line_obj.browse( self.cr, self.uid, self.statement_line2_id) self.assertNotEqual(self.account_id, statement_line2.account_id.id, diff --git a/__unported__/account_statement_transactionid_completion/__init__.py b/__unported__/account_statement_transactionid_completion/__init__.py index a8ce7c24..647f811c 100644 --- a/__unported__/account_statement_transactionid_completion/__init__.py +++ b/__unported__/account_statement_transactionid_completion/__init__.py @@ -19,4 +19,4 @@ # ############################################################################## -import statement +from . import statement diff --git a/__unported__/account_statement_transactionid_completion/statement.py b/__unported__/account_statement_transactionid_completion/statement.py index 8fcb13d2..28fceb84 100644 --- a/__unported__/account_statement_transactionid_completion/statement.py +++ b/__unported__/account_statement_transactionid_completion/statement.py @@ -110,7 +110,7 @@ class AccountStatementCompletionRule(Model): elif len(invoice_id) == 1: invoice = invoice_obj.browse(cr, uid, invoice_id[0], context=context) - res['partner_id'] = invoice.partner_id.id + res['partner_id'] = invoice.commercial_partner_id.id # we want the move to have the same ref than the found # invoice's move, thus it will be easier to link them for the # accountants @@ -151,7 +151,8 @@ class AccountBankStatement(Model): :param browse_record st_line: account.bank.statement.line record to create the move from. - :param int/long move_id: ID of the account.move to link the move line + :param int/long move_id: ID of the account.move to link the move + line :param float debit: debit amount of the move line :param float credit: credit amount of the move line :param int/long currency_id: ID of currency of the move line to @@ -162,7 +163,8 @@ class AccountBankStatement(Model): line if different from the statement line account ID :param int/long analytic_id: ID of analytic account to put on the move line - :param int/long partner_id: ID of the partner to put on the move line + :param int/long partner_id: ID of the partner to put on the move + line :return: dict of value to create() the account.move.line """ res = super(AccountBankStatement, self)._prepare_move_line_vals( diff --git a/__unported__/account_statement_transactionid_completion/test/completion_transactionid_test.yml b/__unported__/account_statement_transactionid_completion/test/completion_transactionid_test.yml index 0d9c0b2f..57066533 100644 --- a/__unported__/account_statement_transactionid_completion/test/completion_transactionid_test.yml +++ b/__unported__/account_statement_transactionid_completion/test/completion_transactionid_test.yml @@ -29,7 +29,7 @@ statement_id: statement_transactionid_test1 transaction_id: XXX66Z ref: 6 - date: '2014-01-06' + date: !eval "'%s-01-06' %(datetime.now().year)" amount: 118.4 - I run the auto complete diff --git a/__unported__/account_statement_transactionid_import/__init__.py b/__unported__/account_statement_transactionid_import/__init__.py index 29698b5e..874730ea 100644 --- a/__unported__/account_statement_transactionid_import/__init__.py +++ b/__unported__/account_statement_transactionid_import/__init__.py @@ -18,5 +18,5 @@ # along with this program. If not, see . # ############################################################################## -import parser -import statement +from . import parser +from . import statement diff --git a/__unported__/account_statement_transactionid_import/__openerp__.py b/__unported__/account_statement_transactionid_import/__openerp__.py index 5b87b77a..e89a6836 100644 --- a/__unported__/account_statement_transactionid_import/__openerp__.py +++ b/__unported__/account_statement_transactionid_import/__openerp__.py @@ -35,9 +35,9 @@ the importation of different bank and offices that uses transactionID. This module allows you to import your bank transactions with a standard .csv - or .xls file (you'll find samples in the 'data' folder). It respects the chosen - profile (model provided by the account_statement_ext module) to generate the - entries. + or .xls file (you'll find samples in the 'data' folder). It respects the + chosen profile (model provided by the account_statement_ext module) to + generate the entries. This module can handle a commission taken by the payment office and has the following format: @@ -48,8 +48,8 @@ * amount: amount paid in the currency of the journal used in the importation profile * commission_amount: amount of the comission for each line - * label: the comunication given by the payment office, used as communication in - the generated entries. + * label: the comunication given by the payment office, used as communication + in the generated entries. """, 'website': 'http://www.camptocamp.com', 'installable': False, diff --git a/__unported__/account_statement_transactionid_import/parser/__init__.py b/__unported__/account_statement_transactionid_import/parser/__init__.py index de4553b9..9cc12870 100644 --- a/__unported__/account_statement_transactionid_import/parser/__init__.py +++ b/__unported__/account_statement_transactionid_import/parser/__init__.py @@ -19,4 +19,4 @@ # ############################################################################## -import transactionid_file_parser +from . import transactionid_file_parser diff --git a/__unported__/account_statement_transactionid_import/parser/transactionid_file_parser.py b/__unported__/account_statement_transactionid_import/parser/transactionid_file_parser.py index 0bb2a2d7..bc9aadb5 100644 --- a/__unported__/account_statement_transactionid_import/parser/transactionid_file_parser.py +++ b/__unported__/account_statement_transactionid_import/parser/transactionid_file_parser.py @@ -18,7 +18,10 @@ # ############################################################################## import datetime -from account_statement_base_import.parser.file_parser import FileParser +from openerp.tools import ustr +from account_statement_base_import.parser.file_parser import ( + FileParser, float_or_zero +) class TransactionIDFileParser(FileParser): @@ -36,14 +39,15 @@ class TransactionIDFileParser(FileParser): :param list: header : specify header fields if the csv file has no header """ - extra_fields = {'transaction_id': unicode} + conversion_dict = { + 'transaction_id': ustr, + 'label': ustr, + 'date': datetime.datetime, + 'amount': float_or_zero, + } super(TransactionIDFileParser, self).__init__( - profile, extra_fields=extra_fields, ftype=ftype, header=header, + profile, extra_fields=conversion_dict, ftype=ftype, header=header, **kwargs) - # ref is replaced by transaction_id thus we delete it from check - self.keys_to_validate = [ - k for k in self.keys_to_validate if k != 'ref'] - del self.conversion_dict['ref'] @classmethod def parser_for(cls, parser_name): @@ -54,9 +58,9 @@ class TransactionIDFileParser(FileParser): 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. + 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 diff --git a/account_invoice_reference/__openerp__.py b/account_invoice_reference/__openerp__.py index 55c1c480..cda206a0 100644 --- a/account_invoice_reference/__openerp__.py +++ b/account_invoice_reference/__openerp__.py @@ -39,10 +39,10 @@ origin, free reference) and above all, to understand which field will be copied in the reference field of the move and move lines. The approach here is to state simple rules with one concern: consistency. -The reference of the move lines must be the number of the document at -their very origin (number of a sales order, of an external document -like a supplier invoice, ...). The goal is for the accountant to be -able to trace to the source document from a ledger). +The reference of the move lines must be the number of the document at their +very origin (number of a sales order, of an external document like a supplier +invoice, ...). The goal is for the accountant to be able to trace to the +source document from a ledger). The description of a line should always be... well, a description. Not a number or a cryptic reference.