Newer
Older
##############################################################################
#
# Redner Odoo module
# Copyright © 2016 XCG Consulting <https://xcg-consulting.fr>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import logging
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError
from ..redner import Redner
LANGUAGE_MJML_MUSTACHE = "text/mjml|mustache"
DEFAULT_LANGUAGE = LANGUAGE_MJML_MUSTACHE
class RednerTemplate(models.Model):
_name = "redner.template"
damien.habets
committed
_description = "Redner Template"
name = fields.Char(
string="Name",
required=True,
help="This is a name of template mjml redner",
)
body = fields.Text(
string="Template remote Id",
translate=True,
help="Code for the mjml redner template must be added here",
)
slug = fields.Char(string="Slug")
active = fields.Boolean(
string="Active",
default=True,
help=(
"If unchecked, it will allow you to hide the "
"template without removing it."
),
)
is_mjml = fields.Boolean(
string="Is MJML",
default=True,
help="set to false if your template doesn't contain MJML",
)
detected_keywords = fields.Text(
string="Variables", readonly=True, compute="_compute_keywords"
selection=[
("text/html|mustache", "HTML + mustache"),
(LANGUAGE_MJML_MUSTACHE, "MJML + mustache"),
(
"application/vnd.oasis.opendocument.text|od+mustache",
"OpenDocument + mustache",
),
],
default="text/html|mustache",
required=True,
help="templating language",
)
redner_id = fields.Char(string="Redner ID", readonly=True)
locale_id = fields.Many2one(
comodel_name="res.lang",
string="Locale",
help="Optional translation language (ISO code).",
)
template_data = fields.Binary("Libreoffice Template")
@property
def redner(self):
"""Try to avoid Redner instance to be over created"""
# Bypass security rules when reading these configuration params. By
# default, only some administrators have access to that model.
config_model = self.env["ir.config_parameter"].sudo()
config_model.get_param("redner.api_key"),
config_model.get_param("redner.server_url"),
config_model.get_param("redner.account"),
int(config_model.get_param("redner.timeout", default="20")),
@api.model_create_multi
def create(self, vals_list):
"""Overwrite create to create redner template"""
for vals in vals_list:
# Prepare template params according to the selected language.
# Use template data field if the selected language is "od";
# otherwise the body field is used.
produces, language = vals.get("language", DEFAULT_LANGUAGE).split("|")
# Check if template data is of type bytes before decoding
if isinstance(vals.get("template_data", ""), bytes):
vals["template_data"] = vals[
"template_data"
].decode() # utf-8 by default
body, body_format = (
(vals.get("template_data", ""), "base64")
if language == "od+mustache"
else (vals.get("body"), "text")
)
# We depend on the API for consistency here
# So raised error should not result with a created template
vals["redner_id"] = self.redner.templates.account_template_add(
language=language,
body=body,
name=vals.get("name"),
produces=produces,
body_format=body_format,
version=fields.Datetime.to_string(fields.Datetime.now()),
)
def write(self, vals):
"""Overwrite write to update redner template"""
# Similar to the "send_to_rednerd_server" method; not worth factoring
# out.
# We depend on the API for consistency here
# So raised error should not result with an updated template
if "name" in vals:
self.ensure_one()
redner_id = self.redner_id
vals["redner_id"] = vals["name"]
produces, language = record.language.split("|")
(record.template_data.decode(), "base64")
if language == "od+mustache"
if "name" not in vals:
redner_id = record.redner_id
record.redner.templates.account_template_update(
template_id=redner_id,
language=language,
body=body,
body_format=body_format,
version=fields.Datetime.to_string(record.write_date),
_("Failed to update render template, %s") % e
) from e
def unlink(self):
"""Overwrite unlink to delete redner template"""
# We do NOT depend on the API for consistency here
# So raised error should not result block template deletion
try:
self.redner.templates.account_template_delete(self.redner_id)
except Exception:
pass
def copy(self, default=None):
self.ensure_one()
default = dict(default or {}, name=_("%s (copy)") % self.name)
record.detected_keywords = "\n".join(record.template_varlist_fetch())
varlist = self.template_varlist_fetch()
for name in varlist:
while "." in name:
name = name[: name.rfind(".")]
if name not in varlist:
varlist.append(name)
varlist.sort()
return varlist
@api.model
def template_varlist_fetch(self):
"""Retrieve the list of variables present in the template."""
try:
if not self.redner_id:
return []
return self.redner.templates.account_template_varlist(self.redner_id)
logger.warning("Failed to fetch account template varlist: %s", e)
def send_to_rednerd_server(self):
"""Send templates to the rednerd server. Useful when you have
existing templates you want to register onto a new rednerd server (or
with a new user).
"""
for record in self:
# Similar to the "write" method override; not worth factoring out.
templates = record.redner.templates
produces, language = record.language.split("|")
(record.template_data.decode(), "base64")
if language == "od+mustache"
template_id=record.redner_id,
language=language,
body=body,
name=record.name,
version=fields.Datetime.to_string(record.write_date),
)
except ValidationError:
record.redner_id = templates.account_template_add(
language=language,
body=body,
name=record.name,
version=fields.Datetime.to_string(fields.Datetime.now()),
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
@api.model
def _redner_demo_make_template(self, name, language, template_data_id):
config_model = self.env["ir.config_parameter"].sudo()
redner_config_list = [
config_model.get_param("redner.api_key"),
config_model.get_param("redner.server_url"),
config_model.get_param("redner.account"),
]
if False in redner_config_list: # Config parameters not completed
logger.error(
"Redner template demo data: THE TEMPLATE CANNOT LOAD "
"IF THE REDNER PARAMETERS ARE NOT COMPLETELY CONFIGURED"
)
else:
check_template = self.env["redner.template"].search_count(
[("name", "=", name)]
)
if check_template == 0: # Check duplicate template name, no update = 0
produces, language_splited = language.split("|")
template_data = self.env["ir.attachment"].browse(template_data_id).datas
path = "template/" + config_model.get_param("redner.account")
# name_test to avoid redner template name duplication
# error during connection test
name_test = "test" + fields.Datetime.to_string(fields.Datetime.now())
checked = True # If redner configs pass and redner server is activated
params = {
"name": name_test,
"language": language_splited,
"body": template_data.decode(),
"produces": produces,
"body-format": "base64",
"locale": "fr_FR",
"version": fields.Datetime.to_string(fields.Datetime.now()),
}
try: # Try to call redner server with params dict
self.redner.call_impl(path=path, http_verb="post", **params)
except Exception as error:
checked = False # Connection with redner a failure
logger.warning(
"Redner template demo data: CONNEXION ERROR %s", str(error)
)
if checked:
self.create(
{
"name": name,
"language": language,
"template_data": template_data,
}
)
logger.info(
"Redner template demo data: "
"INSTALLING DEMO DATA FOR THE REDNER TEMPLATE"
)