From 8b2fa0cf93e0ea86c465dc73cf39503dac5551a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Todorovich?= Date: Wed, 27 Nov 2024 15:18:51 -0300 Subject: [PATCH] [ADD] repair_order_template Create and use templates to save time when creating repair orders. With them, you can pre-fill the repair order fields and spare parts. --- repair_order_template/README.rst | 99 ++++ repair_order_template/__init__.py | 1 + repair_order_template/__manifest__.py | 23 + .../demo/repair_order_template.xml | 32 ++ repair_order_template/models/__init__.py | 3 + repair_order_template/models/repair_order.py | 38 ++ .../models/repair_order_template.py | 33 ++ .../models/repair_order_template_line.py | 72 +++ repair_order_template/pyproject.toml | 3 + repair_order_template/readme/CONFIGURE.md | 2 + repair_order_template/readme/CONTRIBUTORS.md | 3 + repair_order_template/readme/DESCRIPTION.md | 2 + repair_order_template/readme/USAGE.md | 2 + .../security/ir.model.access.csv | 5 + repair_order_template/security/security.xml | 20 + .../static/description/index.html | 441 ++++++++++++++++++ repair_order_template/tests/__init__.py | 1 + .../tests/test_repair_order_template.py | 52 +++ repair_order_template/views/repair_order.xml | 20 + .../views/repair_order_template.xml | 136 ++++++ 20 files changed, 988 insertions(+) create mode 100644 repair_order_template/README.rst create mode 100644 repair_order_template/__init__.py create mode 100644 repair_order_template/__manifest__.py create mode 100644 repair_order_template/demo/repair_order_template.xml create mode 100644 repair_order_template/models/__init__.py create mode 100644 repair_order_template/models/repair_order.py create mode 100644 repair_order_template/models/repair_order_template.py create mode 100644 repair_order_template/models/repair_order_template_line.py create mode 100644 repair_order_template/pyproject.toml create mode 100644 repair_order_template/readme/CONFIGURE.md create mode 100644 repair_order_template/readme/CONTRIBUTORS.md create mode 100644 repair_order_template/readme/DESCRIPTION.md create mode 100644 repair_order_template/readme/USAGE.md create mode 100644 repair_order_template/security/ir.model.access.csv create mode 100644 repair_order_template/security/security.xml create mode 100644 repair_order_template/static/description/index.html create mode 100644 repair_order_template/tests/__init__.py create mode 100644 repair_order_template/tests/test_repair_order_template.py create mode 100644 repair_order_template/views/repair_order.xml create mode 100644 repair_order_template/views/repair_order_template.xml diff --git a/repair_order_template/README.rst b/repair_order_template/README.rst new file mode 100644 index 00000000..28af5336 --- /dev/null +++ b/repair_order_template/README.rst @@ -0,0 +1,99 @@ +===================== +Repair Order Template +===================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:5a5ce7d5e2cfce32a16afc2beff8d76fe1445f91693e087e533fdd2309afeadc + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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%2Frepair-lightgray.png?logo=github + :target: https://github.com/OCA/repair/tree/17.0/repair_order_template + :alt: OCA/repair +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/repair-17-0/repair-17-0-repair_order_template + :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/repair&target_branch=17.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +Create and use templates to save time when creating repair orders. With +them, you can pre-fill the repair order fields and spare parts. + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +Go to **Repairs > Configuration > Repair Orders Templates** to create +and manage your templates. + +Usage +===== + +On a *draft* Repair Order, choose a template to automatically fill some +fields and spare parts, according to the template. + +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 +------------ + +- `Camptocamp `__: + + - Iván Todorovich + +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-ivantodorovich| image:: https://github.com/ivantodorovich.png?size=40px + :target: https://github.com/ivantodorovich + :alt: ivantodorovich + +Current `maintainer `__: + +|maintainer-ivantodorovich| + +This module is part of the `OCA/repair `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/repair_order_template/__init__.py b/repair_order_template/__init__.py new file mode 100644 index 00000000..0650744f --- /dev/null +++ b/repair_order_template/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/repair_order_template/__manifest__.py b/repair_order_template/__manifest__.py new file mode 100644 index 00000000..4e890af3 --- /dev/null +++ b/repair_order_template/__manifest__.py @@ -0,0 +1,23 @@ +# Copyright 2024 Camptocamp SA (https://www.camptocamp.com). +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +{ + "name": "Repair Order Template", + "summary": "Use templates to save time when creating repair orders", + "version": "17.0.1.0.0", + "author": "Camptocamp, Odoo Community Association (OCA)", + "maintainers": ["ivantodorovich"], + "website": "https://github.com/OCA/repair", + "license": "AGPL-3", + "category": "Repair", + "depends": ["repair"], + "data": [ + "security/security.xml", + "security/ir.model.access.csv", + "views/repair_order_template.xml", + "views/repair_order.xml", + ], + "demo": [ + "demo/repair_order_template.xml", + ], +} diff --git a/repair_order_template/demo/repair_order_template.xml b/repair_order_template/demo/repair_order_template.xml new file mode 100644 index 00000000..473583a2 --- /dev/null +++ b/repair_order_template/demo/repair_order_template.xml @@ -0,0 +1,32 @@ + + + + + + General Repair + + + + + add + + + + + + + add + + + + + diff --git a/repair_order_template/models/__init__.py b/repair_order_template/models/__init__.py new file mode 100644 index 00000000..d681ea39 --- /dev/null +++ b/repair_order_template/models/__init__.py @@ -0,0 +1,3 @@ +from . import repair_order_template_line +from . import repair_order_template +from . import repair_order diff --git a/repair_order_template/models/repair_order.py b/repair_order_template/models/repair_order.py new file mode 100644 index 00000000..7bc96871 --- /dev/null +++ b/repair_order_template/models/repair_order.py @@ -0,0 +1,38 @@ +# Copyright 2024 Camptocamp SA (https://www.camptocamp.com). +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import _, api, fields, models +from odoo.exceptions import ValidationError + + +class RepairOrder(models.Model): + _inherit = "repair.order" + + repair_order_template_id = fields.Many2one( + string="Order Template", + help="Use templates to save time when creating repair orders.", + comodel_name="repair.order.template", + check_company=True, + ) + + @api.constrains("repair_order_template_id") + def _check_repair_order_template_id(self): + if self.repair_order_template_id and self.state != "draft": + raise ValidationError(_("Order Template can only be set on draft orders")) + + @api.onchange("repair_order_template_id") + def _onchange_repair_order_template_id(self): + if not self.repair_order_template_id: + return + # Simple fields get copied over if they're set on the template + for fname in ("product_id", "under_warranty", "tag_ids", "internal_notes"): + if self.repair_order_template_id[fname]: + self[fname] = self.repair_order_template_id[fname] + # Lines get replaced by new ones, generated from the template lines + if self.repair_order_template_id.line_ids: + self.move_ids = [fields.Command.clear()] + [ + fields.Command.create( + dict(line._prepare_move_values(), company_id=self.company_id.id) + ) + for line in self.repair_order_template_id.line_ids + ] diff --git a/repair_order_template/models/repair_order_template.py b/repair_order_template/models/repair_order_template.py new file mode 100644 index 00000000..fbee754d --- /dev/null +++ b/repair_order_template/models/repair_order_template.py @@ -0,0 +1,33 @@ +# Copyright 2024 Camptocamp SA (https://www.camptocamp.com). +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class RepairOrderTemplate(models.Model): + _name = "repair.order.template" + _description = "Repair Order Template" + _check_company_auto = True + + name = fields.Char(required=True, translate=True) + active = fields.Boolean(default=True) + company_id = fields.Many2one("res.company", default=lambda self: self.env.company) + tag_ids = fields.Many2many("repair.tags", string="Tags") + internal_notes = fields.Html() + under_warranty = fields.Boolean() + product_id = fields.Many2one( + "product.product", + string="Product to Repair", + domain=""" + [ + ('type', 'in', ['product', 'consu']), + ('company_id', 'in', [False, company_id]) + ] + """, + check_company=True, + ) + line_ids = fields.One2many( + comodel_name="repair.order.template.line", + inverse_name="template_id", + check_company=True, + ) diff --git a/repair_order_template/models/repair_order_template_line.py b/repair_order_template/models/repair_order_template_line.py new file mode 100644 index 00000000..be039887 --- /dev/null +++ b/repair_order_template/models/repair_order_template_line.py @@ -0,0 +1,72 @@ +# Copyright 2024 Camptocamp SA (https://www.camptocamp.com). +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models + + +class RepairOrderTemplateLine(models.Model): + _name = "repair.order.template.line" + _description = "Repair Order Template Line" + _check_company_auto = True + + template_id = fields.Many2one( + "repair.order.template", + required=True, + readonly=True, + ondelete="cascade", + ) + company_id = fields.Many2one( + related="template_id.company_id", + store=True, + ) + type = fields.Selection( + selection=lambda self: ( + self.env["stock.move"] + ._fields["repair_line_type"] + ._description_selection(self.env) + ), + required=True, + ) + product_id = fields.Many2one( + "product.product", + string="Product", + domain=""" + [ + ('type', 'in', ['product', 'consu']), + ('company_id', 'in', [False, company_id]) + ] + """, + check_company=True, + required=True, + ) + product_uom_category_id = fields.Many2one( + related="product_id.uom_id.category_id", + ) + product_uom = fields.Many2one( + "uom.uom", + string="Unit of Measure", + domain="[('category_id', '=', product_uom_category_id)]", + compute="_compute_product_uom", + readonly=False, + required=True, + store=True, + ) + product_uom_qty = fields.Float( + "Quantity", + digits="Product Unit of Measure", + required=True, + default=1.0, + ) + + @api.depends("product_id") + def _compute_product_uom(self): + for rec in self: + rec.product_uom = rec.product_id.uom_id + + def _prepare_move_values(self): + return { + "repair_line_type": self.type, + "product_id": self.product_id, + "product_uom": self.product_uom, + "product_uom_qty": self.product_uom_qty, + } diff --git a/repair_order_template/pyproject.toml b/repair_order_template/pyproject.toml new file mode 100644 index 00000000..4231d0cc --- /dev/null +++ b/repair_order_template/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/repair_order_template/readme/CONFIGURE.md b/repair_order_template/readme/CONFIGURE.md new file mode 100644 index 00000000..40c02dd0 --- /dev/null +++ b/repair_order_template/readme/CONFIGURE.md @@ -0,0 +1,2 @@ +Go to **Repairs > Configuration > Repair Orders Templates** to create and manage your +templates. diff --git a/repair_order_template/readme/CONTRIBUTORS.md b/repair_order_template/readme/CONTRIBUTORS.md new file mode 100644 index 00000000..7f045ba5 --- /dev/null +++ b/repair_order_template/readme/CONTRIBUTORS.md @@ -0,0 +1,3 @@ +- [Camptocamp](https://camptocamp.com/): + + - Iván Todorovich \<\> diff --git a/repair_order_template/readme/DESCRIPTION.md b/repair_order_template/readme/DESCRIPTION.md new file mode 100644 index 00000000..6516a139 --- /dev/null +++ b/repair_order_template/readme/DESCRIPTION.md @@ -0,0 +1,2 @@ +Create and use templates to save time when creating repair orders. +With them, you can pre-fill the repair order fields and spare parts. diff --git a/repair_order_template/readme/USAGE.md b/repair_order_template/readme/USAGE.md new file mode 100644 index 00000000..e6c33685 --- /dev/null +++ b/repair_order_template/readme/USAGE.md @@ -0,0 +1,2 @@ +On a *draft* Repair Order, choose a template to automatically fill some fields +and spare parts, according to the template. diff --git a/repair_order_template/security/ir.model.access.csv b/repair_order_template/security/ir.model.access.csv new file mode 100644 index 00000000..d9515fa6 --- /dev/null +++ b/repair_order_template/security/ir.model.access.csv @@ -0,0 +1,5 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_repair_order_template_user,repair.order.template::user,model_repair_order_template,stock.group_stock_user,1,0,0,0 +access_repair_order_template_manager,repair.order.template::manager,model_repair_order_template,stock.group_stock_manager,1,1,1,1 +access_repair_order_template_line_user,repair.order.template.line::user,model_repair_order_template_line,stock.group_stock_user,1,0,0,0 +access_repair_order_template_line_manager,repair.order.template.line::manager,model_repair_order_template_line,stock.group_stock_manager,1,1,1,1 diff --git a/repair_order_template/security/security.xml b/repair_order_template/security/security.xml new file mode 100644 index 00000000..187e43db --- /dev/null +++ b/repair_order_template/security/security.xml @@ -0,0 +1,20 @@ + + + + + + Repair Order Template: Multi-company + + [('company_id', 'in', company_ids + [False])] + + + + Repair Order Template Line: Multi-company + + [('company_id', 'in', company_ids + [False])] + + + diff --git a/repair_order_template/static/description/index.html b/repair_order_template/static/description/index.html new file mode 100644 index 00000000..106d3f7f --- /dev/null +++ b/repair_order_template/static/description/index.html @@ -0,0 +1,441 @@ + + + + + +Repair Order Template + + + +
+

Repair Order Template

+ + +

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

+

Create and use templates to save time when creating repair orders. With +them, you can pre-fill the repair order fields and spare parts.

+

Table of contents

+ +
+

Configuration

+

Go to Repairs > Configuration > Repair Orders Templates to create +and manage your templates.

+
+
+

Usage

+

On a draft Repair Order, choose a template to automatically fill some +fields and spare parts, according to the template.

+
+
+

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.

+

Current maintainer:

+

ivantodorovich

+

This module is part of the OCA/repair project on GitHub.

+

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

+
+
+
+ + diff --git a/repair_order_template/tests/__init__.py b/repair_order_template/tests/__init__.py new file mode 100644 index 00000000..456903b5 --- /dev/null +++ b/repair_order_template/tests/__init__.py @@ -0,0 +1 @@ +from . import test_repair_order_template diff --git a/repair_order_template/tests/test_repair_order_template.py b/repair_order_template/tests/test_repair_order_template.py new file mode 100644 index 00000000..74168861 --- /dev/null +++ b/repair_order_template/tests/test_repair_order_template.py @@ -0,0 +1,52 @@ +# Copyright 2024 Camptocamp SA (https://www.camptocamp.com). +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo.exceptions import ValidationError +from odoo.tests import Form, TransactionCase +from odoo.tools import html2plaintext + +from odoo.addons.base.tests.common import DISABLED_MAIL_CONTEXT + + +class TestRepairOrderTemplate(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.env = cls.env(context=dict(cls.env.context, **DISABLED_MAIL_CONTEXT)) + cls.template = cls.env.ref("repair_order_template.repair_order_template_demo") + cls.order = cls.env["repair.order"].create({}) + + def test_repair_order_template_fill_lines(self): + with Form(self.order) as order: + order.repair_order_template_id = self.template + self.assertEqual(len(self.order.repair_order_template_id.line_ids), 2) + for move, line in zip( + self.order.move_ids, + self.order.repair_order_template_id.line_ids, + strict=True, + ): + self.assertEqual(move.repair_line_type, line.type) + self.assertEqual(move.product_id, line.product_id) + self.assertEqual(move.product_uom, line.product_uom) + self.assertAlmostEqual(move.product_uom_qty, line.product_uom_qty) + + def test_repair_order_template_fill_simple_fields(self): + self.template.internal_notes = "Template notes" + self.template.under_warranty = True + with Form(self.order) as order: + order.repair_order_template_id = self.template + self.assertEqual(html2plaintext(self.order.internal_notes), "Template notes") + self.assertEqual(self.order.under_warranty, True) + + def test_repair_order_template_does_not_overwrite_unset_fields(self): + self.order.internal_notes = "test" + with Form(self.order) as order: + order.repair_order_template_id = self.template + self.assertEqual(html2plaintext(self.order.internal_notes), "test") + + def test_repair_order_template_readonly(self): + self.order.action_validate() + with self.assertRaisesRegex( + ValidationError, "Order Template can only be set on draft orders" + ): + self.order.repair_order_template_id = self.template diff --git a/repair_order_template/views/repair_order.xml b/repair_order_template/views/repair_order.xml new file mode 100644 index 00000000..e6a8b7d1 --- /dev/null +++ b/repair_order_template/views/repair_order.xml @@ -0,0 +1,20 @@ + + + + + + repair.order + + + + + + + + + + + diff --git a/repair_order_template/views/repair_order_template.xml b/repair_order_template/views/repair_order_template.xml new file mode 100644 index 00000000..801088dd --- /dev/null +++ b/repair_order_template/views/repair_order_template.xml @@ -0,0 +1,136 @@ + + + + + + repair.order.template + + + + + + + + + + + + + repair.order.template + +
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + + repair.order.template + + + + + + + + + + + + Repair Order Templates + repair.order.template + tree,form + +

+ Create your Repair Order template +

+ Use templates to save time when creating repair orders. +

+
+
+ + + +