diff --git a/addons/account_test/__init__.py b/addons/account_test/__init__.py new file mode 100644 index 00000000000..106682f4a12 --- /dev/null +++ b/addons/account_test/__init__.py @@ -0,0 +1,2 @@ +import account_test +import report diff --git a/addons/account_test/__openerp__.py b/addons/account_test/__openerp__.py new file mode 100644 index 00000000000..cfd4007fed0 --- /dev/null +++ b/addons/account_test/__openerp__.py @@ -0,0 +1,47 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (c) 2011 CCI Connect asbl (http://www.cciconnect.be) All Rights Reserved. +# Philmer +# +# 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' : 'Accounting Consistency Tests', + 'version' : '1.0', + 'author' : 'OpenERP', + 'category' : 'Accounting & Finance', + 'website': 'http://www.openerp.com', + 'description': """ +Asserts on accounting. +====================== +With this module you can manually check consistencies and inconsistencies of accounting module from menu Reporting/Accounting/Accounting Tests. + +You can write a query in order to create Consistency Test and you will get the result of the test +in PDF format which can be accessed by Menu Reporting -> Accounting Tests, then select the test +and print the report from Print button in header area. +""", + 'depends' : ['account'], + 'data' : [ + 'security/ir.model.access.csv', + 'account_test_view.xml', + 'account_test_report.xml', + 'account_test_data.xml', + ], + 'active': False, + 'installable': True +} +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_test/account_test.py b/addons/account_test/account_test.py new file mode 100644 index 00000000000..bf925e8236a --- /dev/null +++ b/addons/account_test/account_test.py @@ -0,0 +1,65 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Copyright (c) 2005-2006 TINY SPRL. (http://tiny.be) All Rights Reserved. +# +# $Id: product_expiry.py 4304 2006-10-25 09:54:51Z ged $ +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsability of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# garantees and support are strongly adviced to contract a Free Software +# Service Company +# +# This program is Free Software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################## + +from osv import fields,osv +import pooler +import netsvc +import time +from xml import dom + + +CODE_EXEC_DEFAULT = '''\ +res = [] +cr.execute("select id, code from account_journal") +for record in cr.dictfetchall(): + res.append(record['code']) +result = res +''' + +class accounting_assert_test(osv.osv): + _name = "accounting.assert.test" + _order = "sequence" + + _columns = { + 'name': fields.char('Test Name', size=256, required=True, select=True, translate=True), + 'desc': fields.text('Test Description', select=True, translate=True), + 'code_exec': fields.text('Python code', required=True), + 'active': fields.boolean('Active'), + 'sequence': fields.integer('Sequence'), + } + + _defaults = { + 'code_exec': CODE_EXEC_DEFAULT, + 'active': True, + 'sequence': 10, + } + +accounting_assert_test() + diff --git a/addons/account_test/account_test_data.xml b/addons/account_test/account_test_data.xml new file mode 100644 index 00000000000..4970bef6a0d --- /dev/null +++ b/addons/account_test/account_test_data.xml @@ -0,0 +1,172 @@ + + + + + + 1 + Test 1: General balance + Check the balance: Debit sum = Credit sum + + + + + 2 + Test 2: Opening a fiscal year + Check if the balance of the new opened fiscal year matches with last year's balance + + + + + 3 + Test 3: Movement lines + Check if movement lines are balanced and have the same date and period + 0 or am.period_id!=ml.period_id or (am.date!=ml.date) +""" +cr.execute(sql) +res = cr.dictfetchall() +if res: + res.insert(0,_('* The test failed for these movement lines:')) +result = res + +]]> + + + + 4 + Test 4: Totally reconciled mouvements + Check if the totally reconciled movements are balanced + 0", (record['reconcile_id'],)) + reconcile_ids=cr.dictfetchall() + if reconcile_ids: + res.append(', '.join(["Reconcile name: %(name)s, id=%(id)s " % r for r in reconcile_ids])) +result = res +if result: + result.insert(0,_('* The test failed for these reconciled items(id/name):')) +]]> + + + + 5 + Test 5.1 : Payable and Receivable accountant lines of reconciled invoices + Check that reconciled invoice for Sales/Purchases has reconciled entries for Payable and Receivable Accounts + + + + + 6 + Test 5.2 : Reconcilied invoices and Payable/Receivable accounts + Check that reconciled account moves, that define Payable and Receivable accounts, are belonging to reconciled invoices + + + + + 7 + Test 6 : Invoices status + Check that paid/reconciled invoices are not in 'Open' state + + + + + + 8 + Test 7: « View  » account type + Check that there's no move for any account with « View » account type + + + + + 9 + Test 8 : Closing balance on bank statements + Check on bank statement that the Closing Balance = Starting Balance + sum of statement lines + 0.000000001;") +result = cr.dictfetchall() +if result: + result.insert(0,_('* Unbalanced bank statement that need to be checked: ')) +]]> + + + + 10 + Test 9 : Accounts and partners on account moves + Check that general accounts and partners on account moves are active + + + + diff --git a/addons/account_test/account_test_report.xml b/addons/account_test/account_test_report.xml new file mode 100644 index 00000000000..480507b6072 --- /dev/null +++ b/addons/account_test/account_test_report.xml @@ -0,0 +1,14 @@ + + + + + + + + diff --git a/addons/account_test/account_test_view.xml b/addons/account_test/account_test_view.xml new file mode 100644 index 00000000000..43a67edcc6c --- /dev/null +++ b/addons/account_test/account_test_view.xml @@ -0,0 +1,85 @@ + + + + + + Tests + accounting.assert.test + + + + + + + + + + + Tests + accounting.assert.test + +
+ + + + + + + + + + + + + + + + + + + +
+Code should always set a variable named `result` with the result of your test, that can be a list or
+a dictionary. If `result` is an empty list, it means that the test was succesful. Otherwise it will
+try to translate and print what is inside `result`.
+
+If the result of your test is a dictionary, you can set a variable named `column_order` to choose in
+what order you want to print `result`'s content.
+
+Should you need them, you can also use the following variables into your code:
+    * cr: cursor to the database
+    * uid: ID of the current user
+
+In any ways, the code must be legal python statements with correct indentation (if needed).
+
+Example: 
+    sql = '''SELECT id, name, ref, date
+             FROM account_move_line 
+             WHERE account_id IN (SELECT id FROM account_account WHERE type = 'view')
+          '''
+    cr.execute(sql)
+    result = cr.dictfetchall()
+                                    
+
+
+
+
+
+
+
+ + + Accounting Tests + accounting.assert.test + tree,form + +

+ Click to create Accounting Test. +

+
+
+ + + +
+
diff --git a/addons/account_test/report/__init__.py b/addons/account_test/report/__init__.py new file mode 100644 index 00000000000..0e4fbf07082 --- /dev/null +++ b/addons/account_test/report/__init__.py @@ -0,0 +1,3 @@ +import account_test_report + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_test/report/account_test.rml b/addons/account_test/report/account_test.rml new file mode 100644 index 00000000000..1efa12fd5cb --- /dev/null +++ b/addons/account_test/report/account_test.rml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Accouting tests on [[ datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") ]] + + + +
+ [[repeatIn(objects,'o')]] + + + + [[ o.name ]] + + + + + [[ o.desc or '' ]] + + + + + + + [[ repeatIn(execute_code(o.code_exec), 'test_result') ]] + [[ test_result ]] + + + + + + +
+ +
+
diff --git a/addons/account_test/report/account_test_report.py b/addons/account_test/report/account_test_report.py new file mode 100644 index 00000000000..ab683e18688 --- /dev/null +++ b/addons/account_test/report/account_test_report.py @@ -0,0 +1,87 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved +# $Id$ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +############################################################################## + +import datetime +import time +from report import report_sxw +from tools.translate import _ +# +# Use period and Journal for selection or resources +# +class report_assert_account(report_sxw.rml_parse): + def __init__(self, cr, uid, name, context): + super(report_assert_account, self).__init__(cr, uid, name, context=context) + self.localcontext.update( { + 'time': time, + 'datetime': datetime, + 'execute_code': self.execute_code, + }) + + def execute_code(self, code_exec): + def reconciled_inv(): + """ + returns the list of invoices that are set as reconciled = True + """ + return self.pool.get('account.invoice').search(self.cr, self.uid, [('reconciled','=',True)]) + + def order_columns(item, cols=None): + """ + This function is used to display a dictionary as a string, with its columns in the order chosen. + + :param item: dict + :param cols: list of field names + :returns: a list of tuples (fieldname: value) in a similar way that would dict.items() do except that the + returned values are following the order given by cols + :rtype: [(key, value)] + """ + if cols is None: + cols = item.keys() + return [(col, item.get(col)) for col in cols if col in item.keys()] + + localdict = { + 'cr': self.cr, + 'uid': self.uid, + 'reconciled_inv': reconciled_inv, #specific function used in different tests + 'result': None, #used to store the result of the test + 'column_order': None, #used to choose the display order of columns (in case you are returning a list of dict) + } + exec code_exec in localdict + result = localdict['result'] + column_order = localdict.get('column_order', None) + + if not isinstance(result, (tuple, list, set)): + result = [result] + if not result: + result = [_('The test was passed successfully')] + else: + def _format(item): + if isinstance(item, dict): + return ', '.join(["%s: %s" % (tup[0], tup[1]) for tup in order_columns(item, column_order)]) + else: + return item + result = [_(_format(rec)) for rec in result] + + return result + +report_sxw.report_sxw('report.account.test.assert.print', 'accounting.assert.test', 'addons/account_test/report/account_test.rml', parser=report_assert_account, header=False) + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_test/security/ir.model.access.csv b/addons/account_test/security/ir.model.access.csv new file mode 100644 index 00000000000..cf7e93b6baa --- /dev/null +++ b/addons/account_test/security/ir.model.access.csv @@ -0,0 +1,3 @@ +"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" +"access_accounting_assert_test","accounting.assert.test","model_accounting_assert_test",base.group_system,1,0,0,1 +"access_accounting_assert_test_manager","accounting.assert.test","model_accounting_assert_test",account.group_account_manager,1,0,0,0