diff --git a/base_comment_template/migrations/13.0.1.0.0/pre-migration.py b/base_comment_template/migrations/13.0.1.0.0/pre-migration.py
new file mode 100644
index 000000000..edac68919
--- /dev/null
+++ b/base_comment_template/migrations/13.0.1.0.0/pre-migration.py
@@ -0,0 +1,22 @@
+# Copyright 2020 NextERP Romania SRL
+# Copyright 2021 Tecnativa - Víctor Martínez
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+from openupgradelib import openupgrade
+
+
+@openupgrade.migrate()
+def migrate(env, version):
+ # Not tested
+ openupgrade.logged_query(
+ env.cr,
+ """
+ INSERT INTO base_comment_template_res_partner_rel
+ (res_partner_id, base_comment_template_id)
+ SELECT SPLIT_PART(ip.res_id, ',', 2)::int AS res_partner_id,
+ SPLIT_PART(ip.value_reference, ',', 2)::int AS base_comment_template_id
+ FROM ir_property ip
+ JOIN ir_model_fields imf ON ip.fields_id = imf.id
+ WHERE imf.name = 'property_comment_template_id'
+ AND imf.model = 'res.partner'
+ """,
+ )
diff --git a/base_comment_template/migrations/13.0.2.0.0/pre-migration.py b/base_comment_template/migrations/13.0.2.0.0/pre-migration.py
new file mode 100644
index 000000000..a80f06fc2
--- /dev/null
+++ b/base_comment_template/migrations/13.0.2.0.0/pre-migration.py
@@ -0,0 +1,12 @@
+# Copyright 2021 Tecnativa - Víctor Martínez
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
+from openupgradelib import openupgrade # pylint: disable=W7936
+
+field_renames = [
+ ("base.comment.template", "base_comment_template", "priority", "sequence"),
+]
+
+
+@openupgrade.migrate()
+def migrate(env, version):
+ openupgrade.rename_fields(env, field_renames)
diff --git a/base_comment_template/migrations/14.0.1.0.0/pre-migration.py b/base_comment_template/migrations/14.0.1.0.0/pre-migration.py
deleted file mode 100644
index fd5a0c1cb..000000000
--- a/base_comment_template/migrations/14.0.1.0.0/pre-migration.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright 2020 NextERP Romania SRL
-# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
-from openupgradelib import openupgrade
-
-
-@openupgrade.migrate()
-def migrate(env, version):
- # Not tested
- properties = env["ir.property"].search(
- [
- (
- "fields_id",
- "=",
- env.ref("base.field_res_partner_property_comment_template_id").id,
- )
- ]
- )
- if properties:
- for template in properties.mapped("value_reference"):
- template_id = template.value_reference.split(",")[-1]
- if template_id:
- template = env["base.comment.template"].browse(template_id)
- part_prop = properties.filtered(lambda p: p.value_reference == template)
- template.partner_ids = [
- (prop["res_id"] or "").split(",")[-1] for prop in part_prop
- ]
diff --git a/base_comment_template/models/__init__.py b/base_comment_template/models/__init__.py
index 4d140780f..d695c580a 100644
--- a/base_comment_template/models/__init__.py
+++ b/base_comment_template/models/__init__.py
@@ -1,3 +1,4 @@
from . import base_comment_template
+from . import comment_template
from . import res_partner
from . import ir_model
diff --git a/base_comment_template/models/base_comment_template.py b/base_comment_template/models/base_comment_template.py
index 721e4e0fd..92d86807a 100644
--- a/base_comment_template/models/base_comment_template.py
+++ b/base_comment_template/models/base_comment_template.py
@@ -1,76 +1,9 @@
# Copyright 2014 Guewen Baconnier (Camptocamp SA)
# Copyright 2013-2014 Nicolas Bessi (Camptocamp SA)
# Copyright 2020 NextERP Romania SRL
+# Copyright 2021 Tecnativa - Víctor Martínez
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
-from lxml import etree
-
-from odoo import _, api, fields, models
-from odoo.exceptions import ValidationError
-from odoo.tools.safe_eval import safe_eval
-
-
-class CommentTemplate(models.AbstractModel):
- _name = "comment.template"
- _description = (
- "base.comment.template to put header and footer "
- "in reports based on created comment templates"
- )
-
- def get_comment_template_records(
- self, position="before_lines", company_id=False, partner_id=False
- ):
- self.ensure_one()
- if not company_id:
- company_id = self.env.company.id
- present_model_id = self.env["ir.model"].search([("model", "=", self._name)])
- default_dom = [
- ("model_ids", "in", present_model_id.id),
- ("position", "=", position),
- ]
- lang = False
- if partner_id and "partner_id" in self._fields:
- default_dom += [
- "|",
- ("partner_ids", "=", False),
- ("partner_ids", "in", partner_id),
- ]
- lang = self.env["res.partner"].browse(partner_id).lang
- if company_id and "company_id" in self._fields:
- if partner_id and "partner_id" in self._fields:
- default_dom.insert(-3, "&")
- default_dom += [
- "|",
- ("company_id", "=", company_id),
- ("company_id", "=", False),
- ]
- templates = self.env["base.comment.template"].search(
- default_dom, order="priority"
- )
- if lang:
- templates = templates.with_context({"lang": lang})
- return templates
-
- def get_comment_template(
- self, position="before_lines", company_id=False, partner_id=False
- ):
- """ Method that is called from report xml and is returning the
- position template as a html if exists
- """
- self.ensure_one()
- templates = self.get_comment_template_records(
- position=position, company_id=company_id, partner_id=partner_id
- )
- template = False
- if templates:
- for templ in templates:
- if self in self.search(safe_eval(templ.domain or "[]")):
- template = templ
- break
- if not template:
- return ""
- return self.env["mail.template"]._render_template(
- template.text, self._name, self.id, post_process=True
- )
+from odoo import fields, models
class BaseCommentTemplate(models.Model):
@@ -78,11 +11,12 @@ class BaseCommentTemplate(models.Model):
_name = "base.comment.template"
_description = "Comments Template"
+ _order = "sequence,id"
active = fields.Boolean(default=True)
position = fields.Selection(
string="Position on document",
- selection=[("before_lines", "Before lines"), ("after_lines", "After lines")],
+ selection=[("before_lines", "Top"), ("after_lines", "Bottom")],
required=True,
default="before_lines",
help="This field allows to select the position of the comment on reports.",
@@ -101,7 +35,7 @@ class BaseCommentTemplate(models.Model):
help="This is the text template that will be inserted into reports.",
)
company_id = fields.Many2one(
- "res.company",
+ comodel_name="res.company",
string="Company",
ondelete="cascade",
index=True,
@@ -110,79 +44,46 @@ class BaseCommentTemplate(models.Model):
)
partner_ids = fields.Many2many(
comodel_name="res.partner",
+ relation="base_comment_template_res_partner_rel",
+ column1="res_partner_id",
+ column2="base_comment_template_id",
string="Partner",
- ondelete="cascade",
+ readonly=True,
help="If set, the comment template will be available only for the selected "
"partner.",
)
-
model_ids = fields.Many2many(
comodel_name="ir.model",
string="IR Model",
ondelete="cascade",
+ domain=[
+ ("is_comment_template", "=", True),
+ ("model", "!=", "comment.template"),
+ ],
required=True,
help="This comment template will be available on this models. "
"You can see here only models allowed to set the coment template.",
)
-
domain = fields.Char(
- "Filter Domain",
+ string="Filter Domain",
required=True,
default="[]",
help="This comment template will be available only for objects "
"that satisfy the condition",
)
-
- priority = fields.Integer(
- default=10, copy=False, help="the highest priority = the smallest number",
+ sequence = fields.Integer(
+ required=True, default=10, help="The smaller number = The higher priority"
)
- @api.constrains("domain", "priority", "model_ids", "position")
- def _check_partners_in_company_id(self):
- templates = self.search([])
- for record in self:
- other_template_same_models_and_priority = templates.filtered(
- lambda t: t.priority == record.priority
- and set(record.model_ids).intersection(record.model_ids)
- and t.domain == record.domain
- and t.position == record.position
- and t.id != record.id
+ def name_get(self):
+ """Redefine the name_get method to show the template name with the position.
+ """
+ res = []
+ for item in self:
+ name = "{} ({})".format(
+ item.name, dict(self._fields["position"].selection).get(item.position)
)
- if other_template_same_models_and_priority:
- raise ValidationError(
- _(
- "There are other records with same models, priority, "
- "domain and position."
- )
- )
-
- @api.model
- def fields_view_get(
- self, view_id=None, view_type="form", toolbar=False, submenu=False
- ):
- # modify the form view of base_commnent_template
- # Add domain on model_id to get only models that have a report set
- # and those whom have inherited this model
- res = super().fields_view_get(
- view_id=view_id, view_type=view_type, toolbar=toolbar, submenu=submenu
- )
- if view_type == "form":
- doc = etree.XML(res["arch"])
- for node in doc.xpath("//field[@name='model_ids']"):
- report_models = self.env["ir.actions.report"].search([]).mapped("model")
- model_ids = (
- self.env["ir.model"]
- .search(
- [
- ("model", "in", report_models),
- ("is_comment_template", "=", True),
- "!",
- ("name", "=like", "ir.%"),
- ]
- )
- .ids
- )
- model_filter = "[('id','in'," + str(model_ids) + ")]"
- node.set("domain", model_filter)
- res["arch"] = etree.tostring(doc, encoding="unicode")
+ if self.env.context.get("comment_template_model_display"):
+ name += " (%s)" % ", ".join(item.model_ids.mapped("name"))
+ res.append((item.id, name))
return res
diff --git a/base_comment_template/models/comment_template.py b/base_comment_template/models/comment_template.py
new file mode 100644
index 000000000..465e6ddc6
--- /dev/null
+++ b/base_comment_template/models/comment_template.py
@@ -0,0 +1,45 @@
+# Copyright 2014 Guewen Baconnier (Camptocamp SA)
+# Copyright 2013-2014 Nicolas Bessi (Camptocamp SA)
+# Copyright 2020 NextERP Romania SRL
+# Copyright 2021 Tecnativa - Víctor Martínez
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
+from odoo import api, fields, models
+from odoo.tools.safe_eval import safe_eval
+
+
+class CommentTemplate(models.AbstractModel):
+ _name = "comment.template"
+ _description = (
+ "base.comment.template to put header and footer "
+ "in reports based on created comment templates"
+ )
+ # This field allows to set any given field that determines the source partner for
+ # the comment templates downstream.
+ # E.g.: other models where the partner field is called customer_id.
+ _comment_template_partner_field_name = "partner_id"
+
+ comment_template_ids = fields.Many2many(
+ compute="_compute_comment_template_ids",
+ comodel_name="base.comment.template",
+ string="Comment Template",
+ domain=lambda self: [("model_ids.model", "=", self._name)],
+ store=True,
+ readonly=False,
+ )
+
+ @api.depends(_comment_template_partner_field_name)
+ def _compute_comment_template_ids(self):
+ for record in self:
+ partner = record[self._comment_template_partner_field_name]
+ record.comment_template_ids = [(5,)]
+ templates = self.env["base.comment.template"].search(
+ [
+ ("id", "in", partner.base_comment_template_ids.ids),
+ ("model_ids.model", "=", self._name),
+ ]
+ )
+ for template in templates:
+ if not template.domain or self in self.search(
+ safe_eval(template.domain)
+ ):
+ record.comment_template_ids = [(4, template.id)]
diff --git a/base_comment_template/models/res_partner.py b/base_comment_template/models/res_partner.py
index 0f6124961..9d9b1c606 100644
--- a/base_comment_template/models/res_partner.py
+++ b/base_comment_template/models/res_partner.py
@@ -1,7 +1,8 @@
# Copyright 2020 NextERP Romania SRL
+# Copyright 2021 Tecnativa - Víctor Martínez
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
-from odoo import fields, models
+from odoo import api, fields, models
class ResPartner(models.Model):
@@ -9,6 +10,14 @@ class ResPartner(models.Model):
base_comment_template_ids = fields.Many2many(
comodel_name="base.comment.template",
+ relation="base_comment_template_res_partner_rel",
+ column1="base_comment_template_id",
+ column2="res_partner_id",
string="Comment Templates",
help="Specific partner comments that can be included in reports",
)
+
+ @api.model
+ def _commercial_fields(self):
+ """Add comment templates to commercial fields"""
+ return super()._commercial_fields() + ["base_comment_template_ids"]
diff --git a/base_comment_template/tests/test_base_comment_template.py b/base_comment_template/tests/test_base_comment_template.py
index acf0fd76e..c191546ee 100644
--- a/base_comment_template/tests/test_base_comment_template.py
+++ b/base_comment_template/tests/test_base_comment_template.py
@@ -1,8 +1,6 @@
# Copyright 2020 NextERP Romania SRL
# Copyright 2021 Tecnativa - Víctor Martínez
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
-from lxml import etree
-
from odoo.tests import common
from .fake_models import ResUsers, setup_test_model, teardown_test_model
@@ -25,147 +23,68 @@ class TestCommentTemplate(common.SavepointCase):
cls.company = cls.env["res.company"].create({"name": "Test company"})
cls.before_template_id = cls.env["base.comment.template"].create(
{
- "name": "before_lines",
+ "name": "Top template",
"text": "Text before lines",
"model_ids": [(6, 0, cls.user_obj.ids)],
- "priority": 5,
- "company_id": cls.main_company.id,
+ "company_id": cls.company.id,
}
)
cls.after_template_id = cls.env["base.comment.template"].create(
{
- "name": "after_lines",
+ "name": "Bottom template",
"position": "after_lines",
"text": "Text after lines",
"model_ids": [(6, 0, cls.user_obj.ids)],
- "priority": 6,
- "company_id": cls.main_company.id,
+ "company_id": cls.company.id,
}
)
+ cls.user.partner_id.base_comment_template_ids = [
+ (4, cls.before_template_id.id),
+ (4, cls.after_template_id.id),
+ ]
@classmethod
def tearDownClass(cls):
teardown_test_model(cls.env, ResUsers)
super(TestCommentTemplate, cls).tearDownClass()
- def test_general_template(self):
- # Check getting default comment template
- templ = self.user.get_comment_template("before_lines")
- self.assertEqual(templ, "Text before lines")
- templ = self.user.get_comment_template("after_lines")
- self.assertEqual(templ, "Text after lines")
-
- def test_company_general_template(self):
- # Check getting default comment template company
- self.before_template_id.company_id = self.company
- templ = self.user.get_comment_template("before_lines")
- self.assertEqual(templ, "")
- templ = self.user.get_comment_template(
- "before_lines", company_id=self.company.id
+ def test_template_name_get(self):
+ self.assertEqual(
+ self.before_template_id.display_name, "Top template (Top)",
)
- self.assertEqual(templ, "Text before lines")
- templ = self.user.get_comment_template("after_lines")
- self.assertEqual(templ, "Text after lines")
+ self.assertEqual(
+ self.after_template_id.display_name, "Bottom template (Bottom)",
+ )
+
+ def test_general_template(self):
+ # Need to force _compute because only trigger when partner_id have changed
+ self.user._compute_comment_template_ids()
+ # Check getting default comment template
+ self.assertTrue(self.before_template_id in self.user.comment_template_ids)
+ self.assertTrue(self.after_template_id in self.user.comment_template_ids)
def test_partner_template(self):
- # Check getting the comment template if partner is set
- self.before_template_id.partner_ids = self.partner2_id.ids
- templ = self.user.get_comment_template(
- "before_lines", partner_id=self.partner2_id.id
+ self.partner2_id.base_comment_template_ids = [
+ (4, self.before_template_id.id),
+ (4, self.after_template_id.id),
+ ]
+ self.assertTrue(
+ self.before_template_id in self.partner2_id.base_comment_template_ids
)
- self.assertEqual(templ, "Text before lines")
- templ = self.user.get_comment_template(
- "before_lines", partner_id=self.partner_id.id
+ self.assertTrue(
+ self.after_template_id in self.partner2_id.base_comment_template_ids
)
- self.assertEqual(templ, "")
- templ = self.user.get_comment_template("after_lines")
- self.assertEqual(templ, "Text after lines")
def test_partner_template_domain(self):
# Check getting the comment template if domain is set
- self.before_template_id.partner_ids = self.partner2_id.ids
+ self.partner2_id.base_comment_template_ids = [
+ (4, self.before_template_id.id),
+ (4, self.after_template_id.id),
+ ]
self.before_template_id.domain = "[('id', 'in', %s)]" % self.user.ids
- templ = self.user.get_comment_template(
- "before_lines", partner_id=self.partner2_id.id
- )
- self.assertEqual(templ, "Text before lines")
- templ = self.user2.get_comment_template(
- "before_lines", partner_id=self.partner_id.id
- )
- self.assertEqual(templ, "")
-
- def test_company_partner_template_domain(self):
- # Check getting the comment template with company and if domain is set
- self.before_template_id.company_id = self.company
- templ = self.user.get_comment_template("before_lines")
- self.assertEqual(templ, "")
- templ = self.user.get_comment_template(
- "before_lines", company_id=self.company.id
- )
- self.assertEqual(templ, "Text before lines")
- self.before_template_id.partner_ids = self.partner2_id.ids
- self.before_template_id.domain = "[('id', 'in', %s)]" % self.user.ids
- templ = self.user.get_comment_template(
- "before_lines", partner_id=self.partner2_id.id
- )
- self.assertEqual(templ, "")
- self.before_template_id.company_id = self.env.user.company_id
- templ = self.user.get_comment_template(
- "before_lines", partner_id=self.partner2_id.id
- )
- self.assertEqual(templ, "Text before lines")
- templ = self.user2.get_comment_template(
- "before_lines", partner_id=self.partner2_id.id
- )
- self.assertEqual(templ, "")
-
- def test_priority(self):
- # Check setting default template will change previous record default
- new_template = self.env["base.comment.template"].create(
- {
- "name": "before_lines",
- "text": "Text before lines 1",
- "model_ids": [(6, 0, self.user_obj.ids)],
- "priority": 2,
- }
- )
-
- self.assertEqual(new_template.text, "Text before lines 1")
-
- def test_check_partners_in_company_id(self):
- """ should rise any error because exist the same model,
- domain, position and priority"""
- with self.assertRaises(Exception) as context:
- self.before_template_id_2 = self.env["base.comment.template"].create(
- {
- "name": "before_lines",
- "text": "Text before lines",
- "model_ids": [(6, 0, self.user_obj.ids)],
- "priority": 5,
- }
- )
self.assertTrue(
- "There are other records with same models, priority, domain and position."
- == context.exception.args[0]
+ self.before_template_id in self.partner2_id.base_comment_template_ids
)
-
- # should not rise any error
- self.before_template_id_3 = self.env["base.comment.template"].create(
- {
- "name": "before_lines",
- "text": "Text before lines",
- "model_ids": [(6, 0, self.user_obj.ids)],
- "priority": 55,
- }
+ self.assertTrue(
+ self.before_template_id not in self.partner_id.base_comment_template_ids
)
-
- def test_fields_view_get(
- self, view_id=None, view_type="form", toolbar=False, submenu=False
- ):
- bf_tmp_form_view = self.before_template_id.fields_view_get()
- if view_type == "form":
- doc = etree.XML(bf_tmp_form_view["arch"])
- model_ids = doc.xpath("//field[@name='model_ids']")
- domain = model_ids[0].attrib["domain"]
- # if domain exist means that the filtering is done and the function is ok
- self.assertTrue(domain != "")
diff --git a/base_comment_template/views/base_comment_template_view.xml b/base_comment_template/views/base_comment_template_view.xml
index ab5b97321..79b4979a5 100644
--- a/base_comment_template/views/base_comment_template_view.xml
+++ b/base_comment_template/views/base_comment_template_view.xml
@@ -5,13 +5,13 @@
base.comment.template
+
-
@@ -26,7 +26,7 @@
-
+
@@ -58,9 +58,9 @@
name="company_id"
groups="base.group_multi_company"
/>
+
-
diff --git a/base_comment_template/views/res_partner_view.xml b/base_comment_template/views/res_partner_view.xml
index 74b19e528..d1fd4c7c2 100644
--- a/base_comment_template/views/res_partner_view.xml
+++ b/base_comment_template/views/res_partner_view.xml
@@ -6,14 +6,21 @@
+ context="{'comment_template_model_display': True}"
+ >
+
+
+
+
+
+
+
+