diff --git a/sale_invoice_blocking/README.rst b/sale_invoice_blocking/README.rst new file mode 100644 index 00000000000..63f277115be --- /dev/null +++ b/sale_invoice_blocking/README.rst @@ -0,0 +1,97 @@ +===================== +Sale Invoice Blocking +===================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:781eff8b4be5e835be8d050afe7c26cc9131440c9056d3ed8663984b07f51345 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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-OCA%2Fsale--workflow-lightgray.png?logo=github + :target: https://github.com/OCA/sale-workflow/tree/17.0/sale_invoice_blocking + :alt: OCA/sale-workflow +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/sale-workflow-17-0/sale-workflow-17-0-sale_invoice_blocking + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/sale-workflow&target_branch=17.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module extends the functionality of sales to allow you to block the +creation of invoices from a sales order and give a reason. + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +To configure this module, you need to: + +1. Go to 'Sales > Configuration > Sales Orders > Invoicing block + reasons'. +2. Create the different reasons that can lead to block the invoices of a + sales order. + +Usage +===== + +To use this module, you need to: + +1. Create a new sale order and provide a 'Blocking for invoicing'. +2. When you try to create Regular Invoice if an invoicing blocking + reason is set on the sale order. It will show blocking reasons. + +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 +------- + +* Camptocamp + +Contributors +------------ + +- Damien Crier +- Dhara Solanki + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/sale-workflow `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/sale_invoice_blocking/__init__.py b/sale_invoice_blocking/__init__.py new file mode 100644 index 00000000000..4b76c7b2d5c --- /dev/null +++ b/sale_invoice_blocking/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from . import models diff --git a/sale_invoice_blocking/__manifest__.py b/sale_invoice_blocking/__manifest__.py new file mode 100644 index 00000000000..ab29bafb8b3 --- /dev/null +++ b/sale_invoice_blocking/__manifest__.py @@ -0,0 +1,21 @@ +# Copyright 2021 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +{ + "name": "Sale Invoice Blocking", + "summary": "Allow you to block the creation of invoices from a sale order.", + "version": "17.0.1.0.0", + "author": "Camptocamp, " "Odoo Community Association (OCA)", + "website": "https://github.com/OCA/sale-workflow", + "category": "Sales", + "depends": ["sale", "sales_team"], + "data": [ + "security/ir.model.access.csv", + "views/sale_invoice_blocking_reason_view.xml", + "views/sale_order.xml", + "views/menus.xml", + ], + "license": "AGPL-3", + "installable": True, + "application": False, +} diff --git a/sale_invoice_blocking/i18n/ca.po b/sale_invoice_blocking/i18n/ca.po new file mode 100644 index 00000000000..3f37addf901 --- /dev/null +++ b/sale_invoice_blocking/i18n/ca.po @@ -0,0 +1,98 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * sale_invoice_blocking +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2021-11-22 10:36+0000\n" +"Last-Translator: jabelchi \n" +"Language-Team: none\n" +"Language: ca\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.3.2\n" + +#. module: sale_invoice_blocking +#: code:addons/sale_invoice_blocking/models/sale_order.py:0 +#, python-format +msgid "" +"\n" +"- You may have an invoice blocking reason on the sale order\n" +" " +msgstr "" +"\n" +"- Cal que tingueu un motiu de bloqueig a la comanda de venda\n" +" " + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_sale_order__invoice_blocking_reason_id +msgid "Blocking for invoicing" +msgstr "Bloqueig de facturació" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason__create_uid +msgid "Created by" +msgstr "Creat per" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason__create_date +msgid "Created on" +msgstr "Creat el" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason__display_name +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_sale_order__display_name +msgid "Display Name" +msgstr "Nom a mostrar" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason__id +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_sale_order__id +msgid "ID" +msgstr "ID" + +#. module: sale_invoice_blocking +#: model:ir.actions.act_window,name:sale_invoice_blocking.invoice_blocking_reason_action +#: model:ir.ui.menu,name:sale_invoice_blocking.menu_invoice_blocking_reason +msgid "Invoicing block reasons" +msgstr "Motius de bloqueig de facturació" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason____last_update +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_sale_order____last_update +msgid "Last Modified on" +msgstr "Darrera modificació el" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason__write_uid +msgid "Last Updated by" +msgstr "Darrera actualització per" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason__write_date +msgid "Last Updated on" +msgstr "Darrera actualització el" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason__name +msgid "Reason" +msgstr "Motiu" + +#. module: sale_invoice_blocking +#: model:ir.model,name:sale_invoice_blocking.model_invoice_blocking_reason +msgid "Sale invoice blocking reason" +msgstr "Motiu de bloqueig de facturació" + +#. module: sale_invoice_blocking +#: model:ir.model,name:sale_invoice_blocking.model_sale_order +msgid "Sales Order" +msgstr "Comanda de venda" + +#. module: sale_invoice_blocking +#: model:ir.model.constraint,message:sale_invoice_blocking.constraint_invoice_blocking_reason_name_uniq +msgid "You cannot have two invoice blocking reasons with the same name." +msgstr "No podeu tenir dos motius de bloqueig amb el mateix nom." diff --git a/sale_invoice_blocking/i18n/es.po b/sale_invoice_blocking/i18n/es.po new file mode 100644 index 00000000000..45eff2ca921 --- /dev/null +++ b/sale_invoice_blocking/i18n/es.po @@ -0,0 +1,98 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * sale_invoice_blocking +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2021-11-22 10:36+0000\n" +"Last-Translator: jabelchi \n" +"Language-Team: none\n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.3.2\n" + +#. module: sale_invoice_blocking +#: code:addons/sale_invoice_blocking/models/sale_order.py:0 +#, python-format +msgid "" +"\n" +"- You may have an invoice blocking reason on the sale order\n" +" " +msgstr "" +"\n" +"- Debe tener un motivo de bloqueo en el pedido de venta\n" +" " + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_sale_order__invoice_blocking_reason_id +msgid "Blocking for invoicing" +msgstr "Bloqueo de facturación" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason__create_uid +msgid "Created by" +msgstr "Creado por" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason__create_date +msgid "Created on" +msgstr "Creado el" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason__display_name +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_sale_order__display_name +msgid "Display Name" +msgstr "Nombre a mostrar" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason__id +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_sale_order__id +msgid "ID" +msgstr "ID" + +#. module: sale_invoice_blocking +#: model:ir.actions.act_window,name:sale_invoice_blocking.invoice_blocking_reason_action +#: model:ir.ui.menu,name:sale_invoice_blocking.menu_invoice_blocking_reason +msgid "Invoicing block reasons" +msgstr "Motivos de bloqueo de facturación" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason____last_update +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_sale_order____last_update +msgid "Last Modified on" +msgstr "Última modificación el" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason__write_uid +msgid "Last Updated by" +msgstr "Última actualización por" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason__write_date +msgid "Last Updated on" +msgstr "Última actualización el" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason__name +msgid "Reason" +msgstr "Motivo" + +#. module: sale_invoice_blocking +#: model:ir.model,name:sale_invoice_blocking.model_invoice_blocking_reason +msgid "Sale invoice blocking reason" +msgstr "Motivo de bloqueo de facturación" + +#. module: sale_invoice_blocking +#: model:ir.model,name:sale_invoice_blocking.model_sale_order +msgid "Sales Order" +msgstr "Pedido de venta" + +#. module: sale_invoice_blocking +#: model:ir.model.constraint,message:sale_invoice_blocking.constraint_invoice_blocking_reason_name_uniq +msgid "You cannot have two invoice blocking reasons with the same name." +msgstr "No puede tener dos motivos de bloqueo con el mismo nombre." diff --git a/sale_invoice_blocking/i18n/es_PA.po b/sale_invoice_blocking/i18n/es_PA.po new file mode 100644 index 00000000000..a29b666399f --- /dev/null +++ b/sale_invoice_blocking/i18n/es_PA.po @@ -0,0 +1,93 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * sale_invoice_blocking +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: es_PA\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#. module: sale_invoice_blocking +#: code:addons/sale_invoice_blocking/models/sale_order.py:0 +#, python-format +msgid "" +"\n" +"- You may have an invoice blocking reason on the sale order\n" +" " +msgstr "" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_sale_order__invoice_blocking_reason_id +msgid "Blocking for invoicing" +msgstr "" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason__create_uid +msgid "Created by" +msgstr "" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason__create_date +msgid "Created on" +msgstr "" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason__display_name +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_sale_order__display_name +msgid "Display Name" +msgstr "" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason__id +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_sale_order__id +msgid "ID" +msgstr "" + +#. module: sale_invoice_blocking +#: model:ir.actions.act_window,name:sale_invoice_blocking.invoice_blocking_reason_action +#: model:ir.ui.menu,name:sale_invoice_blocking.menu_invoice_blocking_reason +msgid "Invoicing block reasons" +msgstr "" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason____last_update +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_sale_order____last_update +msgid "Last Modified on" +msgstr "" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason__write_date +msgid "Last Updated on" +msgstr "" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason__name +msgid "Reason" +msgstr "" + +#. module: sale_invoice_blocking +#: model:ir.model,name:sale_invoice_blocking.model_invoice_blocking_reason +msgid "Sale invoice blocking reason" +msgstr "" + +#. module: sale_invoice_blocking +#: model:ir.model,name:sale_invoice_blocking.model_sale_order +msgid "Sales Order" +msgstr "" + +#. module: sale_invoice_blocking +#: model:ir.model.constraint,message:sale_invoice_blocking.constraint_invoice_blocking_reason_name_uniq +msgid "You cannot have two invoice blocking reasons with the same name." +msgstr "" diff --git a/sale_invoice_blocking/i18n/fr.po b/sale_invoice_blocking/i18n/fr.po new file mode 100644 index 00000000000..f90d231a706 --- /dev/null +++ b/sale_invoice_blocking/i18n/fr.po @@ -0,0 +1,100 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * sale_invoice_blocking +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0+e\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-05-25 07:02+0000\n" +"PO-Revision-Date: 2021-05-25 07:02+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: sale_invoice_blocking +#: code:addons/sale_invoice_blocking/models/sale_order.py:0 +#, python-format +msgid "" +"\n" +"- You may have an invoice blocking reason on the sale order\n" +" " +msgstr "" +"\n" +"- Vous avez un motif de blocage de la facturation sur le bon de commande\n" +" " + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_sale_order__invoice_blocking_reason_id +msgid "Blocking for invoicing" +msgstr "Blocage pour facturation" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason__create_uid +msgid "Created by" +msgstr "Créé par" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason__create_date +msgid "Created on" +msgstr "Créé le" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason__display_name +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_sale_order__display_name +msgid "Display Name" +msgstr "Nom affiché" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason__id +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_sale_order__id +msgid "ID" +msgstr "" + +#. module: sale_invoice_blocking +#: model:ir.actions.act_window,name:sale_invoice_blocking.invoice_blocking_reason_action +#: model:ir.ui.menu,name:sale_invoice_blocking.menu_invoice_blocking_reason +msgid "Invoicing block reasons" +msgstr "Motifs de blocage de la facturation" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason____last_update +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_sale_order____last_update +msgid "Last Modified on" +msgstr "Dernière modification le" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason__write_uid +msgid "Last Updated by" +msgstr "Dernière modification par" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason__write_date +msgid "Last Updated on" +msgstr "Dernière modification le" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason__name +msgid "Reason" +msgstr "Motif" + +#. module: sale_invoice_blocking +#: model:ir.model,name:sale_invoice_blocking.model_invoice_blocking_reason +msgid "Sale invoice blocking reason" +msgstr "Motif de blocage de la facturation" + +#. module: sale_invoice_blocking +#: model:ir.model,name:sale_invoice_blocking.model_sale_order +msgid "Sales Order" +msgstr "Bon de commande" + +#. module: sale_invoice_blocking +#: model:ir.model.constraint,message:sale_invoice_blocking.constraint_invoice_blocking_reason_name_uniq +msgid "You cannot have two invoice blocking reasons with the same name." +msgstr "" +"Vous ne pouvez pas avoir deux motifs de blocage de facturation avec le même " +"nom." diff --git a/sale_invoice_blocking/i18n/sale_invoice_blocking.pot b/sale_invoice_blocking/i18n/sale_invoice_blocking.pot new file mode 100644 index 00000000000..7e734bdab87 --- /dev/null +++ b/sale_invoice_blocking/i18n/sale_invoice_blocking.pot @@ -0,0 +1,89 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * sale_invoice_blocking +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 15.0\n" +"Report-Msgid-Bugs-To: \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: sale_invoice_blocking +#: code:addons/sale_invoice_blocking/models/sale_order.py:0 +#, python-format +msgid "" +"\n" +"- You may have an invoice blocking reason on the sale order\n" +" " +msgstr "" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_sale_order__invoice_blocking_reason_id +msgid "Blocking for invoicing" +msgstr "" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason__create_uid +msgid "Created by" +msgstr "" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason__create_date +msgid "Created on" +msgstr "" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason__display_name +msgid "Display Name" +msgstr "" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason__id +msgid "ID" +msgstr "" + +#. module: sale_invoice_blocking +#: model:ir.actions.act_window,name:sale_invoice_blocking.invoice_blocking_reason_action +#: model:ir.ui.menu,name:sale_invoice_blocking.menu_invoice_blocking_reason +msgid "Invoicing block reasons" +msgstr "" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason____last_update +msgid "Last Modified on" +msgstr "" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason__write_date +msgid "Last Updated on" +msgstr "" + +#. module: sale_invoice_blocking +#: model:ir.model.fields,field_description:sale_invoice_blocking.field_invoice_blocking_reason__name +msgid "Reason" +msgstr "" + +#. module: sale_invoice_blocking +#: model:ir.model,name:sale_invoice_blocking.model_invoice_blocking_reason +msgid "Sale invoice blocking reason" +msgstr "" + +#. module: sale_invoice_blocking +#: model:ir.model,name:sale_invoice_blocking.model_sale_order +msgid "Sales Order" +msgstr "" + +#. module: sale_invoice_blocking +#: model:ir.model.constraint,message:sale_invoice_blocking.constraint_invoice_blocking_reason_name_uniq +msgid "You cannot have two invoice blocking reasons with the same name." +msgstr "" diff --git a/sale_invoice_blocking/models/__init__.py b/sale_invoice_blocking/models/__init__.py new file mode 100644 index 00000000000..68cd748692a --- /dev/null +++ b/sale_invoice_blocking/models/__init__.py @@ -0,0 +1,2 @@ +from . import invoice_blocking_reason +from . import sale_order diff --git a/sale_invoice_blocking/models/invoice_blocking_reason.py b/sale_invoice_blocking/models/invoice_blocking_reason.py new file mode 100644 index 00000000000..60b8a5a8b7d --- /dev/null +++ b/sale_invoice_blocking/models/invoice_blocking_reason.py @@ -0,0 +1,18 @@ +# Copyright 2021 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from odoo import fields, models + + +class InvoiceBlockingReason(models.Model): + _name = "invoice.blocking.reason" + _description = "Sale invoice blocking reason" + + name = fields.Char(string="Reason", required=True) + + _sql_constraints = [ + ( + "name_uniq", + "unique (name)", + "You cannot have two invoice blocking reasons with the same name.", + ) + ] diff --git a/sale_invoice_blocking/models/sale_order.py b/sale_invoice_blocking/models/sale_order.py new file mode 100644 index 00000000000..af7bc047991 --- /dev/null +++ b/sale_invoice_blocking/models/sale_order.py @@ -0,0 +1,36 @@ +# Copyright 2021 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from odoo import _, api, fields, models +from odoo.exceptions import UserError + + +class SaleOrder(models.Model): + _inherit = "sale.order" + + invoice_blocking_reason_id = fields.Many2one( + "invoice.blocking.reason", + string="Blocking for invoicing", + ) + + @api.depends("invoice_blocking_reason_id", "state", "order_line.invoice_status") + def _compute_invoice_status(self): + res = super()._compute_invoice_status() + for order in self.filtered( + lambda order: order.invoice_blocking_reason_id + and order.state in ("sale", "done") + ): + order.invoice_status = "no" + return res + + def _get_invoiceable_lines(self, final=False): + """Return the invoiceable lines for order `self`.""" + if self.invoice_blocking_reason_id: + return self.env["sale.order.line"] + + return super()._get_invoiceable_lines(final=final) + + def _nothing_to_invoice_error_message(self): + error = super()._nothing_to_invoice_error_message() + error += _("\n- You may have an invoice blocking reason on the sale order") + + return UserError(error) diff --git a/sale_invoice_blocking/pyproject.toml b/sale_invoice_blocking/pyproject.toml new file mode 100644 index 00000000000..4231d0cccb3 --- /dev/null +++ b/sale_invoice_blocking/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/sale_invoice_blocking/readme/CONFIGURE.md b/sale_invoice_blocking/readme/CONFIGURE.md new file mode 100644 index 00000000000..3541d4942f4 --- /dev/null +++ b/sale_invoice_blocking/readme/CONFIGURE.md @@ -0,0 +1,6 @@ +To configure this module, you need to: + +1. Go to 'Sales \> Configuration \> Sales Orders \> Invoicing block + reasons'. +2. Create the different reasons that can lead to block the invoices of + a sales order. diff --git a/sale_invoice_blocking/readme/CONTRIBUTORS.md b/sale_invoice_blocking/readme/CONTRIBUTORS.md new file mode 100644 index 00000000000..c18189e6c0c --- /dev/null +++ b/sale_invoice_blocking/readme/CONTRIBUTORS.md @@ -0,0 +1,2 @@ +- Damien Crier \<\> +- Dhara Solanki \<\> diff --git a/sale_invoice_blocking/readme/DESCRIPTION.md b/sale_invoice_blocking/readme/DESCRIPTION.md new file mode 100644 index 00000000000..c25877f181f --- /dev/null +++ b/sale_invoice_blocking/readme/DESCRIPTION.md @@ -0,0 +1,2 @@ +This module extends the functionality of sales to allow you to block the +creation of invoices from a sales order and give a reason. diff --git a/sale_invoice_blocking/readme/USAGE.md b/sale_invoice_blocking/readme/USAGE.md new file mode 100644 index 00000000000..80e31984d1c --- /dev/null +++ b/sale_invoice_blocking/readme/USAGE.md @@ -0,0 +1,5 @@ +To use this module, you need to: + +1. Create a new sale order and provide a 'Blocking for invoicing'. +2. When you try to create Regular Invoice if an invoicing blocking + reason is set on the sale order. It will show blocking reasons. diff --git a/sale_invoice_blocking/security/ir.model.access.csv b/sale_invoice_blocking/security/ir.model.access.csv new file mode 100644 index 00000000000..4fc4dc61ca2 --- /dev/null +++ b/sale_invoice_blocking/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_invoice_blocking_reason_base_user,invoice_blocking_reason base user,model_invoice_blocking_reason,base.group_user,1,0,0,0 +access_invoice_blocking_reason_system,invoice_blocking_reason system,model_invoice_blocking_reason,sales_team.group_sale_manager,1,1,1,1 diff --git a/sale_invoice_blocking/static/description/icon.png b/sale_invoice_blocking/static/description/icon.png new file mode 100644 index 00000000000..3a0328b516c Binary files /dev/null and b/sale_invoice_blocking/static/description/icon.png differ diff --git a/sale_invoice_blocking/static/description/index.html b/sale_invoice_blocking/static/description/index.html new file mode 100644 index 00000000000..b6b38b97521 --- /dev/null +++ b/sale_invoice_blocking/static/description/index.html @@ -0,0 +1,446 @@ + + + + + +Sale Invoice Blocking + + + +
+

Sale Invoice Blocking

+ + +

Beta License: AGPL-3 OCA/sale-workflow Translate me on Weblate Try me on Runboat

+

This module extends the functionality of sales to allow you to block the +creation of invoices from a sales order and give a reason.

+

Table of contents

+ +
+

Configuration

+

To configure this module, you need to:

+
    +
  1. Go to ‘Sales > Configuration > Sales Orders > Invoicing block +reasons’.
  2. +
  3. Create the different reasons that can lead to block the invoices of a +sales order.
  4. +
+
+
+

Usage

+

To use this module, you need to:

+
    +
  1. Create a new sale order and provide a ‘Blocking for invoicing’.
  2. +
  3. When you try to create Regular Invoice if an invoicing blocking +reason is set on the sale order. It will show blocking reasons.
  4. +
+
+
+

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

+
    +
  • Camptocamp
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/sale-workflow project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/sale_invoice_blocking/tests/__init__.py b/sale_invoice_blocking/tests/__init__.py new file mode 100644 index 00000000000..b9f4f52a001 --- /dev/null +++ b/sale_invoice_blocking/tests/__init__.py @@ -0,0 +1 @@ +from . import test_sale_invoice_blocking diff --git a/sale_invoice_blocking/tests/test_sale_invoice_blocking.py b/sale_invoice_blocking/tests/test_sale_invoice_blocking.py new file mode 100644 index 00000000000..63ac672b1ea --- /dev/null +++ b/sale_invoice_blocking/tests/test_sale_invoice_blocking.py @@ -0,0 +1,82 @@ +from psycopg2.errors import UniqueViolation + +from odoo.exceptions import UserError +from odoo.tests.common import TransactionCase, mute_logger + + +class TestSaleInvoiceBlocking(TransactionCase): + def setUp(self): + super().setUp() + self.sale_order_model = self.env["sale.order"] + self.sale_order_line_model = self.env["sale.order.line"] + + # Data + product_ctg = self._create_product_category() + self.service_1 = self._create_product("test_product1", product_ctg) + self.service_2 = self._create_product("test_product2", product_ctg) + self.customer = self._create_customer("Test Customer") + + def _create_customer(self, name): + """Create a Partner.""" + return self.env["res.partner"].create( + {"name": name, "email": "example@yourcompany.com", "phone": 123456} + ) + + def _create_product_category(self): + product_ctg = self.env["product.category"].create({"name": "test_product_ctg"}) + return product_ctg + + def _create_product(self, name, product_ctg): + product = self.env["product.product"].create( + { + "name": name, + "categ_id": product_ctg.id, + "type": "service", + "invoice_policy": "order", + } + ) + return product + + @mute_logger("odoo.sql_db") + def test_duplicate_reason(self): + self.env["invoice.blocking.reason"].create({"name": "Test Reason"}) + with self.assertRaises(UniqueViolation): + self.env["invoice.blocking.reason"].create({"name": "Test Reason"}) + + def test_sales_order_invoicing(self): + so = self.sale_order_model.create({"partner_id": self.customer.id}) + sol1 = self.sale_order_line_model.create( + {"product_id": self.service_1.id, "product_uom_qty": 1, "order_id": so.id} + ) + sol2 = self.sale_order_line_model.create( + {"product_id": self.service_2.id, "product_uom_qty": 2, "order_id": so.id} + ) + + # confirm quotation + so.action_confirm() + # update quantities delivered + sol1.qty_delivered = 1 + sol2.qty_delivered = 2 + + self.assertEqual( + so.invoice_status, "to invoice", "The invoice status should be To Invoice" + ) + + so.invoice_blocking_reason_id = self.env["invoice.blocking.reason"].create( + {"name": "Test Reason"} + ) + + self.assertEqual( + so.invoice_status, "no", "The invoice status should be Nothing to Invoice" + ) + + with self.assertRaisesRegex( + UserError, "Cannot create an invoice. No items are available to invoice" + ): + so._create_invoices() + + so.invoice_blocking_reason_id = False + self.assertEqual( + so.invoice_status, "to invoice", "The invoice status should be To Invoice" + ) + so._create_invoices() diff --git a/sale_invoice_blocking/views/menus.xml b/sale_invoice_blocking/views/menus.xml new file mode 100644 index 00000000000..5f731a72520 --- /dev/null +++ b/sale_invoice_blocking/views/menus.xml @@ -0,0 +1,10 @@ + + + + + + diff --git a/sale_invoice_blocking/views/sale_invoice_blocking_reason_view.xml b/sale_invoice_blocking/views/sale_invoice_blocking_reason_view.xml new file mode 100644 index 00000000000..2924202e6b9 --- /dev/null +++ b/sale_invoice_blocking/views/sale_invoice_blocking_reason_view.xml @@ -0,0 +1,44 @@ + + + + + invoice.blocking.reason.search + invoice.blocking.reason + + + + + + + + invoice.blocking.reason.form + invoice.blocking.reason + +
+ + + + + +
+
+
+ + invoice.blocking.reason.list + invoice.blocking.reason + + + + + + + + Invoicing block reasons + ir.actions.act_window + invoice.blocking.reason + + + tree,form + + +
diff --git a/sale_invoice_blocking/views/sale_order.xml b/sale_invoice_blocking/views/sale_order.xml new file mode 100644 index 00000000000..6821b31df53 --- /dev/null +++ b/sale_invoice_blocking/views/sale_order.xml @@ -0,0 +1,14 @@ + + + + + sale.order + + + + + + + + +