File size: 7,633 Bytes
f3997d4
 
 
6621cba
 
f3997d4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6621cba
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f3997d4
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
"""
Service for AI-powered report content generation.
"""
from typing import Dict, Optional
import uuid
from app.llm.client import llm_client


class ReportGenerationService:
    """Service for generating report content using AI."""
    
    @staticmethod
    def generate_section_content(
        section_name: str,
        context: Dict[str, str]
    ) -> str:
        """
        Generate content for a specific report section using AI.
        
        Args:
            section_name: Name/type of the section (e.g., 'summary', 'recommendations')
            context: Dictionary with project/property details for context
            
        Returns:
            Generated content for the section
        """
        # Build context string
        context_str = "\n".join([f"- {k}: {v}" for k, v in context.items() if v])
        
        # Create section-specific prompts
        prompts = {
            "summary": f"""Generate a professional executive summary for a construction/property report based on this information:

{context_str}

Write a comprehensive 2-3 paragraph summary that:
- Highlights key project details
- Emphasizes unique selling points
- Uses professional, formal language
- Is suitable for stakeholders and investors

Return ONLY the summary text, no titles or extra formatting:""",

            "recommendations": f"""Generate professional recommendations for a construction/property report based on this information:

{context_str}

Provide 3-5 specific, actionable recommendations that:
- Address investment potential
- Cover risk mitigation
- Suggest improvements or considerations
- Use bullet points (•) format
- Are data-driven and practical

Return ONLY the recommendations:""",

            "legal_notes": f"""Generate legal compliance notes for a construction/property report based on this information:

{context_str}

Write a professional legal analysis covering:
- Regulatory compliance status
- Required permits and approvals
- Legal clearances
- Compliance recommendations
- 2-3 paragraphs, formal tone

Return ONLY the legal notes:""",

            "risk_assessment": f"""Generate a risk assessment section for a construction/property report based on this information:

{context_str}

Provide a comprehensive risk analysis covering:
- Market risks
- Regulatory/legal risks
- Construction/execution risks
- Financial risks
- Risk mitigation strategies
- Use professional language
- 2-3 paragraphs

Return ONLY the risk assessment:""",

            "financial_summary": f"""Generate a financial summary for a construction/property report based on this information:

{context_str}

Create a professional financial overview covering:
- Investment requirements
- Revenue projections
- Cost breakdowns
- ROI expectations
- Financial highlights
- 2-3 paragraphs, data-focused

Return ONLY the financial summary:""",

            "market_opportunity": f"""Generate a market opportunity analysis for a construction/property report based on this information:

{context_str}

Write a compelling market analysis that:
- Describes market demand
- Highlights growth potential
- Identifies target segments
- Discusses competitive advantages
- 2-3 paragraphs, persuasive yet professional

Return ONLY the market opportunity analysis:""",

            "default": f"""Generate professional content for the "{section_name}" section of a construction/property report based on this information:

{context_str}

Write 2-3 professional paragraphs that:
- Are relevant to the section title
- Use formal, business-appropriate language
- Include specific details from the context
- Are suitable for professional reports

Return ONLY the content:"""
        }
        
        # Get appropriate prompt
        prompt = prompts.get(section_name.lower().replace(' ', '_'), prompts['default'])
        
        try:
            # Generate content
            content = llm_client.get_completion(
                messages=[{"role": "user", "content": prompt}],
                temperature=0.7,
                max_tokens=500
            )
            
            return content.strip()
            
        except Exception as e:
            print(f"[Report Generation] Error: {e}")
            return f"Error generating content for {section_name}. Please try again or edit manually."


    @staticmethod
    def generate_full_pdf(
        template_id: str,
        data: Dict[str, str],
        user_id: Optional[str] = None
    ) -> str:
        """
        Generate a full PDF report from an HTML template.
        
        Args:
            template_id: ID of the template to use
            data: Data to populate the template with
            user_id: Optional user ID
            
        Returns:
            ID of the generated report record
        """
        import os
        from xhtml2pdf import pisa
        from app.database.models import Report
        from app.database.connection import SessionLocal
        from datetime import datetime
        
        template_map = {
            'property_evaluation': 'property-evaluation.html',
            'investor_pitch_deck': 'investor-pitch-deck.html',
            'legal_compliance': 'legal-compliance.html'
        }
        
        template_file = template_map.get(template_id)
        if not template_file:
            raise ValueError(f"Template {template_id} not found")
            
        # Get absolute path to template
        base_dir = os.path.dirname(os.path.dirname(__file__))
        template_path = os.path.join(base_dir, "templates", template_file)
        
        if not os.path.exists(template_path):
            raise FileNotFoundError(f"Template file not found at {template_path}")
            
        # Load template
        with open(template_path, "r", encoding="utf-8") as f:
            template_html = f.read()
            
        # Populate template (simple replacement)
        populated_html = template_html
        
        # Add date
        today = datetime.now().strftime("%d %b %Y")
        populated_html = populated_html.replace("{{DATE}}", today)
        
        # Add data placeholders
        for key, value in data.items():
            placeholder = f"{{{{{key.upper()}}}}}"
            populated_html = populated_html.replace(placeholder, str(value or ""))
            
        # Remove AI buttons and other non-print elements
        populated_html = populated_html.replace('<button class="ai-button"', '<div style="display:none"')
        populated_html = populated_html.replace('</button>', '</div>')
        
        # Define output path
        reports_dir = os.path.join(os.getcwd(), "data", "generated_reports")
        os.makedirs(reports_dir, exist_ok=True)
        
        report_id = str(uuid.uuid4())
        filename = f"{template_id}_{report_id}.pdf"
        file_path = os.path.join(reports_dir, filename)
        
        # Generate PDF
        with open(file_path, "wb") as pdf_file:
            pisa_status = pisa.CreatePDF(populated_html, dest=pdf_file)
            
        if pisa_status.err:
            raise RuntimeError(f"PDF generation failed: {pisa_status.err}")
            
        # Save to database
        db = SessionLocal()
        try:
            report_record = Report(
                id=report_id,
                user_id=user_id,
                template_id=template_id,
                filename=filename,
                file_path=file_path
            )
            db.add(report_record)
            db.commit()
            return report_id
        finally:
            db.close()


# Global service instance
report_generation_service = ReportGenerationService()