OCA reporting engine fork for dev and update.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

74 lines
2.7 KiB

# Copyright 2020 Creu Blanca
# Copyright 2020 Ecosoft Co., Ltd.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import logging
from io import BytesIO
from odoo import _, fields, models
from odoo.exceptions import ValidationError
from odoo.tools.safe_eval import safe_eval
_logger = logging.getLogger(__name__)
try:
from PyPDF2 import PdfFileReader, PdfFileWriter
except ImportError as err:
_logger.debug(err)
class IrActionsReport(models.Model):
_inherit = "ir.actions.report"
encrypt = fields.Selection(
[("manual", "Manual Input Password"), ("auto", "Auto Generated Password")],
string="Encryption",
help="* Manual Input Password: allow user to key in password on the fly. "
"This option available only on document print action.\n"
"* Auto Generated Password: system will auto encrypt password when PDF "
"created, based on provided python syntax.",
)
encrypt_password = fields.Char(
help="Python code syntax to gnerate password.",
)
def _render_qweb_pdf(self, res_ids=None, data=None):
document, ttype = super(IrActionsReport, self)._render_qweb_pdf(
res_ids=res_ids, data=data
)
password = self._get_pdf_password(res_ids[:1])
document = self._encrypt_pdf(document, password)
return document, ttype
def _get_pdf_password(self, res_id):
encrypt_password = False
if self.encrypt == "manual":
# If use document print action, report_download() is called,
# but that can't pass context (encrypt_password) here.
# As such, file will be encrypted by report_download() again.
# --
# Following is used just in case when context is passed in.
encrypt_password = self._context.get("encrypt_password", False)
elif self.encrypt == "auto" and self.encrypt_password:
obj = self.env[self.model].browse(res_id)
try:
encrypt_password = safe_eval(self.encrypt_password, {"object": obj})
except Exception:
raise ValidationError(
_("Python code used for encryption password is invalid.\n%s")
% self.encrypt_password
)
return encrypt_password
def _encrypt_pdf(self, data, password):
if not password:
return data
output_pdf = PdfFileWriter()
in_buff = BytesIO(data)
pdf = PdfFileReader(in_buff)
output_pdf.appendPagesFromReader(pdf)
output_pdf.encrypt(password)
buff = BytesIO()
output_pdf.write(buff)
return buff.getvalue()
def _get_readable_fields(self):
return super()._get_readable_fields() | {"encrypt"}