sign_sequence_field/models/sign_request.py

94 lines
4.4 KiB
Python
Executable File

# -*- coding: utf-8 -*-
import base64
import io
import os
import time
from dateutil.relativedelta import relativedelta
from datetime import timedelta
from reportlab.lib.utils import ImageReader
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.rl_config import TTFSearchPath
from reportlab.pdfgen import canvas
from reportlab.platypus import Paragraph
from reportlab.lib.styles import ParagraphStyle
from reportlab.pdfbase.pdfmetrics import stringWidth
from PIL import UnidentifiedImageError
from odoo import api, fields, models, _, Command
from odoo.exceptions import UserError, ValidationError
from odoo.tools.pdf import PdfFileReader, PdfFileWriter, PdfReadError, reshape_text
import logging
_logger = logging.getLogger(__name__)
# Helper function copied from sign/models/sign_request.py
def _fix_image_transparency(image):
pixels = image.load()
for x in range(image.size[0]):
for y in range(image.size[1]):
if pixels[x, y] == (0, 0, 0, 0):
pixels[x, y] = (255, 255, 255, 0)
class SignRequest(models.Model):
_inherit = "sign.request"
def _sign(self):
""" Override to generate sequence numbers when request is signed """
# We perform sequence generation BEFORE calling super()._sign()
# because super()._sign() triggers _send_completed_document() immediately.
# We need the sequence values to be ready before the document is generated and sent.
# We only generate if we are about to complete the signing process.
# The logic in _post_fill_request_item calls _sign only when all items are completed.
for request in self:
# Generate sequence numbers for sequence items
for sign_item in request.template_id.sign_item_ids:
if sign_item.type_id.item_type == 'sequence' and sign_item.sequence_id:
# Find the responsible request item (signer)
# Use role_id to match.
# Fallback to the first signer if no specific matching signer is found (e.g. role is "Anyone")
request_items = request.request_item_ids.filtered(lambda r: r.role_id == sign_item.responsible_id)
if not request_items:
request_items = request.request_item_ids[:1]
if not request_items:
continue
# We only generate if it hasn't been generated yet for this sign_item across the whole request
# to prevent duplicate generation if multiple request_items were somehow matched.
existing_value = request.env['sign.request.item.value'].search([
('sign_request_id', '=', request.id),
('sign_item_id', '=', sign_item.id)
], limit=1)
# If it exists but value is empty/false OR it equals the placeholder "Sequence Number"
# we must regenerate it.
if not existing_value or not existing_value.value or existing_value.value == "Sequence Number":
new_seq = sign_item.sequence_id.next_by_id()
if new_seq:
if existing_value:
# Update existing empty record
existing_value.write({'value': new_seq})
else:
# Create value for the first matching signer
request.env['sign.request.item.value'].create({
'sign_request_item_id': request_items[0].id,
'sign_item_id': sign_item.id,
'value': new_seq
})
# Rename the document if requested
# User asked to put sequence in prefix of document name.
# request.reference is the document name.
# Check if already renamed to avoid double prefixing
if not request.reference.startswith(f"{new_seq} - "):
request.write({'reference': f"{new_seq} - {request.reference}"})
return super()._sign()