File size: 3,441 Bytes
13b71d5
 
 
 
 
 
 
ccecc05
13b71d5
 
 
 
 
 
 
 
 
 
 
ccecc05
13b71d5
ccecc05
 
 
13b71d5
 
 
 
 
 
 
 
 
ccecc05
 
 
13b71d5
 
 
ccecc05
 
13b71d5
 
ccecc05
13b71d5
 
 
 
ccecc05
 
 
13b71d5
 
 
 
 
ccecc05
 
 
 
 
 
 
 
 
 
 
 
 
13b71d5
ccecc05
13b71d5
ccecc05
13b71d5
 
 
ccecc05
 
 
 
 
 
 
 
 
 
 
 
13b71d5
 
 
 
 
 
 
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
from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas
from reportlab.lib import colors
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph, Spacer
from reportlab.lib.styles import getSampleStyleSheet
import io


def generate_pdf_report(results):
    """

    Generates a PDF report from analysis results.

    Args:

        results: List of dictionaries containing analysis findings.

    Returns:

        bytes: PDF file content.

    """
    buffer = io.BytesIO()
    doc = SimpleDocTemplate(buffer, pagesize=letter)
    elements = []

    styles = getSampleStyleSheet()
    title_style = styles["Title"]
    heading_style = styles["Heading2"]
    normal_style = styles["Normal"]

    # Title
    elements.append(Paragraph("Semantic Integrity Analysis Report", title_style))
    elements.append(Spacer(1, 12))

    if not results:
        elements.append(Paragraph("No integrity issues detected.", normal_style))
    else:
        # Summary
        elements.append(
            Paragraph(f"Total Potential Issues Found: {len(results)}", normal_style)
        )
        elements.append(Spacer(1, 12))

        # Table Header
        data = [["S.No", "Label", "Loc", "Reason"]]

        # Table Data
        for idx, r in enumerate(results):
            # Text wrapping for table cells needs explicit Paragraph usage usually,
            # but for simplicity we truncate or just list them.
            # To make it robust, we'll list details below the table or keep table simple.
            row = [
                str(idx + 1),
                r.get("Label", "N/A"),
                r.get("Location 1", "").replace("Pg ", "P").replace("Ln ", "L"),
                r.get("Reason", "N/A"),
            ]
            data.append(row)

        # Create Table
        t = Table(data, colWidths=[30, 90, 60, 320])
        t.setStyle(
            TableStyle(
                [
                    ("BACKGROUND", (0, 0), (-1, 0), colors.grey),
                    ("TEXTCOLOR", (0, 0), (-1, 0), colors.whitesmoke),
                    ("ALIGN", (0, 0), (-1, -1), "LEFT"),
                    ("FONTNAME", (0, 0), (-1, 0), "Helvetica-Bold"),
                    ("BOTTOMPADDING", (0, 0), (-1, 0), 12),
                    ("BACKGROUND", (0, 1), (-1, -1), colors.beige),
                    ("GRID", (0, 0), (-1, -1), 1, colors.black),
                ]
            )
        )
        elements.append(t)

        elements.append(Spacer(1, 24))

        # Detailed Findings
        elements.append(Paragraph("Detailed Findings", heading_style))
        for idx, r in enumerate(results):
            elements.append(
                Paragraph(f"<b>Issue #{idx + 1}: {r.get('Label')}</b>", normal_style)
            )
            elements.append(
                Paragraph(f"<i>Reason:</i> {r.get('Reason')}", normal_style)
            )
            elements.append(
                Paragraph(f"<i>Clause 1:</i> {r.get('Clause 1')}", normal_style)
            )
            elements.append(
                Paragraph(f"<i>Clause 2:</i> {r.get('Clause 2')}", normal_style)
            )
            elements.append(Spacer(1, 12))
            elements.append(Paragraph("-" * 60, normal_style))
            elements.append(Spacer(1, 12))

    doc.build(elements)
    buffer.seek(0)
    return buffer.getvalue()