PDF_Generation_and_Automation/force-app/main/default/classes/PropertyTemplateController.cls
2025-08-30 17:07:35 +05:30

245 lines
14 KiB
OpenEdge ABL

public with sharing class PropertyTemplateController {
@AuraEnabled(cacheable=true)
public static List<Property_Template__c> 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<pcrm__Property__c> 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<String, Object> getMarketData() {
try {
// For now, return default market data since you might not have Market_Analytics__c
Map<String, Object> result = new Map<String, Object>();
// 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<String> contentModules = new List<String>{'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<String, Object> 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 = '<!DOCTYPE html><html><head><meta charset="UTF-8">';
htmlContent += '<title>' + propertyName + ' - Property Brochure</title>';
htmlContent += '<style>';
htmlContent += 'body { font-family: Arial, sans-serif; margin: 0; padding: 20px; background: #f5f5f5; }';
htmlContent += '.brochure { max-width: 800px; margin: 0 auto; background: white; border-radius: 10px; box-shadow: 0 4px 20px rgba(0,0,0,0.1); overflow: hidden; }';
htmlContent += '.header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 40px; text-align: center; }';
htmlContent += '.header h1 { margin: 0; font-size: 2.5em; font-weight: 300; }';
htmlContent += '.header .subtitle { margin: 10px 0 0 0; font-size: 1.2em; opacity: 0.9; }';
htmlContent += '.content { padding: 40px; }';
htmlContent += '.property-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; margin: 30px 0; }';
htmlContent += '.stat-box { background: #f8f9fa; padding: 20px; border-radius: 8px; text-align: center; border: 1px solid #dee2e6; }';
htmlContent += '.stat-label { font-weight: bold; color: #667eea; font-size: 14px; text-transform: uppercase; margin-bottom: 8px; }';
htmlContent += '.stat-value { font-size: 18px; color: #333; font-weight: 600; }';
htmlContent += '.description { background: #f8f9fa; padding: 25px; border-radius: 10px; margin: 25px 0; }';
htmlContent += '.description h2 { color: #667eea; margin-bottom: 15px; font-size: 20px; border-bottom: 2px solid #667eea; padding-bottom: 8px; }';
htmlContent += '.footer { text-align: center; color: #666; font-size: 12px; border-top: 1px solid #dee2e6; padding-top: 20px; margin-top: 30px; }';
htmlContent += '</style></head><body>';
htmlContent += '<div class="brochure">';
htmlContent += '<div class="header">';
htmlContent += '<h1>' + propertyName + '</h1>';
htmlContent += '<div class="subtitle">' + propertyType + ' ' + location + '</div>';
htmlContent += '</div>';
htmlContent += '<div class="content">';
htmlContent += '<div class="property-stats">';
htmlContent += '<div class="stat-box"><div class="stat-label">Price</div><div class="stat-value">' + price + '</div></div>';
htmlContent += '<div class="stat-box"><div class="stat-label">Bedrooms</div><div class="stat-value">' + bedrooms + '</div></div>';
htmlContent += '<div class="stat-box"><div class="stat-label">Bathrooms</div><div class="stat-value">' + bathrooms + '</div></div>';
htmlContent += '<div class="stat-box"><div class="stat-label">Area</div><div class="stat-value">' + area + '</div></div>';
htmlContent += '</div>';
htmlContent += '<div class="description">';
htmlContent += '<h2>Property Description</h2>';
htmlContent += '<p>' + description + '</p>';
htmlContent += '</div>';
htmlContent += '</div>';
htmlContent += '<div class="footer">';
htmlContent += '<p><strong>Generated on:</strong> ' + Datetime.now().format('MMMM dd, yyyy \'at\' h:mm a') + '</p>';
htmlContent += '<p><em>Property CRM System - Professional Brochure</em></p>';
htmlContent += '</div>';
htmlContent += '</div></body></html>';
return htmlContent;
} catch (Exception e) {
System.debug('Error creating template HTML: ' + e.getMessage());
return '<html><body><h1>Error generating template</h1><p>' + e.getMessage() + '</p></body></html>';
}
}
@AuraEnabled
public static Map<String, Object> generatePropertyPDF(String propertyData, String templateName, Boolean generatePDF) {
try {
// Parse property data
Map<String, Object> propertyMap = (Map<String, Object>) 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<String, Object> requestBody = new Map<String, Object>();
// 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());
// Generate HTML content
String generatedHTML = createTemplateHTML(propertyMap, templateName);
System.debug('Generated HTML length: ' + generatedHTML.length());
System.debug('Generated HTML preview: ' + generatedHTML.substring(0, Math.min(200, generatedHTML.length())));
// Validate that HTML content was generated
if (String.isBlank(generatedHTML)) {
Map<String, Object> result = new Map<String, Object>();
result.put('success', false);
result.put('message', 'Error: HTML content generation failed - content is empty');
System.debug('ERROR: Generated HTML is empty!');
return result;
}
requestBody.put('html_content', generatedHTML);
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<String, Object> responseMap = (Map<String, Object>) JSON.deserializeUntyped(response.getBody());
Map<String, Object> result = new Map<String, Object>();
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<String, Object> result = new Map<String, Object>();
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<String, Object> result = new Map<String, Object>();
result.put('success', false);
result.put('message', 'Error: ' + e.getMessage());
return result;
}
}
@AuraEnabled
public static List<Property_Template__c> 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());
}
}
}