diff --git a/report_carbone/models/base/ir_actions_report.py b/report_carbone/models/base/ir_actions_report.py
index 4834e41..c972366 100644
--- a/report_carbone/models/base/ir_actions_report.py
+++ b/report_carbone/models/base/ir_actions_report.py
@@ -129,6 +129,8 @@ class IrActionsReportCarbone(models.Model):
"supported by Carbone. You must provide a production API key and must not "
"be in test mode.",
)
+ template_file = fields.Binary(string="Template file", attachment=True)
+ template_filename = fields.Char(string="Template filename")
@api.model
def _setup_template_id_and_extension(self, vals):
@@ -849,6 +851,54 @@ class IrActionsReportCarbone(models.Model):
response = self.call_carbone_endpoint("template", method="POST", files=files, data=data)
return {"template_id": response["data"]["id"], "file_extension": file_extension}
+ _OFFICE_MIME_TYPES = {
+ "docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
+ "xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
+ "pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
+ "odt": "application/vnd.oasis.opendocument.text",
+ "ods": "application/vnd.oasis.opendocument.spreadsheet",
+ "odp": "application/vnd.oasis.opendocument.presentation",
+ "html": "text/html",
+ "htm": "text/html",
+ "txt": "text/plain",
+ "csv": "text/csv",
+ "xml": "application/xml",
+ "svg": "image/svg+xml",
+ "md": "text/markdown",
+ }
+
+ def action_upload_template_to_carbone(self):
+ self.ensure_one()
+ if not self.template_file:
+ raise exceptions.UserError(_("Please select a template file to upload."))
+ filename = self.template_filename or "template"
+ file_content = base64.b64decode(self.template_file)
+ file_extension = os.path.splitext(filename)[1].lstrip(".")
+ mime_type = self._OFFICE_MIME_TYPES.get(file_extension.lower()) or mimetypes.guess_type(filename)[0] or "application/octet-stream"
+ files = {
+ "template": (filename, file_content, mime_type),
+ }
+ response = self.call_carbone_endpoint("template", method="POST", files=files)
+ if not isinstance(response, dict) or not response.get("data", {}).get("templateId"):
+ raise exceptions.UserError(_("Carbone did not return a valid template ID. Response: %s") % response)
+ template_id = response["data"]["templateId"]
+ self.write({
+ "template_id": template_id,
+ "file_extension": file_extension or "docx",
+ "template_file": False,
+ "template_filename": False,
+ })
+ return {
+ "type": "ir.actions.client",
+ "tag": "display_notification",
+ "params": {
+ "title": _("Template uploaded"),
+ "message": _("Template ID: %s") % template_id,
+ "type": "success",
+ "sticky": False,
+ },
+ }
+
def get_extension_file_from_api(self, template_id: str, raise_error=True) -> str | bool:
# If we are in install mode, for unit test for example, and we have to init a ir.actions.report from an XML
# file, we don't wan't to call Carbone's API to retrieve extension.
diff --git a/report_carbone/views/base/ir_actions_report.xml b/report_carbone/views/base/ir_actions_report.xml
index 0496855..ae9dbfb 100644
--- a/report_carbone/views/base/ir_actions_report.xml
+++ b/report_carbone/views/base/ir_actions_report.xml
@@ -49,6 +49,17 @@
/>
+
+
+
+
+