# -*- coding: utf-8 -*- import io from odoo import models from odoo.exceptions import ValidationError from odoo.tools.pdf import PdfFileReader, PdfFileWriter, PdfReadError, reshape_text from reportlab.pdfgen import canvas from reportlab.pdfbase import pdfmetrics try: from reportlab.pdfbase.pdfmetrics import stringWidth except ImportError: stringWidth = None class SignDocument(models.Model): _inherit = 'sign.document' def render_document_with_items(self, signed_values=None, values_dict=None, final_log_hash=None): base_output = super().render_document_with_items(signed_values, values_dict, final_log_hash) if not base_output: return base_output items_by_page = self._get_sign_items_by_page() has_sequence_items = any( item.type_id.item_type == 'sequence' for page_items in items_by_page.values() for item in page_items ) if not has_sequence_items: return base_output try: base_output.seek(0) # IMPORTANT: Reset stream position to start base_pdf = PdfFileReader(base_output, strict=False) except (ValueError, PdfReadError): return base_output if not signed_values: signed_values, values_dict = self._get_preview_values() font = self._get_font() normalFontSize = self._get_normal_font_size() packet = io.BytesIO() # Create canvas using page size similar to image logic can = canvas.Canvas(packet, pagesize=self._get_page_size(base_pdf)) for p in range(0, base_pdf.getNumPages()): page = base_pdf.getPage(p) width = float(abs(page.mediaBox.getWidth())) height = float(abs(page.mediaBox.getHeight())) rotation = page.get('/Rotate', 0) if rotation and isinstance(rotation, int): can.rotate(rotation) if rotation == 90: width, height = height, width can.translate(0, -height) elif rotation == 180: can.translate(-width, -height) elif rotation == 270: width, height = height, width can.translate(-width, 0) items = items_by_page.get(p + 1, []) for item in items: if item.type_id.item_type != 'sequence': continue value_dict = signed_values.get(item.id) if not value_dict: continue value = value_dict.get('value') # Sequence value is just text string if not value: continue # Render logic similar to text value = reshape_text(str(value)) # Ensure string can.setFont(font, height * item.height * 0.8) # Alignment logic if item.alignment == "left": can.drawString(width * item.posX, height * (1 - item.posY - item.height * 0.9), value) elif item.alignment == "right": can.drawRightString(width * (item.posX + item.width), height * (1 - item.posY - item.height * 0.9), value) else: can.drawCentredString(width * (item.posX + item.width / 2), height * (1 - item.posY - item.height * 0.9), value) can.showPage() can.save() item_pdf = PdfFileReader(packet) new_pdf = PdfFileWriter() for p in range(0, base_pdf.getNumPages()): page = base_pdf.getPage(p) if p < item_pdf.getNumPages(): page.mergePage(item_pdf.getPage(p)) new_pdf.addPage(page) output = io.BytesIO() try: new_pdf.write(output) except PdfReadError: raise ValidationError(self.env._("There was an issue generating the document.")) return output