diff --git a/base_cancel_confirm/README.rst b/base_cancel_confirm/README.rst new file mode 100644 index 0000000000..ab8a2a9555 --- /dev/null +++ b/base_cancel_confirm/README.rst @@ -0,0 +1,115 @@ +=================== +Base Cancel Confirm +=================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:9f9cb7e551816f0bbd6a68ef73c085e14a8f7eef5ade7d302c522cdd9766845a + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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%2Fserver--ux-lightgray.png?logo=github + :target: https://github.com/OCA/server-ux/tree/17.0/base_cancel_confirm + :alt: OCA/server-ux +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/server-ux-17-0/server-ux-17-0-base_cancel_confirm + :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/server-ux&target_branch=17.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +Many document model that already has cancel action may also want a +confirm dialog with option to provide reason. + +This module does not provide a functionality by itself but an abstract +model to easily implement a confirm with reason wizard when cancel +button is clicked. If reason is provided, it will be visible in form +view. + +**Note:** To be able to use this module in a new model you will need +some development. + +You can see implementation example as followings, + +- `sale_cancel_confirm `__ +- `purchase_cancel_confirm `__ +- `purchase_request_cancel_confirm `__ +- `account_move_cancel_confirm `__ + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +By default, the cancel confirm will be disabled (to ensure no side +effect on other module unit test) + +To enable cancel confirm wizard, please add System Parameter +(ir.config_parameter) for each extended module. + +For example, + +- sale_cancel_confirm, add sale.order.cancel_confirm_disable = False +- purchase_cancel_confirm, add purchase.order.cancel_confirm_disable = + False + +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 +------- + +* Ecosoft + +Contributors +------------ + +- Kitti U. + +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. + +.. |maintainer-kittiu| image:: https://github.com/kittiu.png?size=40px + :target: https://github.com/kittiu + :alt: kittiu + +Current `maintainer `__: + +|maintainer-kittiu| + +This module is part of the `OCA/server-ux `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/base_cancel_confirm/__init__.py b/base_cancel_confirm/__init__.py new file mode 100644 index 0000000000..8a240a4d67 --- /dev/null +++ b/base_cancel_confirm/__init__.py @@ -0,0 +1,5 @@ +# Copyright 2020 Ecosoft Co., Ltd. (http://ecosoft.co.th) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import wizard +from . import model diff --git a/base_cancel_confirm/__manifest__.py b/base_cancel_confirm/__manifest__.py new file mode 100644 index 0000000000..f1d269fdc7 --- /dev/null +++ b/base_cancel_confirm/__manifest__.py @@ -0,0 +1,20 @@ +# Copyright 2020 Ecosoft Co., Ltd. (http://ecosoft.co.th) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +{ + "name": "Base Cancel Confirm", + "version": "17.0.1.0.0", + "author": "Ecosoft,Odoo Community Association (OCA)", + "category": "Usability", + "license": "AGPL-3", + "website": "https://github.com/OCA/server-ux", + "depends": ["base", "web"], + "data": [ + "wizard/cancel_confirm.xml", + "security/ir.model.access.csv", + "views/cancel_confirm_template.xml", + ], + "auto_install": False, + "installable": True, + "maintainers": ["kittiu"], +} diff --git a/base_cancel_confirm/i18n/base_cancel_confirm.pot b/base_cancel_confirm/i18n/base_cancel_confirm.pot new file mode 100644 index 0000000000..5302d50feb --- /dev/null +++ b/base_cancel_confirm/i18n/base_cancel_confirm.pot @@ -0,0 +1,129 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * base_cancel_confirm +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.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: base_cancel_confirm +#: model:ir.model.fields,help:base_cancel_confirm.field_base_cancel_confirm__cancel_confirm +msgid "A flag signify that this document is confirmed for cancellation" +msgstr "" + +#. module: base_cancel_confirm +#: model:ir.model.fields,help:base_cancel_confirm.field_base_cancel_confirm__cancel_reason +msgid "An optional cancel reason" +msgstr "" + +#. module: base_cancel_confirm +#: model_terms:ir.ui.view,arch_db:base_cancel_confirm.view_cancel_confirm_wizard +msgid "Are you sure to cancel this document?" +msgstr "" + +#. module: base_cancel_confirm +#: model_terms:ir.ui.view,arch_db:base_cancel_confirm.view_cancel_confirm_wizard +msgid "Cancel" +msgstr "" + +#. module: base_cancel_confirm +#: model:ir.model,name:base_cancel_confirm.model_cancel_confirm +msgid "Cancel Confirm" +msgstr "" + +#. module: base_cancel_confirm +#: model:ir.actions.act_window,name:base_cancel_confirm.action_cancel_confirm_wizard +#: model:ir.model,name:base_cancel_confirm.model_base_cancel_confirm +#: model_terms:ir.ui.view,arch_db:base_cancel_confirm.view_cancel_confirm_wizard +msgid "Cancel Confirmation" +msgstr "" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_base_cancel_confirm__cancel_confirm +msgid "Cancel Confirmed" +msgstr "" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_base_cancel_confirm__cancel_reason +#: model:ir.model.fields,field_description:base_cancel_confirm.field_cancel_confirm__cancel_reason +msgid "Cancel Reason" +msgstr "" + +#. module: base_cancel_confirm +#. odoo-python +#: code:addons/base_cancel_confirm/model/base_cancel_confirm.py:0 +#, python-format +msgid "Configuration Error (%s), should be 'True' or 'False'" +msgstr "" + +#. module: base_cancel_confirm +#: model_terms:ir.ui.view,arch_db:base_cancel_confirm.view_cancel_confirm_wizard +msgid "Confirm" +msgstr "" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_cancel_confirm__create_uid +msgid "Created by" +msgstr "" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_cancel_confirm__create_date +msgid "Created on" +msgstr "" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_cancel_confirm__display_name +msgid "Display Name" +msgstr "" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_cancel_confirm__has_cancel_reason +msgid "Has Cancel Reason" +msgstr "" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_cancel_confirm__id +msgid "ID" +msgstr "" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_cancel_confirm____last_update +msgid "Last Modified on" +msgstr "" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_cancel_confirm__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_cancel_confirm__write_date +msgid "Last Updated on" +msgstr "" + +#. module: base_cancel_confirm +#: model:ir.model.fields.selection,name:base_cancel_confirm.selection__cancel_confirm__has_cancel_reason__no +msgid "None" +msgstr "" + +#. module: base_cancel_confirm +#: model:ir.model.fields.selection,name:base_cancel_confirm.selection__cancel_confirm__has_cancel_reason__optional +msgid "Optional" +msgstr "" + +#. module: base_cancel_confirm +#: model:ir.model.fields.selection,name:base_cancel_confirm.selection__cancel_confirm__has_cancel_reason__required +msgid "Required" +msgstr "" + +#. module: base_cancel_confirm +#: model_terms:ir.ui.view,arch_db:base_cancel_confirm.view_cancel_confirm_wizard +msgid "or" +msgstr "" diff --git a/base_cancel_confirm/i18n/es.po b/base_cancel_confirm/i18n/es.po new file mode 100644 index 0000000000..f6e99202a7 --- /dev/null +++ b/base_cancel_confirm/i18n/es.po @@ -0,0 +1,133 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * base_cancel_confirm +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2023-11-11 15:33+0000\n" +"Last-Translator: Ivorra78 \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.17\n" + +#. module: base_cancel_confirm +#: model:ir.model.fields,help:base_cancel_confirm.field_base_cancel_confirm__cancel_confirm +msgid "A flag signify that this document is confirmed for cancellation" +msgstr "" +"Una bandera significa que este documento está confirmado para su anulación" + +#. module: base_cancel_confirm +#: model:ir.model.fields,help:base_cancel_confirm.field_base_cancel_confirm__cancel_reason +msgid "An optional cancel reason" +msgstr "Un motivo de cancelación opcional" + +#. module: base_cancel_confirm +#: model_terms:ir.ui.view,arch_db:base_cancel_confirm.view_cancel_confirm_wizard +msgid "Are you sure to cancel this document?" +msgstr "¿Está seguro de cancelar este documento?" + +#. module: base_cancel_confirm +#: model_terms:ir.ui.view,arch_db:base_cancel_confirm.view_cancel_confirm_wizard +msgid "Cancel" +msgstr "Cancelar" + +#. module: base_cancel_confirm +#: model:ir.model,name:base_cancel_confirm.model_cancel_confirm +msgid "Cancel Confirm" +msgstr "Cancelar Confirmar" + +#. module: base_cancel_confirm +#: model:ir.actions.act_window,name:base_cancel_confirm.action_cancel_confirm_wizard +#: model:ir.model,name:base_cancel_confirm.model_base_cancel_confirm +#: model_terms:ir.ui.view,arch_db:base_cancel_confirm.view_cancel_confirm_wizard +msgid "Cancel Confirmation" +msgstr "Cancelar Confirmación" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_base_cancel_confirm__cancel_confirm +msgid "Cancel Confirmed" +msgstr "Cancelar Confirmado" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_base_cancel_confirm__cancel_reason +#: model:ir.model.fields,field_description:base_cancel_confirm.field_cancel_confirm__cancel_reason +msgid "Cancel Reason" +msgstr "Cancelar Razón" + +#. module: base_cancel_confirm +#. odoo-python +#: code:addons/base_cancel_confirm/model/base_cancel_confirm.py:0 +#, python-format +msgid "Configuration Error (%s), should be 'True' or 'False'" +msgstr "Error de configuración (%s), debe ser 'True' o 'False'" + +#. module: base_cancel_confirm +#: model_terms:ir.ui.view,arch_db:base_cancel_confirm.view_cancel_confirm_wizard +msgid "Confirm" +msgstr "Confirmar" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_cancel_confirm__create_uid +msgid "Created by" +msgstr "Creado por" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_cancel_confirm__create_date +msgid "Created on" +msgstr "Creado el" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_cancel_confirm__display_name +msgid "Display Name" +msgstr "Mostrar Nombre" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_cancel_confirm__has_cancel_reason +msgid "Has Cancel Reason" +msgstr "Tiene Motivo de Cancelación" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_cancel_confirm__id +msgid "ID" +msgstr "ID (identificación)" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_cancel_confirm____last_update +msgid "Last Modified on" +msgstr "Última Modifiación el" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_cancel_confirm__write_uid +msgid "Last Updated by" +msgstr "Última actualización por" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_cancel_confirm__write_date +msgid "Last Updated on" +msgstr "Última Actualización el" + +#. module: base_cancel_confirm +#: model:ir.model.fields.selection,name:base_cancel_confirm.selection__cancel_confirm__has_cancel_reason__no +msgid "None" +msgstr "Ninguno/a" + +#. module: base_cancel_confirm +#: model:ir.model.fields.selection,name:base_cancel_confirm.selection__cancel_confirm__has_cancel_reason__optional +msgid "Optional" +msgstr "Opcional" + +#. module: base_cancel_confirm +#: model:ir.model.fields.selection,name:base_cancel_confirm.selection__cancel_confirm__has_cancel_reason__required +msgid "Required" +msgstr "Requerido" + +#. module: base_cancel_confirm +#: model_terms:ir.ui.view,arch_db:base_cancel_confirm.view_cancel_confirm_wizard +msgid "or" +msgstr "o" diff --git a/base_cancel_confirm/i18n/it.po b/base_cancel_confirm/i18n/it.po new file mode 100644 index 0000000000..3f62b95552 --- /dev/null +++ b/base_cancel_confirm/i18n/it.po @@ -0,0 +1,132 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * base_cancel_confirm +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2023-12-31 19:35+0000\n" +"Last-Translator: mymage \n" +"Language-Team: none\n" +"Language: it\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.17\n" + +#. module: base_cancel_confirm +#: model:ir.model.fields,help:base_cancel_confirm.field_base_cancel_confirm__cancel_confirm +msgid "A flag signify that this document is confirmed for cancellation" +msgstr "Una spunta indica che questo documento è confermato per l'annullamento" + +#. module: base_cancel_confirm +#: model:ir.model.fields,help:base_cancel_confirm.field_base_cancel_confirm__cancel_reason +msgid "An optional cancel reason" +msgstr "Un motivo di annullamento opzionale" + +#. module: base_cancel_confirm +#: model_terms:ir.ui.view,arch_db:base_cancel_confirm.view_cancel_confirm_wizard +msgid "Are you sure to cancel this document?" +msgstr "Sicuri di annullare questo documento?" + +#. module: base_cancel_confirm +#: model_terms:ir.ui.view,arch_db:base_cancel_confirm.view_cancel_confirm_wizard +msgid "Cancel" +msgstr "Annulla" + +#. module: base_cancel_confirm +#: model:ir.model,name:base_cancel_confirm.model_cancel_confirm +msgid "Cancel Confirm" +msgstr "Annulla conferma" + +#. module: base_cancel_confirm +#: model:ir.actions.act_window,name:base_cancel_confirm.action_cancel_confirm_wizard +#: model:ir.model,name:base_cancel_confirm.model_base_cancel_confirm +#: model_terms:ir.ui.view,arch_db:base_cancel_confirm.view_cancel_confirm_wizard +msgid "Cancel Confirmation" +msgstr "Annulla conferma" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_base_cancel_confirm__cancel_confirm +msgid "Cancel Confirmed" +msgstr "Annullamento confermato" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_base_cancel_confirm__cancel_reason +#: model:ir.model.fields,field_description:base_cancel_confirm.field_cancel_confirm__cancel_reason +msgid "Cancel Reason" +msgstr "Causale annullamento" + +#. module: base_cancel_confirm +#. odoo-python +#: code:addons/base_cancel_confirm/model/base_cancel_confirm.py:0 +#, python-format +msgid "Configuration Error (%s), should be 'True' or 'False'" +msgstr "Errore configurazione (%s), deve essere 'True' o 'False'" + +#. module: base_cancel_confirm +#: model_terms:ir.ui.view,arch_db:base_cancel_confirm.view_cancel_confirm_wizard +msgid "Confirm" +msgstr "Conferma" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_cancel_confirm__create_uid +msgid "Created by" +msgstr "Creato da" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_cancel_confirm__create_date +msgid "Created on" +msgstr "Creato il" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_cancel_confirm__display_name +msgid "Display Name" +msgstr "Nome visualizzato" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_cancel_confirm__has_cancel_reason +msgid "Has Cancel Reason" +msgstr "Ha causale annullamento" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_cancel_confirm__id +msgid "ID" +msgstr "ID" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_cancel_confirm____last_update +msgid "Last Modified on" +msgstr "Ultima modifica il" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_cancel_confirm__write_uid +msgid "Last Updated by" +msgstr "Ultimo aggiornamento di" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_cancel_confirm__write_date +msgid "Last Updated on" +msgstr "Ultimo aggiornamento il" + +#. module: base_cancel_confirm +#: model:ir.model.fields.selection,name:base_cancel_confirm.selection__cancel_confirm__has_cancel_reason__no +msgid "None" +msgstr "Nessuna" + +#. module: base_cancel_confirm +#: model:ir.model.fields.selection,name:base_cancel_confirm.selection__cancel_confirm__has_cancel_reason__optional +msgid "Optional" +msgstr "Opzionale" + +#. module: base_cancel_confirm +#: model:ir.model.fields.selection,name:base_cancel_confirm.selection__cancel_confirm__has_cancel_reason__required +msgid "Required" +msgstr "Richiesta" + +#. module: base_cancel_confirm +#: model_terms:ir.ui.view,arch_db:base_cancel_confirm.view_cancel_confirm_wizard +msgid "or" +msgstr "o" diff --git a/base_cancel_confirm/i18n/nl.po b/base_cancel_confirm/i18n/nl.po new file mode 100644 index 0000000000..fc1b5423d4 --- /dev/null +++ b/base_cancel_confirm/i18n/nl.po @@ -0,0 +1,132 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * base_cancel_confirm +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2021-04-18 10:46+0000\n" +"Last-Translator: Bosd \n" +"Language-Team: none\n" +"Language: nl\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: base_cancel_confirm +#: model:ir.model.fields,help:base_cancel_confirm.field_base_cancel_confirm__cancel_confirm +msgid "A flag signify that this document is confirmed for cancellation" +msgstr "" + +#. module: base_cancel_confirm +#: model:ir.model.fields,help:base_cancel_confirm.field_base_cancel_confirm__cancel_reason +msgid "An optional cancel reason" +msgstr "" + +#. module: base_cancel_confirm +#: model_terms:ir.ui.view,arch_db:base_cancel_confirm.view_cancel_confirm_wizard +msgid "Are you sure to cancel this document?" +msgstr "" + +#. module: base_cancel_confirm +#: model_terms:ir.ui.view,arch_db:base_cancel_confirm.view_cancel_confirm_wizard +msgid "Cancel" +msgstr "Annuleer" + +#. module: base_cancel_confirm +#: model:ir.model,name:base_cancel_confirm.model_cancel_confirm +msgid "Cancel Confirm" +msgstr "" + +#. module: base_cancel_confirm +#: model:ir.actions.act_window,name:base_cancel_confirm.action_cancel_confirm_wizard +#: model:ir.model,name:base_cancel_confirm.model_base_cancel_confirm +#: model_terms:ir.ui.view,arch_db:base_cancel_confirm.view_cancel_confirm_wizard +msgid "Cancel Confirmation" +msgstr "" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_base_cancel_confirm__cancel_confirm +msgid "Cancel Confirmed" +msgstr "" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_base_cancel_confirm__cancel_reason +#: model:ir.model.fields,field_description:base_cancel_confirm.field_cancel_confirm__cancel_reason +msgid "Cancel Reason" +msgstr "Annuleringsreden" + +#. module: base_cancel_confirm +#. odoo-python +#: code:addons/base_cancel_confirm/model/base_cancel_confirm.py:0 +#, python-format +msgid "Configuration Error (%s), should be 'True' or 'False'" +msgstr "" + +#. module: base_cancel_confirm +#: model_terms:ir.ui.view,arch_db:base_cancel_confirm.view_cancel_confirm_wizard +msgid "Confirm" +msgstr "Bevestig" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_cancel_confirm__create_uid +msgid "Created by" +msgstr "Aangemaakt door" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_cancel_confirm__create_date +msgid "Created on" +msgstr "Aangemaakt op" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_cancel_confirm__display_name +msgid "Display Name" +msgstr "Weergavenaam" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_cancel_confirm__has_cancel_reason +msgid "Has Cancel Reason" +msgstr "Heeft annuleringsreden" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_cancel_confirm__id +msgid "ID" +msgstr "ID" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_cancel_confirm____last_update +msgid "Last Modified on" +msgstr "Laatst bijgewerk op" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_cancel_confirm__write_uid +msgid "Last Updated by" +msgstr "Laatst bijgewerkt door" + +#. module: base_cancel_confirm +#: model:ir.model.fields,field_description:base_cancel_confirm.field_cancel_confirm__write_date +msgid "Last Updated on" +msgstr "Laatst bijgewerkt op" + +#. module: base_cancel_confirm +#: model:ir.model.fields.selection,name:base_cancel_confirm.selection__cancel_confirm__has_cancel_reason__no +msgid "None" +msgstr "Geen" + +#. module: base_cancel_confirm +#: model:ir.model.fields.selection,name:base_cancel_confirm.selection__cancel_confirm__has_cancel_reason__optional +msgid "Optional" +msgstr "Optioneel" + +#. module: base_cancel_confirm +#: model:ir.model.fields.selection,name:base_cancel_confirm.selection__cancel_confirm__has_cancel_reason__required +msgid "Required" +msgstr "Vereist" + +#. module: base_cancel_confirm +#: model_terms:ir.ui.view,arch_db:base_cancel_confirm.view_cancel_confirm_wizard +msgid "or" +msgstr "of" diff --git a/base_cancel_confirm/model/__init__.py b/base_cancel_confirm/model/__init__.py new file mode 100644 index 0000000000..6a575eedfe --- /dev/null +++ b/base_cancel_confirm/model/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2020 Ecosoft Co., Ltd. (http://ecosoft.co.th) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import base_cancel_confirm diff --git a/base_cancel_confirm/model/base_cancel_confirm.py b/base_cancel_confirm/model/base_cancel_confirm.py new file mode 100644 index 0000000000..91c4b36991 --- /dev/null +++ b/base_cancel_confirm/model/base_cancel_confirm.py @@ -0,0 +1,76 @@ +# Copyright 2020 Ecosoft Co., Ltd. (http://ecosoft.co.th) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +import inspect + +from lxml import etree + +from odoo import _, fields, models, tools +from odoo.exceptions import ValidationError + + +class BaseCancelConfirm(models.AbstractModel): + _name = "base.cancel.confirm" + _description = "Cancel Confirmation" + + _has_cancel_reason = "no" # ["no", "optional", "required"] + _cancel_reason_xpath = "/form/sheet/group[last()]" + + cancel_confirm = fields.Boolean( + string="Cancel Confirmed", + default=lambda self: self._cancel_confirm_disabled(), + copy=False, + help="A flag signify that this document is confirmed for cancellation", + ) + cancel_reason = fields.Text( + copy=False, + help="An optional cancel reason", + ) + + def _cancel_confirm_disabled(self): + key = "%s.cancel_confirm_disable" % self._name + res = self.env["ir.config_parameter"].sudo().get_param(key) + if not res: + return True + if res not in ("True", "False"): + raise ValidationError( + _("Configuration Error (%s), should be 'True' or 'False'") % key + ) + return tools.str2bool(res) + + def open_cancel_confirm_wizard(self): + xmlid = "base_cancel_confirm.action_cancel_confirm_wizard" + action = self.env["ir.actions.act_window"]._for_xml_id(xmlid) + action["context"] = { + "cancel_res_model": self._name, + "cancel_res_ids": self.ids, + "cancel_method": inspect.stack()[1][3], + "default_has_cancel_reason": self._has_cancel_reason, + } + return action + + def clear_cancel_confirm_data(self): + self.write({"cancel_confirm": False, "cancel_reason": False}) + + def get_view(self, view_id=None, view_type="form", **options): + res = super().get_view(view_id=view_id, view_type=view_type, **options) + if view_type == "form": + doc = etree.XML(res["arch"]) + for node in doc.xpath(self._cancel_reason_xpath): + str_element = self.env["ir.qweb"]._render( + "base_cancel_confirm.cancel_reason_template" + ) + new_node = etree.fromstring(str_element) + for new_element in new_node: + node.addnext(new_element) + # Override context for postprocessing + view_env = self.env["ir.ui.view"] + if view_id: + view = view_env.search([("id", "=", view_id)]) + res["model"] = view.model if view else res["model"] + new_arch, new_fields = view_env.postprocess_and_fields(doc, self._name) + res["arch"] = new_arch + # We don't want to loose previous configuration, so, we only want to add + # the new fields + new_fields.update(res["models"]) + res["models"] = new_fields + return res diff --git a/base_cancel_confirm/pyproject.toml b/base_cancel_confirm/pyproject.toml new file mode 100644 index 0000000000..4231d0cccb --- /dev/null +++ b/base_cancel_confirm/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/base_cancel_confirm/readme/CONFIGURE.md b/base_cancel_confirm/readme/CONFIGURE.md new file mode 100644 index 0000000000..97654ecf42 --- /dev/null +++ b/base_cancel_confirm/readme/CONFIGURE.md @@ -0,0 +1,11 @@ +By default, the cancel confirm will be disabled (to ensure no side +effect on other module unit test) + +To enable cancel confirm wizard, please add System Parameter +(ir.config_parameter) for each extended module. + +For example, + +- sale_cancel_confirm, add sale.order.cancel_confirm_disable = False +- purchase_cancel_confirm, add purchase.order.cancel_confirm_disable = + False diff --git a/base_cancel_confirm/readme/CONTRIBUTORS.md b/base_cancel_confirm/readme/CONTRIBUTORS.md new file mode 100644 index 0000000000..db1787028b --- /dev/null +++ b/base_cancel_confirm/readme/CONTRIBUTORS.md @@ -0,0 +1 @@ +- Kitti U. \<\> diff --git a/base_cancel_confirm/readme/DESCRIPTION.md b/base_cancel_confirm/readme/DESCRIPTION.md new file mode 100644 index 0000000000..ddb1105444 --- /dev/null +++ b/base_cancel_confirm/readme/DESCRIPTION.md @@ -0,0 +1,17 @@ +Many document model that already has cancel action may also want a +confirm dialog with option to provide reason. + +This module does not provide a functionality by itself but an abstract +model to easily implement a confirm with reason wizard when cancel +button is clicked. If reason is provided, it will be visible in form +view. + +**Note:** To be able to use this module in a new model you will need +some development. + +You can see implementation example as followings, + +- [sale_cancel_confirm](https://github.com/OCA/sale-workflow) +- [purchase_cancel_confirm](https://github.com/OCA/purchase-workflow) +- [purchase_request_cancel_confirm](https://github.com/OCA/purchase-workflow) +- [account_move_cancel_confirm](https://github.com/OCA/account-invoicing) diff --git a/base_cancel_confirm/security/ir.model.access.csv b/base_cancel_confirm/security/ir.model.access.csv new file mode 100644 index 0000000000..b798d0c1a4 --- /dev/null +++ b/base_cancel_confirm/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_cancel_confirm,access_cancel_confirm,model_cancel_confirm,base.group_user,1,1,1,1 diff --git a/base_cancel_confirm/static/description/icon.png b/base_cancel_confirm/static/description/icon.png new file mode 100644 index 0000000000..3a0328b516 Binary files /dev/null and b/base_cancel_confirm/static/description/icon.png differ diff --git a/base_cancel_confirm/static/description/index.html b/base_cancel_confirm/static/description/index.html new file mode 100644 index 0000000000..67f07b25b1 --- /dev/null +++ b/base_cancel_confirm/static/description/index.html @@ -0,0 +1,450 @@ + + + + + +Base Cancel Confirm + + + +
+

Base Cancel Confirm

+ + +

Beta License: AGPL-3 OCA/server-ux Translate me on Weblate Try me on Runboat

+

Many document model that already has cancel action may also want a +confirm dialog with option to provide reason.

+

This module does not provide a functionality by itself but an abstract +model to easily implement a confirm with reason wizard when cancel +button is clicked. If reason is provided, it will be visible in form +view.

+

Note: To be able to use this module in a new model you will need +some development.

+

You can see implementation example as followings,

+ +

Table of contents

+ +
+

Configuration

+

By default, the cancel confirm will be disabled (to ensure no side +effect on other module unit test)

+

To enable cancel confirm wizard, please add System Parameter +(ir.config_parameter) for each extended module.

+

For example,

+
    +
  • sale_cancel_confirm, add sale.order.cancel_confirm_disable = False
  • +
  • purchase_cancel_confirm, add purchase.order.cancel_confirm_disable = +False
  • +
+
+
+

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

+
    +
  • Ecosoft
  • +
+
+ +
+

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.

+

Current maintainer:

+

kittiu

+

This module is part of the OCA/server-ux project on GitHub.

+

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

+
+
+
+ + diff --git a/base_cancel_confirm/tests/__init__.py b/base_cancel_confirm/tests/__init__.py new file mode 100644 index 0000000000..de24118a3d --- /dev/null +++ b/base_cancel_confirm/tests/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from . import test_cancel_confirm diff --git a/base_cancel_confirm/tests/cancel_confirm_tester.py b/base_cancel_confirm/tests/cancel_confirm_tester.py new file mode 100644 index 0000000000..c18dc31e4b --- /dev/null +++ b/base_cancel_confirm/tests/cancel_confirm_tester.py @@ -0,0 +1,34 @@ +# Copyright 2020 Ecosoft Co., Ltd. (http://ecosoft.co.th) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class CancelConfirmTester(models.Model): + _name = "cancel.confirm.tester" + _description = "Cancel Confirm Tester" + _inherit = ["base.cancel.confirm"] + + _has_cancel_reason = "optional" + + name = fields.Char() + state = fields.Selection( + selection=[ + ("draft", "Draft"), + ("confirmed", "Confirmed"), + ("cancel", "Cancel"), + ], + default="draft", + ) + + def action_confirm(self): + self.write({"state": "confirmed"}) + + def action_cancel(self): + if not self.filtered("cancel_confirm"): + return self.open_cancel_confirm_wizard() + self.write({"state": "cancel"}) + + def action_draft(self): + self.clear_cancel_confirm_data() + self.write({"state": "draft"}) diff --git a/base_cancel_confirm/tests/test_cancel_confirm.py b/base_cancel_confirm/tests/test_cancel_confirm.py new file mode 100644 index 0000000000..6f792030d0 --- /dev/null +++ b/base_cancel_confirm/tests/test_cancel_confirm.py @@ -0,0 +1,118 @@ +# Copyright 2020 Ecosoft Co., Ltd. (http://ecosoft.co.th) +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). +from odoo_test_helper import FakeModelLoader + +from odoo.tests import Form, common + + +class TestCancelConfirm(common.TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + + cls.loader = FakeModelLoader(cls.env, cls.__module__) + cls.loader.backup_registry() + from .cancel_confirm_tester import CancelConfirmTester + + cls.loader.update_registry((CancelConfirmTester,)) + cls.test_model = cls.env[CancelConfirmTester._name] + cls.tester_model = cls.env["ir.model"].search( + [("model", "=", "cancel.confirm.tester")] + ) + cls.env["ir.config_parameter"].create( + {"key": "cancel.confirm.tester.cancel_confirm_disable", "value": "False"} + ) + # Access record: + cls.env["ir.model.access"].create( + { + "name": "access.cancel.confirm.tester", + "model_id": cls.tester_model.id, + "perm_read": 1, + "perm_write": 1, + "perm_create": 1, + "perm_unlink": 1, + } + ) + + cls.test_record = cls.test_model.create({"name": "DOC-001"}) + + @classmethod + def tearDownClass(cls): + cls.loader.restore_registry() + return super().tearDownClass() + + def test_01_cancel_confirm_tester(self): + """Cancel a document, I expect cancel_reason. + Then, set to draft, I expect cancel_reason is deleted. + """ + self.test_record.action_confirm() + # Click cance, cancel confirm wizard will open. Type in cancel_reason + res = self.test_record.action_cancel() + ctx = res.get("context") + self.assertEqual(ctx["cancel_method"], "action_cancel") + self.assertEqual(ctx["default_has_cancel_reason"], "optional") + wizard = Form(self.env["cancel.confirm"].with_context(**ctx)) + wizard.cancel_reason = "Wrong information" + wiz = wizard.save() + # Confirm cancel on wizard + wiz.confirm_cancel() + self.assertEqual(self.test_record.cancel_reason, wizard.cancel_reason) + self.assertEqual(self.test_record.state, "cancel") + # Set to draft + self.test_record.action_draft() + self.assertEqual(self.test_record.cancel_reason, False) + self.assertEqual(self.test_record.state, "draft") + # Check set no cancel reason, reason should be False + # wizard.has_cancel_reason = "no" Invisible field cant write + wiz = wizard.save() + # Confirm cancel on wizard + wiz.confirm_cancel() + self.assertTrue(self.test_record.cancel_reason) + + def test_02_cancel_confirm_tester(self): + self.test_record.action_confirm() + res = self.test_record.action_cancel() + ctx = res.get("context") + # Check set no cancel reason, reason should be "no" + ctx["default_has_cancel_reason"] = "no" + wizard = Form(self.env["cancel.confirm"].with_context(**ctx)) + self.assertEqual(wizard.has_cancel_reason, "no") + wiz = wizard.save() + # Confirm cancel on wizard + wiz.confirm_cancel() + self.test_record.action_confirm() + self.assertFalse(self.test_record.cancel_reason) + + def test_view_automatic(self): + # We need to add a view in order to test fields_view_get() + self.env["ir.ui.view"].create( + { + "model": self.test_record._name, + "name": "Demo view", + "arch": """
+ + + + + +
""", + } + ) + with Form(self.test_record) as f: + self.assertTrue(f._view["fields"].get("cancel_confirm")) + self.assertTrue(f._view["fields"].get("cancel_reason")) + + # Check view difference, it should change base_model from view_id + wizard_lang_export = self.env.ref("base.wizard_lang_export") + res = self.test_record.get_view( + view_id=wizard_lang_export.id, + view_type="form", + ) + self.assertEqual(res["model"], wizard_lang_export.model) + + # Check view type is tree. + wizard_lang_export = self.env.ref("base.wizard_lang_export") + self.test_record.get_view( + view_id=wizard_lang_export.id, + view_type="tree", + ) diff --git a/base_cancel_confirm/views/cancel_confirm_template.xml b/base_cancel_confirm/views/cancel_confirm_template.xml new file mode 100644 index 0000000000..261327c5d8 --- /dev/null +++ b/base_cancel_confirm/views/cancel_confirm_template.xml @@ -0,0 +1,11 @@ + + + + diff --git a/base_cancel_confirm/wizard/__init__.py b/base_cancel_confirm/wizard/__init__.py new file mode 100644 index 0000000000..38920ac7c0 --- /dev/null +++ b/base_cancel_confirm/wizard/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2020 Ecosoft Co., Ltd. (http://ecosoft.co.th) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import cancel_confirm diff --git a/base_cancel_confirm/wizard/cancel_confirm.py b/base_cancel_confirm/wizard/cancel_confirm.py new file mode 100644 index 0000000000..c5c80b27c0 --- /dev/null +++ b/base_cancel_confirm/wizard/cancel_confirm.py @@ -0,0 +1,32 @@ +# Copyright 2020 Ecosoft Co., Ltd. (http://ecosoft.co.th) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from odoo import fields, models + + +class CancelConfirm(models.TransientModel): + _name = "cancel.confirm" + _description = "Cancel Confirm" + + cancel_reason = fields.Text() + has_cancel_reason = fields.Selection( + selection=[ + ("no", "None"), + ("optional", "Optional"), + ("required", "Required"), + ], + default="no", + required=True, + ) + + def confirm_cancel(self): + self.ensure_one() + res_model = self._context.get("cancel_res_model") + res_ids = self._context.get("cancel_res_ids") + cancel_method = self._context.get("cancel_method") + docs = self.env[res_model].browse(res_ids) + docs.write({"cancel_confirm": True}) + # Cancel Reason + if self.has_cancel_reason in ["optional", "required"]: + docs.write({"cancel_reason": self.cancel_reason}) + res = getattr(docs, cancel_method)() + return res diff --git a/base_cancel_confirm/wizard/cancel_confirm.xml b/base_cancel_confirm/wizard/cancel_confirm.xml new file mode 100644 index 0000000000..cd3da46ab6 --- /dev/null +++ b/base_cancel_confirm/wizard/cancel_confirm.xml @@ -0,0 +1,38 @@ + + + + Cancel Confirmation + cancel.confirm + +
+

Are you sure to cancel this document?

+ + + + +
+
+
+
+
+ + Cancel Confirmation + ir.actions.act_window + cancel.confirm + form + + new + +