Browse Source

[IMP] base_comment_template: Refactor code and convert to Many2Many

myc-14.0-py3o
Víctor Martínez 4 years ago
parent
commit
19b7692ee8
  1. 22
      base_comment_template/migrations/13.0.1.0.0/pre-migration.py
  2. 12
      base_comment_template/migrations/13.0.2.0.0/pre-migration.py
  3. 26
      base_comment_template/migrations/14.0.1.0.0/pre-migration.py
  4. 1
      base_comment_template/models/__init__.py
  5. 153
      base_comment_template/models/base_comment_template.py
  6. 45
      base_comment_template/models/comment_template.py
  7. 11
      base_comment_template/models/res_partner.py
  8. 151
      base_comment_template/tests/test_base_comment_template.py
  9. 6
      base_comment_template/views/base_comment_template_view.xml
  10. 17
      base_comment_template/views/res_partner_view.xml

22
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'
""",
)

12
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)

26
base_comment_template/migrations/14.0.1.0.0/pre-migration.py

@ -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
]

1
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

153
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",
)
@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
)
if other_template_same_models_and_priority:
raise ValidationError(
_(
"There are other records with same models, priority, "
"domain and position."
)
sequence = fields.Integer(
required=True, default=10, help="The smaller number = The higher priority"
)
@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")
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 self.env.context.get("comment_template_model_display"):
name += " (%s)" % ", ".join(item.model_ids.mapped("name"))
res.append((item.id, name))
return res

45
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)]

11
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"]

151
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_template_name_get(self):
self.assertEqual(
self.before_template_id.display_name, "Top template (Top)",
)
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
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
)
self.assertEqual(templ, "Text before lines")
templ = self.user.get_comment_template("after_lines")
self.assertEqual(templ, "Text after lines")
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 != "")

6
base_comment_template/views/base_comment_template_view.xml

@ -5,13 +5,13 @@
<field name="model">base.comment.template</field>
<field name="arch" type="xml">
<tree string="Comment Templates">
<field name="sequence" widget="handle" />
<field name="name" />
<field name="position" />
<field name="company_id" groups="base.group_multi_company" />
<field name="partner_ids" />
<field name="model_ids" />
<field name="domain" />
<field name="priority" />
</tree>
</field>
</record>
@ -26,7 +26,7 @@
<field name="partner_ids" />
<field name="model_ids" />
<field name="domain" />
<field name="priority" />
<field name="sequence" />
</search>
</field>
</record>
@ -58,9 +58,9 @@
name="company_id"
groups="base.group_multi_company"
/>
<field name="domain" />
<field name="model_ids" widget="many2many_tags" />
<field name="partner_ids" widget="many2many_tags" />
<field name="priority" />
</group>
</group>
<notebook>

17
base_comment_template/views/res_partner_view.xml

@ -6,14 +6,21 @@
<page name='internal_notes' position="after">
<page name='base_comment_template_ids' string="Comment Templates">
<field
colspan="4"
mode="tree"
name="base_comment_template_ids"
nolabel="1"
widget="one2many"
height="300"
context="{'default_partner_id': active_id}"
context="{'comment_template_model_display': True}"
>
<tree>
<field name="display_name" string="Name" />
<field name="position" />
<field
name="company_id"
groups="base.group_multi_company"
/>
<field name="model_ids" />
<field name="domain" />
</tree>
</field>
</page>
</page>
</field>

Loading…
Cancel
Save