From b5ca9344bb427d0fb0757797da54da613b5ba2ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul?= Date: Fri, 18 Apr 2014 14:53:38 +0200 Subject: [PATCH] [ADD] account_partner_required --- account_partner_required/__init__.py | 23 ++++ account_partner_required/__openerp__.py | 46 +++++++ account_partner_required/account.py | 96 ++++++++++++++ account_partner_required/account_view.xml | 24 ++++ account_partner_required/tests/__init__.py | 30 +++++ .../tests/test_account_partner_required.py | 120 ++++++++++++++++++ 6 files changed, 339 insertions(+) create mode 100644 account_partner_required/__init__.py create mode 100644 account_partner_required/__openerp__.py create mode 100644 account_partner_required/account.py create mode 100644 account_partner_required/account_view.xml create mode 100644 account_partner_required/tests/__init__.py create mode 100644 account_partner_required/tests/test_account_partner_required.py diff --git a/account_partner_required/__init__.py b/account_partner_required/__init__.py new file mode 100644 index 00000000..22c8fe29 --- /dev/null +++ b/account_partner_required/__init__.py @@ -0,0 +1,23 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Account partner required module for OpenERP +# Copyright (C) 2014 Acsone (http://acsone.eu). All Rights Reserved +# @author Stéphane Bidoul +# +# 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 . +# +############################################################################## + +import account diff --git a/account_partner_required/__openerp__.py b/account_partner_required/__openerp__.py new file mode 100644 index 00000000..ed9f8259 --- /dev/null +++ b/account_partner_required/__openerp__.py @@ -0,0 +1,46 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Account partner required module for OpenERP +# Copyright (C) 2014 Acsone (http://acsone.eu). All Rights Reserved +# @author Stéphane Bidoul +# +# 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': 'Account partner required', + 'version': '0.1', + 'category': 'Generic Modules/Accounting', + 'license': 'AGPL-3', + 'description': """This module adds an option "partner policy" +on account types. + +You have the choice between 3 policies : optional (the default), +always (require a partner), and never (forbid a partner). + +This module is useful to enforce a partner on account move lines on +customer and supplier accounts. + +Module developed by Stéphane Bidoul , +inspired by Alexis de Lattre 's +account_analytic_required module. +""", + 'author': 'ACSONE SA/NV', + 'website': 'http://acsone.eu/', + 'depends': ['account'], + 'data': ['account_view.xml'], + 'installable': True, +} diff --git a/account_partner_required/account.py b/account_partner_required/account.py new file mode 100644 index 00000000..5c7053b3 --- /dev/null +++ b/account_partner_required/account.py @@ -0,0 +1,96 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Account partner required module for OpenERP +# Copyright (C) 2014 Acsone (http://acsone.eu). All Rights Reserved +# @author Stéphane Bidoul +# +# 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 +from openerp.tools.translate import _ + + +class account_account_type(orm.Model): + _inherit = "account.account.type" + + _columns = { + 'partner_policy': fields.selection([ + ('optional', 'Optional'), + ('always', 'Always'), + ('never', 'Never') + ], 'Policy for partner field', + help="Set the policy for the partner field : if you select " + "'Optional', the accountant is free to put a partner " + "on an account move line with this type of account ; " + "if you select 'Always', the accountant will get an error " + "message if there is no partner ; if you select 'Never', " + "the accountant will get an error message if a partner " + "is present."), + } + + _defaults = { + 'partner_policy': 'optional', + } + + +class account_move_line(orm.Model): + _inherit = "account.move.line" + + def check_partner_required(self, cr, uid, ids, vals, context=None): + if 'account_id' in vals or 'partner_id' in vals or \ + 'debit' in vals or 'credit' in vals: + if isinstance(ids, (int, long)): + ids = [ids] + for move_line in self.browse(cr, uid, ids, context): + if move_line.debit == 0 and move_line.credit == 0: + continue + policy = move_line.account_id.user_type.partner_policy + if policy == 'always' and not move_line.partner_id: + raise orm.except_orm(_('Error :'), + _("Partner policy is set to 'Always' " + "with account %s '%s' but the " + "partner is missing in the account " + "move line with label '%s'." % + (move_line.account_id.code, + move_line.account_id.name, + move_line.name))) + elif policy == 'never' and move_line.partner_id: + raise orm.except_orm(_('Error :'), + _("Partner policy is set to 'Never' " + "with account %s '%s' but the " + "account move line with label '%s' " + "has a partner '%s'." % + (move_line.account_id.code, + move_line.account_id.name, + move_line.name, + move_line.partner_id.name))) + + def create(self, cr, uid, vals, context=None, check=True): + line_id = super(account_move_line, self).create(cr, uid, vals, + context=context, + check=check) + self.check_partner_required(cr, uid, line_id, vals, context=context) + return line_id + + def write(self, cr, uid, ids, vals, context=None, check=True, + update_check=True): + res = super(account_move_line, self).write(cr, uid, ids, vals, + context=context, + check=check, + update_check=update_check) + self.check_partner_required(cr, uid, ids, vals, context=context) + return res diff --git a/account_partner_required/account_view.xml b/account_partner_required/account_view.xml new file mode 100644 index 00000000..3f94ad52 --- /dev/null +++ b/account_partner_required/account_view.xml @@ -0,0 +1,24 @@ + + + + + + + + account_partner_required.account_type_form + account.account.type + + + + + + + + + + diff --git a/account_partner_required/tests/__init__.py b/account_partner_required/tests/__init__.py new file mode 100644 index 00000000..7b4043fc --- /dev/null +++ b/account_partner_required/tests/__init__.py @@ -0,0 +1,30 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Account partner required module for OpenERP +# Copyright (C) 2014 Acsone (http://acsone.eu). All Rights Reserved +# @author Stéphane Bidoul +# +# 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 test_account_partner_required + +fast_suite = [ +] + +checks = [ + test_account_partner_required, +] diff --git a/account_partner_required/tests/test_account_partner_required.py b/account_partner_required/tests/test_account_partner_required.py new file mode 100644 index 00000000..79af6ed0 --- /dev/null +++ b/account_partner_required/tests/test_account_partner_required.py @@ -0,0 +1,120 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Account partner required module for OpenERP +# Copyright (C) 2014 Acsone (http://acsone.eu). All Rights Reserved +# @author Stéphane Bidoul +# +# 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 datetime import datetime + +from openerp.tests import common +from openerp.osv import orm + + +class test_account_partner_required(common.TransactionCase): + + def setUp(self): + super(test_account_partner_required, self).setUp() + self.account_obj = self.registry('account.account') + self.account_type_obj = self.registry('account.account.type') + self.move_obj = self.registry('account.move') + self.move_line_obj = self.registry('account.move.line') + + def _create_move(self, with_partner, amount=100): + date = datetime.now() + period_id = self.registry('account.period').find(self.cr, self.uid, date, context={'account_period_prefer_normal': True})[0] + move_vals = { + 'journal_id': self.ref('account.sales_journal'), + 'period_id': period_id, + 'date': date, + } + move_id = self.move_obj.create(self.cr, self.uid, move_vals) + self.move_line_obj.create(self.cr, self.uid, + {'move_id': move_id, + 'name': '/', + 'debit': 0, + 'credit': amount, + 'account_id': self.ref('account.a_sale'), + }) + move_line_id = self.move_line_obj.create(self.cr, self.uid, + {'move_id': move_id, + 'name': '/', + 'debit': amount, + 'credit': 0, + 'account_id': self.ref('account.a_recv'), + 'partner_id': self.ref('base.res_partner_1') if with_partner else False, + }) + return move_line_id + + def _set_partner_policy(self, policy, aref='account.a_recv'): + account_type = self.account_obj.browse(self.cr, self.uid, + self.ref(aref)).user_type + self.account_type_obj.write(self.cr, self.uid, account_type.id, + {'partner_policy': policy}) + + def test_optional(self): + self._create_move(with_partner=False) + self._create_move(with_partner=True) + + def test_always_no_partner(self): + self._set_partner_policy('always') + with self.assertRaises(orm.except_orm): + self._create_move(with_partner=False) + + def test_always_no_partner_0(self): + # accept missing partner when debit=credit=0 + self._set_partner_policy('always') + self._create_move(with_partner=False, amount=0) + + def test_always_with_partner(self): + self._set_partner_policy('always') + self._create_move(with_partner=True) + + def test_never_no_partner(self): + self._set_partner_policy('never') + self._create_move(with_partner=False) + + def test_never_with_partner(self): + self._set_partner_policy('never') + with self.assertRaises(orm.except_orm): + self._create_move(with_partner=True) + + def test_never_with_partner_0(self): + # accept partner when debit=credit=0 + self._set_partner_policy('never') + self._create_move(with_partner=True, amount=0) + + def test_always_remove_partner(self): + # remove partner when policy is always + self._set_partner_policy('always') + line_id = self._create_move(with_partner=True) + with self.assertRaises(orm.except_orm): + self.move_line_obj.write(self.cr, self.uid, line_id, + {'partner_id': False}) + + def test_change_account(self): + self._set_partner_policy('always', aref='account.a_pay') + line_id = self._create_move(with_partner=False) + # change account to a_pay with policy always but missing partner + with self.assertRaises(orm.except_orm): + self.move_line_obj.write(self.cr, self.uid, line_id, + {'account_id': self.ref('account.a_pay')}) + # change account to a_pay with policy always with partner -> ok + self.move_line_obj.write(self.cr, self.uid, line_id, + {'account_id': self.ref('account.a_pay'), + 'partner_id': self.ref('base.res_partner_1')})