diff --git a/account_invoice_constraint_chronology/__init__.py b/account_invoice_constraint_chronology/__init__.py new file mode 100644 index 000000000..dcf937772 --- /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 000000000..46a44738b --- /dev/null +++ b/account_invoice_constraint_chronology/__openerp__.py @@ -0,0 +1,59 @@ +# -*- 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 helps 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/i18n/account_invoice_constraint_chronology.pot b/account_invoice_constraint_chronology/i18n/account_invoice_constraint_chronology.pot new file mode 100644 index 000000000..c13b71e5f --- /dev/null +++ b/account_invoice_constraint_chronology/i18n/account_invoice_constraint_chronology.pot @@ -0,0 +1,44 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * account_invoice_constraint_chronology +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0rc1\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-08-20 14:51+0000\n" +"PO-Revision-Date: 2014-08-20 14:51+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_invoice_constraint_chronology +#: field:account.journal,check_chronology:0 +msgid "Check Chronology" +msgstr "" + +#. module: account_invoice_constraint_chronology +#: code:addons/account_invoice_constraint_chronology/model/account_invoice.py:58 +#, python-format +msgid "Chronology Error. Please confirm older draft invoices before %s and try again." +msgstr "" + +#. module: account_invoice_constraint_chronology +#: code:addons/account_invoice_constraint_chronology/model/account_invoice.py:76 +#, python-format +msgid "Chronology Error. There exist at least one invoice with a date posterior to %s." +msgstr "" + +#. module: account_invoice_constraint_chronology +#: model:ir.model,name:account_invoice_constraint_chronology.model_account_invoice +msgid "Invoice" +msgstr "" + +#. module: account_invoice_constraint_chronology +#: model:ir.model,name:account_invoice_constraint_chronology.model_account_journal +msgid "Journal" +msgstr "" + diff --git a/account_invoice_constraint_chronology/model/__init__.py b/account_invoice_constraint_chronology/model/__init__.py new file mode 100644 index 000000000..d01496542 --- /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 000000000..9a7d36337 --- /dev/null +++ b/account_invoice_constraint_chronology/model/account.py @@ -0,0 +1,44 @@ +# -*- 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, fields, api + + +class account_journal(models.Model): + _inherit = ['account.journal'] + + check_chronology = fields.Boolean(string='Check Chronology', default=False) + + @api.one + @api.onchange('type') + def on_change_type(self): + if self.type not in ['sale', 'purchase', 'sale_refund', + 'purchase_refund']: + self.check_chronology = False + return True 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 000000000..c9ac805f5 --- /dev/null +++ b/account_invoice_constraint_chronology/model/account_invoice.py @@ -0,0 +1,83 @@ +# -*- 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, fields +from openerp.tools.translate import _ +from openerp.tools import DEFAULT_SERVER_DATE_FORMAT +from datetime import datetime +from openerp import exceptions + + +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', + 'proforma2']), + ('date_invoice', '!=', False), + ('date_invoice', '<', inv.date_invoice), + ('journal_id', '=', inv.journal_id.id)], + limit=1) + if len(invoices) > 0: + date_invoice_format = datetime\ + .strptime(inv.date_invoice, + DEFAULT_SERVER_DATE_FORMAT) + date_invoice_tz = fields\ + .Date.context_today(self, date_invoice_format) + raise exceptions.Warning(_("Chronology Error." + " Please confirm older draft" + " invoices before %s and" + " try again.") % + date_invoice_tz) + + if inv.internal_number is False: + invoices = self.search([('state', 'in', ['open', 'paid']), + ('date_invoice', '>', + inv.date_invoice), + ('journal_id', '=', + inv.journal_id.id)], + limit=1) + if len(invoices) > 0: + date_invoice_format = datetime\ + .strptime(inv.date_invoice, + DEFAULT_SERVER_DATE_FORMAT) + date_invoice_tz = fields\ + .Date.context_today(self, date_invoice_format) + raise exceptions.Warning(_("Chronology Error. There" + " exist at least one" + " invoice with a date" + " posterior to %s.") % + date_invoice_tz) + 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 000000000..cd63538c6 --- /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 000000000..70895831e --- /dev/null +++ b/account_invoice_constraint_chronology/tests/test_account_constraint_chronology.py @@ -0,0 +1,127 @@ +# -*- 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 import exceptions +from datetime import datetime, timedelta +from openerp.tools import DEFAULT_SERVER_DATE_FORMAT + +DB = common.DB +ADMIN_USER_ID = common.ADMIN_USER_ID + + +def get_simple_product_id(self): + return self.env['product.product'].create({'name': 'product_test_01', + 'lst_price': 2000.00, + }) + + +def get_journal_check(self, value): + sale_journal_id = self.ref('account.sales_journal') + sale_journal = self.env['account.journal'].browse([sale_journal_id]) + journal = sale_journal.copy() + journal.check_chronology = value + return journal + + +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 = 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() + self.context = self.registry("res.users").context_get(self.cr, + self.uid) + + def test_invoice_draft(self): + journal = get_journal_check(self, True) + today = datetime.now() + yesterday = today - timedelta(days=1) + date = yesterday.strftime(DEFAULT_SERVER_DATE_FORMAT) + create_simple_invoice(self, journal.id, date) + date = today.strftime(DEFAULT_SERVER_DATE_FORMAT) + invoice_2 = create_simple_invoice(self, journal.id, date) + self.assertRaises(exceptions.Warning, workflow.trg_validate, self.uid, + 'account.invoice', invoice_2.id, 'invoice_open', + self.cr) + + def test_invoice_validate(self): + journal = get_journal_check(self, True) + today = datetime.now() + tomorrow = today + timedelta(days=1) + date = tomorrow.strftime(DEFAULT_SERVER_DATE_FORMAT) + invoice = create_simple_invoice(self, journal.id, date) + workflow.trg_validate(self.uid, 'account.invoice', invoice.id, + 'invoice_open', self.cr) + date = today.strftime(DEFAULT_SERVER_DATE_FORMAT) + invoice_2 = create_simple_invoice(self, journal.id, date) + self.assertRaises(exceptions.Warning, workflow.trg_validate, self.uid, + 'account.invoice', invoice_2.id, 'invoice_open', + self.cr) + + def test_invoice_without_date(self): + journal = get_journal_check(self, True) + today = datetime.now() + yesterday = today - timedelta(days=1) + date = yesterday.strftime(DEFAULT_SERVER_DATE_FORMAT) + create_simple_invoice(self, journal.id, date) + invoice_2 = create_simple_invoice(self, journal.id, False) + self.assertRaises(exceptions.Warning, 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 000000000..1fc86dfe7 --- /dev/null +++ b/account_invoice_constraint_chronology/view/account_view.xml @@ -0,0 +1,15 @@ + + + + + account.journal.form (account_constraint_chronology) + account.journal + + + + + + + + +