diff --git a/.hgtags b/.hgtags
index 7e4a9e871c6fac7a9b92f06c85592aa931d4c99b_LmhndGFncw==..277162113e09c062d2e9c264681989fc18f2d5fd_LmhndGFncw== 100644
--- a/.hgtags
+++ b/.hgtags
@@ -32,3 +32,4 @@
 e94d63bf437de0659004cdf649ad3f418d555ec4 18.0.1.0.1
 36dcec66b1c134aab072935b3e7e322c040a4ca2 18.0.1.0.2
 b03479db80cd1185c50e02fc10e489fbc92abe56 18.0.1.0.3
+b4d7830ecd569274bc4f4de3453c5669368d1b33 18.0.1.0.4
diff --git a/NEWS.rst b/NEWS.rst
index 7e4a9e871c6fac7a9b92f06c85592aa931d4c99b_TkVXUy5yc3Q=..277162113e09c062d2e9c264681989fc18f2d5fd_TkVXUy5yc3Q= 100644
--- a/NEWS.rst
+++ b/NEWS.rst
@@ -2,6 +2,11 @@
 Changelog
 =========
 
+18.0.1.0.4
+----------
+
+Refactor redner.template model to improve template management.
+
 18.0.1.0.3
 ----------
 
diff --git a/__manifest__.py b/__manifest__.py
index 7e4a9e871c6fac7a9b92f06c85592aa931d4c99b_X19tYW5pZmVzdF9fLnB5..277162113e09c062d2e9c264681989fc18f2d5fd_X19tYW5pZmVzdF9fLnB5 100644
--- a/__manifest__.py
+++ b/__manifest__.py
@@ -21,7 +21,7 @@
 {
     "name": "Redner",
     "license": "AGPL-3",
-    "version": "18.0.1.0.3",
+    "version": "18.0.1.0.4",
     "category": "Reporting",
     "author": "XCG Consulting",
     "website": "https://orbeet.io/",
diff --git a/models/redner_template.py b/models/redner_template.py
index 7e4a9e871c6fac7a9b92f06c85592aa931d4c99b_bW9kZWxzL3JlZG5lcl90ZW1wbGF0ZS5weQ==..277162113e09c062d2e9c264681989fc18f2d5fd_bW9kZWxzL3JlZG5lcl90ZW1wbGF0ZS5weQ== 100644
--- a/models/redner_template.py
+++ b/models/redner_template.py
@@ -26,10 +26,10 @@
 from odoo.tools.cache import ormcache
 
 from ..redner import REDNER_API_PATH, Redner
-from ..utils.mimetype import b64_to_extension
+from ..utils.mimetype import get_file_extension
 
 logger = logging.getLogger(__name__)
 
 _redner = None
 
 LANGUAGE_MJML_MUSTACHE = "text/mjml|mustache"
@@ -30,9 +30,10 @@
 
 logger = logging.getLogger(__name__)
 
 _redner = None
 
 LANGUAGE_MJML_MUSTACHE = "text/mjml|mustache"
+LANGUAGE_OPENDOCUMENT_MUSTACHE = "application/vnd.oasis.opendocument.text|od+mustache"
 DEFAULT_LANGUAGE = LANGUAGE_MJML_MUSTACHE
 COMPUTED_FIELDS = [
     "body",
@@ -87,7 +88,11 @@
         string="Name",
         default="New",
         required=True,
-        help="This is a name of template mjml redner",
+        help=(
+            "The name of the template. Once the template is created, "
+            "updating the name is not allowed. To change the name, "
+            "delete the template and create a new one."
+        ),
     )
 
     description = fields.Char(
@@ -138,7 +143,7 @@
             ("text/html|mustache", "HTML + mustache"),
             (LANGUAGE_MJML_MUSTACHE, "MJML + mustache"),
             (
-                "application/vnd.oasis.opendocument.text|od+mustache",
+                LANGUAGE_OPENDOCUMENT_MUSTACHE,
                 "OpenDocument + mustache",
             ),
         ],
@@ -163,7 +168,8 @@
         string="Libreoffice Template",
         readonly=False,
         compute="_compute_template_data",
+        inverse="_inverse_template_data",
     )
 
     template_data_filename = fields.Char(
         string="Libreoffice Template Filename",
@@ -166,7 +172,7 @@
     )
 
     template_data_filename = fields.Char(
         string="Libreoffice Template Filename",
-        readonly=True,
+        compute="_compute_template_data_filename",
     )
 
@@ -171,7 +177,6 @@
     )
 
-    def import_from_redner(self):
-        tl_wizard = self.env["template.list.wizard"]
-        templates = self.list_external_templates()
-        tl_wizard.populate(templates)
+    # -------------------------------------------------------------------------
+    # COMPUTE METHODS
+    # -------------------------------------------------------------------------
 
@@ -177,13 +182,9 @@
 
-        return {
-            "type": "ir.actions.act_window",
-            "res_model": "template.list.wizard",
-            "view_mode": "list",
-            "view_id": self.env.ref("redner.view_template_list_wizard_tree").id,
-            "target": "new",
-            #'context': self.env.context,
-        }
+    @api.depends("body", "template_data")
+    def _compute_keywords(self):
+        for record in self:
+            record.detected_keywords = "\n".join(record.template_varlist_fetch())
 
     @api.depends("body", "template_data")
     def _compute_preview(self):
         for record in self:
@@ -186,8 +187,123 @@
 
     @api.depends("body", "template_data")
     def _compute_preview(self):
         for record in self:
-            response = self.get_preview(record.redner_id)
-            b64 = base64.b64encode(response.content)
-            record.preview = b64
+            if record.body or record.template_data:
+                response = self.get_preview(record.redner_id)
+
+                # Check if response is valid and has content
+                if response and hasattr(response, "content"):
+                    record.preview = base64.b64encode(response.content)
+                else:
+                    record.preview = False  # If no valid response, set preview to False
+            else:
+                record.preview = False
+
+    def _compute_template(self):
+        """
+        Computes the template values for the records and applies cached or fetched data.
+        """
+        for record in self:
+            if not record.id or not record.redner_id:
+                continue
+
+            # Fetch the cached template
+            cached_template = self._get_cached_template(record.id)
+
+            if not any([getattr(record, f) for f in COMPUTED_FIELDS]):
+                # If all computed fields are undefined, populate them
+                # from the cached template.
+                for f in COMPUTED_FIELDS + EDITABLE_FIELDS:
+                    if f in cached_template:
+                        setattr(record, f, cached_template[f])
+            else:
+                # If at least one field is defined, populate only undefined fields
+                for f in COMPUTED_FIELDS:
+                    if not getattr(record, f):
+                        setattr(record, f, cached_template.get(f, None))
+
+    def _inverse_template_data(self):
+        """
+        Inverse function for `template_data`. Called when `template_data` is"
+        manually set.
+        """
+        for record in self:
+            if not record.template_data or not record.id or not record.language:
+                continue
+            try:
+                # Update the external system with the new data
+                self._set_cached_template(record.id, record.template_data)
+            except Exception as e:
+                logger.error("Failed to update template data in Redner: %s", e)
+                raise ValidationError(
+                    _(
+                        "Unable to update the template data. Please check the logs "
+                        "for more details."
+                    )
+                ) from e
+
+    def _compute_template_data(self):
+        for record in self:
+            # Skip records that do not have a redner_id or are missing essential data
+            if not record.id or not record.redner_id:
+                continue
+
+            if (
+                not record.template_data
+                and record.language == LANGUAGE_OPENDOCUMENT_MUSTACHE
+            ):
+                cached_template = self._get_cached_template(record.id)
+
+                template_data = (
+                    cached_template.get("template_data") if cached_template else None
+                )
+                if template_data:
+                    try:
+                        # Perform base64 encoding and store the result
+                        record.template_data = base64.b64encode(template_data).decode(
+                            "utf-8"
+                        )
+                    except Exception as e:
+                        logger.error(
+                            "Failed to encode redner template data for record %s: %s",
+                            record.id,
+                            e,
+                        )
+                        continue  # Proceed with next record if encoding fails
+
+    @api.depends("template_data")
+    def _compute_template_data_filename(self):
+        """Compute the template filename based on the template data"""
+        for record in self:
+            if not record.id or not record.redner_id or not record.template_data:
+                record.template_data_filename = (
+                    f"{record.name}.odt" if record.name else "template.odt"
+                )
+            else:
+                try:
+                    # Attempt to extract the file extension from the base64 data
+                    ext = get_file_extension(record.template_data)
+                    record.template_data_filename = f"{record.name}{ext}"
+
+                except Exception as e:
+                    logger.error("Error while computing template filename: %s", e)
+                    record.template_data_filename = False
+
+    @property
+    def redner(self):
+        """
+        Returns a Redner instance.
+        Recomputes the instance if any system parameter changes.
+        Uses a global variable to cache the instance across sessions.
+        """
+        global _redner, _redner_params
+
+        # Fetch current system parameters
+        config_model = self.env["ir.config_parameter"].sudo()
+        current_params = {
+            "api_key": config_model.get_param("redner.api_key"),
+            "server_url": config_model.get_param("redner.server_url"),
+            "account": config_model.get_param("redner.account"),
+            "timeout": int(config_model.get_param("redner.timeout", default="20")),
+        }
 
@@ -193,3 +309,127 @@
 
-    def get_preview(self, redner_id):
+        # Check if parameters have changed or if _redner is None
+        if _redner is None or _redner_params != current_params:
+            # Recompute the Redner instance
+            _redner = Redner(
+                current_params["api_key"],
+                current_params["server_url"],
+                current_params["account"],
+                current_params["timeout"],
+            )
+            _redner_params = current_params  # Update the stored parameters
+
+        return _redner
+
+    # -------------------------------------------------------------------------
+    # LOW-LEVEL METHODS
+    # -------------------------------------------------------------------------
+
+    @api.model_create_multi
+    def create(self, vals_list):
+        """Overwrite create to create redner template"""
+
+        for vals in vals_list:
+            # If "name" is missing or equals "New", set the source and
+            # proceed with creation.
+            if not vals.get("name", False) or vals["name"] == "New":
+                vals["source"] = "redner"
+                continue  # Continue processing the next record
+
+            # 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("|")
+            body, body_format = (
+                (vals.get("template_data", ""), "base64")
+                if language == "od+mustache"
+                else (vals.get("body"), "text")
+            )
+
+            locale = self.env["res.lang"].browse(vals.get("locale_id")).code
+
+            # We depend on the API for consistency here
+            # So raised error should not result with a created template
+            if language and body:
+                template = self.redner.templates.account_template_add(
+                    language=language,
+                    body=body,
+                    name=vals.get("name"),
+                    description=vals.get("description"),
+                    produces=produces,
+                    body_format=body_format,
+                    version=fields.Datetime.to_string(fields.Datetime.now()),
+                    locale=locale if locale else "fr_FR",
+                )
+                vals["redner_id"] = template["name"]
+            else:
+                # If the language and body are not defined, we return early
+                # to prevent saving an incomplete template and sending it
+                # to the Redner server.
+                return self
+
+        return super().create(vals_list)
+
+    def write(self, vals):
+        """Overwrite write to update redner template"""
+
+        # Determine if we should update redner or not
+        should = self._should_update_redner(vals)
+
+        # Perform the write operation
+        ret = super().write(vals)
+
+        # Update Redner templates if applicable
+        if should:
+            for record in self:
+                if (
+                    not self.env.context.get("importing")  # Skip during imports
+                    and record.allow_modification_from_odoo
+                ):
+                    record._sync_with_redner()
+
+        return ret
+
+    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
+        for record in self:
+            if record.redner_id and record.allow_modification_from_odoo:
+                try:
+                    self.redner.templates.account_template_delete(record.redner_id)
+                except Exception as e:
+                    logger.warning(
+                        "Failed to delete Redner template with ID %s. Reason: %s",
+                        record.redner_id,
+                        e,
+                    )
+        self.env.registry.clear_cache()
+        return super().unlink()
+
+    def copy(self, default=None):
+        self.ensure_one()
+        default = dict(default or {}, name=_("%s (copy)") % self.name)
+        return super().copy(default)
+
+    # ------------------------------------------------------------
+    # ACTIONS / BUSINESS
+    # ------------------------------------------------------------
+
+    def _should_update_redner(self, vals):
+        """
+        Determine if Redner should be updated based on the modified fields.
+        """
+        for field in COMPUTED_FIELDS + ["template_data"]:
+            if field in vals:
+                current_value = getattr(self, field)
+                if vals[field] != current_value and vals[field]:
+                    return True
+        return False
+
+    def _sync_with_redner(self):
+        """
+        Sync the current record's template with Redner.
+        """
+        self.ensure_one()
         try:
@@ -195,4 +435,31 @@
         try:
-            preview = self.redner.templates.account_template_preview(redner_id)
-            return preview
+            # Check if 'language' is a valid string before splitting
+            if isinstance(self.language, str) and "|" in self.language:
+                produces, language = self.language.split("|")
+            else:
+                logger.warning(
+                    "Invalid language format for record %s: %s",
+                    self.id,
+                    self.language,
+                )
+            body, body_format = (
+                (self.template_data.decode(), "base64")
+                if language == "od+mustache"
+                else (self.body, "text")
+            )
+
+            # Use the existing `redner_id`
+            redner_id = self.redner_id
+
+            self._update_redner_template(
+                template_id=redner_id,
+                language=language,
+                body=body,
+                name=self.name,
+                description=self.description,
+                produces=produces,
+                body_format=body_format,
+                version=fields.Datetime.to_string(self.write_date),
+                locale=self.locale_id.code,
+            )
         except Exception as e:
@@ -198,7 +465,39 @@
         except Exception as e:
-            logger.error("Failed to get preview of redner template :%s", e)
-            return
+            logger.error("Failed to sync with Redner template: %s", e)
+            raise ValidationError(_("Failed to update Redner template, %s") % e) from e
+
+    def _update_redner_template(self, **kwargs):
+        """
+        Perform the Redner `account_template_update` API call.
+
+        :param kwargs: Payload for the `account_template_update` API.
+        """
+        try:
+            self.redner.templates.account_template_update(**kwargs)
+            self.env.registry.clear_cache()
+        except Exception as e:
+            logger.error("Redner API update failed: %s", e)
+            raise ValueError("Unable to update the Redner template.") from e
+
+    @ormcache("redner_id")
+    def get_preview(self, redner_id):
+        """
+        Retrieve the preview of a Redner template by its ID.
+        Returns None if the redner_id is not provided or if the preview
+        cannot be retrieved.
+        """
+        if not redner_id:
+            return None
+
+        result = None
+        try:
+            result = self.redner.templates.account_template_preview(redner_id)
+        except Exception as e:
+            logger.error(
+                "Failed to get preview of Redner template with ID %s: %s", redner_id, e
+            )
+        return result
 
     def _to_odoo_template(self, template):
         """
         Convert the external template to the Odoo format.
@@ -201,6 +500,5 @@
 
     def _to_odoo_template(self, template):
         """
         Convert the external template to the Odoo format.
-        This function assumes the existence of this logic in the original `to_cache`.
         """
@@ -206,6 +504,4 @@
         """
-        # Implement the transformation logic here
-        # define a odoo_like template to put into the cache
         language = "{}|{}".format(template.get("produces"), template.get("language"))
 
         odoo_template = {
@@ -249,5 +545,6 @@
             logger.error("Failed to read Redner template: %s", e)
             return {}
 
-    def _compute_template(self):
+    @ormcache("record_id", "new_template_data")
+    def _set_cached_template(self, record_id, new_template_data):
         """
@@ -253,3 +550,3 @@
         """
-        Computes the template values for the records and applies cached or fetched data.
+        Sets and caches the template in Redner for a given record.
         """
@@ -255,5 +552,5 @@
         """
-        for record in self:
-            if not record.id or not record.redner_id:
-                continue
+        record = self.browse(record_id)
+        if not record.redner_id:
+            raise ValueError("The record must have a valid Redner ID.")
 
@@ -259,4 +556,9 @@
 
-            # Fetch the cached template
-            cached_template = self._get_cached_template(record.id)
+        try:
+            produces, language = record.language.split("|")
+            body, body_format = (
+                (new_template_data.decode(), "base64")
+                if language == "od+mustache"
+                else (record.body, "text")
+            )
 
@@ -262,13 +564,21 @@
 
-            if not any([getattr(record, f) for f in COMPUTED_FIELDS]):
-                # If all computed fields are undefined, populate them
-                # from the cached template.
-                for f in COMPUTED_FIELDS + EDITABLE_FIELDS:
-                    if f in cached_template:
-                        setattr(record, f, cached_template[f])
-            else:
-                # If at least one field is defined, populate only undefined fields
-                for f in COMPUTED_FIELDS:
-                    if not getattr(record, f):
-                        setattr(record, f, cached_template.get(f, None))
+            # Send the updated template to the external system
+            self.redner.templates.account_template_update(
+                template_id=record.redner_id,
+                language=language,
+                body=body,
+                name=record.name,
+                description=record.description,
+                produces=produces,
+                body_format=body_format,
+                version=fields.Datetime.to_string(record.write_date),
+                locale=record.locale_id.code,
+            )
+
+            self.env.registry.clear_cache()
+
+            return True
+        except Exception as e:
+            logger.error("Failed to set Redner template: %s", e)
+            raise ValueError("Unable to update the Redner template.") from e
 
@@ -274,26 +584,49 @@
 
-    @api.depends("template_data")
-    def _compute_template_data(self):
-        for record in self:
-            if not record.id or not record.redner_id:
-                continue
-            if not record.template_data:
-                try:
-                    cached_template = self._get_cached_template(record.id)
-                    if "template_data" in cached_template:
-                        new_val = cached_template["template_data"]
-                        encoded = base64.b64encode(new_val).decode("utf-8")
-                        ext = ".odt"  # default extension
-                        try:
-                            ext = b64_to_extension(encoded)
-                        except Exception as e:
-                            logger.error("Failed to read extension from file:%s", e)
-                            return
-                        record.template_data = encoded
-                        record.template_data_filename = f"{record.name}{ext}"
-                except Exception as e:
-                    logger.error("Failed to read redner template :%s", e)
-                    return
+    def import_from_redner(self):
+        tl_wizard = self.env["template.list.wizard"]
+        templates = self.list_external_templates()
+        tl_wizard.populate(templates)
+
+        return {
+            "type": "ir.actions.act_window",
+            "res_model": "template.list.wizard",
+            "view_mode": "list",
+            "view_id": self.env.ref("redner.view_template_list_wizard_tree").id,
+            "target": "new",
+            #'context': self.env.context,
+        }
+
+    @api.model
+    def get_keywords(self):
+        """Return template redner keywords"""
+        self.ensure_one()
+
+        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
+    @ormcache("self.redner_id")
+    def template_varlist_fetch(self):
+        """Retrieve the list of variables present in the template."""
+        self.ensure_one()
+        try:
+            if not self.redner_id:
+                return []
+
+            return self.redner.templates.account_template_varlist(self.redner_id)
+
+        except Exception as e:
+            logger.warning("Failed to fetch account template varlist: %s", e)
+            return []
 
     def list_external_templates(self):
         try:
@@ -312,203 +645,6 @@
                 new_templates.append(self._to_odoo_template(template))
         return new_templates
 
-    @property
-    def redner(self):
-        """
-        Returns a Redner instance.
-        Recomputes the instance if any system parameter changes.
-        Uses a global variable to cache the instance across sessions.
-        """
-        global _redner, _redner_params
-
-        # Fetch current system parameters
-        config_model = self.env["ir.config_parameter"].sudo()
-        current_params = {
-            "api_key": config_model.get_param("redner.api_key"),
-            "server_url": config_model.get_param("redner.server_url"),
-            "account": config_model.get_param("redner.account"),
-            "timeout": int(config_model.get_param("redner.timeout", default="20")),
-        }
-
-        # Check if parameters have changed or if _redner is None
-        if _redner is None or _redner_params != current_params:
-            # Recompute the Redner instance
-            _redner = Redner(
-                current_params["api_key"],
-                current_params["server_url"],
-                current_params["account"],
-                current_params["timeout"],
-            )
-            _redner_params = current_params  # Update the stored parameters
-
-        return _redner
-
-    @api.model_create_multi
-    def create(self, vals_list):
-        """Overwrite create to create redner template"""
-
-        for vals in vals_list:
-            if not vals.get("name", False) or vals["name"] == "New":
-                # source
-                vals["source"] = "redner"
-                return super().create(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("|")
-            body, body_format = (
-                (vals.get("template_data", ""), "base64")
-                if language == "od+mustache"
-                else (vals.get("body"), "text")
-            )
-
-            locale = self.env["res.lang"].browse(vals.get("locale_id")).code
-
-            # We depend on the API for consistency here
-            # So raised error should not result with a created template
-            template = self.redner.templates.account_template_add(
-                language=language,
-                body=body,
-                name=vals.get("name"),
-                description=vals.get("description"),
-                produces=produces,
-                body_format=body_format,
-                version=fields.Datetime.to_string(fields.Datetime.now()),
-                locale=locale if locale else "fr_FR",
-            )
-            vals["redner_id"] = template["name"]
-
-        return super().create(vals_list)
-
-    def write(self, vals):
-        """Overwrite write to update redner template"""
-        # We depend on the API for consistency here
-        # So raised error should not result with an updated template
-
-        if "allow_modification_from_odoo" in vals:
-            if vals["allow_modification_from_odoo"]:
-                # case where we want to actually update the template from odoo
-                # safe, since passing this parameter from false to true can
-                # only be done separetly from changing other fields.
-                # we write the change and move on
-                return super().write(vals)
-            else:
-                # this case is more tricky
-                if len(vals) == 1:
-                    # ie the only field to be changed is the boolean
-                    # we write and move on. no need for updates
-                    return super().write(vals)
-                # at the same time, we updated some fields and
-                # we decided that odoo could not longer update the fields.
-                # so we  decide that this is the last update we send to
-                # redner
-
-        # compute if we should update redner or not
-        should_update_redner = False
-        for f in EDITABLE_FIELDS + COMPUTED_FIELDS + ["template_data"]:
-            # if we made a change in the record, update redner
-            if f in vals:
-                attr = getattr(self, f)
-                if vals[f] != attr:
-                    should_update_redner = True
-
-        if "name" in vals:
-            self.ensure_one()
-
-            redner_id = self.redner_id
-            vals["redner_id"] = vals["name"]
-
-        ret = super().write(vals)
-
-        for record in self:
-            if (
-                should_update_redner
-                and not self.env.context.get("importing")
-                and record.allow_modification_from_odoo
-            ):
-                try:
-                    produces, language = record.language.split("|")
-                    body, body_format = (
-                        (record.template_data.decode(), "base64")
-                        if language == "od+mustache"
-                        else (record.body, "text")
-                    )
-
-                    if "name" not in vals:
-                        redner_id = record.redner_id
-
-                    record.redner.templates.account_template_update(
-                        template_id=redner_id,
-                        language=language,
-                        body=body,
-                        name=vals.get("name", ""),
-                        description=record.description,
-                        produces=produces,
-                        body_format=body_format,
-                        version=fields.Datetime.to_string(record.write_date),
-                        locale=record.locale_id.code,
-                    )
-                except Exception as e:
-                    logger.error("Failed to update redner template :%s", e)
-                    raise ValidationError(
-                        _("Failed to update render template, %s") % e
-                    ) from e
-        return ret
-
-    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
-        for record in self:
-            if record.redner_id and record.allow_modification_from_odoo:
-                try:
-                    self.redner.templates.account_template_delete(record.redner_id)
-                except Exception:
-                    pass
-
-        return super().unlink()
-
-    def copy(self, default=None):
-        self.ensure_one()
-        default = dict(default or {}, name=_("%s (copy)") % self.name)
-        return super().copy(default)
-
-    @api.depends("body", "template_data")
-    def _compute_keywords(self):
-        for record in self:
-            record.detected_keywords = "\n".join(record.template_varlist_fetch())
-
-    @api.model
-    def get_keywords(self):
-        """Return template redner keywords"""
-
-        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)
-
-        except Exception as e:
-            logger.warning("Failed to fetch account template varlist: %s", e)
-            return []
-
     def redner_url(self):
         if self.redner_id is None:
             return ""
diff --git a/tests/test_redner_template.py b/tests/test_redner_template.py
index 7e4a9e871c6fac7a9b92f06c85592aa931d4c99b_dGVzdHMvdGVzdF9yZWRuZXJfdGVtcGxhdGUucHk=..277162113e09c062d2e9c264681989fc18f2d5fd_dGVzdHMvdGVzdF9yZWRuZXJfdGVtcGxhdGUucHk= 100644
--- a/tests/test_redner_template.py
+++ b/tests/test_redner_template.py
@@ -113,10 +113,5 @@
         # Update template.
         redner_template.name = updated_name
         requests_post_mock.assert_not_called()
-        requests_put_mock.assert_called_once_with(
-            TEMPLATE_URL + "/" + base_name,
-            json=updated_template,
-            headers={"Rednerd-API-Key": "test-api-key"},
-            timeout=20,
-        )
+        requests_put_mock.assert_not_called()
         requests_put_mock.reset_mock()
diff --git a/utils/mimetype.py b/utils/mimetype.py
index 7e4a9e871c6fac7a9b92f06c85592aa931d4c99b_dXRpbHMvbWltZXR5cGUucHk=..277162113e09c062d2e9c264681989fc18f2d5fd_dXRpbHMvbWltZXR5cGUucHk= 100644
--- a/utils/mimetype.py
+++ b/utils/mimetype.py
@@ -16,3 +16,22 @@
     except Exception as e:
         print(f"Error detecting file type: {e}")
         return None
+
+
+def get_file_extension(binary_data):
+    """Determine the file extension from binary content."""
+    mime = magic.Magic(mime=True)
+    file_type = mime.from_buffer(binary_data)
+
+    # Mapping MIME types to extensions
+    mime_to_ext = {
+        "application/vnd.oasis.opendocument.text": ".odt",
+        "application/pdf": ".pdf",
+        "image/jpeg": ".jpg",
+        "image/png": ".png",
+        "application/msword": ".doc",
+        "application/vnd.openxmlformats-officedocument.wordprocessingml.document": ".docx",  # noqa: E501
+    }
+    return mime_to_ext.get(
+        file_type, ".odt"
+    )  # Default to empty string if MIME type not found
diff --git a/views/redner_template.xml b/views/redner_template.xml
index 7e4a9e871c6fac7a9b92f06c85592aa931d4c99b_dmlld3MvcmVkbmVyX3RlbXBsYXRlLnhtbA==..277162113e09c062d2e9c264681989fc18f2d5fd_dmlld3MvcmVkbmVyX3RlbXBsYXRlLnhtbA== 100644
--- a/views/redner_template.xml
+++ b/views/redner_template.xml
@@ -34,6 +34,7 @@
         <field name="arch" type="xml">
             <form>
                 <header>
+                    <field name="id" invisible="1" />
                     <field name="redner_id" invisible="1" />
                     <button
                         name="view_in_redner"
@@ -73,7 +74,7 @@
                             <h1>
                                 <field
                                     name="name"
-                                    readonly="not allow_modification_from_odoo"
+                                    readonly="not allow_modification_from_odoo or id != False"
                                 />
                             </h1>
                         </div>