|
|
""" |
|
|
PDF Report Generator for Farmer.Chat |
|
|
Exports query results as downloadable PDF |
|
|
""" |
|
|
|
|
|
from reportlab.lib.pagesizes import letter, A4 |
|
|
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle |
|
|
from reportlab.lib.units import inch |
|
|
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, PageBreak |
|
|
from reportlab.lib import colors |
|
|
from reportlab.lib.enums import TA_CENTER, TA_LEFT |
|
|
from datetime import datetime |
|
|
import json |
|
|
import os |
|
|
from typing import Dict, Any |
|
|
|
|
|
|
|
|
def generate_pdf_report( |
|
|
query: str, |
|
|
advice: str, |
|
|
data: Dict[str, Any], |
|
|
location: Dict[str, Any] |
|
|
) -> str: |
|
|
""" |
|
|
Generate PDF report from query results |
|
|
|
|
|
Args: |
|
|
query: Farmer's question |
|
|
advice: Generated advice |
|
|
data: Compiled data from MCP servers |
|
|
location: Location information |
|
|
|
|
|
Returns: |
|
|
str: Path to generated PDF file |
|
|
""" |
|
|
|
|
|
output_dir = "./pdf_reports" |
|
|
os.makedirs(output_dir, exist_ok=True) |
|
|
|
|
|
|
|
|
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") |
|
|
filename = f"farmer_chat_report_{timestamp}.pdf" |
|
|
filepath = os.path.join(output_dir, filename) |
|
|
|
|
|
|
|
|
doc = SimpleDocTemplate(filepath, pagesize=letter) |
|
|
story = [] |
|
|
styles = getSampleStyleSheet() |
|
|
|
|
|
|
|
|
title_style = ParagraphStyle( |
|
|
'CustomTitle', |
|
|
parent=styles['Heading1'], |
|
|
fontSize=24, |
|
|
textColor=colors.HexColor('#2E7D32'), |
|
|
spaceAfter=30, |
|
|
alignment=TA_CENTER |
|
|
) |
|
|
|
|
|
heading_style = ParagraphStyle( |
|
|
'CustomHeading', |
|
|
parent=styles['Heading2'], |
|
|
fontSize=16, |
|
|
textColor=colors.HexColor('#1B5E20'), |
|
|
spaceAfter=12, |
|
|
spaceBefore=20 |
|
|
) |
|
|
|
|
|
|
|
|
story.append(Paragraph("🌾 Farmer.Chat Report", title_style)) |
|
|
story.append(Spacer(1, 0.2*inch)) |
|
|
|
|
|
|
|
|
metadata_data = [ |
|
|
["Report Generated:", datetime.now().strftime("%B %d, %Y at %I:%M %p")], |
|
|
["Location:", f"{location['name']}"], |
|
|
["Coordinates:", f"{location['lat']}°N, {location['lon']}°E"], |
|
|
["Data Sources:", f"{len(data.get('successful_servers', []))} MCP Servers"] |
|
|
] |
|
|
|
|
|
metadata_table = Table(metadata_data, colWidths=[2*inch, 4*inch]) |
|
|
metadata_table.setStyle(TableStyle([ |
|
|
('BACKGROUND', (0, 0), (0, -1), colors.HexColor('#E8F5E9')), |
|
|
('TEXTCOLOR', (0, 0), (-1, -1), colors.black), |
|
|
('ALIGN', (0, 0), (-1, -1), 'LEFT'), |
|
|
('FONTNAME', (0, 0), (0, -1), 'Helvetica-Bold'), |
|
|
('FONTNAME', (1, 0), (1, -1), 'Helvetica'), |
|
|
('FONTSIZE', (0, 0), (-1, -1), 10), |
|
|
('BOTTOMPADDING', (0, 0), (-1, -1), 8), |
|
|
('GRID', (0, 0), (-1, -1), 1, colors.grey) |
|
|
])) |
|
|
|
|
|
story.append(metadata_table) |
|
|
story.append(Spacer(1, 0.3*inch)) |
|
|
|
|
|
|
|
|
story.append(Paragraph("Your Query", heading_style)) |
|
|
story.append(Paragraph(query, styles['Normal'])) |
|
|
story.append(Spacer(1, 0.2*inch)) |
|
|
|
|
|
|
|
|
story.append(Paragraph("Recommendations", heading_style)) |
|
|
|
|
|
|
|
|
advice_paragraphs = advice.split('\n\n') |
|
|
for para in advice_paragraphs: |
|
|
if para.strip(): |
|
|
story.append(Paragraph(para.strip(), styles['Normal'])) |
|
|
story.append(Spacer(1, 0.1*inch)) |
|
|
|
|
|
story.append(Spacer(1, 0.2*inch)) |
|
|
|
|
|
|
|
|
story.append(Paragraph("Data Sources", heading_style)) |
|
|
|
|
|
compiled_data = data.get('data', {}) |
|
|
|
|
|
for server_name, server_data in compiled_data.items(): |
|
|
|
|
|
server_title = server_name.replace('_', ' ').title() |
|
|
story.append(Paragraph(f"<b>{server_title}</b>", styles['Normal'])) |
|
|
story.append(Spacer(1, 0.05*inch)) |
|
|
|
|
|
|
|
|
server_items = [] |
|
|
if isinstance(server_data, dict): |
|
|
for key, value in server_data.items(): |
|
|
if isinstance(value, (str, int, float)): |
|
|
display_key = key.replace('_', ' ').title() |
|
|
server_items.append([display_key, str(value)]) |
|
|
|
|
|
if server_items: |
|
|
data_table = Table(server_items, colWidths=[2.5*inch, 3.5*inch]) |
|
|
data_table.setStyle(TableStyle([ |
|
|
('BACKGROUND', (0, 0), (0, -1), colors.HexColor('#F1F8E9')), |
|
|
('TEXTCOLOR', (0, 0), (-1, -1), colors.black), |
|
|
('ALIGN', (0, 0), (-1, -1), 'LEFT'), |
|
|
('FONTNAME', (0, 0), (0, -1), 'Helvetica'), |
|
|
('FONTNAME', (1, 0), (1, -1), 'Helvetica'), |
|
|
('FONTSIZE', (0, 0), (-1, -1), 9), |
|
|
('BOTTOMPADDING', (0, 0), (-1, -1), 6), |
|
|
('GRID', (0, 0), (-1, -1), 0.5, colors.grey) |
|
|
])) |
|
|
story.append(data_table) |
|
|
story.append(Spacer(1, 0.15*inch)) |
|
|
|
|
|
|
|
|
story.append(Spacer(1, 0.3*inch)) |
|
|
footer_style = ParagraphStyle( |
|
|
'Footer', |
|
|
parent=styles['Normal'], |
|
|
fontSize=9, |
|
|
textColor=colors.grey, |
|
|
alignment=TA_CENTER |
|
|
) |
|
|
story.append(Paragraph("Generated by Farmer.Chat - Agricultural Intelligence System", footer_style)) |
|
|
story.append(Paragraph("Powered by Multi-stage MCP Pipeline", footer_style)) |
|
|
|
|
|
|
|
|
doc.build(story) |
|
|
|
|
|
return filepath |