# -*- coding: utf-8 -*- # Fusion PDF Field Editor Controller # Provides routes for the visual drag-and-drop field position editor import base64 import json import logging from odoo import http from odoo.http import request _logger = logging.getLogger(__name__) class FusionPdfEditorController(http.Controller): """Controller for the PDF field position visual editor.""" # ================================================================ # Editor Page # ================================================================ @http.route('/fusion/pdf-editor/', type='http', auth='user', website=True) def pdf_field_editor(self, template_id, **kw): """Render the visual field editor for a PDF template.""" template = request.env['fusion.pdf.template'].browse(template_id) if not template.exists(): return request.redirect('/web') # Get preview image for page 1 preview_url = '' preview = template.preview_ids.filtered(lambda p: p.page == 1) if preview and preview[0].image: preview_url = f'/web/image/fusion.pdf.template.preview/{preview[0].id}/image' fields = template.field_ids.read([ 'name', 'label', 'page', 'pos_x', 'pos_y', 'width', 'height', 'field_type', 'font_size', 'font_name', 'field_key', 'default_value', 'is_active', ]) return request.render('fusion_authorizer_portal.portal_pdf_field_editor', { 'template': template, 'fields': fields, 'preview_url': preview_url, }) # ================================================================ # JSONRPC: Get fields for template # ================================================================ @http.route('/fusion/pdf-editor/fields', type='json', auth='user') def get_fields(self, template_id, **kw): """Return all fields for a template.""" template = request.env['fusion.pdf.template'].browse(template_id) if not template.exists(): return [] return template.field_ids.read([ 'name', 'label', 'page', 'pos_x', 'pos_y', 'width', 'height', 'field_type', 'font_size', 'font_name', 'field_key', 'default_value', 'is_active', ]) # ================================================================ # JSONRPC: Update field position/properties # ================================================================ @http.route('/fusion/pdf-editor/update-field', type='json', auth='user') def update_field(self, field_id, values, **kw): """Update a field's position or properties.""" field = request.env['fusion.pdf.template.field'].browse(field_id) if not field.exists(): return {'error': 'Field not found'} # Filter to allowed fields only allowed = { 'name', 'label', 'page', 'pos_x', 'pos_y', 'width', 'height', 'field_type', 'font_size', 'font_name', 'field_key', 'default_value', 'is_active', } safe_values = {k: v for k, v in values.items() if k in allowed} if safe_values: field.write(safe_values) return {'success': True} # ================================================================ # JSONRPC: Create new field # ================================================================ @http.route('/fusion/pdf-editor/create-field', type='json', auth='user') def create_field(self, **kw): """Create a new field on a template.""" template_id = kw.get('template_id') if not template_id: return {'error': 'Missing template_id'} vals = { 'template_id': int(template_id), 'name': kw.get('name', 'new_field'), 'label': kw.get('label', 'New Field'), 'field_type': kw.get('field_type', 'text'), 'field_key': kw.get('field_key', kw.get('name', '')), 'page': int(kw.get('page', 1)), 'pos_x': float(kw.get('pos_x', 0.3)), 'pos_y': float(kw.get('pos_y', 0.3)), 'width': float(kw.get('width', 0.150)), 'height': float(kw.get('height', 0.015)), 'font_size': float(kw.get('font_size', 10)), } field = request.env['fusion.pdf.template.field'].create(vals) return {'id': field.id, 'success': True} # ================================================================ # JSONRPC: Delete field # ================================================================ @http.route('/fusion/pdf-editor/delete-field', type='json', auth='user') def delete_field(self, field_id, **kw): """Delete a field from a template.""" field = request.env['fusion.pdf.template.field'].browse(field_id) if field.exists(): field.unlink() return {'success': True} # ================================================================ # JSONRPC: Get page preview image URL # ================================================================ @http.route('/fusion/pdf-editor/page-image', type='json', auth='user') def get_page_image(self, template_id, page, **kw): """Return the preview image URL for a specific page.""" template = request.env['fusion.pdf.template'].browse(template_id) if not template.exists(): return {'image_url': ''} preview = template.preview_ids.filtered(lambda p: p.page == page) if preview and preview[0].image: return {'image_url': f'/web/image/fusion.pdf.template.preview/{preview[0].id}/image'} return {'image_url': ''} # ================================================================ # Upload page preview image (from editor) # ================================================================ @http.route('/fusion/pdf-editor/upload-preview', type='http', auth='user', methods=['POST'], csrf=True, website=True) def upload_preview_image(self, **kw): """Upload a preview image for a template page directly from the editor.""" template_id = int(kw.get('template_id', 0)) page = int(kw.get('page', 1)) template = request.env['fusion.pdf.template'].browse(template_id) if not template.exists(): return json.dumps({'error': 'Template not found'}) image_file = request.httprequest.files.get('preview_image') if not image_file: return json.dumps({'error': 'No image uploaded'}) image_data = base64.b64encode(image_file.read()) # Find or create preview for this page preview = template.preview_ids.filtered(lambda p: p.page == page) if preview: preview[0].write({'image': image_data, 'image_filename': image_file.filename}) else: request.env['fusion.pdf.template.preview'].create({ 'template_id': template_id, 'page': page, 'image': image_data, 'image_filename': image_file.filename, }) _logger.info("Uploaded preview image for template %s page %d", template.name, page) return request.redirect(f'/fusion/pdf-editor/{template_id}') # ================================================================ # Preview: Generate sample filled PDF # ================================================================ @http.route('/fusion/pdf-editor/preview/', type='http', auth='user') def preview_pdf(self, template_id, **kw): """Generate a preview filled PDF with sample data.""" template = request.env['fusion.pdf.template'].browse(template_id) if not template.exists() or not template.pdf_file: return request.redirect('/web') # Build sample data for preview sample_context = { 'client_last_name': 'Smith', 'client_first_name': 'John', 'client_middle_name': 'A', 'client_health_card': '1234-567-890', 'client_health_card_version': 'AB', 'client_street': '123 Main Street', 'client_unit': 'Unit 4B', 'client_city': 'Toronto', 'client_state': 'Ontario', 'client_postal_code': 'M5V 2T6', 'client_phone': '(416) 555-0123', 'client_email': 'john.smith@example.com', 'client_weight': '185', 'consent_applicant': True, 'consent_agent': False, 'consent_date': '2026-02-08', 'agent_last_name': '', 'agent_first_name': '', } try: pdf_bytes = template.generate_filled_pdf(sample_context) headers = [ ('Content-Type', 'application/pdf'), ('Content-Disposition', f'inline; filename="preview_{template.name}.pdf"'), ] return request.make_response(pdf_bytes, headers=headers) except Exception as e: _logger.error("PDF preview generation failed: %s", e) return request.redirect(f'/fusion/pdf-editor/{template_id}?error=preview_failed')