File size: 6,445 Bytes
061a93c
 
 
 
 
f547301
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
061a93c
 
 
 
 
 
 
295d256
061a93c
 
295d256
 
 
 
061a93c
295d256
f547301
295d256
 
 
 
 
 
 
f547301
295d256
 
 
 
 
 
 
 
 
f547301
 
295d256
 
 
 
 
 
 
 
f547301
 
 
 
fde5743
 
 
f547301
fde5743
f547301
fde5743
061a93c
 
 
f547301
 
 
 
 
 
 
061a93c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
295d256
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fde5743
 
 
 
 
 
295d256
 
061a93c
295d256
 
 
 
 
 
 
061a93c
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
import csv
from fpdf import FPDF
import tempfile
import os

def _safe_text_for_pdf(s: object) -> str:
    """
    Ensure text passed to FPDF only contains characters encodable in latin-1.
    FPDF (classic) writes using latin-1 encoding by default and will raise
    an error when encountering characters outside that range (e.g. •).
    This helper replaces unsupported characters with a best-effort replacement
    so PDF generation doesn't fail.
    """
    if s is None:
        return ""
    try:
        text = str(s)
    except Exception:
        text = ""
    # encode -> decode using latin-1 with replacement to avoid exceptions
    return text.encode('latin-1', 'replace').decode('latin-1')
def export_evidence_pack_pdf(data, filename=None):
    """
    Export evidence pack as PDF. Data should include clause, summary, checklist, scenario, metadata.
    Returns path to PDF file.
    """
    pdf = FPDF()
    pdf.add_page()
    pdf.set_font("Arial", "B", size=16)
    pdf.cell(200, 10, txt="Evidence Pack", ln=True, align='C')
    pdf.ln(10)
    
    # Clause section
    pdf.set_font("Arial", "B", size=12)
    pdf.cell(0, 8, txt="Clause:", ln=True)
    pdf.set_font("Arial", size=10)
    clause_text = data.get('clause_text', 'No clause information available')
    pdf.multi_cell(0, 6, _safe_text_for_pdf(clause_text))
    pdf.ln(3)
    
    # Summary section  
    pdf.set_font("Arial", "B", size=12)
    pdf.cell(0, 8, txt="Summary:", ln=True)
    pdf.set_font("Arial", size=10)
    summary_text = data.get('summary', 'No summary available')
    pdf.multi_cell(0, 6, _safe_text_for_pdf(summary_text))
    pdf.ln(3)
    
    # Checklist section
    pdf.set_font("Arial", "B", size=12) 
    pdf.cell(0, 8, txt="Checklist:", ln=True)
    pdf.set_font("Arial", size=10)
    checklist = data.get('role_checklist', [])
    if checklist:
        for item in checklist:
            # use a simple hyphen bullet and sanitize text
            pdf.multi_cell(0, 6, _safe_text_for_pdf(f"- {item}"))
    else:
        pdf.multi_cell(0, 6, "No checklist items available")
    pdf.ln(3)
    
    # Source information section
    pdf.set_font("Arial", "B", size=12)
    pdf.cell(0, 8, txt="Source Information:", ln=True) 
    pdf.set_font("Arial", size=10)
    pdf.multi_cell(0, 6, _safe_text_for_pdf(f"Source: {data.get('source_title', 'Not specified')}"))
    pdf.multi_cell(0, 6, _safe_text_for_pdf(f"Clause ID: {data.get('clause_id', 'Not assigned')}"))
    pdf.multi_cell(0, 6, _safe_text_for_pdf(f"Date: {data.get('date', 'Not specified')}"))
    pdf.multi_cell(0, 6, _safe_text_for_pdf(f"URL: {data.get('url', 'Not available')}"))
    
    # User role and context information
    if data.get('user_role'):
        pdf.multi_cell(0, 6, _safe_text_for_pdf(f"User Role: {data.get('user_role', '').title()}"))
    if data.get('language_preference'):
        pdf.multi_cell(0, 6, _safe_text_for_pdf(f"Language: {data.get('language_preference', '').title()}"))
    
    pdf.ln(5)
    scenario = data.get('scenario_analysis',{})
    if scenario:
        pdf.multi_cell(0, 8, _safe_text_for_pdf(f"Scenario Analysis:"))
        pdf.multi_cell(0, 8, _safe_text_for_pdf(f"Yearly Results: {scenario.get('yearly_results','')}"))
        pdf.multi_cell(0, 8, _safe_text_for_pdf(f"Cumulative Base: {scenario.get('cumulative_base','')}"))
        pdf.multi_cell(0, 8, _safe_text_for_pdf(f"Cumulative Scenario: {scenario.get('cumulative_scenario','')}"))
        pdf.multi_cell(0, 8, _safe_text_for_pdf(f"Optimistic: {scenario.get('optimistic','')}"))
        pdf.multi_cell(0, 8, _safe_text_for_pdf(f"Pessimistic: {scenario.get('pessimistic','')}"))
        pdf.multi_cell(0, 8, _safe_text_for_pdf(f"Driver Breakdown: {scenario.get('driver_breakdown','')}"))
    if not filename:
        filename = os.path.join(tempfile.gettempdir(), f"evidence_pack_{os.getpid()}.pdf")
    pdf.output(filename)
    return filename

def export_evidence_pack_csv(data, filename=None):
    """
    Export evidence pack as CSV. Data should include clause, summary, checklist, scenario, metadata.
    Returns path to CSV file.
    """
    if not filename:
        filename = os.path.join(tempfile.gettempdir(), f"evidence_pack_{os.getpid()}.csv")
    with open(filename, 'w', newline='', encoding='utf-8') as csvfile:
        writer = csv.writer(csvfile)
        writer.writerow(["Field", "Value"])
        writer.writerow(["Clause", data.get('clause_text', 'No clause information available')])
        writer.writerow(["Summary", data.get('summary', 'No summary available')])
        
        # Handle checklist properly
        checklist = data.get('role_checklist', [])
        if checklist:
            checklist_text = '; '.join(checklist)
        else:
            checklist_text = "No checklist items available"
        writer.writerow(["Checklist", checklist_text])
        
        writer.writerow(["Source", data.get('source_title', 'Not specified')])
        writer.writerow(["Clause ID", data.get('clause_id', 'Not assigned')])
        writer.writerow(["Date", data.get('date', 'Not specified')])
        writer.writerow(["URL", data.get('url', 'Not available')])
        
        # Add timestamp if available
        if 'timestamp' in data:
            writer.writerow(["Generated At", data.get('timestamp', '')])
            
        # Add original query if available
        if 'original_query' in data:
            writer.writerow(["Original Query", data.get('original_query', '')])
            
        # Add user context information
        if 'user_role' in data:
            writer.writerow(["User Role", data.get('user_role', '').title()])
        if 'language_preference' in data:
            writer.writerow(["Language Preference", data.get('language_preference', '').title()])
        
        scenario = data.get('scenario_analysis', {})
        if scenario:
            writer.writerow(["=== SCENARIO ANALYSIS ===", ""])
            writer.writerow(["Yearly Results", scenario.get('yearly_results', '')])
            writer.writerow(["Cumulative Base", scenario.get('cumulative_base', '')])
            writer.writerow(["Cumulative Scenario", scenario.get('cumulative_scenario', '')])
            writer.writerow(["Optimistic", scenario.get('optimistic', '')])
            writer.writerow(["Pessimistic", scenario.get('pessimistic', '')])
            writer.writerow(["Driver Breakdown", scenario.get('driver_breakdown', '')])
    return filename