diff --git a/account_advanced_reconcile/__openerp__.py b/account_advanced_reconcile/__openerp__.py index 4212c3bc..00ec44b4 100644 --- a/account_advanced_reconcile/__openerp__.py +++ b/account_advanced_reconcile/__openerp__.py @@ -30,8 +30,6 @@ 'description': """ Advanced reconciliation methods for the module account_easy_reconcile. -account_easy_reconcile, which is a dependency, is available in the branch: lp:account-extra-addons - In addition to the features implemented in account_easy_reconcile, which are: - reconciliation facilities for big volume of transactions - setup different profiles of reconciliation by account @@ -39,31 +37,31 @@ In addition to the features implemented in account_easy_reconcile, which are: - this module is also a base to create others reconciliation methods which can plug in the profiles - a profile a reconciliation can be run manually or by a cron - - monitoring of reconcilation runs with a few logs + - monitoring of reconcilation runs with an history It implements a basis to created advanced reconciliation methods in a few lines of code. Typically, such a method can be: - - Reconcile entries if the partner and the ref are equal - - Reconcile entries if the partner is equal and the ref is the same than ref - or name - - Reconcile entries if the partner is equal and the ref match with a pattern + - Reconcile Journal items if the partner and the ref are equal + - Reconcile Journal items if the partner is equal and the ref + is the same than ref or name + - Reconcile Journal items if the partner is equal and the ref + match with a pattern And they allows: - Reconciliations with multiple credit / multiple debit lines - Partial reconciliations - Write-off amount as well -A method is already implemented in this module, it matches on entries: - * Partner - * Ref on credit move lines should be case insensitive equals to the ref or +A method is already implemented in this module, it matches on items: + - Partner + - Ref on credit move lines should be case insensitive equals to the ref or the name of the debit move line 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 payments, @@ -75,9 +73,7 @@ many offices. """, 'website': 'http://www.camptocamp.com', - 'init_xml': [], - 'update_xml': ['easy_reconcile_view.xml'], - 'demo_xml': [], + 'data': ['easy_reconcile_view.xml'], 'test': [], 'images': [], 'installable': True, diff --git a/account_advanced_reconcile/advanced_reconciliation.py b/account_advanced_reconcile/advanced_reconciliation.py index 8654284b..92011a1d 100644 --- a/account_advanced_reconcile/advanced_reconciliation.py +++ b/account_advanced_reconcile/advanced_reconciliation.py @@ -19,14 +19,13 @@ # ############################################################################## -from openerp.osv.orm import TransientModel +from openerp.osv import orm -class easy_reconcile_advanced_ref(TransientModel): +class easy_reconcile_advanced_ref(orm.TransientModel): _name = 'easy.reconcile.advanced.ref' _inherit = 'easy.reconcile.advanced' - _auto = True # False when inherited from AbstractModel def _skip_line(self, cr, uid, rec, move_line, context=None): """ diff --git a/account_advanced_reconcile/base_advanced_reconciliation.py b/account_advanced_reconcile/base_advanced_reconciliation.py index f4b74e80..14177f26 100644 --- a/account_advanced_reconcile/base_advanced_reconciliation.py +++ b/account_advanced_reconcile/base_advanced_reconciliation.py @@ -19,21 +19,17 @@ # ############################################################################## -from itertools import groupby, product -from operator import itemgetter -from openerp.osv.orm import Model, AbstractModel, TransientModel -from openerp.osv import fields, osv +from itertools import product +from openerp.osv import orm -class easy_reconcile_advanced(AbstractModel): +class easy_reconcile_advanced(orm.AbstractModel): _name = 'easy.reconcile.advanced' _inherit = 'easy.reconcile.base' def _query_debit(self, cr, uid, rec, context=None): - """Select all move (debit>0) as candidate. Optional choice on invoice - will filter with an inner join on the related moves. - """ + """Select all move (debit>0) as candidate. """ select = self._select(rec) sql_from = self._from(rec) where, params = self._where(rec) @@ -47,9 +43,7 @@ class easy_reconcile_advanced(AbstractModel): return cr.dictfetchall() def _query_credit(self, cr, uid, rec, context=None): - """Select all move (credit>0) as candidate. Optional choice on invoice - will filter with an inner join on the related moves. - """ + """Select all move (credit>0) as candidate. """ select = self._select(rec) sql_from = self._from(rec) where, params = self._where(rec) @@ -176,9 +170,9 @@ class easy_reconcile_advanced(AbstractModel): """ mkey, mvalue = matcher omkey, omvalue = opposite_matcher - assert mkey == omkey, "A matcher %s is compared with a matcher %s, " \ - " the _matchers and _opposite_matchers are probably wrong" % \ - (mkey, omkey) + assert mkey == omkey, ("A matcher %s is compared with a matcher %s, " + " the _matchers and _opposite_matchers are probably wrong" % + (mkey, omkey)) if not isinstance(mvalue, (list, tuple)): mvalue = mvalue, if not isinstance(omvalue, (list, tuple)): @@ -186,7 +180,13 @@ class easy_reconcile_advanced(AbstractModel): return easy_reconcile_advanced._compare_matcher_values(mkey, mvalue, omvalue) def _compare_opposite(self, cr, uid, rec, move_line, opposite_move_line, - matchers, context=None): + matchers, context=None): + """ Iterate over the matchers of the move lines vs opposite move lines + and if they all match, return True. + + 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, context=context) for matcher in matchers: @@ -216,14 +216,15 @@ class easy_reconcile_advanced(AbstractModel): :return: list of matching lines """ matchers = self._matchers(cr, uid, rec, move_line, context=context) - return [op for op in opposite_move_lines if \ - self._compare_opposite(cr, uid, rec, move_line, op, matchers, context=context)] + return [op for op in opposite_move_lines if + self._compare_opposite( + cr, uid, rec, move_line, op, matchers, context=context)] 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, context=context) + cr, uid, rec, credit_lines, debit_lines, context=context) def _skip_line(self, cr, uid, rec, move_line, context=None): """ @@ -234,9 +235,7 @@ class easy_reconcile_advanced(AbstractModel): return False def _rec_auto_lines_advanced(self, cr, uid, rec, credit_lines, debit_lines, context=None): - if context is None: - context = {} - + """ Advanced reconciliation main loop """ reconciled_ids = [] partial_reconciled_ids = [] reconcile_groups = [] diff --git a/account_advanced_reconcile/easy_reconcile.py b/account_advanced_reconcile/easy_reconcile.py index 0a4be152..5506917b 100644 --- a/account_advanced_reconcile/easy_reconcile.py +++ b/account_advanced_reconcile/easy_reconcile.py @@ -19,10 +19,10 @@ # ############################################################################## -from openerp.osv.orm import Model +from openerp.osv import orm -class account_easy_reconcile_method(Model): +class account_easy_reconcile_method(orm.Model): _inherit = 'account.easy.reconcile.method' @@ -31,6 +31,6 @@ class account_easy_reconcile_method(Model): _get_all_rec_method(cr, uid, context=context) methods += [ ('easy.reconcile.advanced.ref', - 'Advanced. Partner and Ref.'), + 'Advanced. Partner and Ref.'), ] return methods diff --git a/account_advanced_reconcile/easy_reconcile_view.xml b/account_advanced_reconcile/easy_reconcile_view.xml index 961add68..7d35927d 100644 --- a/account_advanced_reconcile/easy_reconcile_view.xml +++ b/account_advanced_reconcile/easy_reconcile_view.xml @@ -4,13 +4,12 @@ account.easy.reconcile.form account.easy.reconcile - form - diff --git a/account_advanced_reconcile/i18n/fr.po b/account_advanced_reconcile/i18n/fr.po index b5f20627..4a32f6a7 100644 --- a/account_advanced_reconcile/i18n/fr.po +++ b/account_advanced_reconcile/i18n/fr.po @@ -1,18 +1,19 @@ # Translation of OpenERP Server. # This file contains the translation of the following modules: -# * account_advanced_reconcile +# * account_advanced_reconcile # msgid "" msgstr "" "Project-Id-Version: OpenERP Server 6.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-11-07 12:34+0000\n" -"PO-Revision-Date: 2012-11-07 12:34+0000\n" -"Last-Translator: <>\n" +"POT-Creation-Date: 2013-01-04 08:25+0000\n" +"PO-Revision-Date: 2013-01-04 09:27+0100\n" +"Last-Translator: Guewen Baconnier \n" "Language-Team: \n" +"Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: \n" +"Content-Transfer-Encoding: 8bit\n" "Plural-Forms: \n" #. module: account_advanced_reconcile @@ -32,12 +33,6 @@ msgstr "Compte" msgid "reconcile method for account_easy_reconcile" msgstr "Méthode de lettrage pour le module account_easy_reconcile" -#. module: account_advanced_reconcile -#: field:easy.reconcile.advanced,date_base_on:0 -#: field:easy.reconcile.advanced.ref,date_base_on:0 -msgid "Date of reconcilation" -msgstr "Date de lettrage" - #. module: account_advanced_reconcile #: field:easy.reconcile.advanced,journal_id:0 #: field:easy.reconcile.advanced.ref,journal_id:0 @@ -50,6 +45,11 @@ msgstr "Journal" msgid "Account Profit" msgstr "Compte de produit" +#. module: account_advanced_reconcile +#: 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 ref. is matched vs the debit entry ref. or 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 la référence ou la description sur les écritures de débit." + #. module: account_advanced_reconcile #: field:easy.reconcile.advanced,filter:0 #: field:easy.reconcile.advanced.ref,filter:0 @@ -62,9 +62,10 @@ msgid "Advanced. Partner and Ref" msgstr "Avancé. Partenaire et Réf." #. module: account_advanced_reconcile -#: view:account.easy.reconcile:0 -msgid "Match multiple debit vs multiple credit entries. Allow partial reconcilation. The lines should have the partner, the credit entry ref. is matched vs the debit entry ref. or 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 la référence ou la description sur les écritures de débit." +#: field:easy.reconcile.advanced,date_base_on:0 +#: field:easy.reconcile.advanced.ref,date_base_on:0 +msgid "Date of reconciliation" +msgstr "Date de lettrage" #. module: account_advanced_reconcile #: model:ir.model,name:account_advanced_reconcile.model_easy_reconcile_advanced diff --git a/account_easy_reconcile/__openerp__.py b/account_easy_reconcile/__openerp__.py index 6131accf..eb8b1fc0 100755 --- a/account_easy_reconcile/__openerp__.py +++ b/account_easy_reconcile/__openerp__.py @@ -20,11 +20,11 @@ ############################################################################## { - "name" : "Easy Reconcile", - "version" : "1.1", - "depends" : ["account", + "name": "Easy Reconcile", + "version": "1.1", + "depends": ["account", ], - "author" : "Akretion,Camptocamp", + "author": "Akretion,Camptocamp", "description": """ Easy Reconcile ============== @@ -39,13 +39,13 @@ in order to provide: - a profile a reconciliation can be run manually or by a cron - monitoring of reconciliation runs with an history - which keep track of the reconciled entries + which keep track of the reconciled Journal items 2 simple reconciliation methods are integrated in this module, the simple reconciliations works on 2 lines (1 debit / 1 credit) and do not allow partial reconcilation, they also match on 1 key, -partner or entry name. +partner or Journal item name. You may be interested to install also the ``account_advanced_reconciliation`` module. @@ -53,11 +53,11 @@ This latter add more complex reconciliations, allows multiple lines and partial. """, - "website" : "http://www.akretion.com/", - "category" : "Finance", - "init_xml" : [], - "demo_xml" : [], - "update_xml" : [ + "website": "http://www.akretion.com/", + "category": "Finance", + "init_xml": [], + "demo_xml": [], + "update_xml": [ "easy_reconcile.xml", "easy_reconcile_history_view.xml", ], diff --git a/account_easy_reconcile/base_reconciliation.py b/account_easy_reconcile/base_reconciliation.py index b1134c55..b50c06b9 100644 --- a/account_easy_reconcile/base_reconciliation.py +++ b/account_easy_reconcile/base_reconciliation.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- ############################################################################## # -# Copyright 2012 Camptocamp SA (Guewen Baconnier) +# Copyright 2012-2013 Camptocamp SA (Guewen Baconnier) # Copyright (C) 2010 Sébastien Beau # # This program is free software: you can redistribute it and/or modify @@ -19,29 +19,29 @@ # ############################################################################## -from openerp.osv.orm import AbstractModel -from openerp.osv import fields, osv +from openerp.osv import fields, orm from operator import itemgetter, attrgetter -class easy_reconcile_base(AbstractModel): +class easy_reconcile_base(orm.AbstractModel): """Abstract Model for reconciliation methods""" _name = 'easy.reconcile.base' _inherit = 'easy.reconcile.options' - _auto = True # restore property set to False by AbstractModel _columns = { - 'account_id': fields.many2one('account.account', 'Account', required=True), - 'partner_ids': fields.many2many('res.partner', - string="Restrict on partners"), + 'account_id': fields.many2one( + 'account.account', 'Account', required=True), + 'partner_ids': fields.many2many( + 'res.partner', string="Restrict on partners"), # other columns are inherited from easy.reconcile.options } def automatic_reconcile(self, cr, uid, ids, context=None): - """ - :return: list of reconciled ids, list of partially reconciled entries + """ Reconciliation method called from the view. + + :return: list of reconciled ids, list of partially reconciled items """ if isinstance(ids, (int, long)): ids = [ids] @@ -50,14 +50,15 @@ class easy_reconcile_base(AbstractModel): return self._action_rec(cr, uid, rec, context=context) def _action_rec(self, cr, uid, rec, context=None): - """Must be inherited to implement the reconciliation + """ Must be inherited to implement the reconciliation + :return: list of reconciled ids """ raise NotImplementedError def _base_columns(self, rec): - """Mandatory columns for move lines queries - An extra column aliased as `key` should be defined + """ Mandatory columns for move lines queries + An extra column aliased as ``key`` should be defined in each query.""" aml_cols = ( 'id', @@ -104,7 +105,7 @@ class easy_reconcile_base(AbstractModel): return where, params def _below_writeoff_limit(self, cr, uid, rec, lines, - writeoff_limit, context=None): + writeoff_limit, context=None): precision = self.pool.get('decimal.precision').precision_get( cr, uid, 'Account') keys = ('debit', 'credit') @@ -119,7 +120,8 @@ class easy_reconcile_base(AbstractModel): writeoff_amount = round(debit - credit, precision) return bool(writeoff_limit >= abs(writeoff_amount)), debit, credit - def _get_rec_date(self, cr, uid, rec, lines, based_on='end_period_last_credit', context=None): + def _get_rec_date(self, cr, uid, rec, lines, + based_on='end_period_last_credit', context=None): period_obj = self.pool.get('account.period') def last_period(mlines): @@ -155,12 +157,14 @@ class easy_reconcile_base(AbstractModel): """ Try to reconcile given lines :param list lines: list of dict of move lines, they must at least - contain values for : id, debit, credit + contain values for : id, debit, credit :param boolean allow_partial: if True, partial reconciliation will be - created, otherwise only Full reconciliation will be created - :return: tuple of boolean values, first item is wether the the entries - have been reconciled or not, the second is wether the reconciliation - is full (True) or partial (False) + created, otherwise only Full + reconciliation will be created + :return: tuple of boolean values, first item is wether the items + have been reconciled or not, + the second is wether the reconciliation is full (True) + or partial (False) """ if context is None: context = {} @@ -168,8 +172,6 @@ class easy_reconcile_base(AbstractModel): ml_obj = self.pool.get('account.move.line') writeoff = rec.write_off - keys = ('debit', 'credit') - line_ids = [l['id'] for l in lines] below_writeoff, sum_debit, sum_credit = self._below_writeoff_limit( cr, uid, rec, lines, writeoff, context=context) @@ -204,4 +206,3 @@ class easy_reconcile_base(AbstractModel): return True, False return False, False - diff --git a/account_easy_reconcile/easy_reconcile.py b/account_easy_reconcile/easy_reconcile.py index e45e4876..3f7b2774 100644 --- a/account_easy_reconcile/easy_reconcile.py +++ b/account_easy_reconcile/easy_reconcile.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- ############################################################################## # -# Copyright 2012 Camptocamp SA (Guewen Baconnier) +# Copyright 2012-2013 Camptocamp SA (Guewen Baconnier) # Copyright (C) 2010 Sébastien Beau # # This program is free software: you can redistribute it and/or modify @@ -19,19 +19,18 @@ # ############################################################################## -import time -from openerp.osv.orm import Model, AbstractModel -from openerp.osv import fields, osv +from openerp.osv import fields, osv, orm from openerp.tools.translate import _ from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT -class easy_reconcile_options(AbstractModel): - """Options of a reconciliation profile, columns - shared by the configuration of methods and by the - reconciliation wizards. This allows decoupling - of the methods with the wizards and allows to - launch the wizards alone +class easy_reconcile_options(orm.AbstractModel): + """Options of a reconciliation profile + + Columns shared by the configuration of methods + and by the reconciliation wizards. + This allows decoupling of the methods and the + wizards and allows to launch the wizards alone """ _name = 'easy.reconcile.options' @@ -46,12 +45,16 @@ class easy_reconcile_options(AbstractModel): _columns = { 'write_off': fields.float('Write off allowed'), - 'account_lost_id': fields.many2one('account.account', 'Account Lost'), - 'account_profit_id': fields.many2one('account.account', 'Account Profit'), - 'journal_id': fields.many2one('account.journal', 'Journal'), - 'date_base_on': fields.selection(_get_rec_base_date, + 'account_lost_id': fields.many2one( + 'account.account', 'Account Lost'), + 'account_profit_id': fields.many2one( + 'account.account', 'Account Profit'), + 'journal_id': fields.many2one( + 'account.journal', 'Journal'), + 'date_base_on': fields.selection( + _get_rec_base_date, required=True, - string='Date of reconcilation'), + string='Date of reconciliation'), 'filter': fields.char('Filter', size=128), } @@ -61,13 +64,12 @@ class easy_reconcile_options(AbstractModel): } -class account_easy_reconcile_method(Model): +class account_easy_reconcile_method(orm.Model): _name = 'account.easy.reconcile.method' _description = 'reconcile method for account_easy_reconcile' _inherit = 'easy.reconcile.options' - _auto = True # restore property set to False by AbstractModel _order = 'sequence' @@ -82,11 +84,18 @@ class account_easy_reconcile_method(Model): return self._get_all_rec_method(cr, uid, context=None) _columns = { - 'name': fields.selection(_get_rec_method, 'Type', size=128, required=True), - 'sequence': fields.integer('Sequence', required=True, - help="The sequence field is used to order the reconcile method"), - 'task_id': fields.many2one('account.easy.reconcile', 'Task', - required=True, ondelete='cascade'), + 'name': fields.selection( + _get_rec_method, 'Type', required=True), + 'sequence': fields.integer( + 'Sequence', + required=True, + help="The sequence field is used to order " + "the reconcile method"), + 'task_id': fields.many2one( + 'account.easy.reconcile', + string='Task', + required=True, + ondelete='cascade'), } _defaults = { @@ -94,8 +103,11 @@ class account_easy_reconcile_method(Model): } def init(self, cr): - """ Migration stuff, name is not anymore methods names - but models name""" + """ Migration stuff + + Name is not anymore methods names but the name + of the model which does the reconciliation + """ cr.execute(""" UPDATE account_easy_reconcile_method SET name = 'easy.reconcile.simple.partner' @@ -108,7 +120,7 @@ class account_easy_reconcile_method(Model): """) -class account_easy_reconcile(Model): +class account_easy_reconcile(orm.Model): _name = 'account.easy.reconcile' _description = 'account easy reconcile' @@ -140,22 +152,29 @@ class account_easy_reconcile(Model): def _last_history(self, cr, uid, ids, name, args, context=None): result = {} for history in self.browse(cr, uid, ids, context=context): - # history is sorted by date desc - result[history.id] = history.history_ids[0].id + result[history.id] = False + if history.history_ids: + # history is sorted by date desc + result[history.id] = history.history_ids[0].id return result _columns = { - 'name': fields.char('Name', size=64, required=True), - 'account': fields.many2one('account.account', 'Account', required=True), - 'reconcile_method': fields.one2many('account.easy.reconcile.method', 'task_id', 'Method'), - 'unreconciled_count': fields.function(_get_total_unrec, - type='integer', string='Unreconciled Entries'), - 'reconciled_partial_count': fields.function(_get_partial_rec, - type='integer', string='Partially Reconciled Entries'), + 'name': fields.char('Name', required=True), + 'account': fields.many2one( + 'account.account', 'Account', required=True), + 'reconcile_method': fields.one2many( + 'account.easy.reconcile.method', 'task_id', 'Method'), + 'unreconciled_count': fields.function( + _get_total_unrec, type='integer', string='Unreconciled Items'), + 'reconciled_partial_count': fields.function( + _get_partial_rec, + type='integer', + string='Partially Reconciled Items'), 'history_ids': fields.one2many( 'easy.reconcile.history', 'easy_reconcile_id', - string='History'), + string='History', + readonly=True), 'last_history': fields.function( _last_history, @@ -168,11 +187,12 @@ class account_easy_reconcile(Model): def _prepare_run_transient(self, cr, uid, rec_method, context=None): return {'account_id': rec_method.task_id.account.id, 'write_off': rec_method.write_off, - 'account_lost_id': rec_method.account_lost_id and \ - rec_method.account_lost_id.id, - 'account_profit_id': rec_method.account_profit_id and \ - rec_method.account_profit_id.id, - 'journal_id': rec_method.journal_id and rec_method.journal_id.id, + 'account_lost_id': (rec_method.account_lost_id and + rec_method.account_lost_id.id), + 'account_profit_id': (rec_method.account_profit_id and + rec_method.account_profit_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} @@ -188,8 +208,6 @@ class account_easy_reconcile(Model): res = cr.fetchall() return [row[0] for row in res] - if context is None: - context = {} for rec in self.browse(cr, uid, ids, context=context): all_ml_rec_ids = [] all_ml_partial_ids = [] @@ -198,7 +216,8 @@ class account_easy_reconcile(Model): rec_model = self.pool.get(method.name) auto_rec_id = rec_model.create( cr, uid, - self._prepare_run_transient(cr, uid, method, context=context), + self._prepare_run_transient( + cr, uid, method, context=context), context=context) ml_rec_ids, ml_partial_ids = rec_model.automatic_reconcile( @@ -222,6 +241,16 @@ class account_easy_reconcile(Model): context=context) return True + def _no_history(self, cr, uid, rec, context=None): + """ Raise an `osv.except_osv` error, supposed to + be called when there is no history on the reconciliation + task. + """ + raise osv.except_osv( + _('Error'), + _('There is no history of reconciled ' + 'items on the task: %s.') % rec.name) + def last_history_reconcile(self, cr, uid, rec_id, context=None): """ Get the last history record for this reconciliation profile and return the action which opens move lines reconciled @@ -231,6 +260,8 @@ class account_easy_reconcile(Model): "Only 1 id expected" rec_id = rec_id[0] rec = self.browse(cr, uid, rec_id, context=context) + if not rec.last_history: + self._no_history(cr, uid, rec, context=context) return rec.last_history.open_reconcile() def last_history_partial(self, cr, uid, rec_id, context=None): @@ -242,4 +273,6 @@ class account_easy_reconcile(Model): "Only 1 id expected" rec_id = rec_id[0] rec = self.browse(cr, uid, rec_id, context=context) + if not rec.last_history: + self._no_history(cr, uid, rec, context=context) return rec.last_history.open_partial() diff --git a/account_easy_reconcile/easy_reconcile.xml b/account_easy_reconcile/easy_reconcile.xml index 6c93e70d..25d60720 100644 --- a/account_easy_reconcile/easy_reconcile.xml +++ b/account_easy_reconcile/easy_reconcile.xml @@ -1,4 +1,4 @@ - + @@ -7,52 +7,63 @@ account.easy.reconcile.form 20 account.easy.reconcile - form -
- - - - - - - - - -