File size: 5,184 Bytes
0ebef7d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""
make_real_style_pdf.py — faithful reproduction of the user's real-style US bank
statement (First National Bank mock), block 1 (30 txns, 2 pages).

Reproduces the REAL-WORLD structural features that synthetic tests lacked:
  - account info as a label/value TABLE (no "Label:" colon lines)
  - balances in a Beginning/Ending SUMMARY TABLE (not "Opening Balance: $X")
  - a "Reference" column between Description and Debit
  - gridded, multi-page transaction table with repeated header
"""
from __future__ import annotations
from pathlib import Path
from reportlab.lib import colors
from reportlab.lib.pagesizes import LETTER
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib.units import mm
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle

HERE = Path(__file__).resolve().parent
OUT = HERE / "real_style_statement.pdf"

# (date, description, reference, debit, credit, balance) — transcribed from the real PDF
TXNS = [
    ("04/01/26", "POS PURCHASE MERCHANT 1", "REF10001", "37.35", "", "25,962.65"),
    ("04/02/26", "POS PURCHASE MERCHANT 2", "REF10002", "49.70", "", "25,912.95"),
    ("04/03/26", "ACH Payroll Deposit", "REF10003", "", "1,821.00", "27,733.95"),
    ("04/04/26", "POS PURCHASE MERCHANT 4", "REF10004", "74.40", "", "27,659.55"),
    ("04/05/26", "POS PURCHASE MERCHANT 5", "REF10005", "86.75", "", "27,572.80"),
    ("04/06/26", "ACH Payroll Deposit", "REF10006", "", "1,842.00", "29,414.80"),
    ("04/07/26", "POS PURCHASE MERCHANT 7", "REF10007", "111.45", "", "29,303.35"),
    ("04/08/26", "POS PURCHASE MERCHANT 8", "REF10008", "123.80", "", "29,179.55"),
    ("04/09/26", "ACH Payroll Deposit", "REF10009", "", "1,863.00", "31,042.55"),
    ("04/10/26", "POS PURCHASE MERCHANT 10", "REF10010", "148.50", "", "30,894.05"),
    ("04/11/26", "POS PURCHASE MERCHANT 11", "REF10011", "160.85", "", "30,733.20"),
    ("04/12/26", "ACH Payroll Deposit", "REF10012", "", "1,884.00", "32,617.20"),
    ("04/13/26", "POS PURCHASE MERCHANT 13", "REF10013", "185.55", "", "32,431.65"),
    ("04/14/26", "POS PURCHASE MERCHANT 14", "REF10014", "197.90", "", "32,233.75"),
    ("04/15/26", "ACH Payroll Deposit", "REF10015", "", "1,905.00", "34,138.75"),
    ("04/16/26", "POS PURCHASE MERCHANT 16", "REF10016", "222.60", "", "33,916.15"),
    ("04/17/26", "POS PURCHASE MERCHANT 17", "REF10017", "234.95", "", "33,681.20"),
    ("04/18/26", "ACH Payroll Deposit", "REF10018", "", "1,926.00", "35,607.20"),
    ("04/19/26", "POS PURCHASE MERCHANT 19", "REF10019", "259.65", "", "35,347.55"),
    ("04/20/26", "POS PURCHASE MERCHANT 20", "REF10020", "272.00", "", "35,075.55"),
    ("04/21/26", "ACH Payroll Deposit", "REF10021", "", "1,947.00", "37,022.55"),
    ("04/22/26", "POS PURCHASE MERCHANT 22", "REF10022", "296.70", "", "36,725.85"),
    ("04/23/26", "POS PURCHASE MERCHANT 23", "REF10023", "309.05", "", "36,416.80"),
    ("04/24/26", "ACH Payroll Deposit", "REF10024", "", "1,968.00", "38,384.80"),
    ("04/25/26", "POS PURCHASE MERCHANT 25", "REF10025", "333.75", "", "38,051.05"),
    ("04/26/26", "POS PURCHASE MERCHANT 26", "REF10026", "346.10", "", "37,704.95"),
    ("04/27/26", "ACH Payroll Deposit", "REF10027", "", "1,989.00", "39,693.95"),
    ("04/28/26", "POS PURCHASE MERCHANT 28", "REF10028", "370.80", "", "39,323.15"),
    ("04/29/26", "POS PURCHASE MERCHANT 29", "REF10029", "383.15", "", "38,940.00"),
    ("04/30/26", "ACH Payroll Deposit", "REF10030", "", "2,010.00", "40,950.00"),
]

styles = getSampleStyleSheet()
doc = SimpleDocTemplate(str(OUT), pagesize=LETTER, topMargin=14 * mm, bottomMargin=14 * mm,
                        leftMargin=14 * mm, rightMargin=14 * mm)
story = [
    Paragraph("<b>FIRST NATIONAL BANK</b>", styles["Title"]),
    Paragraph("123 Market Street, New York, NY 10001", styles["Normal"]),
    Paragraph("MOCK STATEMENT – FICTIONAL DATA FOR SOFTWARE TESTING ONLY", styles["Normal"]),
    Spacer(1, 8),
]

acct = Table([["Account Holder", "JOHN SAMPLE"],
              ["Account Type", "Checking Account"],
              ["Account Number", "XXXXXX4321"],
              ["Statement Period", "04/01/2026 - 04/30/2026"]], colWidths=[45 * mm, 90 * mm])
acct.setStyle(TableStyle([("GRID", (0, 0), (-1, -1), 0.5, colors.grey), ("FONTSIZE", (0, 0), (-1, -1), 9)]))
story += [acct, Spacer(1, 8)]

summary = Table([["Beginning Balance", "Deposits", "Withdrawals", "Ending Balance"],
                 ["$24,580.12", "$12,440.00", "$8,915.45", "$28,104.67"]],
                colWidths=[40 * mm, 35 * mm, 35 * mm, 40 * mm])
summary.setStyle(TableStyle([("GRID", (0, 0), (-1, -1), 0.5, colors.grey), ("FONTSIZE", (0, 0), (-1, -1), 9)]))
story += [summary, Spacer(1, 10)]

rows = [["Date", "Description", "Reference", "Debit", "Credit", "Balance"]] + [list(t) for t in TXNS]
tbl = Table(rows, colWidths=[20 * mm, 62 * mm, 26 * mm, 22 * mm, 22 * mm, 26 * mm], repeatRows=1)
tbl.setStyle(TableStyle([
    ("GRID", (0, 0), (-1, -1), 0.4, colors.grey),
    ("BACKGROUND", (0, 0), (-1, 0), colors.HexColor("#e6e6e6")),
    ("FONTSIZE", (0, 0), (-1, -1), 8),
    ("ALIGN", (3, 0), (-1, -1), "RIGHT"),
]))
story.append(tbl)
doc.build(story)
print("Wrote", OUT)