add package generation

This commit is contained in:
Мухамадеев Рамиль 2024-11-05 11:59:20 +05:00
parent 568dc25595
commit 2f38569c5e
2 changed files with 43 additions and 31 deletions

View File

@ -14,7 +14,7 @@
"author": "RYDLAB", "author": "RYDLAB",
"website": "https://rydlab.ru", "website": "https://rydlab.ru",
"category": "Technical", "category": "Technical",
"version": "16.0.1.0.0", "version": "16.0.2.0.0",
"license": "LGPL-3", "license": "LGPL-3",
"depends": ["base", "web", "custom_report_field", "report_monetary_helpers"], "depends": ["base", "web", "custom_report_field", "report_monetary_helpers"],
"external_dependencies": {"python": ["docxcompose", "docxtpl", "bs4"]}, "external_dependencies": {"python": ["docxcompose", "docxtpl", "bs4"]},

View File

@ -189,7 +189,10 @@ class IrActionsReport(models.Model):
_logger.info("The DOCS report has been generated from attachment.") _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_contents = []
for record_id in res_ids:
docx_content = self._render_docx([record_id], data=data)
docx_contents.append(docx_content)
if res_ids: if res_ids:
_logger.info( _logger.info(
@ -198,11 +201,11 @@ class IrActionsReport(models.Model):
) )
return ( return (
self_sudo._post_docx( self_sudo._post_docx(
save_in_attachment, docx_content=docx_content, res_ids=res_ids save_in_attachment, docx_contents=docx_contents, res_ids=res_ids
), ),
"docx", "docx",
) )
return docx_content, "docx" return docx_contents, "docx"
def _post_pdf(self, save_in_attachment, pdf_content=None, res_ids=None): def _post_pdf(self, save_in_attachment, pdf_content=None, res_ids=None):
""" """
@ -225,9 +228,12 @@ class IrActionsReport(models.Model):
return self._merge_pdfs(reports_data) return self._merge_pdfs(reports_data)
for res_id in res_ids: for res_id in res_ids:
record = self.env[self_sudo.model].browse(res_id) record = self.env[self_sudo.model].browse(res_id)
attachment_name = safe_eval( if not self_sudo.attachment:
self_sudo.attachment, {"object": record, "time": time} attachment_name = False
) else:
attachment_name = safe_eval(
self_sudo.attachment, {"object": record, "time": time}
)
# Unable to compute a name for the attachment. # Unable to compute a name for the attachment.
if not attachment_name: if not attachment_name:
continue continue
@ -257,7 +263,7 @@ class IrActionsReport(models.Model):
) )
return pdf_content return pdf_content
def _post_docx(self, save_in_attachment, docx_content=None, res_ids=None): def _post_docx(self, save_in_attachment, docx_contents=None, res_ids=None):
""" """
Adds generated file in attachments. Adds generated file in attachments.
""" """
@ -269,10 +275,11 @@ class IrActionsReport(models.Model):
except Exception: except Exception:
pass pass
if len(save_in_attachment) == 1 and not docx_content: if len(save_in_attachment) == 1 and not docx_contents:
return list(save_in_attachment.values())[0].getvalue() return list(save_in_attachment.values())[0].getvalue()
streams = [] streams = []
if docx_content: if docx_contents:
# Build a record_map mapping id -> record # Build a record_map mapping id -> record
record_map = { record_map = {
r.id: r r.id: r
@ -282,24 +289,18 @@ class IrActionsReport(models.Model):
} }
# If no value in attachment or no record specified, only append the whole docx. # If no value in attachment or no record specified, only append the whole docx.
if not record_map or not self.attachment: if not record_map or not self.attachment:
streams.append(docx_content) streams.extend(docx_contents)
else: else:
if len(res_ids) == 1: for res_id, docx_content in zip(res_ids, docx_contents):
# Only one record, so postprocess directly and append the whole docx. if res_id in record_map and not res_id in save_in_attachment:
if (
res_ids[0] in record_map
and not res_ids[0] in save_in_attachment
):
new_stream = self._postprocess_docx_report( new_stream = self._postprocess_docx_report(
record_map[res_ids[0]], docx_content record_map[res_id], docx_content
) )
# If the buffer has been modified, mark the old buffer to be closed as well. # If the buffer has been modified, mark the old buffer to be closed as well.
if new_stream and new_stream != docx_content: if new_stream and new_stream != docx_content:
close_streams([docx_content]) close_streams([docx_content])
docx_content = new_stream docx_content = new_stream
streams.append(docx_content) streams.append(docx_content)
else:
streams.append(docx_content)
if self.attachment_use: if self.attachment_use:
for stream in save_in_attachment.values(): for stream in save_in_attachment.values():
streams.append(stream) streams.append(stream)
@ -307,7 +308,8 @@ class IrActionsReport(models.Model):
result = streams[0].getvalue() result = streams[0].getvalue()
else: else:
try: try:
result = self._merge_docx(streams) merged_stream = self._merge_docx(streams)
result = merged_stream.getvalue()
except Exception as e: except Exception as e:
_logger.exception(e) _logger.exception(e)
raise UserError( raise UserError(
@ -347,17 +349,27 @@ class IrActionsReport(models.Model):
@staticmethod @staticmethod
def _merge_docx(streams): def _merge_docx(streams):
""" """
Joins several docx files into one. Joins several docx files into one with page breaks between them.
""" """
if streams: if not streams:
writer = Document(streams[0]) return None
composer = Composer(writer)
for stream in streams[1:]: merged_document = Document()
reader = Document(stream) composer = Composer(merged_document)
composer.append(reader)
return composer.getvalue() for stream in streams:
else: document = Document(stream)
return streams
if composer.doc.paragraphs:
composer.doc.add_page_break()
composer.append(document)
merged_stream = BytesIO()
merged_document.save(merged_stream)
merged_stream.seek(0)
return merged_stream
def _render_docx(self, docids: list, data: dict = None): def _render_docx(self, docids: list, data: dict = None):
""" """