From c52963bf27f0c93a9b70b50d1615cb1274cd5e79 Mon Sep 17 00:00:00 2001 From: Adrien Peiffer Date: Thu, 7 Aug 2014 12:58:07 +0200 Subject: [PATCH] [ADD] Add account_invoice_constraint_chronology --- .../__init__.py | 31 ++++ .../__openerp__.py | 60 ++++++++ .../model/__init__.py | 31 ++++ .../model/account.py | 47 +++++++ .../model/account_invoice.py | 69 +++++++++ .../tests/__init__.py | 38 +++++ .../test_account_constraint_chronology.py | 133 ++++++++++++++++++ .../view/account_view.xml | 18 +++ 8 files changed, 427 insertions(+) create mode 100644 account_invoice_constraint_chronology/__init__.py create mode 100644 account_invoice_constraint_chronology/__openerp__.py create mode 100644 account_invoice_constraint_chronology/model/__init__.py create mode 100644 account_invoice_constraint_chronology/model/account.py create mode 100644 account_invoice_constraint_chronology/model/account_invoice.py create mode 100644 account_invoice_constraint_chronology/tests/__init__.py create mode 100644 account_invoice_constraint_chronology/tests/test_account_constraint_chronology.py create mode 100644 account_invoice_constraint_chronology/view/account_view.xml diff --git a/account_invoice_constraint_chronology/__init__.py b/account_invoice_constraint_chronology/__init__.py new file mode 100644 index 00000000..dcf93777 --- /dev/null +++ b/account_invoice_constraint_chronology/__init__.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# +# +# Authors: Adrien Peiffer +# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu) +# All Rights Reserved +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsibility 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 +# guarantees and support are strongly advised to contact a Free Software +# Service Company. +# +# 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 model +from . import tests diff --git a/account_invoice_constraint_chronology/__openerp__.py b/account_invoice_constraint_chronology/__openerp__.py new file mode 100644 index 00000000..a69b5ee0 --- /dev/null +++ b/account_invoice_constraint_chronology/__openerp__.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# +# +# Authors: Adrien Peiffer +# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu) +# All Rights Reserved +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsibility 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 +# guarantees and support are strongly advised to contact a Free Software +# Service Company. +# +# 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 Invoice Constraint Chronology", + "version": "1.0", + "author": "ACSONE SA/NV", + "maintainer": "ACSONE SA/NV", + "website": "http://www.acsone.eu", + "images": [], + "category": "Accounting", + "depends": [ + "account"], + "description": """ +Account Invoice Constraint Chronology +===================================== + +This module help ensuring the chronology of invoice numbers. + +It prevents the validation of invoices when: +* there are draft invoices with an anterior date +* there are validated invoices with a posterior date + +The check can be activated on a per-journal basis +(for sale and purchase journals). +""", + "data": ["view/account_view.xml"], + "demo": [], + "test": [], + "licence": "AGPL-3", + "installable": True, + "auto_install": False, + "application": True, +} diff --git a/account_invoice_constraint_chronology/model/__init__.py b/account_invoice_constraint_chronology/model/__init__.py new file mode 100644 index 00000000..d0149654 --- /dev/null +++ b/account_invoice_constraint_chronology/model/__init__.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# +# +# Authors: Adrien Peiffer +# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu) +# All Rights Reserved +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsibility 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 +# guarantees and support are strongly advised to contact a Free Software +# Service Company. +# +# 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 account_invoice +from . import account diff --git a/account_invoice_constraint_chronology/model/account.py b/account_invoice_constraint_chronology/model/account.py new file mode 100644 index 00000000..07cc781c --- /dev/null +++ b/account_invoice_constraint_chronology/model/account.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# +# +# Authors: Adrien Peiffer +# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu) +# All Rights Reserved +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsibility 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 +# guarantees and support are strongly advised to contact a Free Software +# Service Company. +# +# 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 account_jounrnal(orm.Model): + _inherit = "account.journal" + _columns = { + 'check_chronology': fields.boolean('Check Chronology'), + } + _defaults = { + 'check_chronology': False, + } + + def on_change_type(self, cr, uid, ids, type_journal, context=None): + value = {} + if type_journal not in ['sale', 'purchase', 'sale_refund', + 'purchase_refund']: + value.update({'check_chronology': False}) + return {'value': value} diff --git a/account_invoice_constraint_chronology/model/account_invoice.py b/account_invoice_constraint_chronology/model/account_invoice.py new file mode 100644 index 00000000..63f9402c --- /dev/null +++ b/account_invoice_constraint_chronology/model/account_invoice.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +# +# +# Authors: Adrien Peiffer +# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu) +# All Rights Reserved +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsibility 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 +# guarantees and support are strongly advised to contact a Free Software +# Service Company. +# +# 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 import models, api +from openerp.tools.translate import _ + + +class account_invoice(models.Model): + _inherit = "account.invoice" + + @api.multi + def action_move_create(self): + res = super(account_invoice, self).action_move_create() + for inv in self: + if inv.journal_id.check_chronology: + invoices = \ + self.search([('state', 'not in', + ['open', 'paid', 'cancel', 'proforma']), + ('date_invoice', '!=', False), + ('date_invoice', '<', inv.date_invoice), + ('journal_id', '=', inv.journal_id.id)]) + if len(invoices) > 0: + raise models.except_orm(_('Error !'), + _("Chronology Error!" + " Please confirm older draft" + " invoices before %s and" + " try again.") % + inv.date_invoice) + + if inv.internal_number is False: + invoices = self.search([('state', 'in', ['open', 'paid']), + ('date_invoice', '>', + inv.date_invoice), + ('journal_id', '=', + inv.journal_id.id)]) + if len(invoices) > 0: + raise models.except_orm(_('Error !'), + _("Chronology Error! There" + " exist at least one invoice" + " with a date posterior" + " to %s.") % + inv.date_invoice) + return res diff --git a/account_invoice_constraint_chronology/tests/__init__.py b/account_invoice_constraint_chronology/tests/__init__.py new file mode 100644 index 00000000..cd63538c --- /dev/null +++ b/account_invoice_constraint_chronology/tests/__init__.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +# +# +# Authors: Adrien Peiffer +# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu) +# All Rights Reserved +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsibility 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 +# guarantees and support are strongly advised to contact a Free Software +# Service Company. +# +# 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_constraint_chronology + +fast_suite = [ + test_account_constraint_chronology, +] + +checks = [ + test_account_constraint_chronology, +] diff --git a/account_invoice_constraint_chronology/tests/test_account_constraint_chronology.py b/account_invoice_constraint_chronology/tests/test_account_constraint_chronology.py new file mode 100644 index 00000000..c51c4e6e --- /dev/null +++ b/account_invoice_constraint_chronology/tests/test_account_constraint_chronology.py @@ -0,0 +1,133 @@ +# -*- coding: utf-8 -*- +# +# +# Authors: Adrien Peiffer +# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu) +# All Rights Reserved +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsibility 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 +# guarantees and support are strongly advised to contact a Free Software +# Service Company. +# +# 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 openerp.tests.common as common +from openerp import workflow +from openerp.osv import orm +from datetime import datetime, timedelta + +DB = common.DB +ADMIN_USER_ID = common.ADMIN_USER_ID + + +def get_simple_product_id(self): + return self.registry('product.product').create(self.cr, + self.uid, + {'name': 'product_test_01', + 'lst_price': 2000.00, + }, context={}) + + +def get_journal_check(self, value): + sale_journal_id = self.ref('account.sales_journal') + journal_id = self.registry('account.journal').copy(self.cr, + self.uid, + sale_journal_id, + {}, + context={}) + self.registry('account.journal').write(self.cr, + self.uid, + [journal_id], + {'check_chronology': value}, + context={}) + return journal_id + + +def get_simple_account_invoice_line_values(self, product_id): + return {'name': 'test', + 'account_id': self.ref('account.a_sale'), + 'price_unit': 2000.00, + 'quantity': 1, + 'product_id': product_id, + } + + +def create_simple_invoice(self, journal_id, date): + partner_id = self.ref('base.res_partner_2') + product_id = get_simple_product_id(self) + return self.env['account.invoice']\ + .create({'partner_id': partner_id, + 'account_id': + self.ref('account.a_recv'), + 'journal_id': + journal_id, + 'date_invoice': date, + 'invoice_line': [(0, 0, {'name': 'test', + 'account_id': + self.ref('account.a_sale'), + 'price_unit': 2000.00, + 'quantity': 1, + 'product_id': product_id, + } + ) + ], + }) + + +class TestAccountConstraintChronology(common.TransactionCase): + + def setUp(self): + super(TestAccountConstraintChronology, self).setUp() + + def test_invoice_draft(self): + journal_id = get_journal_check(self, True) + today = datetime.now() + yesterday = today - timedelta(days=1) + date = yesterday.strftime('%Y-%m-%d') + create_simple_invoice(self, journal_id, date) + date = today.strftime('%Y-%m-%d') + invoice_2 = create_simple_invoice(self, journal_id, date) + self.assertRaises(orm.except_orm, workflow.trg_validate, self.uid, + 'account.invoice', invoice_2.id, 'invoice_open', + self.cr) + + def test_invoice_validate(self): + journal_id = get_journal_check(self, True) + today = datetime.now() + tomorrow = today + timedelta(days=1) + date = tomorrow.strftime('%Y-%m-%d') + invoice = create_simple_invoice(self, journal_id, date) + workflow.trg_validate(self.uid, 'account.invoice', invoice.id, + 'invoice_open', self.cr) + date = today.strftime('%Y-%m-%d') + invoice_2 = create_simple_invoice(self, journal_id, date) + self.assertRaises(orm.except_orm, workflow.trg_validate, self.uid, + 'account.invoice', invoice_2.id, 'invoice_open', + self.cr) + + def test_invoice_without_date(self): + journal_id = get_journal_check(self, True) + today = datetime.now() + yesterday = today - timedelta(days=1) + date = yesterday.strftime('%Y-%m-%d') + create_simple_invoice(self, journal_id, date) + invoice_2 = create_simple_invoice(self, journal_id, False) + self.assertRaises(orm.except_orm, workflow.trg_validate, self.uid, + 'account.invoice', invoice_2.id, 'invoice_open', + self.cr) diff --git a/account_invoice_constraint_chronology/view/account_view.xml b/account_invoice_constraint_chronology/view/account_view.xml new file mode 100644 index 00000000..892ef81b --- /dev/null +++ b/account_invoice_constraint_chronology/view/account_view.xml @@ -0,0 +1,18 @@ + + + + + account.journal.form (account_constraint_chronology) + account.journal + + + + + + + on_change_type(type) + + + + + \ No newline at end of file