public with sharing class PropertyTemplateController { @AuraEnabled(cacheable=true) public static List getPropertyTemplates() { try { return [SELECT Id, Name, Description__c, Preview_Image_URL__c, Tags__c, Is_Active__c, Template_Definition__c FROM Property_Template__c WHERE Is_Active__c = true ORDER BY Name]; } catch (Exception e) { throw new AuraHandledException('Error fetching templates: ' + e.getMessage()); } } @AuraEnabled(cacheable=true) public static Property_Template__c getPropertyTemplateById(String templateId) { try { return [SELECT Id, Name, Description__c, Preview_Image_URL__c, Tags__c, Is_Active__c, Template_Definition__c FROM Property_Template__c WHERE Id = :templateId AND Is_Active__c = true LIMIT 1]; } catch (Exception e) { throw new AuraHandledException('Error fetching template: ' + e.getMessage()); } } @AuraEnabled(cacheable=true) public static List getPropertyData() { try { return [SELECT Id, Name, pcrm__Property_Type__c, pcrm__Sub_Locality_Bayut_Dubizzle__c, pcrm__Sale_Price_max__c, pcrm__Rent_Price_max__c, pcrm__Bedrooms__c, pcrm__Bathrooms__c, pcrm__Size__c, pcrm__Description_English__c, pcrm__Title_English__c, pcrm__Unit_Number__c, pcrm__Completion_Status__c, pcrm__Furnished__c, pcrm__Tower_Bayut_Dubizzle__c, pcrm__Community_Propertyfinder__c, pcrm__Sub_Community_Propertyfinder__c, pcrm__City_Propertyfinder__c, pcrm__City_Bayut_Dubizzle__c FROM pcrm__Property__c ORDER BY Name]; } catch (Exception e) { throw new AuraHandledException('Error fetching properties: ' + e.getMessage()); } } @AuraEnabled(cacheable=true) public static pcrm__Property__c getPropertyById(String propertyId) { try { return [SELECT Id, Name, pcrm__Property_Type__c, pcrm__Sub_Locality_Bayut_Dubizzle__c, pcrm__Sale_Price_max__c, pcrm__Rent_Price_max__c, pcrm__Bedrooms__c, pcrm__Bathrooms__c, pcrm__Size__c, pcrm__Description_English__c, pcrm__Title_English__c, pcrm__Unit_Number__c, pcrm__Completion_Status__c, pcrm__Furnished__c, pcrm__Tower_Bayut_Dubizzle__c, pcrm__Community_Propertyfinder__c, pcrm__Sub_Community_Propertyfinder__c, pcrm__City_Propertyfinder__c, pcrm__City_Bayut_Dubizzle__c FROM pcrm__Property__c WHERE Id = :propertyId LIMIT 1]; } catch (Exception e) { throw new AuraHandledException('Error fetching property: ' + e.getMessage()); } } @AuraEnabled(cacheable=true) public static Map getMarketData() { try { // For now, return default market data since you might not have Market_Analytics__c Map result = new Map(); // Default Dubai market data result.put('marketTrend', 'Rising'); result.put('roiPotential', '8.5'); result.put('avgPricePerSqft', '1200'); result.put('marketDemand', 'High'); result.put('investmentType', 'Buy-to-Rent'); result.put('rentalYield', '6.2'); result.put('investmentHighlights', 'Prime location with high rental demand and capital appreciation potential'); result.put('locationAdvantages', 'Excellent connectivity, premium amenities, and strong infrastructure'); List contentModules = new List{'Market Analysis', 'Investment Overview', 'Location Highlights'}; result.put('contentModules', contentModules); result.put('additionalContent', 'Dubai real estate market shows strong growth potential with government initiatives and Expo 2020 legacy'); return result; } catch (Exception e) { throw new AuraHandledException('Error fetching market data: ' + e.getMessage()); } } // Helper method to create template HTML content private static String createTemplateHTML(Map propertyMap, String templateName) { try { String propertyName = (String) propertyMap.get('propertyName') != null ? (String) propertyMap.get('propertyName') : 'Property Name'; String propertyType = (String) propertyMap.get('propertyType') != null ? (String) propertyMap.get('propertyType') : 'Property Type'; String location = (String) propertyMap.get('location') != null ? (String) propertyMap.get('location') : 'Location'; String price = (String) propertyMap.get('price') != null ? (String) propertyMap.get('price') : 'Price'; String bedrooms = (String) propertyMap.get('bedrooms') != null ? (String) propertyMap.get('bedrooms') : 'N/A'; String bathrooms = (String) propertyMap.get('bathrooms') != null ? (String) propertyMap.get('bathrooms') : 'N/A'; String area = (String) propertyMap.get('area') != null ? (String) propertyMap.get('area') : 'N/A'; String description = (String) propertyMap.get('description') != null ? (String) propertyMap.get('description') : 'Property Description'; // Create a professional property brochure HTML String htmlContent = ''; htmlContent += '' + propertyName + ' - Property Brochure'; htmlContent += ''; htmlContent += '
'; htmlContent += '
'; htmlContent += '

' + propertyName + '

'; htmlContent += '
' + propertyType + ' • ' + location + '
'; htmlContent += '
'; htmlContent += '
'; htmlContent += '
'; htmlContent += '
Price
' + price + '
'; htmlContent += '
Bedrooms
' + bedrooms + '
'; htmlContent += '
Bathrooms
' + bathrooms + '
'; htmlContent += '
Area
' + area + '
'; htmlContent += '
'; htmlContent += '
'; htmlContent += '

Property Description

'; htmlContent += '

' + description + '

'; htmlContent += '
'; htmlContent += '
'; htmlContent += ''; htmlContent += '
'; return htmlContent; } catch (Exception e) { System.debug('Error creating template HTML: ' + e.getMessage()); return '

Error generating template

' + e.getMessage() + '

'; } } @AuraEnabled public static Map generatePropertyPDF(String propertyData, String templateName, Boolean generatePDF, String htmlContent) { try { // Parse property data Map propertyMap = (Map) JSON.deserializeUntyped(propertyData); // Call external Python API for PDF generation String apiEndpoint = 'https://salesforce.tech4biz.io/generate-pdf'; // Production PDF Generator API // Prepare request body - using the format that was working in first prompt Map requestBody = new Map(); // Debug: Log the property data and template name System.debug('=== DEBUG INFO ==='); System.debug('propertyMap: ' + propertyMap); System.debug('templateName: ' + templateName); System.debug('propertyMap keys: ' + propertyMap.keySet()); System.debug('HTML Content Length: ' + (htmlContent != null ? htmlContent.length() : 0)); // Use the provided HTML content directly instead of generating it String finalHTMLContent = htmlContent; // If no HTML content provided, fall back to generating it (for backward compatibility) if (String.isBlank(finalHTMLContent)) { System.debug('No HTML content provided, generating fallback HTML...'); finalHTMLContent = createTemplateHTML(propertyMap, templateName); } // Validate that HTML content exists if (String.isBlank(finalHTMLContent)) { Map result = new Map(); result.put('success', false); result.put('message', 'Error: HTML content is empty - cannot generate PDF'); System.debug('ERROR: Final HTML content is empty!'); return result; } System.debug('Final HTML content length: ' + finalHTMLContent.length()); System.debug('Final HTML content preview: ' + finalHTMLContent.substring(0, Math.min(200, finalHTMLContent.length()))); requestBody.put('html_content', finalHTMLContent); requestBody.put('property_data', propertyMap); requestBody.put('template_name', templateName); requestBody.put('filename', 'property_brochure.pdf'); // Make HTTP callout to Python API Http http = new Http(); HttpRequest request = new HttpRequest(); request.setEndpoint(apiEndpoint); request.setMethod('POST'); request.setHeader('Content-Type', 'application/json'); request.setHeader('Accept', 'application/json'); request.setBody(JSON.serialize(requestBody)); request.setTimeout(120000); // 2 minutes timeout System.debug('Calling Python API at: ' + apiEndpoint); System.debug('Request body: ' + JSON.serialize(requestBody)); HttpResponse response = http.send(request); System.debug('Response status: ' + response.getStatusCode()); System.debug('Response body: ' + response.getBody()); if (response.getStatusCode() == 200) { Map responseMap = (Map) JSON.deserializeUntyped(response.getBody()); Map result = new Map(); result.put('success', true); result.put('pdfUrl', responseMap.get('pdf_url')); result.put('message', 'PDF generated successfully'); System.debug('PDF generation successful: ' + result); return result; } else { Map result = new Map(); result.put('success', false); result.put('message', 'Failed to generate PDF: ' + response.getStatus() + ' - ' + response.getBody()); System.debug('PDF generation failed: ' + result); return result; } } catch (Exception e) { Map result = new Map(); result.put('success', false); result.put('message', 'Error: ' + e.getMessage()); return result; } } @AuraEnabled public static List searchPropertyTemplates(String searchTerm) { try { String searchQuery = '%' + searchTerm + '%'; return [SELECT Id, Name, Description__c, Preview_Image_URL__c, Tags__c, Is_Active__c, Template_Definition__c FROM Property_Template__c WHERE Is_Active__c = true AND (Name LIKE :searchQuery OR Tags__c LIKE :searchQuery) ORDER BY Name]; } catch (Exception e) { throw new AuraHandledException('Error searching templates: ' + e.getMessage()); } } }