#!/usr/bin/env python3 """ Flask API for Salesforce PDF Generation Takes HTML content from Salesforce and returns a downloadable PDF """ from flask import Flask, request, send_file, jsonify from flask_cors import CORS import pdfkit import os import tempfile import base64 from datetime import datetime import logging import json # Configure logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) app = Flask(__name__) CORS(app) # Configure pdfkit options for better PDF generation PDF_OPTIONS = { 'page-size': 'A4', 'margin-top': '0.75in', 'margin-right': '0.75in', 'margin-bottom': '0.75in', 'margin-left': '0.75in', 'encoding': "UTF-8", 'no-outline': None, 'enable-local-file-access': None, 'print-media-type': None, 'dpi': 300, 'image-quality': 100, 'javascript-delay': 1000, 'no-stop-slow-scripts': None, 'custom-header': [ ('Accept-Encoding', 'gzip') ] } @app.route('/health', methods=['GET']) def health_check(): """Health check endpoint""" return jsonify({ 'status': 'healthy', 'timestamp': datetime.now().isoformat(), 'service': 'Salesforce PDF Generator API' }) @app.route('/generate-pdf', methods=['POST']) def generate_pdf(): """ Generate PDF from HTML content sent from Salesforce Expected JSON payload: { "html_content": "...", "property_data": {...}, "template_name": "everkind", "filename": "property_brochure.pdf" } """ try: logger.info("Received PDF generation request from Salesforce") # Get request data data = request.get_json() if not data: return jsonify({'error': 'No data provided'}), 400 html_content = data.get('html_content') property_data = data.get('property_data', {}) template_name = data.get('template_name', 'default') filename = data.get('filename', f'property_brochure_{datetime.now().strftime("%Y%m%d_%H%M%S")}.pdf') if not html_content: return jsonify({'error': 'HTML content is required'}), 400 logger.info(f"Processing template: {template_name}") logger.info(f"Property data keys: {list(property_data.keys()) if property_data else 'None'}") logger.info(f"HTML content length: {len(html_content)}") # Create complete HTML document with proper styling complete_html = create_complete_html_document(html_content, property_data, template_name) # Generate PDF pdf_path = generate_pdf_from_html(complete_html, filename) if not pdf_path or not os.path.exists(pdf_path): return jsonify({'error': 'Failed to generate PDF'}), 500 logger.info(f"PDF generated successfully: {pdf_path}") # Return the PDF file return send_file( pdf_path, as_attachment=True, download_name=filename, mimetype='application/pdf' ) except Exception as e: logger.error(f"Error generating PDF: {str(e)}") return jsonify({'error': f'PDF generation failed: {str(e)}'}), 500 def create_complete_html_document(html_content, property_data, template_name): """Create a complete HTML document with proper styling and data""" # Base CSS styles for consistent PDF output base_css = """ """ # Create the complete HTML document complete_html = f""" Property Brochure - {property_data.get('propertyName', 'Property')} {base_css} {html_content} """ return complete_html def generate_pdf_from_html(html_content, filename): """Generate PDF from HTML content using pdfkit""" try: # Create temporary file for the PDF temp_dir = tempfile.gettempdir() pdf_path = os.path.join(temp_dir, filename) logger.info(f"Generating PDF at: {pdf_path}") # Configure pdfkit with wkhtmltopdf try: # Try to use system wkhtmltopdf config = pdfkit.configuration(wkhtmltopdf='/usr/bin/wkhtmltopdf') pdfkit.from_string(html_content, pdf_path, options=PDF_OPTIONS, configuration=config) except Exception as e: logger.warning(f"System wkhtmltopdf failed: {e}") # Try without configuration (uses PATH) pdfkit.from_string(html_content, pdf_path, options=PDF_OPTIONS) if os.path.exists(pdf_path): file_size = os.path.getsize(pdf_path) logger.info(f"PDF generated successfully. Size: {file_size} bytes") return pdf_path else: logger.error("PDF file was not created") return None except Exception as e: logger.error(f"Error in generate_pdf_from_html: {str(e)}") return None @app.route('/test-pdf', methods=['GET']) def test_pdf(): """Test endpoint to verify PDF generation works""" try: test_html = """

Test Property

Villa in Dubai Marina

Price
AED 2,500,000
Bedrooms
3
""" test_data = { 'propertyName': 'Test Property', 'propertyType': 'Villa', 'location': 'Dubai Marina' } complete_html = create_complete_html_document(test_html, test_data, 'test') pdf_path = generate_pdf_from_html(complete_html, 'test_property.pdf') if pdf_path and os.path.exists(pdf_path): return send_file( pdf_path, as_attachment=True, download_name='test_property.pdf', mimetype='application/pdf' ) else: return jsonify({'error': 'Test PDF generation failed'}), 500 except Exception as e: return jsonify({'error': f'Test failed: {str(e)}'}), 500 @app.route('/api/info', methods=['GET']) def api_info(): """Get API information""" return jsonify({ 'name': 'Salesforce PDF Generator API', 'version': '1.0.0', 'description': 'Takes HTML content from Salesforce and returns downloadable PDF', 'endpoints': { 'health': '/health', 'generate_pdf': '/generate-pdf', 'test_pdf': '/test-pdf', 'api_info': '/api/info' }, 'usage': { 'method': 'POST', 'endpoint': '/generate-pdf', 'content_type': 'application/json', 'payload': { 'html_content': 'HTML content from Salesforce', 'property_data': 'Property information object', 'template_name': 'Template name', 'filename': 'Output filename (optional)' } } }) if __name__ == '__main__': logger.info("Starting Salesforce PDF Generator API Server...") logger.info("Available endpoints:") logger.info(" GET /health - Health check") logger.info(" POST /generate-pdf - Generate PDF from HTML") logger.info(" GET /test-pdf - Test PDF generation") logger.info(" GET /api/info - API information") app.run(host='0.0.0.0', port=8000, debug=True)