File size: 7,465 Bytes
7394f7b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""
sample_docs.py — Generates realistic synthetic document images for instant 1-click testing in DocIQ.
"""

from PIL import Image, ImageDraw, ImageFont
import io


def _get_fonts():
    """Try to obtain clean TrueType fonts, fall back to default."""
    try:
        title_font = ImageFont.truetype("arial.ttf", 24)
        heading_font = ImageFont.truetype("arial.ttf", 18)
        body_font = ImageFont.truetype("arial.ttf", 15)
        mono_font = ImageFont.truetype("cour.ttf", 14)
        small_font = ImageFont.truetype("arial.ttf", 12)
    except Exception:
        title_font = ImageFont.load_default()
        heading_font = title_font
        body_font = title_font
        mono_font = title_font
        small_font = title_font
    return title_font, heading_font, body_font, mono_font, small_font


def generate_invoice_sample() -> Image.Image:
    """Generate a clean business invoice document."""
    width, height = 800, 1000
    img = Image.new("RGB", (width, height), (255, 255, 255))
    draw = ImageDraw.Draw(img)
    title_font, heading_font, body_font, mono_font, small_font = _get_fonts()

    # Header Banner
    draw.rectangle([0, 0, width, 90], fill=(30, 41, 59))
    draw.text((40, 28), "ACME CLOUD SOLUTIONS INC.", fill=(255, 255, 255), font=title_font)
    draw.text((580, 32), "INVOICE", fill=(129, 140, 248), font=title_font)

    # Invoice Meta
    y = 120
    draw.text((40, y), "Billed To:", fill=(100, 116, 139), font=small_font)
    draw.text((40, y + 20), "TechCorp International Ltd.", fill=(15, 23, 42), font=heading_font)
    draw.text((40, y + 46), "100 Innovation Way, Suite 400", fill=(71, 85, 105), font=body_font)
    draw.text((40, y + 70), "Email: billing@techcorp.com", fill=(71, 85, 105), font=body_font)
    draw.text((40, y + 94), "Phone: +1 (555) 234-5678", fill=(71, 85, 105), font=body_font)

    draw.text((540, y), "Invoice Details:", fill=(100, 116, 139), font=small_font)
    draw.text((540, y + 20), "Invoice #: INV-2026-8842", fill=(15, 23, 42), font=mono_font)
    draw.text((540, y + 46), "Date: 15/09/2026", fill=(71, 85, 105), font=body_font)
    draw.text((540, y + 70), "Due Date: 30/09/2026", fill=(71, 85, 105), font=body_font)
    draw.text((540, y + 94), "Status: PENDING", fill=(217, 119, 6), font=mono_font)

    # Table Header
    y = 280
    draw.rectangle([40, y, width - 40, y + 40], fill=(241, 245, 249))
    draw.text((55, y + 10), "Description", fill=(30, 41, 59), font=heading_font)
    draw.text((420, y + 10), "Qty", fill=(30, 41, 59), font=heading_font)
    draw.text((520, y + 10), "Unit Price", fill=(30, 41, 59), font=heading_font)
    draw.text((660, y + 10), "Amount", fill=(30, 41, 59), font=heading_font)

    # Table Rows
    items = [
        ("Cloud Server Hosting - Cluster A", "2", "$450.00", "$900.00"),
        ("Database Backup & Storage (10TB)", "1", "$250.00", "$250.00"),
        ("API Gateway Bandwidth Overages", "1", "$150.00", "$150.00"),
        ("Security SSL & Compliance Pack", "1", "$199.00", "$199.00"),
    ]

    row_y = y + 55
    for desc, qty, price, total in items:
        draw.text((55, row_y), desc, fill=(51, 65, 85), font=body_font)
        draw.text((430, row_y), qty, fill=(51, 65, 85), font=body_font)
        draw.text((520, row_y), price, fill=(51, 65, 85), font=body_font)
        draw.text((660, row_y), total, fill=(15, 23, 42), font=body_font)
        draw.line([(40, row_y + 35), (width - 40, row_y + 35)], fill=(226, 232, 240), width=1)
        row_y += 48

    # Summary
    sum_y = row_y + 20
    draw.text((520, sum_y), "Subtotal:", fill=(71, 85, 105), font=body_font)
    draw.text((660, sum_y), "$1,499.00", fill=(15, 23, 42), font=body_font)

    draw.text((520, sum_y + 30), "Tax (10%):", fill=(71, 85, 105), font=body_font)
    draw.text((660, sum_y + 30), "$149.90", fill=(15, 23, 42), font=body_font)

    draw.rectangle([500, sum_y + 65, width - 40, sum_y + 115], fill=(238, 242, 255))
    draw.text((520, sum_y + 78), "Total Due:", fill=(67, 56, 202), font=heading_font)
    draw.text((650, sum_y + 78), "$1,648.90", fill=(67, 56, 202), font=heading_font)

    # Footer note
    draw.text((40, 850), "Payment Terms: Wire transfer payable to ACME Cloud Solutions within 15 days.", fill=(100, 116, 139), font=small_font)
    draw.text((40, 875), "Support inquiries: support@acmecloud.io | Website: https://acmecloud.io", fill=(100, 116, 139), font=small_font)
    draw.text((40, 920), "CONFIDENTIAL DOCUMENT - FOR RECIPIENT USE ONLY", fill=(148, 163, 184), font=small_font)

    return img


def generate_receipt_sample() -> Image.Image:
    """Generate a clean retail store receipt with PII and pricing."""
    width, height = 500, 750
    img = Image.new("RGB", (width, height), (252, 252, 252))
    draw = ImageDraw.Draw(img)
    title_font, heading_font, body_font, mono_font, small_font = _get_fonts()

    y = 30
    draw.text((160, y), "METRO MART", fill=(20, 20, 20), font=title_font)
    draw.text((140, y + 35), "Store #402 - 5th Avenue", fill=(80, 80, 80), font=body_font)
    draw.text((170, y + 60), "Tel: 555-019-2834", fill=(80, 80, 80), font=small_font)
    draw.line([(30, y + 85), (width - 30, y + 85)], fill=(180, 180, 180), width=1)

    y = 130
    draw.text((30, y), "Date: 22/09/2026", fill=(60, 60, 60), font=small_font)
    draw.text((300, y), "Time: 14:32:05", fill=(60, 60, 60), font=small_font)
    draw.text((30, y + 22), "Cashier: David M.", fill=(60, 60, 60), font=small_font)
    draw.text((300, y + 22), "Receipt: #89211", fill=(60, 60, 60), font=small_font)

    y = 180
    draw.line([(30, y), (width - 30, y)], fill=(180, 180, 180), width=1)
    y += 10
    draw.text((30, y), "ITEM", fill=(40, 40, 40), font=heading_font)
    draw.text((380, y), "PRICE", fill=(40, 40, 40), font=heading_font)
    y += 30

    items = [
        ("Organic Whole Milk 1L", "$3.49"),
        ("Artisan Sourdough Loaf", "$4.99"),
        ("Dark Roast Ground Coffee 250g", "$8.99"),
        ("Greek Yogurt Honey 500g", "$4.29"),
        ("Fresh Valencia Oranges 1kg", "$5.50"),
        ("Avocados Hass (Pack of 3)", "$3.99"),
    ]

    for item, price in items:
        draw.text((30, y), item, fill=(50, 50, 50), font=body_font)
        draw.text((390, y), price, fill=(20, 20, 20), font=mono_font)
        y += 28

    y += 15
    draw.line([(30, y), (width - 30, y)], fill=(180, 180, 180), width=1)
    y += 15
    draw.text((250, y), "SUBTOTAL:", fill=(80, 80, 80), font=body_font)
    draw.text((380, y), "$31.25", fill=(20, 20, 20), font=mono_font)
    y += 26
    draw.text((250, y), "TAX (8%):", fill=(80, 80, 80), font=body_font)
    draw.text((380, y), "$2.50", fill=(20, 20, 20), font=mono_font)
    y += 30
    draw.text((220, y), "TOTAL AMOUNT:", fill=(15, 23, 42), font=heading_font)
    draw.text((370, y), "$33.75", fill=(15, 23, 42), font=heading_font)

    y += 50
    draw.line([(30, y), (width - 30, y)], fill=(200, 200, 200), width=1)
    y += 15
    draw.text((30, y), "Card: Visa Ending in 4521", fill=(80, 80, 80), font=small_font)
    draw.text((30, y + 20), "Auth Code: 092813 - Approved", fill=(80, 80, 80), font=small_font)
    y += 50
    draw.text((150, y), "*** THANK YOU FOR SHOPPING ***", fill=(100, 100, 100), font=small_font)
    draw.text((175, y + 20), "Visit us at metromart.com", fill=(120, 120, 120), font=small_font)

    return img


SAMPLE_DOCUMENTS = {
    "Commercial Invoice": generate_invoice_sample,
    "Retail Store Receipt": generate_receipt_sample,
}