fix problem with fields of Html type

This commit is contained in:
alexandr.uritskiy 2022-06-10 18:38:22 +05:00
parent 3209a208e6
commit da4f636fde
3 changed files with 39 additions and 22 deletions

View File

@ -16,7 +16,7 @@
"category": "Technical", "category": "Technical",
"version": "0.8.1", "version": "0.8.1",
"depends": ["base", "web", "custom_report_field", "report_monetary_helpers"], "depends": ["base", "web", "custom_report_field", "report_monetary_helpers"],
"external_dependencies": {"python": ["docxcompose", "docxtpl"]}, "external_dependencies": {"python": ["docxcompose", "docxtpl", "bs4"]},
"data": [ "data": [
"views/ir_actions_report_views.xml", "views/ir_actions_report_views.xml",
], ],

View File

@ -22,8 +22,7 @@ class DocxReportController(ReportController):
report = request.env["ir.actions.report"]._get_report_from_name(reportname) report = request.env["ir.actions.report"]._get_report_from_name(reportname)
context = dict(request.env.context) context = dict(request.env.context)
_data = dict() _data = dict()
if docids: _docids = [int(i) for i in docids.split(",")] if docids else []
_docids = [int(i) for i in docids.split(",")]
if data.get("options"): if data.get("options"):
_data.update(json_loads(data.pop("options"))) _data.update(json_loads(data.pop("options")))
if data.get("context"): if data.get("context"):

View File

@ -1,4 +1,5 @@
from base64 import b64decode from base64 import b64decode
from bs4 import BeautifulSoup
from collections import OrderedDict from collections import OrderedDict
from io import BytesIO from io import BytesIO
from logging import getLogger from logging import getLogger
@ -6,7 +7,6 @@ from logging import getLogger
from docx import Document from docx import Document
from docxcompose.composer import Composer from docxcompose.composer import Composer
from docxtpl import DocxTemplate from docxtpl import DocxTemplate
from jinja2 import Environment as Jinja2Environment
from requests import codes as codes_request, post as post_request from requests import codes as codes_request, post as post_request
from requests.exceptions import RequestException from requests.exceptions import RequestException
@ -119,7 +119,7 @@ class IrActionsReport(models.Model):
res_ids = docx_record_ids.ids res_ids = docx_record_ids.ids
if save_in_attachment and not res_ids: if save_in_attachment and not res_ids:
_logger.info("The PDF report has been generated from attachments.") _logger.info("The PDF report has been generated from attachment.")
self._raise_on_unreadable_pdfs(save_in_attachment.values(), stream_record) self._raise_on_unreadable_pdfs(save_in_attachment.values(), stream_record)
return self_sudo._post_pdf(save_in_attachment), "pdf" return self_sudo._post_pdf(save_in_attachment), "pdf"
@ -186,7 +186,7 @@ class IrActionsReport(models.Model):
res_ids = docx_record_ids.ids res_ids = docx_record_ids.ids
if save_in_attachment and not res_ids: if save_in_attachment and not res_ids:
_logger.info("The DOCS report has been generated from attachments.") _logger.info("The DOCS report has been generated from attachment.")
return self_sudo._post_docx(save_in_attachment), "docx" return self_sudo._post_docx(save_in_attachment), "docx"
docx_content = self._render_docx(res_ids, data=data) docx_content = self._render_docx(res_ids, data=data)
@ -262,7 +262,9 @@ class IrActionsReport(models.Model):
result = self._merge_docx(streams) result = self._merge_docx(streams)
except Exception as e: except Exception as e:
_logger.exception(e) _logger.exception(e)
raise UserError(_("One of the documents, you try to merge is fallback")) raise UserError(
_("One of the documents you try to merge caused failure.")
)
close_streams(streams) close_streams(streams)
return result return result
@ -294,9 +296,10 @@ class IrActionsReport(models.Model):
) )
return buffer return buffer
def _merge_docx(self, streams): @staticmethod
def _merge_docx(streams):
""" """
Объединяет несколько docx файлов в один Joins several docx files into one.
""" """
if streams: if streams:
writer = Document(streams[0]) writer = Document(streams[0])
@ -318,15 +321,13 @@ class IrActionsReport(models.Model):
data = self._get_rendering_context(docids, data) data = self._get_rendering_context(docids, data)
return self._render_docx_template(self.report_docx_template, values=data) return self._render_docx_template(self.report_docx_template, values=data)
def _render_docx_template(self, template, values=None): def _render_docx_template(self, template: bytes, values: dict = None):
""" """
Непосредственно рендеринг docx файла Непосредственно рендеринг docx файла
""" """
if values is None: if values is None:
values = {} values = {}
context = dict(self.env.context, inherit_branding=False) context = dict(self.env.context, inherit_branding=False)
# Browse the user instead of using the sudo self.env.user # Browse the user instead of using the sudo self.env.user
user = self.env["res.users"].browse(self.env.uid) user = self.env["res.users"].browse(self.env.uid)
website = None website = None
@ -338,7 +339,6 @@ class IrActionsReport(models.Model):
translatable=context.get("lang") translatable=context.get("lang")
!= request.env["ir.http"]._get_default_lang().code, != request.env["ir.http"]._get_default_lang().code,
) )
values.update( values.update(
time=time, time=time,
context_timestamp=lambda t: fields.Datetime.context_timestamp( context_timestamp=lambda t: fields.Datetime.context_timestamp(
@ -352,23 +352,41 @@ class IrActionsReport(models.Model):
.get_param("web.base.url", default=""), .get_param("web.base.url", default=""),
) )
data = {key: value for key, value in values.items() if not callable(value)} record_to_render = values["docs"]
functions = {key: value for key, value in values.items() if callable(value)} docs = {
key: record_to_render[key]
for key in record_to_render._fields.keys()
if not isinstance(record_to_render[key], fields.Markup)
}
docs.update(
{
key: self._parse_markup(record_to_render[key])
for key in record_to_render._fields.keys()
if isinstance(record_to_render[key], fields.Markup)
}
)
values["docs"] = docs
docx_content = BytesIO() docx_content = BytesIO()
jinja_env = Jinja2Environment()
jinja_env.globals.update(**functions)
with BytesIO(b64decode(template)) as template_file: with BytesIO(b64decode(template)) as template_file:
doc = DocxTemplate(template_file) doc = DocxTemplate(template_file)
doc.render(data, jinja_env) doc.render(values)
doc.save(docx_content) doc.save(docx_content)
docx_content.seek(0) docx_content.seek(0)
return docx_content return docx_content
def _get_pdf_from_office(self, content_stream): @staticmethod
def _parse_markup(markup_data: fields.Markup):
"""
Extracts data from field of Html type and returns them in text format,
without html tags.
"""
soup = BeautifulSoup(markup_data.__str__())
data_arr = list(soup.strings)
return "\n".join(data_arr)
@staticmethod
def _get_pdf_from_office(content_stream):
""" """
Вызов конвертации docx в pdf с помощью gotenberg Вызов конвертации docx в pdf с помощью gotenberg
""" """