diff --git a/purchase_request_substate/README.rst b/purchase_request_substate/README.rst new file mode 100644 index 00000000000..fa608ca9aa8 --- /dev/null +++ b/purchase_request_substate/README.rst @@ -0,0 +1,99 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + +========================== +Purchase Request Sub State +========================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:8a17c5c0411a565e677833e932a9815a269e7aca828b3c4ecab158e09e9dc653 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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/license-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%2Fpurchase--workflow-lightgray.png?logo=github + :target: https://github.com/OCA/purchase-workflow/tree/19.0/purchase_request_substate + :alt: OCA/purchase-workflow +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/purchase-workflow-19-0/purchase-workflow-19-0-purchase_request_substate + :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/purchase-workflow&target_branch=19.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module allows to add a substate to purchase request. For each +purchase request state you can define a substate. We this module you can +define substate which allow you to extend purchase request workflow. For +example, you can add substate "To Verify" if the order can not be +approved without document checked and verified + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +1. | Go to \*\* Settings > Technical > Database Structure \*\* and Add + "Base substate". + | If necessery you can add "target State values" (ex define a + substate for "cancel" state). Substate sequence is very important. + +2. Create a purchae request and check if the substate are displayed on + the header of form view. Check if you can't set substate defined for + purchase request if sate is a To be approved. + +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. +- `Heliconia Solutions Pvt. Ltd. `__ + + - Bhavesh Heliconia + +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/purchase-workflow `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/purchase_request_substate/__init__.py b/purchase_request_substate/__init__.py new file mode 100644 index 00000000000..0650744f6bc --- /dev/null +++ b/purchase_request_substate/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/purchase_request_substate/__manifest__.py b/purchase_request_substate/__manifest__.py new file mode 100644 index 00000000000..71c2c2b2aae --- /dev/null +++ b/purchase_request_substate/__manifest__.py @@ -0,0 +1,19 @@ +# Copyright 2021 Ecosoft () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + "name": "Purchase Request Sub State", + "version": "19.0.1.0.0", + "category": "Tools", + "author": "Ecosoft,Odoo Community Association (OCA)", + "website": "https://github.com/OCA/purchase-workflow", + "license": "AGPL-3", + "depends": ["base_substate", "purchase_request"], + "data": [ + "views/purchase_request_views.xml", + "data/purchase_substate_mail_template_data.xml", + "data/purchase_request_substate_data.xml", + ], + "demo": ["demo/purchase_request_substate_demo.xml"], + "installable": True, +} diff --git a/purchase_request_substate/data/purchase_request_substate_data.xml b/purchase_request_substate/data/purchase_request_substate_data.xml new file mode 100644 index 00000000000..4c8cfc36101 --- /dev/null +++ b/purchase_request_substate/data/purchase_request_substate_data.xml @@ -0,0 +1,19 @@ + + + + Purchase Request Substate + purchase.request + state + + + + To be approved + + to_approve + + + Approved + + approved + + diff --git a/purchase_request_substate/data/purchase_substate_mail_template_data.xml b/purchase_request_substate/data/purchase_substate_mail_template_data.xml new file mode 100644 index 00000000000..86bd20e8c31 --- /dev/null +++ b/purchase_request_substate/data/purchase_substate_mail_template_data.xml @@ -0,0 +1,22 @@ + + + + Verified + + Your purchase request ${object.name} is verified + + +
+ Dear ${object.requested_by.name or 'requester'},
+ This email is to inform that your purchase request ${object.name} was verified by procurement team. +

+ Thank you, +
+
+
+ +
+
diff --git a/purchase_request_substate/demo/purchase_request_substate_demo.xml b/purchase_request_substate/demo/purchase_request_substate_demo.xml new file mode 100644 index 00000000000..7d2a31e01c1 --- /dev/null +++ b/purchase_request_substate/demo/purchase_request_substate_demo.xml @@ -0,0 +1,23 @@ + + + + + To Verify + 1 + + + + Checked + 2 + + + + Verified + 3 + + + + diff --git a/purchase_request_substate/i18n/it.po b/purchase_request_substate/i18n/it.po new file mode 100644 index 00000000000..b41dcc38823 --- /dev/null +++ b/purchase_request_substate/i18n/it.po @@ -0,0 +1,96 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * purchase_request_substate +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2025-07-21 14:57+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 5.10.4\n" + +#. module: purchase_request_substate +#: model:mail.template,body_html:purchase_request_substate.mail_template_data_purchase_request_substate_verified +msgid "" +"
\n" +" Dear ${object.requested_by.name or 'requester'},
\n" +" This email is to inform that your purchase request ${object.name} was verified by procurement team.\n" +"

\n" +" Thank you,\n" +"
\n" +"
\n" +" " +msgstr "" +"
\n" +"Gentile ${object.requested_by.name o 'requester'},
\n" +"Questa e-mail la informa che la sua richiesta di acquisto ${object.name} è " +"stata verificata dal team acquisti.\n" +"

\n" +"Grazie,\n" +"
\n" +"
\n" +" " + +#. module: purchase_request_substate +#: model:ir.model.fields,field_description:purchase_request_substate.field_base_substate_type__model +msgid "Apply on" +msgstr "Applica a" + +#. module: purchase_request_substate +#: model:target.state.value,name:purchase_request_substate.target_state_value_approved +msgid "Approved" +msgstr "Approvata" + +#. module: purchase_request_substate +#: model:ir.model,name:purchase_request_substate.model_base_substate_type +msgid "Base Substate Type" +msgstr "Tipo substato base" + +#. module: purchase_request_substate +#: model:base.substate,name:purchase_request_substate.base_substate_checked +msgid "Checked" +msgstr "Selezionato" + +#. module: purchase_request_substate +#: model:ir.model,name:purchase_request_substate.model_purchase_request +#: model:ir.model.fields.selection,name:purchase_request_substate.selection__base_substate_type__model__purchase_request +msgid "Purchase Request" +msgstr "Richiesta di acquisto" + +#. module: purchase_request_substate +#: model:base.substate.type,name:purchase_request_substate.base_substate_type_purchase_request +msgid "Purchase Request Substate" +msgstr "Substato richiesta di acquisto" + +#. module: purchase_request_substate +#: model:ir.model.fields,field_description:purchase_request_substate.field_purchase_request__substate_id +msgid "Sub State" +msgstr "Substato" + +#. module: purchase_request_substate +#: model:base.substate,name:purchase_request_substate.base_substate_to_verify +msgid "To Verify" +msgstr "Da verificare" + +#. module: purchase_request_substate +#: model:target.state.value,name:purchase_request_substate.target_state_value_to_approve +msgid "To be approved" +msgstr "Da approvare" + +#. module: purchase_request_substate +#: model:base.substate,name:purchase_request_substate.base_substate_verified +#: model:mail.template,name:purchase_request_substate.mail_template_data_purchase_request_substate_verified +msgid "Verified" +msgstr "Verificato" + +#. module: purchase_request_substate +#: model:mail.template,subject:purchase_request_substate.mail_template_data_purchase_request_substate_verified +msgid "Your purchase request ${object.name} is verified" +msgstr "La sua richiesta di acquisto ${object.name} è verificata" diff --git a/purchase_request_substate/i18n/purchase_request_substate.pot b/purchase_request_substate/i18n/purchase_request_substate.pot new file mode 100644 index 00000000000..69a5c462b1c --- /dev/null +++ b/purchase_request_substate/i18n/purchase_request_substate.pot @@ -0,0 +1,84 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * purchase_request_substate +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.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: purchase_request_substate +#: model:mail.template,body_html:purchase_request_substate.mail_template_data_purchase_request_substate_verified +msgid "" +"
\n" +" Dear ${object.requested_by.name or 'requester'},
\n" +" This email is to inform that your purchase request ${object.name} was verified by procurement team.\n" +"

\n" +" Thank you,\n" +"
\n" +"
\n" +" " +msgstr "" + +#. module: purchase_request_substate +#: model:ir.model.fields,field_description:purchase_request_substate.field_base_substate_type__model +msgid "Apply on" +msgstr "" + +#. module: purchase_request_substate +#: model:target.state.value,name:purchase_request_substate.target_state_value_approved +msgid "Approved" +msgstr "" + +#. module: purchase_request_substate +#: model:ir.model,name:purchase_request_substate.model_base_substate_type +msgid "Base Substate Type" +msgstr "" + +#. module: purchase_request_substate +#: model:base.substate,name:purchase_request_substate.base_substate_checked +msgid "Checked" +msgstr "" + +#. module: purchase_request_substate +#: model:ir.model,name:purchase_request_substate.model_purchase_request +#: model:ir.model.fields.selection,name:purchase_request_substate.selection__base_substate_type__model__purchase_request +msgid "Purchase Request" +msgstr "" + +#. module: purchase_request_substate +#: model:base.substate.type,name:purchase_request_substate.base_substate_type_purchase_request +msgid "Purchase Request Substate" +msgstr "" + +#. module: purchase_request_substate +#: model:ir.model.fields,field_description:purchase_request_substate.field_purchase_request__substate_id +msgid "Sub State" +msgstr "" + +#. module: purchase_request_substate +#: model:base.substate,name:purchase_request_substate.base_substate_to_verify +msgid "To Verify" +msgstr "" + +#. module: purchase_request_substate +#: model:target.state.value,name:purchase_request_substate.target_state_value_to_approve +msgid "To be approved" +msgstr "" + +#. module: purchase_request_substate +#: model:base.substate,name:purchase_request_substate.base_substate_verified +#: model:mail.template,name:purchase_request_substate.mail_template_data_purchase_request_substate_verified +msgid "Verified" +msgstr "" + +#. module: purchase_request_substate +#: model:mail.template,subject:purchase_request_substate.mail_template_data_purchase_request_substate_verified +msgid "Your purchase request ${object.name} is verified" +msgstr "" diff --git a/purchase_request_substate/models/__init__.py b/purchase_request_substate/models/__init__.py new file mode 100644 index 00000000000..91be581c56a --- /dev/null +++ b/purchase_request_substate/models/__init__.py @@ -0,0 +1 @@ +from . import purchase_request diff --git a/purchase_request_substate/models/purchase_request.py b/purchase_request_substate/models/purchase_request.py new file mode 100644 index 00000000000..72b0552a132 --- /dev/null +++ b/purchase_request_substate/models/purchase_request.py @@ -0,0 +1,19 @@ +# Copyright 2021 Ecosoft () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class BaseSubstateType(models.Model): + _inherit = "base.substate.type" + + model = fields.Selection( + selection_add=[("purchase.request", "Purchase Request")], + ondelete={"purchase.request": "cascade"}, + ) + + +class PurchaseRequest(models.Model): + _name = "purchase.request" + _inherit = ["purchase.request", "base.substate.mixin"] + _state_field = "state" diff --git a/purchase_request_substate/pyproject.toml b/purchase_request_substate/pyproject.toml new file mode 100644 index 00000000000..4231d0cccb3 --- /dev/null +++ b/purchase_request_substate/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/purchase_request_substate/readme/CONTRIBUTORS.md b/purchase_request_substate/readme/CONTRIBUTORS.md new file mode 100644 index 00000000000..f538d5b01f7 --- /dev/null +++ b/purchase_request_substate/readme/CONTRIBUTORS.md @@ -0,0 +1,3 @@ +- Kitti U. \<\> +- [Heliconia Solutions Pvt. Ltd.](https://www.heliconia.io) + - Bhavesh Heliconia diff --git a/purchase_request_substate/readme/DESCRIPTION.md b/purchase_request_substate/readme/DESCRIPTION.md new file mode 100644 index 00000000000..1154772aa61 --- /dev/null +++ b/purchase_request_substate/readme/DESCRIPTION.md @@ -0,0 +1,5 @@ +This module allows to add a substate to purchase request. For each +purchase request state you can define a substate. We this module you can +define substate which allow you to extend purchase request workflow. For +example, you can add substate "To Verify" if the order can not be +approved without document checked and verified diff --git a/purchase_request_substate/readme/USAGE.md b/purchase_request_substate/readme/USAGE.md new file mode 100644 index 00000000000..06f29734dae --- /dev/null +++ b/purchase_request_substate/readme/USAGE.md @@ -0,0 +1,7 @@ +1. Go to \*\* Settings \> Technical \> Database Structure \*\* and Add "Base substate". + If necessery you can add "target State values" (ex define a substate + for "cancel" state). Substate sequence is very important. + +2. Create a purchae request and check if the substate are displayed on + the header of form view. Check if you can't set substate defined for + purchase request if sate is a To be approved. diff --git a/purchase_request_substate/static/description/icon.png b/purchase_request_substate/static/description/icon.png new file mode 100644 index 00000000000..3a0328b516c Binary files /dev/null and b/purchase_request_substate/static/description/icon.png differ diff --git a/purchase_request_substate/static/description/index.html b/purchase_request_substate/static/description/index.html new file mode 100644 index 00000000000..79fcc687a35 --- /dev/null +++ b/purchase_request_substate/static/description/index.html @@ -0,0 +1,454 @@ + + + + + +README.rst + + + +
+ + + +Odoo Community Association + +
+

Purchase Request Sub State

+ +

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

+

This module allows to add a substate to purchase request. For each +purchase request state you can define a substate. We this module you can +define substate which allow you to extend purchase request workflow. For +example, you can add substate “To Verify” if the order can not be +approved without document checked and verified

+

Table of contents

+ +
+

Usage

+
    +
  1. +
    Go to ** Settings > Technical > Database Structure ** and Add +“Base substate”.
    +
    If necessery you can add “target State values” (ex define a +substate for “cancel” state). Substate sequence is very important.
    +
    +
  2. +
  3. Create a purchae request and check if the substate are displayed on +the header of form view. Check if you can’t set substate defined for +purchase request if sate is a To be approved.

    +
  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

+
    +
  • Ecosoft
  • +
+
+
+

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/purchase-workflow project on GitHub.

+

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

+
+
+
+
+ + diff --git a/purchase_request_substate/tests/__init__.py b/purchase_request_substate/tests/__init__.py new file mode 100644 index 00000000000..208bcd4d3e3 --- /dev/null +++ b/purchase_request_substate/tests/__init__.py @@ -0,0 +1 @@ +from . import test_purchase_request_substate diff --git a/purchase_request_substate/tests/test_purchase_request_substate.py b/purchase_request_substate/tests/test_purchase_request_substate.py new file mode 100644 index 00000000000..91098788ac4 --- /dev/null +++ b/purchase_request_substate/tests/test_purchase_request_substate.py @@ -0,0 +1,82 @@ +# Copyright 2021 Ecosoft () +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). +from odoo import SUPERUSER_ID +from odoo.exceptions import ValidationError + +from odoo.addons.base.tests.common import BaseCommon + + +class TestPurchaseRequestSubstate(BaseCommon): + @classmethod + def setUpClass(cls): + super().setUpClass() + # Prepare PR + cls.purchase_request_obj = cls.env["purchase.request"] + cls.purchase_request_line_obj = cls.env["purchase.request.line"] + cls.product = cls.env["product.product"].create( + { + "name": "Test Product", + "is_storable": True, + } + ) + cls.substate_type = cls.env.ref( + "purchase_request_substate.base_substate_type_purchase_request" + ) + cls.target_state_value_to_approve = cls.env.ref( + "purchase_request_substate.target_state_value_to_approve" + ) + cls.substate_to_verify = cls.env["base.substate"].create( + { + "name": "To Verify", + "sequence": 1, + "target_state_value_id": cls.target_state_value_to_approve.id, + "active": True, + } + ) + cls.substate_checked = cls.env["base.substate"].create( + { + "name": "Checked", + "sequence": 2, + "target_state_value_id": cls.target_state_value_to_approve.id, + "active": True, + } + ) + cls.substate_verified = cls.env["base.substate"].create( + { + "name": "Verified", + "sequence": 3, + "target_state_value_id": cls.target_state_value_to_approve.id, + "active": True, + } + ) + vals = { + "picking_type_id": cls.env.ref("stock.picking_type_in").id, + "requested_by": SUPERUSER_ID, + } + cls.pr_test = cls.purchase_request_obj.create(vals) + cls.purchase_request_line_obj.create( + { + "request_id": cls.pr_test.id, + "product_id": cls.product.id, + "product_uom_id": cls.env.ref("uom.product_uom_unit").id, + "product_qty": 5.0, + } + ) + + def test_purchase_request_order_substate(self): + self.assertEqual(self.pr_test.state, "draft") + self.assertFalse(self.pr_test.substate_id) + + # Block substate not corresponding to draft state + with self.assertRaises(ValidationError): + self.pr_test.substate_id = self.substate_to_verify + # Test that validation of purchase_request order change substate_id + self.pr_test.button_to_approve() + self.assertEqual(self.pr_test.state, "to_approve") + self.assertEqual(self.pr_test.substate_id, self.substate_to_verify) + + # Test that substate_id is set to false if + # there is not substate corresponding to state + self.pr_test.button_approved() + self.assertEqual(self.pr_test.state, "approved") + self.assertFalse(self.pr_test.substate_id) diff --git a/purchase_request_substate/views/purchase_request_views.xml b/purchase_request_substate/views/purchase_request_views.xml new file mode 100644 index 00000000000..4d3d7e8aaa3 --- /dev/null +++ b/purchase_request_substate/views/purchase_request_views.xml @@ -0,0 +1,20 @@ + + + + + purchase.request + + + +
+ +
+
+
+
+