115 lines
6.5 KiB
Python
Executable File
115 lines
6.5 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.
|
|
|
|
_logger.info("SignSequenceField: Starting sequence generation for sign.request %s", self.ids)
|
|
for request in self:
|
|
# Generate sequence numbers for sequence items
|
|
# Use template_id.document_ids.sign_item_ids to be safe
|
|
signer_items = request.template_id.document_ids.sign_item_ids
|
|
_logger.info("SignSequenceField: Found %s total sign items on template documents for request %s", len(signer_items), request.id)
|
|
for sign_item in signer_items:
|
|
_logger.debug("SignSequenceField: Checking item %s: type=%s, sequence_id=%s", sign_item.id, sign_item.type_id.item_type, sign_item.sequence_id.id if sign_item.sequence_id else 'None')
|
|
if sign_item.type_id.item_type == 'sequence' and sign_item.sequence_id:
|
|
_logger.info("SignSequenceField: Processing sequence item %s (ID: %s) for request %s", sign_item.name, sign_item.id, request.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:
|
|
_logger.info("SignSequenceField: No matching request items for role %s, falling back to first signer", sign_item.responsible_id.name)
|
|
request_items = request.request_item_ids[:1]
|
|
|
|
if not request_items:
|
|
_logger.warning("SignSequenceField: No request items found at all for request %s", request.id)
|
|
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)
|
|
|
|
placeholder = (sign_item.type_id.placeholder or "Sequence Number").strip().lower()
|
|
current_val = str(existing_value.value or "").strip().lower()
|
|
_logger.debug("SignSequenceField: existing_value check for item %s: '%s' (placeholder: '%s')", sign_item.id, current_val, placeholder)
|
|
|
|
# If it exists but value is empty/false OR it equals the placeholder
|
|
# we must regenerate it.
|
|
if not existing_value or not current_val or current_val == placeholder:
|
|
_logger.info("SignSequenceField: Generating sequence for item %s", sign_item.id)
|
|
new_seq = sign_item.sequence_id.next_by_id()
|
|
_logger.info("SignSequenceField: Generated new sequence: %s", new_seq)
|
|
if new_seq:
|
|
if existing_value:
|
|
# Update existing empty record
|
|
_logger.debug("SignSequenceField: Updating existing value record %s", existing_value.id)
|
|
existing_value.write({'value': new_seq})
|
|
else:
|
|
# Create value for the first matching signer
|
|
_logger.debug("SignSequenceField: Creating new value record for signer %s", request_items[0].id)
|
|
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} - "):
|
|
_logger.info("SignSequenceField: Prefixing document name with sequence: %s", new_seq)
|
|
request.write({'reference': f"{new_seq} - {request.reference}"})
|
|
else:
|
|
_logger.error("SignSequenceField: next_by_id() returned None for sequence %s", sign_item.sequence_id.id)
|
|
else:
|
|
_logger.info("SignSequenceField: Sequence already exists for item %s: %s", sign_item.id, existing_value.value)
|
|
|
|
return super()._sign()
|
|
|
|
|
|
|