This commit is contained in:
gsinghpal
2026-02-23 00:32:20 -05:00
parent d6bac8e623
commit e8e554de95
549 changed files with 1330 additions and 124935 deletions

View File

@@ -1141,22 +1141,6 @@ class SaleOrder(models.Model):
default=2,
help='Page number in approval form where signature should be placed (1-indexed)',
)
x_fc_sa_signature_position = fields.Selection([
('default', 'Default (SA Mobility Standard)'),
('middle', 'Middle of Page'),
('bottom', 'Bottom of Page'),
('custom', 'Custom Position'),
], string='Signature Position', default='default')
x_fc_sa_signature_offset_x = fields.Integer(
string='Signature X Offset',
default=0,
help='Horizontal offset in points (positive = right)',
)
x_fc_sa_signature_offset_y = fields.Integer(
string='Signature Y Offset',
default=0,
help='Vertical offset in points (positive = up)',
)
# --- Ontario Works document fields ---
x_fc_ow_discretionary_form = fields.Binary(
@@ -1593,48 +1577,12 @@ class SaleOrder(models.Model):
return {'type': 'ir.actions.act_window_close'}
def _get_sa_pdf_template(self):
"""Find the active SA Mobility signature template."""
return self.env['fusion.sa.signature.template'].search([
('active', '=', True),
], limit=1)
def _get_sa_signature_coordinates(self, page_h=792):
"""Get signature overlay coordinates.
Reads the global template from Configuration > PDF Templates,
then applies any per-case offsets stored on this sale order.
"""
self.ensure_one()
tpl = self._get_sa_pdf_template()
ox = self.x_fc_sa_signature_offset_x or 0
oy = self.x_fc_sa_signature_offset_y or 0
if tpl:
coords = tpl.get_sa_coordinates(page_h)
else:
coords = {
'name_x': 105, 'name_y': page_h - 97,
'date_x': 430, 'date_y': page_h - 97,
'sig_x': 72, 'sig_y': page_h - 72 - 25,
'sig_w': 190, 'sig_h': 25,
}
if ox or oy:
coords = {
'name_x': coords['name_x'] + ox,
'name_y': coords['name_y'] + oy,
'date_x': coords['date_x'] + ox,
'date_y': coords['date_y'] + oy,
'sig_x': coords['sig_x'] + ox,
'sig_y': coords['sig_y'] + oy,
'sig_w': coords['sig_w'],
'sig_h': coords['sig_h'],
}
return coords
def _apply_pod_signature_to_approval_form(self):
"""Auto-overlay POD signature onto the ODSP approval form at the configured page/position."""
"""Auto-overlay POD signature onto the ODSP approval form.
Uses the ODSP PDF Template (fusion.pdf.template, category=odsp) for
field positions, and the per-case signature page number.
"""
self.ensure_one()
if not all([
self.x_fc_odsp_division == 'sa_mobility',
@@ -1645,71 +1593,54 @@ class SaleOrder(models.Model):
return
import base64
from io import BytesIO
try:
from reportlab.pdfgen import canvas as rl_canvas
from reportlab.lib.utils import ImageReader
from odoo.tools.pdf import PdfFileReader, PdfFileWriter
except ImportError:
_logger.warning("PDF libraries not available for approval form signing.")
from odoo.addons.fusion_authorizer_portal.utils.pdf_filler import PDFTemplateFiller
tpl = self.env['fusion.pdf.template'].search([
('category', '=', 'odsp'), ('state', '=', 'active'),
], limit=1)
if not tpl:
_logger.warning("No active ODSP PDF template found for signing %s", self.name)
return
sig_page = self.x_fc_sa_signature_page or 2
fields_by_page = {}
for field in tpl.field_ids.filtered(lambda f: f.is_active):
page = sig_page
if page not in fields_by_page:
fields_by_page[page] = []
fields_by_page[page].append({
'field_name': field.name,
'field_key': field.field_key or field.name,
'pos_x': field.pos_x,
'pos_y': field.pos_y,
'width': field.width,
'height': field.height,
'field_type': field.field_type,
'font_size': field.font_size,
'font_name': field.font_name or 'Helvetica',
'text_align': field.text_align or 'left',
})
client_name = self.x_fc_pod_client_name or self.x_fc_sa_client_name or self.partner_id.name or ''
sign_date = self.x_fc_pod_signature_date or self.x_fc_sa_client_signed_date
context_data = {
'sa_client_name': client_name,
'sa_sign_date': sign_date.strftime('%b %d, %Y') if sign_date else '',
}
signatures = {
'sa_signature': base64.b64decode(self.x_fc_pod_signature),
}
pdf_bytes = base64.b64decode(self.x_fc_sa_approval_form)
original = PdfFileReader(BytesIO(pdf_bytes))
output = PdfFileWriter()
num_pages = original.getNumPages()
target_page = (self.x_fc_sa_signature_page or 2) - 1
if target_page < 0 or target_page >= num_pages:
_logger.warning(
"Signature page %s out of range (total %s) for %s",
self.x_fc_sa_signature_page, num_pages, self.name
try:
signed_pdf = PDFTemplateFiller.fill_template(
pdf_bytes, fields_by_page, context_data, signatures,
)
except Exception as e:
_logger.error("Failed to apply signature to approval form for %s: %s", self.name, e)
return
for page_idx in range(num_pages):
page = original.getPage(page_idx)
if page_idx == target_page:
page_w = float(page.mediaBox.getWidth())
page_h = float(page.mediaBox.getHeight())
coords = self._get_sa_signature_coordinates(page_h)
overlay_buf = BytesIO()
c = rl_canvas.Canvas(overlay_buf, pagesize=(page_w, page_h))
client_name = self.x_fc_pod_client_name or self.x_fc_sa_client_name or self.partner_id.name or ''
if client_name:
c.setFont('Helvetica', 11)
c.drawString(coords['name_x'], coords['name_y'], client_name)
sign_date = self.x_fc_pod_signature_date or self.x_fc_sa_client_signed_date
if sign_date:
date_str = sign_date.strftime('%b %d, %Y')
c.setFont('Helvetica', 11)
c.drawString(coords['date_x'], coords['date_y'], date_str)
if self.x_fc_pod_signature:
sig_data = base64.b64decode(self.x_fc_pod_signature)
sig_image = ImageReader(BytesIO(sig_data))
c.drawImage(
sig_image,
coords['sig_x'], coords['sig_y'],
width=coords['sig_w'], height=coords['sig_h'],
preserveAspectRatio=True, mask='auto',
)
c.save()
overlay_buf.seek(0)
overlay_pdf = PdfFileReader(overlay_buf)
page.mergePage(overlay_pdf.getPage(0))
output.addPage(page)
result_buf = BytesIO()
output.write(result_buf)
signed_pdf = result_buf.getvalue()
filename = f'SA_Approval_Signed_{self.name}.pdf'
self.with_context(skip_pod_signature_hook=True).write({
'x_fc_sa_signed_form': base64.b64encode(signed_pdf),
@@ -1725,7 +1656,7 @@ class SaleOrder(models.Model):
'mimetype': 'application/pdf',
})
self.message_post(
body="POD signature applied to ODSP approval form (page %s)." % self.x_fc_sa_signature_page,
body="POD signature applied to ODSP approval form (page %s)." % sig_page,
message_type='comment',
attachment_ids=[att.id],
)
@@ -6546,7 +6477,7 @@ class SaleOrder(models.Model):
'default_model': 'sale.order',
'default_res_ids': self.ids,
'default_template_id': template.id,
'default_email_layout_xmlid': 'mail.mail_notification_layout_with_responsible_signature',
'default_email_layout_xmlid': 'mail.mail_notification_layout',
'default_composition_mode': 'comment',
'mark_so_as_sent': True,
'force_email': True,