# -*- 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()