From 2f8a8efeec46887530ae66d1edab4e7ea90ea9ba Mon Sep 17 00:00:00 2001
From: Nils Coenen
Date: Mon, 1 Sep 2025 20:08:36 +0200
Subject: [PATCH 1/4] [ADD] sale_project_task_description_template: apply task
templates from service products
- Add `task_description_template_id` and `include_sale_line_info_in_task` fields to products
- Automatically apply task description templates when creating project tasks
- Optionally include sale order line info (product and quantity) in task description
- Include tests for product and sale order line behavior
[UPD] Update sale_project_task_description_template.pot
[BOT] post-merge updates
---
.../README.rst | 135 +++++
.../__init__.py | 1 +
.../__manifest__.py | 22 +
...sale_project_task_description_template.pot | 57 +++
.../models/__init__.py | 2 +
.../models/product_template.py | 20 +
.../models/sale_order_line.py | 32 ++
.../pyproject.toml | 3 +
.../readme/CONTRIBUTORS.md | 1 +
.../readme/DESCRIPTION.md | 11 +
.../readme/USAGE.md | 16 +
.../static/description/icon.png | Bin 0 -> 9455 bytes
.../static/description/index.html | 479 ++++++++++++++++++
.../tests/__init__.py | 2 +
.../tests/test_product_template.py | 37 ++
.../tests/test_sale_order_line.py | 92 ++++
.../views/product_template_views.xml | 23 +
17 files changed, 933 insertions(+)
create mode 100644 sale_project_task_description_template/README.rst
create mode 100644 sale_project_task_description_template/__init__.py
create mode 100644 sale_project_task_description_template/__manifest__.py
create mode 100644 sale_project_task_description_template/i18n/sale_project_task_description_template.pot
create mode 100644 sale_project_task_description_template/models/__init__.py
create mode 100644 sale_project_task_description_template/models/product_template.py
create mode 100644 sale_project_task_description_template/models/sale_order_line.py
create mode 100644 sale_project_task_description_template/pyproject.toml
create mode 100644 sale_project_task_description_template/readme/CONTRIBUTORS.md
create mode 100644 sale_project_task_description_template/readme/DESCRIPTION.md
create mode 100644 sale_project_task_description_template/readme/USAGE.md
create mode 100644 sale_project_task_description_template/static/description/icon.png
create mode 100644 sale_project_task_description_template/static/description/index.html
create mode 100644 sale_project_task_description_template/tests/__init__.py
create mode 100644 sale_project_task_description_template/tests/test_product_template.py
create mode 100644 sale_project_task_description_template/tests/test_sale_order_line.py
create mode 100644 sale_project_task_description_template/views/product_template_views.xml
diff --git a/sale_project_task_description_template/README.rst b/sale_project_task_description_template/README.rst
new file mode 100644
index 0000000000..c66bb313f5
--- /dev/null
+++ b/sale_project_task_description_template/README.rst
@@ -0,0 +1,135 @@
+.. image:: https://odoo-community.org/readme-banner-image
+ :target: https://odoo-community.org/get-involved?utm_source=readme
+ :alt: Odoo Community Association
+
+======================================
+Sale Project Task Description Template
+======================================
+
+..
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ !! This file is generated by oca-gen-addon-readme !!
+ !! changes will be overwritten. !!
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ !! source digest: sha256:fc4721c380633a7a1854f4da47d823d8567e854b849849096e6e48d7dc348107
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+.. |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-LGPL--3-blue.png
+ :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
+ :alt: License: LGPL-3
+.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fproject-lightgray.png?logo=github
+ :target: https://github.com/OCA/project/tree/18.0/sale_project_task_description_template
+ :alt: OCA/project
+.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
+ :target: https://translation.odoo-community.org/projects/project-18-0/project-18-0-sale_project_task_description_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/project&target_branch=18.0
+ :alt: Try me on Runboat
+
+|badge1| |badge2| |badge3| |badge4| |badge5|
+
+This module extends the Project Task Description Template and integrates
+it with Sales and Projects. When tasks are generated from sales order
+lines, the task will automatically use the Task Description Template
+defined on the related product.
+
+Optionally, you can include key information from the sales order line
+(like product name and quantity) above the template, providing more
+context directly in the task description.
+
+Key Features:
+
+- New field on product: assign a Task Description Template for service
+ products with Service Tracking set to 'Task' or 'Project & Task'.
+- Optional boolean to include the sale order line info in the task
+ description.
+- Automatic application of the template (and optionally the sales line
+ info) when creating tasks from sales orders.
+
+**Table of contents**
+
+.. contents::
+ :local:
+
+Usage
+=====
+
+To use this module:
+
+- Create a Task Description Template
+
+ - Go to Project → Configuration → Task Description Templates.
+ - Define a template with a name and description.
+
+- Assign the Template to a Product.
+
+ - Open a Product and set it as a Service.
+ - Ensure that Service Tracking is set to Task or Project & Task.
+ - Set the Task Description Template field.
+ - Optionally, enable the Include Sale Line Info in Task checkbox to
+ add product and quantity information above the template in generated
+ tasks.
+
+- Create a Sale Order
+
+ - Add the product(s) with assigned templates to a sales order.
+ - Confirm the order.
+
+- Generated Project Tasks
+
+ - The tasks created from the sales order lines will automatically
+ include the description from the assigned template.
+ - If enabled, the sales line info (product and quantity) will appear
+ above the template in the task description.
+
+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
+-------
+
+* NICO SOLUTIONS - ENGINEERING & IT
+
+Contributors
+------------
+
+- Nils Coenen
+
+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-NICO-SOLUTIONS| image:: https://github.com/NICO-SOLUTIONS.png?size=40px
+ :target: https://github.com/NICO-SOLUTIONS
+ :alt: NICO-SOLUTIONS
+
+Current `maintainer `__:
+
+|maintainer-NICO-SOLUTIONS|
+
+This module is part of the `OCA/project `_ project on GitHub.
+
+You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/sale_project_task_description_template/__init__.py b/sale_project_task_description_template/__init__.py
new file mode 100644
index 0000000000..0650744f6b
--- /dev/null
+++ b/sale_project_task_description_template/__init__.py
@@ -0,0 +1 @@
+from . import models
diff --git a/sale_project_task_description_template/__manifest__.py b/sale_project_task_description_template/__manifest__.py
new file mode 100644
index 0000000000..f75227eae0
--- /dev/null
+++ b/sale_project_task_description_template/__manifest__.py
@@ -0,0 +1,22 @@
+# Copyright 2025 NICO SOLUTIONS - ENGINEERING & IT
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl-3.0).
+{
+ "name": "Sale Project Task Description Template",
+ "summary": (
+ "Apply task description templates from products to tasks, "
+ "with optional sale info"
+ ),
+ "version": "18.0.1.0.0",
+ "category": "Project",
+ "website": "https://github.com/OCA/project",
+ "author": "NICO SOLUTIONS - ENGINEERING & IT, Odoo Community Association (OCA)",
+ "maintainers": ["NICO-SOLUTIONS"],
+ "license": "LGPL-3",
+ "depends": ["project_task_description_template", "sale_timesheet"],
+ "data": [
+ "views/product_template_views.xml",
+ ],
+ "installable": True,
+ "application": False,
+ "auto_install": False,
+}
diff --git a/sale_project_task_description_template/i18n/sale_project_task_description_template.pot b/sale_project_task_description_template/i18n/sale_project_task_description_template.pot
new file mode 100644
index 0000000000..c9a1ffd639
--- /dev/null
+++ b/sale_project_task_description_template/i18n/sale_project_task_description_template.pot
@@ -0,0 +1,57 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * sale_project_task_description_template
+#
+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: sale_project_task_description_template
+#. odoo-python
+#: code:addons/sale_project_task_description_template/models/sale_order_line.py:0
+msgid "%(product)s - Qty: %(qty)s"
+msgstr ""
+
+#. module: sale_project_task_description_template
+#: model:ir.model.fields,help:sale_project_task_description_template.field_product_product__task_description_template_id
+#: model:ir.model.fields,help:sale_project_task_description_template.field_product_template__task_description_template_id
+msgid "Applies automatically when creating tasks"
+msgstr ""
+
+#. module: sale_project_task_description_template
+#: model:ir.model.fields,help:sale_project_task_description_template.field_product_product__include_sale_line_info_in_task
+#: model:ir.model.fields,help:sale_project_task_description_template.field_product_template__include_sale_line_info_in_task
+msgid ""
+"If enabled, the sale order line details (e.g., product and quantity) will be"
+" added to the task description before the template content."
+msgstr ""
+
+#. module: sale_project_task_description_template
+#: model:ir.model.fields,field_description:sale_project_task_description_template.field_product_product__include_sale_line_info_in_task
+#: model:ir.model.fields,field_description:sale_project_task_description_template.field_product_template__include_sale_line_info_in_task
+msgid "Include Sale Line Info in Task description"
+msgstr ""
+
+#. module: sale_project_task_description_template
+#: model:ir.model,name:sale_project_task_description_template.model_product_template
+msgid "Product"
+msgstr ""
+
+#. module: sale_project_task_description_template
+#: model:ir.model,name:sale_project_task_description_template.model_sale_order_line
+msgid "Sales Order Line"
+msgstr ""
+
+#. module: sale_project_task_description_template
+#: model:ir.model.fields,field_description:sale_project_task_description_template.field_product_product__task_description_template_id
+#: model:ir.model.fields,field_description:sale_project_task_description_template.field_product_template__task_description_template_id
+#: model_terms:ir.ui.view,arch_db:sale_project_task_description_template.product_template_form_inherit_task_template
+msgid "Task Description Template"
+msgstr ""
diff --git a/sale_project_task_description_template/models/__init__.py b/sale_project_task_description_template/models/__init__.py
new file mode 100644
index 0000000000..83527162d0
--- /dev/null
+++ b/sale_project_task_description_template/models/__init__.py
@@ -0,0 +1,2 @@
+from . import product_template
+from . import sale_order_line
diff --git a/sale_project_task_description_template/models/product_template.py b/sale_project_task_description_template/models/product_template.py
new file mode 100644
index 0000000000..fe4d6a9499
--- /dev/null
+++ b/sale_project_task_description_template/models/product_template.py
@@ -0,0 +1,20 @@
+# Copyright 2025 NICO SOLUTIONS - ENGINEERING & IT
+# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
+
+from odoo import fields, models
+
+
+class ProductTemplate(models.Model):
+ _inherit = "product.template"
+
+ task_description_template_id = fields.Many2one(
+ "project.task.description.template",
+ string="Task Description Template",
+ help="Applies automatically when creating tasks",
+ )
+
+ include_sale_line_info_in_task = fields.Boolean(
+ string="Include Sale Line Info in Task description",
+ help="If enabled, the sale order line details (e.g., product and quantity) "
+ "will be added to the task description before the template content.",
+ )
diff --git a/sale_project_task_description_template/models/sale_order_line.py b/sale_project_task_description_template/models/sale_order_line.py
new file mode 100644
index 0000000000..9623fb6ce6
--- /dev/null
+++ b/sale_project_task_description_template/models/sale_order_line.py
@@ -0,0 +1,32 @@
+# Copyright 2025 NICO SOLUTIONS - ENGINEERING & IT
+# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
+
+from odoo import _, models
+
+
+class SaleOrderLine(models.Model):
+ _inherit = "sale.order.line"
+
+ def _timesheet_create_task_prepare_values(self, project):
+ values = super()._timesheet_create_task_prepare_values(project)
+
+ product = self.product_id.product_tmpl_id
+ template = product.task_description_template_id
+
+ if template:
+ values["description_template_id"] = template.id
+
+ if product.include_sale_line_info_in_task:
+ product_info = _("%(product)s - Qty: %(qty)s") % {
+ "product": self.product_id.name,
+ "qty": self.product_uom_qty,
+ }
+
+ if template and template.description:
+ values["description"] = f"{product_info}\n\n{template.description}"
+ else:
+ values["description"] = product_info
+ elif template and template.description:
+ values["description"] = template.description
+
+ return values
diff --git a/sale_project_task_description_template/pyproject.toml b/sale_project_task_description_template/pyproject.toml
new file mode 100644
index 0000000000..4231d0cccb
--- /dev/null
+++ b/sale_project_task_description_template/pyproject.toml
@@ -0,0 +1,3 @@
+[build-system]
+requires = ["whool"]
+build-backend = "whool.buildapi"
diff --git a/sale_project_task_description_template/readme/CONTRIBUTORS.md b/sale_project_task_description_template/readme/CONTRIBUTORS.md
new file mode 100644
index 0000000000..a3de8d2a4f
--- /dev/null
+++ b/sale_project_task_description_template/readme/CONTRIBUTORS.md
@@ -0,0 +1 @@
+- Nils Coenen \<\>
diff --git a/sale_project_task_description_template/readme/DESCRIPTION.md b/sale_project_task_description_template/readme/DESCRIPTION.md
new file mode 100644
index 0000000000..b4a06a1fca
--- /dev/null
+++ b/sale_project_task_description_template/readme/DESCRIPTION.md
@@ -0,0 +1,11 @@
+This module extends the Project Task Description Template and integrates it with Sales and Projects.
+When tasks are generated from sales order lines, the task will automatically use the Task Description Template
+defined on the related product.
+
+Optionally, you can include key information from the sales order line (like product name and quantity) above
+the template, providing more context directly in the task description.
+
+Key Features:
+- New field on product: assign a Task Description Template for service products with Service Tracking set to 'Task' or 'Project & Task'.
+- Optional boolean to include the sale order line info in the task description.
+- Automatic application of the template (and optionally the sales line info) when creating tasks from sales orders.
diff --git a/sale_project_task_description_template/readme/USAGE.md b/sale_project_task_description_template/readme/USAGE.md
new file mode 100644
index 0000000000..9d0d8a8c4d
--- /dev/null
+++ b/sale_project_task_description_template/readme/USAGE.md
@@ -0,0 +1,16 @@
+To use this module:
+
+- Create a Task Description Template
+ - Go to Project → Configuration → Task Description Templates.
+ - Define a template with a name and description.
+- Assign the Template to a Product.
+ - Open a Product and set it as a Service.
+ - Ensure that Service Tracking is set to Task or Project & Task.
+ - Set the Task Description Template field.
+ - Optionally, enable the Include Sale Line Info in Task checkbox to add product and quantity information above the template in generated tasks.
+- Create a Sale Order
+ - Add the product(s) with assigned templates to a sales order.
+ - Confirm the order.
+- Generated Project Tasks
+ - The tasks created from the sales order lines will automatically include the description from the assigned template.
+ - If enabled, the sales line info (product and quantity) will appear above the template in the task description.
diff --git a/sale_project_task_description_template/static/description/icon.png b/sale_project_task_description_template/static/description/icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d
GIT binary patch
literal 9455
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
z
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
Xviia!U7SGha1wx#SCgwmn*{w2TRX*I
literal 0
HcmV?d00001
diff --git a/sale_project_task_description_template/static/description/index.html b/sale_project_task_description_template/static/description/index.html
new file mode 100644
index 0000000000..1dd675dd84
--- /dev/null
+++ b/sale_project_task_description_template/static/description/index.html
@@ -0,0 +1,479 @@
+
+
+
+
+
+README.rst
+
+
+
+
+
+
+
+
+
+
+
Sale Project Task Description Template
+
+

+
This module extends the Project Task Description Template and integrates
+it with Sales and Projects. When tasks are generated from sales order
+lines, the task will automatically use the Task Description Template
+defined on the related product.
+
Optionally, you can include key information from the sales order line
+(like product name and quantity) above the template, providing more
+context directly in the task description.
+
Key Features:
+
+- New field on product: assign a Task Description Template for service
+products with Service Tracking set to ‘Task’ or ‘Project & Task’.
+- Optional boolean to include the sale order line info in the task
+description.
+- Automatic application of the template (and optionally the sales line
+info) when creating tasks from sales orders.
+
+
Table of contents
+
+
+
+
To use this module:
+
+- Create a Task Description Template
+- Go to Project → Configuration → Task Description Templates.
+- Define a template with a name and description.
+
+
+- Assign the Template to a Product.
+- Open a Product and set it as a Service.
+- Ensure that Service Tracking is set to Task or Project & Task.
+- Set the Task Description Template field.
+- Optionally, enable the Include Sale Line Info in Task checkbox to
+add product and quantity information above the template in generated
+tasks.
+
+
+- Create a Sale Order
+- Add the product(s) with assigned templates to a sales order.
+- Confirm the order.
+
+
+- Generated Project Tasks
+- The tasks created from the sales order lines will automatically
+include the description from the assigned template.
+- If enabled, the sales line info (product and quantity) will appear
+above the template in the task description.
+
+
+
+
+
+
+
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.
+
+
+
+
+
+
+- NICO SOLUTIONS - ENGINEERING & IT
+
+
+
+
+
+
This module is maintained by the OCA.
+
+
+
+
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:
+

+
This module is part of the OCA/project project on GitHub.
+
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
+
+
+
+
+
+
diff --git a/sale_project_task_description_template/tests/__init__.py b/sale_project_task_description_template/tests/__init__.py
new file mode 100644
index 0000000000..3bd542de4f
--- /dev/null
+++ b/sale_project_task_description_template/tests/__init__.py
@@ -0,0 +1,2 @@
+from . import test_product_template
+from . import test_sale_order_line
diff --git a/sale_project_task_description_template/tests/test_product_template.py b/sale_project_task_description_template/tests/test_product_template.py
new file mode 100644
index 0000000000..b85d7b13e2
--- /dev/null
+++ b/sale_project_task_description_template/tests/test_product_template.py
@@ -0,0 +1,37 @@
+# Copyright 2025 NICO SOLUTIONS - ENGINEERING & IT
+# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
+
+from odoo.tests.common import TransactionCase
+
+
+class TestProductTemplate(TransactionCase):
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass()
+ cls.task_template = cls.env["project.task.description.template"].create(
+ {
+ "name": "Test Task Template",
+ "description": "Template Description",
+ }
+ )
+ cls.product = cls.env["product.template"].create(
+ {
+ "name": "Test Product",
+ "task_description_template_id": cls.task_template.id,
+ "include_sale_line_info_in_task": True,
+ }
+ )
+
+ def test_template_assignment(self):
+ self.assertEqual(
+ self.product.task_description_template_id,
+ self.task_template,
+ "Template should be saved correctly in the product.",
+ )
+
+ def test_flag_include_sale_line_info(self):
+ self.product.include_sale_line_info_in_task = False
+ self.assertFalse(
+ self.product.include_sale_line_info_in_task,
+ "Flag should be False after change.",
+ )
diff --git a/sale_project_task_description_template/tests/test_sale_order_line.py b/sale_project_task_description_template/tests/test_sale_order_line.py
new file mode 100644
index 0000000000..0a9200303a
--- /dev/null
+++ b/sale_project_task_description_template/tests/test_sale_order_line.py
@@ -0,0 +1,92 @@
+# Copyright 2025 NICO SOLUTIONS - ENGINEERING & IT
+# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
+
+from odoo.tests.common import TransactionCase
+
+
+class TestSaleOrderLine(TransactionCase):
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass()
+ cls.task_template = cls.env["project.task.description.template"].create(
+ {
+ "name": "Test Template",
+ "description": "Template Description",
+ }
+ )
+ cls.empty_template = cls.env["project.task.description.template"].create(
+ {
+ "name": "Empty Template",
+ "description": "",
+ }
+ )
+ cls.product = cls.env["product.template"].create(
+ {
+ "name": "Test Product",
+ "task_description_template_id": cls.task_template.id,
+ "include_sale_line_info_in_task": True,
+ }
+ )
+ cls.partner = cls.env["res.partner"].search([], limit=1)
+ cls.sale_order = cls.env["sale.order"].create({"partner_id": cls.partner.id})
+ cls.project = cls.env["project.project"].create(
+ {
+ "name": "Test Project",
+ "billing_type": "not_billable",
+ "allow_timesheets": True,
+ }
+ )
+
+ def _prepare_task_values(self, include_sale_line_info=False, template=None, qty=1):
+ self.product.include_sale_line_info_in_task = include_sale_line_info
+ self.product.task_description_template_id = template or False
+ sale_line = self.env["sale.order.line"].create(
+ {
+ "order_id": self.sale_order.id,
+ "product_id": self.product.product_variant_id.id,
+ "product_uom_qty": qty,
+ }
+ )
+ return sale_line._timesheet_create_task_prepare_values(project=self.project)
+
+ def test_task_values_without_template(self):
+ values = self._prepare_task_values(
+ include_sale_line_info=False, template=None, qty=1
+ )
+ self.assertNotIn("description_template_id", values)
+ self.assertIn("description", values)
+ self.assertEqual(values["description"], "")
+
+ def test_task_values_with_template_only(self):
+ values = self._prepare_task_values(
+ include_sale_line_info=False, template=self.task_template, qty=2
+ )
+ self.assertIn("description_template_id", values)
+ self.assertEqual(values["description_template_id"], self.task_template.id)
+ self.assertEqual(values["description"], self.task_template.description)
+
+ def test_task_values_with_template_and_sale_info(self):
+ values = self._prepare_task_values(
+ include_sale_line_info=True, template=self.task_template, qty=3
+ )
+ expected_prefix = f"{self.product.name} - Qty: 3"
+ self.assertIn("description_template_id", values)
+ self.assertTrue(values["description"].startswith(expected_prefix))
+ self.assertIn(self.task_template.description, values["description"])
+
+ def test_task_values_with_empty_template_only(self):
+ values = self._prepare_task_values(
+ include_sale_line_info=False, template=self.empty_template, qty=5
+ )
+ self.assertIn("description", values)
+ self.assertEqual(values["description"], "")
+ self.assertIn("description_template_id", values)
+
+ def test_task_values_with_empty_template_and_sale_info(self):
+ values = self._prepare_task_values(
+ include_sale_line_info=True, template=self.empty_template, qty=4
+ )
+ expected_prefix = f"{self.product.name} - Qty: 4.0"
+ self.assertIn("description", values)
+ self.assertEqual(values["description"], expected_prefix)
+ self.assertIn("description_template_id", values)
diff --git a/sale_project_task_description_template/views/product_template_views.xml b/sale_project_task_description_template/views/product_template_views.xml
new file mode 100644
index 0000000000..0e38cb5e5b
--- /dev/null
+++ b/sale_project_task_description_template/views/product_template_views.xml
@@ -0,0 +1,23 @@
+
+
+
+
+ product.template.form.inherit.task.template
+ product.template
+
+
+
+
+
+
+
+
+
From bf8fefdbfd84ce74126adbfd74ef99d70cab90bb Mon Sep 17 00:00:00 2001
From: Bosd
Date: Tue, 14 Jul 2026 11:55:45 +0000
Subject: [PATCH 2/4] Added translation using Weblate (Dutch)
Translated using Weblate (Dutch)
Currently translated at 100.0% (7 of 7 strings)
Translation: project-18.0/project-18.0-sale_project_task_description_template
Translate-URL: https://translation.odoo-community.org/projects/project-18-0/project-18-0-sale_project_task_description_template/nl/
---
.../i18n/nl.po | 63 +++++++++++++++++++
1 file changed, 63 insertions(+)
create mode 100644 sale_project_task_description_template/i18n/nl.po
diff --git a/sale_project_task_description_template/i18n/nl.po b/sale_project_task_description_template/i18n/nl.po
new file mode 100644
index 0000000000..017dfa557c
--- /dev/null
+++ b/sale_project_task_description_template/i18n/nl.po
@@ -0,0 +1,63 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * sale_project_task_description_template
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 18.0\n"
+"Report-Msgid-Bugs-To: \n"
+"PO-Revision-Date: 2026-07-14 12:11+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 5.15.2\n"
+
+#. module: sale_project_task_description_template
+#. odoo-python
+#: code:addons/sale_project_task_description_template/models/sale_order_line.py:0
+msgid "%(product)s - Qty: %(qty)s"
+msgstr "%(product)s - Aantal: %(qty)s"
+
+#. module: sale_project_task_description_template
+#: model:ir.model.fields,help:sale_project_task_description_template.field_product_product__task_description_template_id
+#: model:ir.model.fields,help:sale_project_task_description_template.field_product_template__task_description_template_id
+msgid "Applies automatically when creating tasks"
+msgstr "Wordt automatisch toegepast bij het aanmaken van taken"
+
+#. module: sale_project_task_description_template
+#: model:ir.model.fields,help:sale_project_task_description_template.field_product_product__include_sale_line_info_in_task
+#: model:ir.model.fields,help:sale_project_task_description_template.field_product_template__include_sale_line_info_in_task
+msgid ""
+"If enabled, the sale order line details (e.g., product and quantity) will be"
+" added to the task description before the template content."
+msgstr ""
+"Indien ingeschakeld, worden de details van de verkooporderregel (bijv. "
+"product en aantal) toegevoegd aan de taakomschrijving vóór de inhoud van de "
+"sjabloon."
+
+#. module: sale_project_task_description_template
+#: model:ir.model.fields,field_description:sale_project_task_description_template.field_product_product__include_sale_line_info_in_task
+#: model:ir.model.fields,field_description:sale_project_task_description_template.field_product_template__include_sale_line_info_in_task
+msgid "Include Sale Line Info in Task description"
+msgstr "Verkoopregelinfo opnemen in taakomschrijving"
+
+#. module: sale_project_task_description_template
+#: model:ir.model,name:sale_project_task_description_template.model_product_template
+msgid "Product"
+msgstr "Product"
+
+#. module: sale_project_task_description_template
+#: model:ir.model,name:sale_project_task_description_template.model_sale_order_line
+msgid "Sales Order Line"
+msgstr "Verkooporderregel"
+
+#. module: sale_project_task_description_template
+#: model:ir.model.fields,field_description:sale_project_task_description_template.field_product_product__task_description_template_id
+#: model:ir.model.fields,field_description:sale_project_task_description_template.field_product_template__task_description_template_id
+#: model_terms:ir.ui.view,arch_db:sale_project_task_description_template.product_template_form_inherit_task_template
+msgid "Task Description Template"
+msgstr "Sjabloon taakomschrijving"
From 28241c1ff35782e65bb63267f3a27a0260e1b029 Mon Sep 17 00:00:00 2001
From: Nils Coenen
Date: Tue, 14 Jul 2026 15:11:32 +0000
Subject: [PATCH 3/4] Added translation using Weblate (German)
Translated using Weblate (German)
Currently translated at 100.0% (7 of 7 strings)
Translation: project-18.0/project-18.0-sale_project_task_description_template
Translate-URL: https://translation.odoo-community.org/projects/project-18-0/project-18-0-sale_project_task_description_template/de/
---
.../i18n/de.po | 63 +++++++++++++++++++
1 file changed, 63 insertions(+)
create mode 100644 sale_project_task_description_template/i18n/de.po
diff --git a/sale_project_task_description_template/i18n/de.po b/sale_project_task_description_template/i18n/de.po
new file mode 100644
index 0000000000..bb347f9520
--- /dev/null
+++ b/sale_project_task_description_template/i18n/de.po
@@ -0,0 +1,63 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * sale_project_task_description_template
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 18.0\n"
+"Report-Msgid-Bugs-To: \n"
+"PO-Revision-Date: 2026-07-14 16:41+0000\n"
+"Last-Translator: Nils Coenen \n"
+"Language-Team: none\n"
+"Language: de\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.15.2\n"
+
+#. module: sale_project_task_description_template
+#. odoo-python
+#: code:addons/sale_project_task_description_template/models/sale_order_line.py:0
+msgid "%(product)s - Qty: %(qty)s"
+msgstr "%(product)s - Anzahl: %(qty)s"
+
+#. module: sale_project_task_description_template
+#: model:ir.model.fields,help:sale_project_task_description_template.field_product_product__task_description_template_id
+#: model:ir.model.fields,help:sale_project_task_description_template.field_product_template__task_description_template_id
+msgid "Applies automatically when creating tasks"
+msgstr "Wird beim Erstellen von Aufgaben automatisch angewendet."
+
+#. module: sale_project_task_description_template
+#: model:ir.model.fields,help:sale_project_task_description_template.field_product_product__include_sale_line_info_in_task
+#: model:ir.model.fields,help:sale_project_task_description_template.field_product_template__include_sale_line_info_in_task
+msgid ""
+"If enabled, the sale order line details (e.g., product and quantity) will be"
+" added to the task description before the template content."
+msgstr ""
+"Wenn diese Option aktiviert ist, werden die Details der "
+"Verkaufsauftragsposition (z. B. Produkt und Menge) vor dem Inhalt der "
+"Vorlage zur Aufgabenbeschreibung hinzugefügt."
+
+#. module: sale_project_task_description_template
+#: model:ir.model.fields,field_description:sale_project_task_description_template.field_product_product__include_sale_line_info_in_task
+#: model:ir.model.fields,field_description:sale_project_task_description_template.field_product_template__include_sale_line_info_in_task
+msgid "Include Sale Line Info in Task description"
+msgstr "Verkaufsinformationen in die Aufgabenbeschreibung aufnehmen"
+
+#. module: sale_project_task_description_template
+#: model:ir.model,name:sale_project_task_description_template.model_product_template
+msgid "Product"
+msgstr "Produkt"
+
+#. module: sale_project_task_description_template
+#: model:ir.model,name:sale_project_task_description_template.model_sale_order_line
+msgid "Sales Order Line"
+msgstr "Auftragsposition"
+
+#. module: sale_project_task_description_template
+#: model:ir.model.fields,field_description:sale_project_task_description_template.field_product_product__task_description_template_id
+#: model:ir.model.fields,field_description:sale_project_task_description_template.field_product_template__task_description_template_id
+#: model_terms:ir.ui.view,arch_db:sale_project_task_description_template.product_template_form_inherit_task_template
+msgid "Task Description Template"
+msgstr "Vorlage für Aufgabenbeschreibungen"
From ad093c5100a3c62096f49b0e68e811d9dbbe60ab Mon Sep 17 00:00:00 2001
From: Nils Coenen
Date: Wed, 15 Jul 2026 13:15:47 +0200
Subject: [PATCH 4/4] [MIG] sale_project_task_description_template: Migration
to 19.0
---
.../README.rst | 60 +++++++++----------
.../__manifest__.py | 2 +-
.../models/sale_order_line.py | 11 ++--
.../static/description/index.html | 10 ++--
4 files changed, 42 insertions(+), 41 deletions(-)
diff --git a/sale_project_task_description_template/README.rst b/sale_project_task_description_template/README.rst
index c66bb313f5..d2f0e7484a 100644
--- a/sale_project_task_description_template/README.rst
+++ b/sale_project_task_description_template/README.rst
@@ -21,13 +21,13 @@ Sale Project Task Description Template
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
:alt: License: LGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fproject-lightgray.png?logo=github
- :target: https://github.com/OCA/project/tree/18.0/sale_project_task_description_template
+ :target: https://github.com/OCA/project/tree/19.0/sale_project_task_description_template
:alt: OCA/project
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
- :target: https://translation.odoo-community.org/projects/project-18-0/project-18-0-sale_project_task_description_template
+ :target: https://translation.odoo-community.org/projects/project-19-0/project-19-0-sale_project_task_description_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/project&target_branch=18.0
+ :target: https://runboat.odoo-community.org/builds?repo=OCA/project&target_branch=19.0
:alt: Try me on Runboat
|badge1| |badge2| |badge3| |badge4| |badge5|
@@ -43,12 +43,12 @@ context directly in the task description.
Key Features:
-- New field on product: assign a Task Description Template for service
- products with Service Tracking set to 'Task' or 'Project & Task'.
-- Optional boolean to include the sale order line info in the task
- description.
-- Automatic application of the template (and optionally the sales line
- info) when creating tasks from sales orders.
+- New field on product: assign a Task Description Template for service
+ products with Service Tracking set to 'Task' or 'Project & Task'.
+- Optional boolean to include the sale order line info in the task
+ description.
+- Automatic application of the template (and optionally the sales line
+ info) when creating tasks from sales orders.
**Table of contents**
@@ -60,31 +60,31 @@ Usage
To use this module:
-- Create a Task Description Template
+- Create a Task Description Template
- - Go to Project → Configuration → Task Description Templates.
- - Define a template with a name and description.
+ - Go to Project → Configuration → Task Description Templates.
+ - Define a template with a name and description.
-- Assign the Template to a Product.
+- Assign the Template to a Product.
- - Open a Product and set it as a Service.
- - Ensure that Service Tracking is set to Task or Project & Task.
- - Set the Task Description Template field.
- - Optionally, enable the Include Sale Line Info in Task checkbox to
- add product and quantity information above the template in generated
- tasks.
+ - Open a Product and set it as a Service.
+ - Ensure that Service Tracking is set to Task or Project & Task.
+ - Set the Task Description Template field.
+ - Optionally, enable the Include Sale Line Info in Task checkbox to
+ add product and quantity information above the template in
+ generated tasks.
-- Create a Sale Order
+- Create a Sale Order
- - Add the product(s) with assigned templates to a sales order.
- - Confirm the order.
+ - Add the product(s) with assigned templates to a sales order.
+ - Confirm the order.
-- Generated Project Tasks
+- Generated Project Tasks
- - The tasks created from the sales order lines will automatically
- include the description from the assigned template.
- - If enabled, the sales line info (product and quantity) will appear
- above the template in the task description.
+ - The tasks created from the sales order lines will automatically
+ include the description from the assigned template.
+ - If enabled, the sales line info (product and quantity) will appear
+ above the template in the task description.
Bug Tracker
===========
@@ -92,7 +92,7 @@ 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 `_.
+`feedback `_.
Do not contact contributors directly about support or help with technical issues.
@@ -107,7 +107,7 @@ Authors
Contributors
------------
-- Nils Coenen
+- Nils Coenen
Maintainers
-----------
@@ -130,6 +130,6 @@ Current `maintainer `__:
|maintainer-NICO-SOLUTIONS|
-This module is part of the `OCA/project `_ project on GitHub.
+This module is part of the `OCA/project `_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/sale_project_task_description_template/__manifest__.py b/sale_project_task_description_template/__manifest__.py
index f75227eae0..4d567a0c6b 100644
--- a/sale_project_task_description_template/__manifest__.py
+++ b/sale_project_task_description_template/__manifest__.py
@@ -6,7 +6,7 @@
"Apply task description templates from products to tasks, "
"with optional sale info"
),
- "version": "18.0.1.0.0",
+ "version": "19.0.1.0.0",
"category": "Project",
"website": "https://github.com/OCA/project",
"author": "NICO SOLUTIONS - ENGINEERING & IT, Odoo Community Association (OCA)",
diff --git a/sale_project_task_description_template/models/sale_order_line.py b/sale_project_task_description_template/models/sale_order_line.py
index 9623fb6ce6..5f9956be9a 100644
--- a/sale_project_task_description_template/models/sale_order_line.py
+++ b/sale_project_task_description_template/models/sale_order_line.py
@@ -1,7 +1,7 @@
# Copyright 2025 NICO SOLUTIONS - ENGINEERING & IT
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
-from odoo import _, models
+from odoo import models
class SaleOrderLine(models.Model):
@@ -17,10 +17,11 @@ def _timesheet_create_task_prepare_values(self, project):
values["description_template_id"] = template.id
if product.include_sale_line_info_in_task:
- product_info = _("%(product)s - Qty: %(qty)s") % {
- "product": self.product_id.name,
- "qty": self.product_uom_qty,
- }
+ product_info = self.env._(
+ "%(product)s - Qty: %(qty)s",
+ product=self.product_id.name,
+ qty=self.product_uom_qty,
+ )
if template and template.description:
values["description"] = f"{product_info}\n\n{template.description}"
diff --git a/sale_project_task_description_template/static/description/index.html b/sale_project_task_description_template/static/description/index.html
index 1dd675dd84..c1f5a96dd3 100644
--- a/sale_project_task_description_template/static/description/index.html
+++ b/sale_project_task_description_template/static/description/index.html
@@ -374,7 +374,7 @@ Sale Project Task Description Template
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:fc4721c380633a7a1854f4da47d823d8567e854b849849096e6e48d7dc348107
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
-

+

This module extends the Project Task Description Template and integrates
it with Sales and Projects. When tasks are generated from sales order
lines, the task will automatically use the Task Description Template
@@ -418,8 +418,8 @@
Ensure that Service Tracking is set to Task or Project & Task.
Set the Task Description Template field.
Optionally, enable the Include Sale Line Info in Task checkbox to
-add product and quantity information above the template in generated
-tasks.
+add product and quantity information above the template in
+generated tasks.
Create a Sale Order
@@ -441,7 +441,7 @@
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.
+feedback.
Do not contact contributors directly about support or help with technical issues.