diff --git a/duplication_account_invoice/README.rst b/duplication_account_invoice/README.rst new file mode 100644 index 00000000..2c27b53f --- /dev/null +++ b/duplication_account_invoice/README.rst @@ -0,0 +1,85 @@ +============================= +Account Invoice - Duplication +============================= + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:9fe9ebce9e450f3a308617c0f4cde279b6b779c636907c81cd5487dbcb78f190 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-grap%2Fgrap--odoo--incubator-lightgray.png?logo=github + :target: https://github.com/grap/grap-odoo-incubator/tree/12.0/duplication_account_invoice + :alt: grap/grap-odoo-incubator + +|badge1| |badge2| |badge3| + +This module extends the functionality of Account Module to provide a wizard to +duplicate a given Account Invoice. + +User can define: + +* a begin date +* a frequency (week, ...) +* a recurring quantity +* a duration for the due date + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +To use this module, you need to + +* go to Invoices / (Customer / Supplier ) Invoices + +* Select any invoice and click on 'More' / 'Duplication Wizard' + +.. figure:: https://raw.githubusercontent.com/grap/grap-odoo-incubator/12.0/duplication_account_invoice/static/description/account_invoice_duplication_wizard_form.png + +Known issues / Roadmap +====================== + +Change the field due_date_duration in the wizard by the selection of a +``account.payment.term`` + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* GRAP + +Contributors +~~~~~~~~~~~~ + +* Sylvain LE GAL (https://www.twitter.com/legalsylvain) + +Maintainers +~~~~~~~~~~~ + +This module is part of the `grap/grap-odoo-incubator `_ project on GitHub. + +You are welcome to contribute. diff --git a/duplication_account_invoice/__init__.py b/duplication_account_invoice/__init__.py new file mode 100644 index 00000000..0650744f --- /dev/null +++ b/duplication_account_invoice/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/duplication_account_invoice/__manifest__.py b/duplication_account_invoice/__manifest__.py new file mode 100644 index 00000000..984032cc --- /dev/null +++ b/duplication_account_invoice/__manifest__.py @@ -0,0 +1,21 @@ +# Copyright (C) 2015 - Today: GRAP (http://www.grap.coop) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +{ + "name": "Account Invoice - Duplication", + "summary": "Duplication Tools for Invoices with a given frequency", + "version": "16.0.1.0.0", + "category": "Account", + "author": "GRAP, Odoo Community Association (OCA)", + "website": "https://github.com/grap/grap-odoo-incubator", + "license": "AGPL-3", + "depends": [ + "account", + ], + "data": [ + "views/view_account_invoice_duplication_wizard.xml", + "views/action.xml", + ], + "installable": True, +} diff --git a/duplication_account_invoice/i18n/fr.po b/duplication_account_invoice/i18n/fr.po new file mode 100644 index 00000000..89e2fca3 --- /dev/null +++ b/duplication_account_invoice/i18n/fr.po @@ -0,0 +1,164 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * duplication_account_invoice +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-07-18 09:56+0000\n" +"PO-Revision-Date: 2019-07-18 09:56+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: duplication_account_invoice +#: model:ir.model.fields,field_description:duplication_account_invoice.field_account_invoice_duplication_wizard__begin_date +msgid "Begin Date" +msgstr "Date de début" + +#. module: duplication_account_invoice +#: model_terms:ir.ui.view,arch_db:duplication_account_invoice.view_account_invoice_duplication_wizard_form +msgid "Cancel" +msgstr "Annuler" + +#. module: duplication_account_invoice +#: model:ir.model.fields,field_description:duplication_account_invoice.field_account_invoice_duplication_wizard__create_uid +#: model:ir.model.fields,field_description:duplication_account_invoice.field_account_invoice_duplication_wizard_date_line__create_uid +msgid "Created by" +msgstr "Créé par" + +#. module: duplication_account_invoice +#: model:ir.model.fields,field_description:duplication_account_invoice.field_account_invoice_duplication_wizard__create_date +#: model:ir.model.fields,field_description:duplication_account_invoice.field_account_invoice_duplication_wizard_date_line__create_date +msgid "Created on" +msgstr "Créé le" + +#. module: duplication_account_invoice +#: model:ir.model.fields,field_description:duplication_account_invoice.field_account_invoice_duplication_wizard__display_name +#: model:ir.model.fields,field_description:duplication_account_invoice.field_account_invoice_duplication_wizard_date_line__display_name +msgid "Display Name" +msgstr "Nom affiché" + +#. module: duplication_account_invoice +#: model:ir.model.fields,field_description:duplication_account_invoice.field_account_invoice_duplication_wizard_date_line__date_due +msgid "Due Date" +msgstr "Date d'échéance" + +#. module: duplication_account_invoice +#: model:ir.model.fields,field_description:duplication_account_invoice.field_account_invoice_duplication_wizard__date_due_duration +msgid "Due Date Duration" +msgstr "Durée avant l'échéance" + +#. module: duplication_account_invoice +#: model_terms:ir.ui.view,arch_db:duplication_account_invoice.view_account_invoice_duplication_wizard_form +msgid "Duplicate" +msgstr "Dupliquer" + +#. module: duplication_account_invoice +#: model_terms:ir.ui.view,arch_db:duplication_account_invoice.view_account_invoice_duplication_wizard_form +msgid "Duplicate and Open" +msgstr "Dupliquer et Ouvrir" + +#. module: duplication_account_invoice +#: model:ir.model.fields,field_description:duplication_account_invoice.field_account_invoice_duplication_wizard__duplication_duration +msgid "Duplication Duration" +msgstr "Durée de la duplication" + +#. module: duplication_account_invoice +#: model:ir.model.fields,field_description:duplication_account_invoice.field_account_invoice_duplication_wizard__duplication_type +msgid "Duplication Type" +msgstr "Type de duplication" + +#. module: duplication_account_invoice +#: model:ir.actions.act_window,name:duplication_account_invoice.action_account_invoice_duplication_wizard +msgid "Duplication Wizard" +msgstr "Assistant de duplication" + +#. module: duplication_account_invoice +#: model:ir.model.fields,field_description:duplication_account_invoice.field_account_invoice_duplication_wizard__id +#: model:ir.model.fields,field_description:duplication_account_invoice.field_account_invoice_duplication_wizard_date_line__id +msgid "ID" +msgstr "ID" + +#. module: duplication_account_invoice +#: model:ir.model.fields,field_description:duplication_account_invoice.field_account_invoice_duplication_wizard__include_current_date +msgid "Include Current Date" +msgstr "Inclure la date courante" + +#. module: duplication_account_invoice +#: model:ir.model.fields,field_description:duplication_account_invoice.field_account_invoice_duplication_wizard__invoice_id +msgid "Invoice" +msgstr "Facture" + +#. module: duplication_account_invoice +#: model:ir.model.fields,field_description:duplication_account_invoice.field_account_invoice_duplication_wizard_date_line__date_invoice +msgid "Invoice Date" +msgstr "Date de facturation" + +#. module: duplication_account_invoice +#: model_terms:ir.ui.view,arch_db:duplication_account_invoice.view_account_invoice_duplication_wizard_form +msgid "Item to duplicate" +msgstr "Elément à dupliquer" + +#. module: duplication_account_invoice +#: model:ir.model.fields,field_description:duplication_account_invoice.field_account_invoice_duplication_wizard____last_update +#: model:ir.model.fields,field_description:duplication_account_invoice.field_account_invoice_duplication_wizard_date_line____last_update +msgid "Last Modified on" +msgstr "Dernière modification le" + +#. module: duplication_account_invoice +#: model:ir.model.fields,field_description:duplication_account_invoice.field_account_invoice_duplication_wizard__write_uid +#: model:ir.model.fields,field_description:duplication_account_invoice.field_account_invoice_duplication_wizard_date_line__write_uid +msgid "Last Updated by" +msgstr "Dernière mise à jour par" + +#. module: duplication_account_invoice +#: model:ir.model.fields,field_description:duplication_account_invoice.field_account_invoice_duplication_wizard__write_date +#: model:ir.model.fields,field_description:duplication_account_invoice.field_account_invoice_duplication_wizard_date_line__write_date +msgid "Last Updated on" +msgstr "Dernière mise à jour le" + +#. module: duplication_account_invoice +#: selection:account.invoice.duplication.wizard,duplication_type:0 +msgid "Monthly" +msgstr "Mensuelle" + +#. module: duplication_account_invoice +#: model:ir.model.fields,field_description:duplication_account_invoice.field_account_invoice_duplication_wizard__date_line_ids +msgid "New Dates" +msgstr "Nouvelles Dates" + +#. module: duplication_account_invoice +#: model:ir.model.fields,field_description:duplication_account_invoice.field_account_invoice_duplication_wizard__partner_id +msgid "Partner" +msgstr "Partenaire" + +#. module: duplication_account_invoice +#: model_terms:ir.ui.view,arch_db:duplication_account_invoice.view_account_invoice_duplication_wizard_form +msgid "Settings" +msgstr "Configuration" + +#. module: duplication_account_invoice +#: selection:account.invoice.duplication.wizard,duplication_type:0 +msgid "Weekly" +msgstr "Hebdomadaire" + +#. module: duplication_account_invoice +#: model:ir.model.fields,field_description:duplication_account_invoice.field_account_invoice_duplication_wizard_date_line__wizard_id +msgid "Wizard" +msgstr "Assistant" + +#. module: duplication_account_invoice +#: model:ir.model,name:duplication_account_invoice.model_account_invoice_duplication_wizard +msgid "account.invoice.duplication.wizard" +msgstr "" + +#. module: duplication_account_invoice +#: model:ir.model,name:duplication_account_invoice.model_account_invoice_duplication_wizard_date_line +msgid "account.invoice.duplication.wizard.date.line" +msgstr "" + diff --git a/duplication_account_invoice/models/__init__.py b/duplication_account_invoice/models/__init__.py new file mode 100644 index 00000000..e03e6a82 --- /dev/null +++ b/duplication_account_invoice/models/__init__.py @@ -0,0 +1,2 @@ +from . import account_invoice_duplication_wizard +from . import account_invoice_duplication_wizard_date_line diff --git a/duplication_account_invoice/models/account_invoice_duplication_wizard.py b/duplication_account_invoice/models/account_invoice_duplication_wizard.py new file mode 100644 index 00000000..95a4d7b3 --- /dev/null +++ b/duplication_account_invoice/models/account_invoice_duplication_wizard.py @@ -0,0 +1,167 @@ +# Copyright (C) 2015 - Today: GRAP (http://www.grap.coop) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# @author: Quentin DUPONT (quentin.dupont@grap.coop) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import datetime + +from dateutil.relativedelta import relativedelta + +from odoo import api, fields, models + + +class AccountInvoiceDuplicationWizard(models.TransientModel): + _name = "account.invoice.duplication.wizard" + _description = "Account Invoice Duplication Wizard" + + _DUPLICATION_TYPE_KEYS = [ + ("week", "Weekly"), + ("month", "Monthly"), + ] + + invoice_id = fields.Many2one( + comodel_name="account.invoice", + string="Invoice", + readonly=True, + default=lambda s: s._default_invoice_id(), + ) + + partner_id = fields.Many2one( + comodel_name="res.partner", + string="Partner", + readonly=True, + default=lambda s: s._default_partner_id(), + ) + + begin_date = fields.Date( + string="Begin Date", required=True, default=lambda s: s._default_begin_date() + ) + + include_current_date = fields.Boolean(string="Include Current Date", default=False) + + duplication_type = fields.Selection( + selection=_DUPLICATION_TYPE_KEYS, + string="Duplication Type", + default="month", + required=True, + ) + + duplication_duration = fields.Integer( + string="Duplication Duration", required=True, default=0 + ) + + date_line_ids = fields.One2many( + comodel_name="account.invoice.duplication.wizard.date.line", + inverse_name="wizard_id", + string="New Dates", + ) + + date_due_duration = fields.Integer( + string="Due Date Duration", + required=True, + default=lambda s: s._default_date_due_duration(), + ) + + # Default Section + @api.model + def _default_invoice_id(self): + return self.env.context.get("active_id", False) + + @api.model + def _default_partner_id(self): + invoice_obj = self.env["account.invoice"] + invoice_id = self.env.context.get("active_id", False) + if not invoice_id: + return False + else: + return invoice_obj.browse(invoice_id).partner_id + + @api.model + def _default_begin_date(self): + invoice_obj = self.env["account.invoice"] + invoice_id = self.env.context.get("active_id", False) + if not invoice_id: + return False + else: + return invoice_obj.browse(invoice_id).date_invoice + + @api.model + def _default_date_due_duration(self): + invoice_obj = self.env["account.invoice"] + invoice_id = self.env.context.get("active_id", False) + if invoice_id: + invoice = invoice_obj.browse(invoice_id) + if invoice.date_due and invoice.date_invoice: + return (invoice.date_due - invoice.date_invoice).days + return 0 + + # View Section + @api.onchange( + "begin_date", + "duplication_type", + "duplication_duration", + "include_current_date", + "date_due_duration", + ) + def onchange_duplication_settings(self): + self.ensure_one() + self.date_line_ids = [] + + if self.begin_date and self.duplication_type and self.duplication_duration: + date_line_ids = [] + date_line_ids.append((5, 0, 0)) + begin_index = 0 + end_index = self.duplication_duration + if not self.include_current_date: + begin_index += 1 + end_index += 1 + for i in range(begin_index, end_index): + if self.duplication_type == "week": + date_invoice = self.begin_date + datetime.timedelta(weeks=i) + else: + date_invoice = self.begin_date + relativedelta(months=i) + date_due = date_invoice + datetime.timedelta( + days=self.date_due_duration + ) + date_line_ids.append( + ( + 0, + 0, + { + "date_invoice": date_invoice, + "date_due": date_due, + }, + ) + ) + self.date_line_ids = date_line_ids + + def duplicate_button(self): + self._duplicate() + return True + + def duplicate_open_button(self): + invoice_ids = self._duplicate() + if self.invoice_id.type == "out_invoice": + result = self.env.ref("account.action_invoice_tree1").read()[0] + elif self.invoice_id.type == "out_refund": + result = self.env.ref("account.action_invoice_tree3").read()[0] + elif self.invoice_id.type == "in_invoice": + result = self.env.ref("account.action_invoice_tree2").read()[0] + elif self.invoice_id.type == "in_refund": + result = self.env.ref("account.action_invoice_tree4").read()[0] + result["domain"] = "[('id', 'in', [" + ",".join(map(str, invoice_ids)) + "])]" + return result + + def _duplicate(self): + self.ensure_one() + invoice_ids = [] + for date_line in self.date_line_ids: + invoice_ids.append( + self.invoice_id.copy( + default={ + "date_invoice": date_line.date_invoice, + "date_due": date_line.date_due, + } + ).id + ) + return invoice_ids diff --git a/duplication_account_invoice/models/account_invoice_duplication_wizard_date_line.py b/duplication_account_invoice/models/account_invoice_duplication_wizard_date_line.py new file mode 100644 index 00000000..42ad73f6 --- /dev/null +++ b/duplication_account_invoice/models/account_invoice_duplication_wizard_date_line.py @@ -0,0 +1,16 @@ +# Copyright (C) 2015 - Today: GRAP (http://www.grap.coop) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import fields, models + + +class AccountInvoiceDuplicationWizardDateLine(models.TransientModel): + _name = "account.invoice.duplication.wizard.date.line" + _description = "Account Invoice Duplication Wizard Line" + + wizard_id = fields.Many2one(comodel_name="account.invoice.duplication.wizard") + + date_invoice = fields.Date(string="Invoice Date", required=True) + + date_due = fields.Date(string="Due Date", required=True) diff --git a/duplication_account_invoice/readme/CONTRIBUTORS.rst b/duplication_account_invoice/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000..e1525ce0 --- /dev/null +++ b/duplication_account_invoice/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +* Sylvain LE GAL (https://www.twitter.com/legalsylvain) diff --git a/duplication_account_invoice/readme/DESCRIPTION.rst b/duplication_account_invoice/readme/DESCRIPTION.rst new file mode 100644 index 00000000..619f97d3 --- /dev/null +++ b/duplication_account_invoice/readme/DESCRIPTION.rst @@ -0,0 +1,9 @@ +This module extends the functionality of Account Module to provide a wizard to +duplicate a given Account Invoice. + +User can define: + +* a begin date +* a frequency (week, ...) +* a recurring quantity +* a duration for the due date diff --git a/duplication_account_invoice/readme/ROADMAP.rst b/duplication_account_invoice/readme/ROADMAP.rst new file mode 100644 index 00000000..e4469053 --- /dev/null +++ b/duplication_account_invoice/readme/ROADMAP.rst @@ -0,0 +1,2 @@ +Change the field due_date_duration in the wizard by the selection of a +``account.payment.term`` diff --git a/duplication_account_invoice/readme/USAGE.rst b/duplication_account_invoice/readme/USAGE.rst new file mode 100644 index 00000000..996300a1 --- /dev/null +++ b/duplication_account_invoice/readme/USAGE.rst @@ -0,0 +1,7 @@ +To use this module, you need to + +* go to Invoices / (Customer / Supplier ) Invoices + +* Select any invoice and click on 'More' / 'Duplication Wizard' + +.. figure:: ../static/description/account_invoice_duplication_wizard_form.png diff --git a/duplication_account_invoice/static/description/account_invoice_duplication_wizard_form.png b/duplication_account_invoice/static/description/account_invoice_duplication_wizard_form.png new file mode 100644 index 00000000..c8ca9a2d Binary files /dev/null and b/duplication_account_invoice/static/description/account_invoice_duplication_wizard_form.png differ diff --git a/duplication_account_invoice/tests/__init__.py b/duplication_account_invoice/tests/__init__.py new file mode 100644 index 00000000..ce518a3b --- /dev/null +++ b/duplication_account_invoice/tests/__init__.py @@ -0,0 +1 @@ +from . import test_duplication_account_invoice diff --git a/duplication_account_invoice/tests/test_duplication_account_invoice.py b/duplication_account_invoice/tests/test_duplication_account_invoice.py new file mode 100644 index 00000000..99697b8b --- /dev/null +++ b/duplication_account_invoice/tests/test_duplication_account_invoice.py @@ -0,0 +1,38 @@ +# Copyright (C) 2018 - Today: GRAP (http://www.grap.coop) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# @author: Quentin DUPONT (quentin.dupont@grap.coop) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo.tests.common import TransactionCase + + +class TestDuplicationAccountInvoice(TransactionCase): + """Tests for 'Duplication Tools - Account Invoice' Module""" + + def setUp(self): + super(TestDuplicationAccountInvoice, self).setUp() + self.wizard_obj = self.env["account.invoice.duplication.wizard"] + self.invoice_obj = self.env["account.invoice"] + self.invoice = self.env.ref("l10n_generic_coa.demo_invoice_1") + + # Test Section + def test_01_duplicate_account_invoice(self): + invoice_qty = len(self.invoice_obj.search([])) + wizard = self.wizard_obj.create( + { + "invoice_id": self.invoice.id, + "partner_id": self.invoice.partner_id.id, + "begin_date": "09-09-2019", + "include_current_date": False, + "duplication_type": "week", + "duplication_duration": 10, + } + ) + wizard.onchange_duplication_settings() + wizard.duplicate_open_button() + new_invoice_qty = len(self.invoice_obj.search([])) + self.assertEqual( + invoice_qty + 10, + new_invoice_qty, + "Duplication wizard should create new account invoices", + ) diff --git a/duplication_account_invoice/views/action.xml b/duplication_account_invoice/views/action.xml new file mode 100644 index 00000000..9e0ccba5 --- /dev/null +++ b/duplication_account_invoice/views/action.xml @@ -0,0 +1,18 @@ + + + + + + Duplication Wizard + account.invoice.duplication.wizard + form + new + + + + diff --git a/duplication_account_invoice/views/view_account_invoice_duplication_wizard.xml b/duplication_account_invoice/views/view_account_invoice_duplication_wizard.xml new file mode 100644 index 00000000..43e20246 --- /dev/null +++ b/duplication_account_invoice/views/view_account_invoice_duplication_wizard.xml @@ -0,0 +1,41 @@ + + + + + + account.invoice.duplication.wizard + +
+ + + + + + + + + + + + + + + + + + + + +
+
+
+ +
diff --git a/setup/duplication_account_invoice/odoo/addons/duplication_account_invoice b/setup/duplication_account_invoice/odoo/addons/duplication_account_invoice new file mode 120000 index 00000000..479808b4 --- /dev/null +++ b/setup/duplication_account_invoice/odoo/addons/duplication_account_invoice @@ -0,0 +1 @@ +../../../../duplication_account_invoice \ No newline at end of file diff --git a/setup/duplication_account_invoice/setup.py b/setup/duplication_account_invoice/setup.py new file mode 100644 index 00000000..28c57bb6 --- /dev/null +++ b/setup/duplication_account_invoice/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)