feat: Add sign_document model to enable rendering of sequence type sign items on signed PDFs.
This commit is contained in:
parent
2100c197b9
commit
8493d62d08
@ -2,3 +2,4 @@
|
|||||||
from . import sign_item_type
|
from . import sign_item_type
|
||||||
from . import sign_item
|
from . import sign_item
|
||||||
from . import sign_request
|
from . import sign_request
|
||||||
|
from . import sign_document
|
||||||
|
|||||||
109
models/sign_document.py
Normal file
109
models/sign_document.py
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
# -*- 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(SignDocument, self).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_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
|
||||||
Loading…
Reference in New Issue
Block a user