[FIX] [base, account_edi_facturx]: Fix pdf export
There is an issue when exporting pdf using edi documents created before the PDF/A commit. With the subtype now included, the system would try to use the subtype given by the ir.attachment which would not be formated as expected by the pdf file format. The attachment may get neutered by the ORM, so we may have to force the mimetype when embedding it. This fix in two parts will allow to force a subtype when adding an attachment into a pdf, as well as parse the subtype of ir.attachment to give them the right format. xxx/xxx should become /xxx#2Fxxx opw-2714040 closes odoo/odoo#81898 X-original-commit: 880d7a1c8474a3bee4fd05474788fbd4a63f4ae7 Signed-off-by: Laurent Smet <las@odoo.com>
This commit is contained in:
@@ -36,7 +36,7 @@ class AccountEdiFormat(models.Model):
|
||||
if not edi_document.attachment_id:
|
||||
return
|
||||
|
||||
pdf_writer.embed_odoo_attachment(edi_document.attachment_id)
|
||||
pdf_writer.embed_odoo_attachment(edi_document.attachment_id, subtype='application/xml')
|
||||
if not pdf_writer.is_pdfa and str2bool(self.env['ir.config_parameter'].sudo().get_param('edi.use_pdfa', 'False')):
|
||||
try:
|
||||
pdf_writer.convert_to_pdfa()
|
||||
@@ -75,7 +75,7 @@ class AccountEdiFormat(models.Model):
|
||||
return self.env['ir.attachment'].create({
|
||||
'name': 'factur-x.xml',
|
||||
'raw': xml_content.encode(),
|
||||
'mimetype': '/application#2Fxml'
|
||||
'mimetype': 'application/xml'
|
||||
})
|
||||
|
||||
def _is_facturx(self, filename, tree):
|
||||
|
||||
+24
-13
@@ -1,6 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
import io
|
||||
import re
|
||||
|
||||
from datetime import datetime
|
||||
from hashlib import md5
|
||||
@@ -18,6 +19,8 @@ from odoo.tools.misc import file_open
|
||||
|
||||
_logger = getLogger(__name__)
|
||||
DEFAULT_PDF_DATETIME_FORMAT = "D:%Y%m%d%H%M%S+00'00'"
|
||||
REGEX_SUBTYPE_UNFORMATED = re.compile(r'^\w+/[\w-]+$')
|
||||
REGEX_SUBTYPE_FORMATED = re.compile(r'^/\w+#2F[\w-]+$')
|
||||
|
||||
|
||||
# make sure values are unwrapped by calling the specialized __getitem__
|
||||
@@ -95,16 +98,16 @@ class OdooPdfFileReader(PdfFileReader):
|
||||
|
||||
try:
|
||||
file_path = self.trailer["/Root"].get("/Names", {}).get("/EmbeddedFiles", {}).get("/Names")
|
||||
|
||||
if not file_path:
|
||||
return []
|
||||
for i in range(0, len(file_path), 2):
|
||||
attachment = file_path[i+1].getObject()
|
||||
yield (attachment["/F"], attachment["/EF"]["/F"].getObject().getData())
|
||||
except Exception:
|
||||
# malformed pdf (i.e. invalid xref page)
|
||||
return []
|
||||
|
||||
if not file_path:
|
||||
return []
|
||||
for i in range(0, len(file_path), 2):
|
||||
attachment = file_path[i+1].getObject()
|
||||
yield (attachment["/F"], attachment["/EF"]["/F"].getObject().getData())
|
||||
|
||||
|
||||
class OdooPdfFileWriter(PdfFileWriter):
|
||||
|
||||
@@ -117,21 +120,29 @@ class OdooPdfFileWriter(PdfFileWriter):
|
||||
self._reader = None
|
||||
self.is_pdfa = False
|
||||
|
||||
def addAttachment(self, name, data, subtype=""):
|
||||
def addAttachment(self, name, data, subtype=None):
|
||||
"""
|
||||
Add an attachment to the pdf. Supports adding multiple attachment, while respecting PDF/A rules.
|
||||
:param name: The name of the attachement
|
||||
:param data: The data of the attachement
|
||||
:param subtype: The mime-type of the attachement. This is required by PDF/A, but not essential otherwise.
|
||||
It should take the form of "/xxx%2Fxxx". E.g. for "text/xml": "/text%2Fxml"
|
||||
It should take the form of "/xxx#2Fxxx". E.g. for "text/xml": "/text#2Fxml"
|
||||
"""
|
||||
if subtype == 'application/xml':
|
||||
subtype = '/application#2Fxml'
|
||||
adapted_subtype = subtype
|
||||
if subtype:
|
||||
# If we receive the subtype in an 'unformated' (mimetype) format, we'll try to convert it to a pdf-valid one
|
||||
if REGEX_SUBTYPE_UNFORMATED.match(subtype):
|
||||
adapted_subtype = '/' + subtype.replace('/', '#2F')
|
||||
|
||||
if not REGEX_SUBTYPE_FORMATED.match(adapted_subtype):
|
||||
# The subtype still does not match the correct format, so we will not add it to the document
|
||||
_logger.warning("Attempt to add an attachment with the incorrect subtype '%s'. The subtype will be ignored.", subtype)
|
||||
adapted_subtype = ''
|
||||
|
||||
attachment = self._create_attachment_object({
|
||||
'filename': name,
|
||||
'content': data,
|
||||
'subtype': subtype,
|
||||
'subtype': adapted_subtype,
|
||||
})
|
||||
if self._root_object.get('/Names') and self._root_object['/Names'].get('/EmbeddedFiles'):
|
||||
names_array = self._root_object["/Names"]["/EmbeddedFiles"]["/Names"]
|
||||
@@ -163,9 +174,9 @@ class OdooPdfFileWriter(PdfFileWriter):
|
||||
NameObject("/AF"): attachment_array
|
||||
})
|
||||
|
||||
def embed_odoo_attachment(self, attachment):
|
||||
def embed_odoo_attachment(self, attachment, subtype=None):
|
||||
assert attachment, "embed_odoo_attachment cannot be called without attachment."
|
||||
self.addAttachment(attachment.name, attachment.raw, attachment.mimetype)
|
||||
self.addAttachment(attachment.name, attachment.raw, subtype=subtype or attachment.mimetype)
|
||||
|
||||
def cloneReaderDocumentRoot(self, reader):
|
||||
super().cloneReaderDocumentRoot(reader)
|
||||
|
||||
Reference in New Issue
Block a user