statementproof 0.1.0__tar.gz → 0.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- statementproof-0.1.1/PKG-INFO +167 -0
- {statementproof-0.1.0 → statementproof-0.1.1}/pyproject.toml +7 -1
- statementproof-0.1.1/statementproof/README.md +142 -0
- statementproof-0.1.1/statementproof.egg-info/PKG-INFO +167 -0
- statementproof-0.1.0/PKG-INFO +0 -117
- statementproof-0.1.0/statementproof/README.md +0 -96
- statementproof-0.1.0/statementproof.egg-info/PKG-INFO +0 -117
- {statementproof-0.1.0 → statementproof-0.1.1}/LICENSE +0 -0
- {statementproof-0.1.0 → statementproof-0.1.1}/README.md +0 -0
- {statementproof-0.1.0 → statementproof-0.1.1}/setup.cfg +0 -0
- {statementproof-0.1.0 → statementproof-0.1.1}/statementproof/__init__.py +0 -0
- {statementproof-0.1.0 → statementproof-0.1.1}/statementproof/__main__.py +0 -0
- {statementproof-0.1.0 → statementproof-0.1.1}/statementproof/cli.py +0 -0
- {statementproof-0.1.0 → statementproof-0.1.1}/statementproof/extract.py +0 -0
- {statementproof-0.1.0 → statementproof-0.1.1}/statementproof/validate.py +0 -0
- {statementproof-0.1.0 → statementproof-0.1.1}/statementproof.egg-info/SOURCES.txt +0 -0
- {statementproof-0.1.0 → statementproof-0.1.1}/statementproof.egg-info/dependency_links.txt +0 -0
- {statementproof-0.1.0 → statementproof-0.1.1}/statementproof.egg-info/entry_points.txt +0 -0
- {statementproof-0.1.0 → statementproof-0.1.1}/statementproof.egg-info/requires.txt +0 -0
- {statementproof-0.1.0 → statementproof-0.1.1}/statementproof.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: statementproof
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Extract transactions from bank statement PDFs -- and prove the extraction is right, or say it isn't.
|
|
5
|
+
License: MIT
|
|
6
|
+
Project-URL: Homepage, https://github.com/OrbitalKeyAi/statementproof
|
|
7
|
+
Project-URL: Documentation, https://orbitalkeyai.github.io/statementproof/
|
|
8
|
+
Project-URL: Source, https://github.com/OrbitalKeyAi/statementproof
|
|
9
|
+
Project-URL: Issues, https://github.com/OrbitalKeyAi/statementproof/issues
|
|
10
|
+
Keywords: bank-statement,pdf,csv,bookkeeping,accounting,reconciliation,extraction,converter,quickbooks,xero
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
13
|
+
Classifier: Topic :: Office/Business :: Financial :: Accounting
|
|
14
|
+
Classifier: Topic :: Text Processing :: Filters
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Requires-Python: >=3.9
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Requires-Dist: pdfplumber>=0.10
|
|
22
|
+
Provides-Extra: dev
|
|
23
|
+
Requires-Dist: reportlab>=4.0; extra == "dev"
|
|
24
|
+
Dynamic: license-file
|
|
25
|
+
|
|
26
|
+
# statementproof
|
|
27
|
+
|
|
28
|
+
**Convert bank statement PDFs to CSV — and find out when the conversion is wrong.**
|
|
29
|
+
|
|
30
|
+
Most PDF-to-CSV converters hand you rows with no way to check them. The best of them
|
|
31
|
+
(monopoly) does check totals — but tells you only that *something* is wrong, somewhere. The expensive failure isn't a crash you notice — it's one debit read as a credit,
|
|
32
|
+
which reconciles to nothing and turns up weeks later inside a client's books.
|
|
33
|
+
|
|
34
|
+
A bank statement is one of the few documents that carries its own checksum: the balances.
|
|
35
|
+
statementproof uses them.
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
$ statementproof october.pdf
|
|
39
|
+
|
|
40
|
+
opening balance : 69.96
|
|
41
|
+
closing balance : 586.71
|
|
42
|
+
transactions : 21 extracted, 0 skipped
|
|
43
|
+
|
|
44
|
+
VERIFIED (21 transactions, checks: chain, aggregate)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
And when a row is misread:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
FAILED (21 transactions, checks: chain, aggregate)
|
|
51
|
+
[chain_break] row 14: running balance does not follow:
|
|
52
|
+
534.66 +37.07 should give 571.73, statement shows 497.59 (off by -74.14)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Install
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
pip install statementproof
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Python 3.9+. One dependency (`pdfplumber`).
|
|
62
|
+
|
|
63
|
+
## Usage
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# check a statement and print the report
|
|
67
|
+
statementproof statement.pdf
|
|
68
|
+
|
|
69
|
+
# write the transactions to CSV
|
|
70
|
+
statementproof statement.pdf --csv transactions.csv
|
|
71
|
+
|
|
72
|
+
# layout report you can share — contains no financial data
|
|
73
|
+
statementproof statement.pdf --diagnostic
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Exit code is `0` when verified, `1` otherwise, so it drops into a script.
|
|
77
|
+
|
|
78
|
+
## Three verdicts, and it will not bluff
|
|
79
|
+
|
|
80
|
+
| verdict | meaning |
|
|
81
|
+
|---|---|
|
|
82
|
+
| `VERIFIED` | the rows reproduce the statement's opening and closing balances, and each running balance follows from the last |
|
|
83
|
+
| `FAILED` | they don't — **with the row number, expected figure, and size of the gap** |
|
|
84
|
+
| `UNVERIFIED` | the statement carries no balances to check against. Output may be perfect; nothing proves it, so nothing is claimed |
|
|
85
|
+
|
|
86
|
+
A converter that returns a clean-looking CSV it cannot vouch for is the problem this
|
|
87
|
+
exists to solve, so `UNVERIFIED` is never dressed up as success.
|
|
88
|
+
|
|
89
|
+
## Your statement never leaves your machine
|
|
90
|
+
|
|
91
|
+
This tool asks you to point it at a document carrying your name, address, account
|
|
92
|
+
number, employer, and every merchant you used last month. "Nothing uploaded" can't be a
|
|
93
|
+
policy — it has to be a property of the code.
|
|
94
|
+
|
|
95
|
+
**No networking library is imported anywhere in this package**, and
|
|
96
|
+
[`tests/test_privacy.py`](statementproof/tests/test_privacy.py) parses every module's
|
|
97
|
+
AST and **fails the build if one ever is.** No file is written unless you name it.
|
|
98
|
+
|
|
99
|
+
The `--diagnostic` flag exists because a library of real statement *layouts* is what
|
|
100
|
+
would most improve this tool — and a layout can be described without describing anyone's
|
|
101
|
+
money. It reports column positions, column density, date-token **shapes** (`DD/DD`, not
|
|
102
|
+
`10/02`), and where extraction broke. It contains no amounts, balances, descriptions,
|
|
103
|
+
dates, account numbers, names, or even the filename. It prints to your screen so you can
|
|
104
|
+
read all of it before deciding whether to share it. The tool never sends it anywhere.
|
|
105
|
+
|
|
106
|
+
Those exclusions are asserted by tests against a known statement, not merely intended.
|
|
107
|
+
|
|
108
|
+
## How it works
|
|
109
|
+
|
|
110
|
+
**Geometry, not regex.** The most-cited converter failure is *"columns shift, debit and
|
|
111
|
+
credit values land in the wrong places."* That happens because `extract_text()` flattens
|
|
112
|
+
a two-dimensional page and discards the x-position — the only signal separating a debit
|
|
113
|
+
column from a credit column. statementproof reads each number's coordinates and clusters
|
|
114
|
+
the money columns by their right edges.
|
|
115
|
+
|
|
116
|
+
**Column roles from arithmetic, not headers.** Which column holds the running balance is
|
|
117
|
+
decided by behaviour, because header wording differs by bank and often vanishes on
|
|
118
|
+
continuation pages.
|
|
119
|
+
|
|
120
|
+
**Sign from the balance chain.** If the balance went down it was a debit, whether or not
|
|
121
|
+
a minus glyph survived extraction.
|
|
122
|
+
|
|
123
|
+
## Limitations — read these first
|
|
124
|
+
|
|
125
|
+
**Text-layer PDFs only.** A statement downloaded from your bank's website normally has a
|
|
126
|
+
text layer; a scan or a phone photo does not. Given one, statementproof says so rather
|
|
127
|
+
than inventing rows. **OCR is not built yet.**
|
|
128
|
+
|
|
129
|
+
**Arithmetic consistency, not correctness.** It cannot see an error that leaves the
|
|
130
|
+
totals intact:
|
|
131
|
+
|
|
132
|
+
- a page header picked up as a row with a `0.00` amount
|
|
133
|
+
- a wrong date or a truncated description
|
|
134
|
+
- two errors that cancel out
|
|
135
|
+
|
|
136
|
+
*"Provably arithmetically consistent"* is the honest claim. *"Provably correct"* is not,
|
|
137
|
+
and is not made here.
|
|
138
|
+
|
|
139
|
+
**It has not met your bank.** Seven layouts extract exactly — six written by the author,
|
|
140
|
+
one reproduced from a real bank's published specimen. That seventh immediately found
|
|
141
|
+
three bugs the other six could not, including `MM/DD` dates with no year, which took
|
|
142
|
+
extraction from 21/21 to 0/21 while the author's own suite still reported 6/6 passing.
|
|
143
|
+
**Passing tests you wrote yourself is worth very little.**
|
|
144
|
+
|
|
145
|
+
If it fails on your statement, run `--diagnostic` and
|
|
146
|
+
[open an issue](https://github.com/OrbitalKeyAi/statementproof/issues) with that output.
|
|
147
|
+
It contains no financial data, and each new layout makes the parser better for everyone.
|
|
148
|
+
|
|
149
|
+
## Tests
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
python statementproof/tests/make_statements.py # build synthetic corpus
|
|
153
|
+
python statementproof/tests/make_real_derived.py # build real-bank-derived layout
|
|
154
|
+
python statementproof/tests/score.py # score extraction vs ground truth
|
|
155
|
+
python statementproof/tests/test_failure_modes.py # validator behaviour
|
|
156
|
+
python statementproof/tests/test_privacy.py # privacy promises
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Current: **7/7 layouts extracted exactly · 9/9 failure-mode tests · 8/8 privacy checks ·
|
|
160
|
+
0 false assurances.**
|
|
161
|
+
|
|
162
|
+
"False assurance" — reporting `VERIFIED` on a bad extraction — is the number that
|
|
163
|
+
matters. A validator that green-lights an error is worse than no validator.
|
|
164
|
+
|
|
165
|
+
## License
|
|
166
|
+
|
|
167
|
+
MIT.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "statementproof"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.1"
|
|
8
8
|
description = "Extract transactions from bank statement PDFs -- and prove the extraction is right, or say it isn't."
|
|
9
9
|
readme = "statementproof/README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
@@ -26,6 +26,12 @@ dependencies = [
|
|
|
26
26
|
"pdfplumber>=0.10",
|
|
27
27
|
]
|
|
28
28
|
|
|
29
|
+
[project.urls]
|
|
30
|
+
Homepage = "https://github.com/OrbitalKeyAi/statementproof"
|
|
31
|
+
Documentation = "https://orbitalkeyai.github.io/statementproof/"
|
|
32
|
+
Source = "https://github.com/OrbitalKeyAi/statementproof"
|
|
33
|
+
Issues = "https://github.com/OrbitalKeyAi/statementproof/issues"
|
|
34
|
+
|
|
29
35
|
[project.optional-dependencies]
|
|
30
36
|
dev = ["reportlab>=4.0"]
|
|
31
37
|
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# statementproof
|
|
2
|
+
|
|
3
|
+
**Convert bank statement PDFs to CSV — and find out when the conversion is wrong.**
|
|
4
|
+
|
|
5
|
+
Most PDF-to-CSV converters hand you rows with no way to check them. The best of them
|
|
6
|
+
(monopoly) does check totals — but tells you only that *something* is wrong, somewhere. The expensive failure isn't a crash you notice — it's one debit read as a credit,
|
|
7
|
+
which reconciles to nothing and turns up weeks later inside a client's books.
|
|
8
|
+
|
|
9
|
+
A bank statement is one of the few documents that carries its own checksum: the balances.
|
|
10
|
+
statementproof uses them.
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
$ statementproof october.pdf
|
|
14
|
+
|
|
15
|
+
opening balance : 69.96
|
|
16
|
+
closing balance : 586.71
|
|
17
|
+
transactions : 21 extracted, 0 skipped
|
|
18
|
+
|
|
19
|
+
VERIFIED (21 transactions, checks: chain, aggregate)
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
And when a row is misread:
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
FAILED (21 transactions, checks: chain, aggregate)
|
|
26
|
+
[chain_break] row 14: running balance does not follow:
|
|
27
|
+
534.66 +37.07 should give 571.73, statement shows 497.59 (off by -74.14)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Install
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install statementproof
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Python 3.9+. One dependency (`pdfplumber`).
|
|
37
|
+
|
|
38
|
+
## Usage
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
# check a statement and print the report
|
|
42
|
+
statementproof statement.pdf
|
|
43
|
+
|
|
44
|
+
# write the transactions to CSV
|
|
45
|
+
statementproof statement.pdf --csv transactions.csv
|
|
46
|
+
|
|
47
|
+
# layout report you can share — contains no financial data
|
|
48
|
+
statementproof statement.pdf --diagnostic
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Exit code is `0` when verified, `1` otherwise, so it drops into a script.
|
|
52
|
+
|
|
53
|
+
## Three verdicts, and it will not bluff
|
|
54
|
+
|
|
55
|
+
| verdict | meaning |
|
|
56
|
+
|---|---|
|
|
57
|
+
| `VERIFIED` | the rows reproduce the statement's opening and closing balances, and each running balance follows from the last |
|
|
58
|
+
| `FAILED` | they don't — **with the row number, expected figure, and size of the gap** |
|
|
59
|
+
| `UNVERIFIED` | the statement carries no balances to check against. Output may be perfect; nothing proves it, so nothing is claimed |
|
|
60
|
+
|
|
61
|
+
A converter that returns a clean-looking CSV it cannot vouch for is the problem this
|
|
62
|
+
exists to solve, so `UNVERIFIED` is never dressed up as success.
|
|
63
|
+
|
|
64
|
+
## Your statement never leaves your machine
|
|
65
|
+
|
|
66
|
+
This tool asks you to point it at a document carrying your name, address, account
|
|
67
|
+
number, employer, and every merchant you used last month. "Nothing uploaded" can't be a
|
|
68
|
+
policy — it has to be a property of the code.
|
|
69
|
+
|
|
70
|
+
**No networking library is imported anywhere in this package**, and
|
|
71
|
+
[`tests/test_privacy.py`](statementproof/tests/test_privacy.py) parses every module's
|
|
72
|
+
AST and **fails the build if one ever is.** No file is written unless you name it.
|
|
73
|
+
|
|
74
|
+
The `--diagnostic` flag exists because a library of real statement *layouts* is what
|
|
75
|
+
would most improve this tool — and a layout can be described without describing anyone's
|
|
76
|
+
money. It reports column positions, column density, date-token **shapes** (`DD/DD`, not
|
|
77
|
+
`10/02`), and where extraction broke. It contains no amounts, balances, descriptions,
|
|
78
|
+
dates, account numbers, names, or even the filename. It prints to your screen so you can
|
|
79
|
+
read all of it before deciding whether to share it. The tool never sends it anywhere.
|
|
80
|
+
|
|
81
|
+
Those exclusions are asserted by tests against a known statement, not merely intended.
|
|
82
|
+
|
|
83
|
+
## How it works
|
|
84
|
+
|
|
85
|
+
**Geometry, not regex.** The most-cited converter failure is *"columns shift, debit and
|
|
86
|
+
credit values land in the wrong places."* That happens because `extract_text()` flattens
|
|
87
|
+
a two-dimensional page and discards the x-position — the only signal separating a debit
|
|
88
|
+
column from a credit column. statementproof reads each number's coordinates and clusters
|
|
89
|
+
the money columns by their right edges.
|
|
90
|
+
|
|
91
|
+
**Column roles from arithmetic, not headers.** Which column holds the running balance is
|
|
92
|
+
decided by behaviour, because header wording differs by bank and often vanishes on
|
|
93
|
+
continuation pages.
|
|
94
|
+
|
|
95
|
+
**Sign from the balance chain.** If the balance went down it was a debit, whether or not
|
|
96
|
+
a minus glyph survived extraction.
|
|
97
|
+
|
|
98
|
+
## Limitations — read these first
|
|
99
|
+
|
|
100
|
+
**Text-layer PDFs only.** A statement downloaded from your bank's website normally has a
|
|
101
|
+
text layer; a scan or a phone photo does not. Given one, statementproof says so rather
|
|
102
|
+
than inventing rows. **OCR is not built yet.**
|
|
103
|
+
|
|
104
|
+
**Arithmetic consistency, not correctness.** It cannot see an error that leaves the
|
|
105
|
+
totals intact:
|
|
106
|
+
|
|
107
|
+
- a page header picked up as a row with a `0.00` amount
|
|
108
|
+
- a wrong date or a truncated description
|
|
109
|
+
- two errors that cancel out
|
|
110
|
+
|
|
111
|
+
*"Provably arithmetically consistent"* is the honest claim. *"Provably correct"* is not,
|
|
112
|
+
and is not made here.
|
|
113
|
+
|
|
114
|
+
**It has not met your bank.** Seven layouts extract exactly — six written by the author,
|
|
115
|
+
one reproduced from a real bank's published specimen. That seventh immediately found
|
|
116
|
+
three bugs the other six could not, including `MM/DD` dates with no year, which took
|
|
117
|
+
extraction from 21/21 to 0/21 while the author's own suite still reported 6/6 passing.
|
|
118
|
+
**Passing tests you wrote yourself is worth very little.**
|
|
119
|
+
|
|
120
|
+
If it fails on your statement, run `--diagnostic` and
|
|
121
|
+
[open an issue](https://github.com/OrbitalKeyAi/statementproof/issues) with that output.
|
|
122
|
+
It contains no financial data, and each new layout makes the parser better for everyone.
|
|
123
|
+
|
|
124
|
+
## Tests
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
python statementproof/tests/make_statements.py # build synthetic corpus
|
|
128
|
+
python statementproof/tests/make_real_derived.py # build real-bank-derived layout
|
|
129
|
+
python statementproof/tests/score.py # score extraction vs ground truth
|
|
130
|
+
python statementproof/tests/test_failure_modes.py # validator behaviour
|
|
131
|
+
python statementproof/tests/test_privacy.py # privacy promises
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Current: **7/7 layouts extracted exactly · 9/9 failure-mode tests · 8/8 privacy checks ·
|
|
135
|
+
0 false assurances.**
|
|
136
|
+
|
|
137
|
+
"False assurance" — reporting `VERIFIED` on a bad extraction — is the number that
|
|
138
|
+
matters. A validator that green-lights an error is worse than no validator.
|
|
139
|
+
|
|
140
|
+
## License
|
|
141
|
+
|
|
142
|
+
MIT.
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: statementproof
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Extract transactions from bank statement PDFs -- and prove the extraction is right, or say it isn't.
|
|
5
|
+
License: MIT
|
|
6
|
+
Project-URL: Homepage, https://github.com/OrbitalKeyAi/statementproof
|
|
7
|
+
Project-URL: Documentation, https://orbitalkeyai.github.io/statementproof/
|
|
8
|
+
Project-URL: Source, https://github.com/OrbitalKeyAi/statementproof
|
|
9
|
+
Project-URL: Issues, https://github.com/OrbitalKeyAi/statementproof/issues
|
|
10
|
+
Keywords: bank-statement,pdf,csv,bookkeeping,accounting,reconciliation,extraction,converter,quickbooks,xero
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
13
|
+
Classifier: Topic :: Office/Business :: Financial :: Accounting
|
|
14
|
+
Classifier: Topic :: Text Processing :: Filters
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Requires-Python: >=3.9
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Requires-Dist: pdfplumber>=0.10
|
|
22
|
+
Provides-Extra: dev
|
|
23
|
+
Requires-Dist: reportlab>=4.0; extra == "dev"
|
|
24
|
+
Dynamic: license-file
|
|
25
|
+
|
|
26
|
+
# statementproof
|
|
27
|
+
|
|
28
|
+
**Convert bank statement PDFs to CSV — and find out when the conversion is wrong.**
|
|
29
|
+
|
|
30
|
+
Most PDF-to-CSV converters hand you rows with no way to check them. The best of them
|
|
31
|
+
(monopoly) does check totals — but tells you only that *something* is wrong, somewhere. The expensive failure isn't a crash you notice — it's one debit read as a credit,
|
|
32
|
+
which reconciles to nothing and turns up weeks later inside a client's books.
|
|
33
|
+
|
|
34
|
+
A bank statement is one of the few documents that carries its own checksum: the balances.
|
|
35
|
+
statementproof uses them.
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
$ statementproof october.pdf
|
|
39
|
+
|
|
40
|
+
opening balance : 69.96
|
|
41
|
+
closing balance : 586.71
|
|
42
|
+
transactions : 21 extracted, 0 skipped
|
|
43
|
+
|
|
44
|
+
VERIFIED (21 transactions, checks: chain, aggregate)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
And when a row is misread:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
FAILED (21 transactions, checks: chain, aggregate)
|
|
51
|
+
[chain_break] row 14: running balance does not follow:
|
|
52
|
+
534.66 +37.07 should give 571.73, statement shows 497.59 (off by -74.14)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Install
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
pip install statementproof
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Python 3.9+. One dependency (`pdfplumber`).
|
|
62
|
+
|
|
63
|
+
## Usage
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# check a statement and print the report
|
|
67
|
+
statementproof statement.pdf
|
|
68
|
+
|
|
69
|
+
# write the transactions to CSV
|
|
70
|
+
statementproof statement.pdf --csv transactions.csv
|
|
71
|
+
|
|
72
|
+
# layout report you can share — contains no financial data
|
|
73
|
+
statementproof statement.pdf --diagnostic
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Exit code is `0` when verified, `1` otherwise, so it drops into a script.
|
|
77
|
+
|
|
78
|
+
## Three verdicts, and it will not bluff
|
|
79
|
+
|
|
80
|
+
| verdict | meaning |
|
|
81
|
+
|---|---|
|
|
82
|
+
| `VERIFIED` | the rows reproduce the statement's opening and closing balances, and each running balance follows from the last |
|
|
83
|
+
| `FAILED` | they don't — **with the row number, expected figure, and size of the gap** |
|
|
84
|
+
| `UNVERIFIED` | the statement carries no balances to check against. Output may be perfect; nothing proves it, so nothing is claimed |
|
|
85
|
+
|
|
86
|
+
A converter that returns a clean-looking CSV it cannot vouch for is the problem this
|
|
87
|
+
exists to solve, so `UNVERIFIED` is never dressed up as success.
|
|
88
|
+
|
|
89
|
+
## Your statement never leaves your machine
|
|
90
|
+
|
|
91
|
+
This tool asks you to point it at a document carrying your name, address, account
|
|
92
|
+
number, employer, and every merchant you used last month. "Nothing uploaded" can't be a
|
|
93
|
+
policy — it has to be a property of the code.
|
|
94
|
+
|
|
95
|
+
**No networking library is imported anywhere in this package**, and
|
|
96
|
+
[`tests/test_privacy.py`](statementproof/tests/test_privacy.py) parses every module's
|
|
97
|
+
AST and **fails the build if one ever is.** No file is written unless you name it.
|
|
98
|
+
|
|
99
|
+
The `--diagnostic` flag exists because a library of real statement *layouts* is what
|
|
100
|
+
would most improve this tool — and a layout can be described without describing anyone's
|
|
101
|
+
money. It reports column positions, column density, date-token **shapes** (`DD/DD`, not
|
|
102
|
+
`10/02`), and where extraction broke. It contains no amounts, balances, descriptions,
|
|
103
|
+
dates, account numbers, names, or even the filename. It prints to your screen so you can
|
|
104
|
+
read all of it before deciding whether to share it. The tool never sends it anywhere.
|
|
105
|
+
|
|
106
|
+
Those exclusions are asserted by tests against a known statement, not merely intended.
|
|
107
|
+
|
|
108
|
+
## How it works
|
|
109
|
+
|
|
110
|
+
**Geometry, not regex.** The most-cited converter failure is *"columns shift, debit and
|
|
111
|
+
credit values land in the wrong places."* That happens because `extract_text()` flattens
|
|
112
|
+
a two-dimensional page and discards the x-position — the only signal separating a debit
|
|
113
|
+
column from a credit column. statementproof reads each number's coordinates and clusters
|
|
114
|
+
the money columns by their right edges.
|
|
115
|
+
|
|
116
|
+
**Column roles from arithmetic, not headers.** Which column holds the running balance is
|
|
117
|
+
decided by behaviour, because header wording differs by bank and often vanishes on
|
|
118
|
+
continuation pages.
|
|
119
|
+
|
|
120
|
+
**Sign from the balance chain.** If the balance went down it was a debit, whether or not
|
|
121
|
+
a minus glyph survived extraction.
|
|
122
|
+
|
|
123
|
+
## Limitations — read these first
|
|
124
|
+
|
|
125
|
+
**Text-layer PDFs only.** A statement downloaded from your bank's website normally has a
|
|
126
|
+
text layer; a scan or a phone photo does not. Given one, statementproof says so rather
|
|
127
|
+
than inventing rows. **OCR is not built yet.**
|
|
128
|
+
|
|
129
|
+
**Arithmetic consistency, not correctness.** It cannot see an error that leaves the
|
|
130
|
+
totals intact:
|
|
131
|
+
|
|
132
|
+
- a page header picked up as a row with a `0.00` amount
|
|
133
|
+
- a wrong date or a truncated description
|
|
134
|
+
- two errors that cancel out
|
|
135
|
+
|
|
136
|
+
*"Provably arithmetically consistent"* is the honest claim. *"Provably correct"* is not,
|
|
137
|
+
and is not made here.
|
|
138
|
+
|
|
139
|
+
**It has not met your bank.** Seven layouts extract exactly — six written by the author,
|
|
140
|
+
one reproduced from a real bank's published specimen. That seventh immediately found
|
|
141
|
+
three bugs the other six could not, including `MM/DD` dates with no year, which took
|
|
142
|
+
extraction from 21/21 to 0/21 while the author's own suite still reported 6/6 passing.
|
|
143
|
+
**Passing tests you wrote yourself is worth very little.**
|
|
144
|
+
|
|
145
|
+
If it fails on your statement, run `--diagnostic` and
|
|
146
|
+
[open an issue](https://github.com/OrbitalKeyAi/statementproof/issues) with that output.
|
|
147
|
+
It contains no financial data, and each new layout makes the parser better for everyone.
|
|
148
|
+
|
|
149
|
+
## Tests
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
python statementproof/tests/make_statements.py # build synthetic corpus
|
|
153
|
+
python statementproof/tests/make_real_derived.py # build real-bank-derived layout
|
|
154
|
+
python statementproof/tests/score.py # score extraction vs ground truth
|
|
155
|
+
python statementproof/tests/test_failure_modes.py # validator behaviour
|
|
156
|
+
python statementproof/tests/test_privacy.py # privacy promises
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Current: **7/7 layouts extracted exactly · 9/9 failure-mode tests · 8/8 privacy checks ·
|
|
160
|
+
0 false assurances.**
|
|
161
|
+
|
|
162
|
+
"False assurance" — reporting `VERIFIED` on a bad extraction — is the number that
|
|
163
|
+
matters. A validator that green-lights an error is worse than no validator.
|
|
164
|
+
|
|
165
|
+
## License
|
|
166
|
+
|
|
167
|
+
MIT.
|
statementproof-0.1.0/PKG-INFO
DELETED
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: statementproof
|
|
3
|
-
Version: 0.1.0
|
|
4
|
-
Summary: Extract transactions from bank statement PDFs -- and prove the extraction is right, or say it isn't.
|
|
5
|
-
License: MIT
|
|
6
|
-
Keywords: bank-statement,pdf,csv,bookkeeping,accounting,reconciliation,extraction,converter,quickbooks,xero
|
|
7
|
-
Classifier: Development Status :: 3 - Alpha
|
|
8
|
-
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
9
|
-
Classifier: Topic :: Office/Business :: Financial :: Accounting
|
|
10
|
-
Classifier: Topic :: Text Processing :: Filters
|
|
11
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
-
Classifier: Programming Language :: Python :: 3
|
|
13
|
-
Classifier: Operating System :: OS Independent
|
|
14
|
-
Requires-Python: >=3.9
|
|
15
|
-
Description-Content-Type: text/markdown
|
|
16
|
-
License-File: LICENSE
|
|
17
|
-
Requires-Dist: pdfplumber>=0.10
|
|
18
|
-
Provides-Extra: dev
|
|
19
|
-
Requires-Dist: reportlab>=4.0; extra == "dev"
|
|
20
|
-
Dynamic: license-file
|
|
21
|
-
|
|
22
|
-
# statementproof
|
|
23
|
-
|
|
24
|
-
Bank statement PDF → CSV extraction that **tells you when it got it wrong.**
|
|
25
|
-
|
|
26
|
-
Most converters hand you output with no way to know if it is correct. A bank
|
|
27
|
-
statement is one of the few documents carrying its own checksum — the balances.
|
|
28
|
-
|
|
29
|
-
## What it does differently
|
|
30
|
-
|
|
31
|
-
**1. Geometry, not regex.** The most-cited converter failure is *"columns shift,
|
|
32
|
-
debit and credit values land in the wrong places."* That happens because
|
|
33
|
-
`extract_text()` flattens a 2-D layout and discards x-position — the only signal that
|
|
34
|
-
distinguishes a debit column from a credit column. This reads word coordinates and
|
|
35
|
-
clusters money columns by their right edges.
|
|
36
|
-
|
|
37
|
-
**2. Column roles from arithmetic, not headers.** Which column is the running balance
|
|
38
|
-
is decided by behaviour, not by header text — header text differs across banks and is
|
|
39
|
-
often missing on continuation pages.
|
|
40
|
-
|
|
41
|
-
**3. Sign from the balance chain.** If the balance went down, it was a debit,
|
|
42
|
-
regardless of whether a minus glyph survived extraction.
|
|
43
|
-
|
|
44
|
-
**4. It refuses to bluff.** With nothing to check against, output is `UNVERIFIED` —
|
|
45
|
-
never a silent pass.
|
|
46
|
-
|
|
47
|
-
## Verdicts
|
|
48
|
-
|
|
49
|
-
| verdict | meaning |
|
|
50
|
-
|---|---|
|
|
51
|
-
| `VERIFIED` | transactions reproduce the statement's own balances |
|
|
52
|
-
| `FAILED` | they do not — **with the offending row named** |
|
|
53
|
-
| `UNVERIFIED` | statement carries no balances to check against |
|
|
54
|
-
|
|
55
|
-
## What it CANNOT catch — read this
|
|
56
|
-
|
|
57
|
-
The check is **arithmetic consistency**, not correctness. It cannot see errors that do
|
|
58
|
-
not disturb the arithmetic:
|
|
59
|
-
|
|
60
|
-
- junk rows with a `0.00` amount (page headers picked up as transactions)
|
|
61
|
-
- wrong dates
|
|
62
|
-
- garbled or truncated descriptions
|
|
63
|
-
- two errors that cancel out
|
|
64
|
-
|
|
65
|
-
**"Provably arithmetically consistent" is the honest claim. "Provably correct" is not,
|
|
66
|
-
and is not made here.**
|
|
67
|
-
|
|
68
|
-
## Free test mode — try it on your own statement
|
|
69
|
-
|
|
70
|
-
```bash
|
|
71
|
-
python -m statementproof YOUR_STATEMENT.pdf # validate, print a report
|
|
72
|
-
python -m statementproof YOUR_STATEMENT.pdf --csv out.csv
|
|
73
|
-
python -m statementproof YOUR_STATEMENT.pdf --diagnostic # shareable layout report
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
**It runs entirely on your machine. Nothing is uploaded, nothing is stored, no file is
|
|
77
|
-
written unless you name one with `--csv`.**
|
|
78
|
-
|
|
79
|
-
That is not a policy, it is a property of the code, and it is tested:
|
|
80
|
-
`tests/test_privacy.py` parses every module's AST and **fails the build if any
|
|
81
|
-
networking library is imported anywhere in the package.**
|
|
82
|
-
|
|
83
|
-
### The `--diagnostic` flag, and why it exists
|
|
84
|
-
|
|
85
|
-
The single thing that would most improve this tool is a library of real statement
|
|
86
|
-
*layouts*. A layout can be described without describing anyone's money, so
|
|
87
|
-
`--diagnostic` prints exactly that: column positions, column density, date-token
|
|
88
|
-
**shapes** (`DD/DD`, not `10/02`), and where extraction broke.
|
|
89
|
-
|
|
90
|
-
It contains **no amounts, no balances, no descriptions, no dates, no account numbers,
|
|
91
|
-
no names, and not even the filename.** It prints to your screen so you can read the
|
|
92
|
-
whole thing before deciding whether to share it. The tool never sends it anywhere —
|
|
93
|
-
there is no code that could.
|
|
94
|
-
|
|
95
|
-
Those exclusions are asserted by tests against a known statement, not just intended.
|
|
96
|
-
|
|
97
|
-
## Status
|
|
98
|
-
|
|
99
|
-
Early, and scoped to **text-layer PDFs only** — statements downloaded from a bank
|
|
100
|
-
portal. Scans and photographs are not supported; the tool detects them and says so
|
|
101
|
-
rather than producing garbage.
|
|
102
|
-
|
|
103
|
-
**7/7 layouts extracted exactly, 0 false assurances.** Six are synthetic; the seventh
|
|
104
|
-
is reproduced from a real bank's published specimen and is the useful one — it found
|
|
105
|
-
three bugs the synthetic set never could, including `MM/DD` dates with no year, which
|
|
106
|
-
alone produced **0/21 extracted** while the synthetic suite still reported 6/6.
|
|
107
|
-
|
|
108
|
-
⚠️ **Passing a test suite written by the author of the code under test is worth very
|
|
109
|
-
little.** Six invented layouts passed while a real bank's date format extracted
|
|
110
|
-
nothing. **No real customer file has been processed yet** — which is what the free
|
|
111
|
-
test mode above is for.
|
|
112
|
-
|
|
113
|
-
python statementproof/tests/make_statements.py # build synthetic corpus
|
|
114
|
-
python statementproof/tests/make_real_derived.py # build real-bank-derived layout
|
|
115
|
-
python statementproof/tests/score.py # score extraction
|
|
116
|
-
python statementproof/tests/test_failure_modes.py # validator behaviour
|
|
117
|
-
python statementproof/tests/test_privacy.py # privacy promises
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
# statementproof
|
|
2
|
-
|
|
3
|
-
Bank statement PDF → CSV extraction that **tells you when it got it wrong.**
|
|
4
|
-
|
|
5
|
-
Most converters hand you output with no way to know if it is correct. A bank
|
|
6
|
-
statement is one of the few documents carrying its own checksum — the balances.
|
|
7
|
-
|
|
8
|
-
## What it does differently
|
|
9
|
-
|
|
10
|
-
**1. Geometry, not regex.** The most-cited converter failure is *"columns shift,
|
|
11
|
-
debit and credit values land in the wrong places."* That happens because
|
|
12
|
-
`extract_text()` flattens a 2-D layout and discards x-position — the only signal that
|
|
13
|
-
distinguishes a debit column from a credit column. This reads word coordinates and
|
|
14
|
-
clusters money columns by their right edges.
|
|
15
|
-
|
|
16
|
-
**2. Column roles from arithmetic, not headers.** Which column is the running balance
|
|
17
|
-
is decided by behaviour, not by header text — header text differs across banks and is
|
|
18
|
-
often missing on continuation pages.
|
|
19
|
-
|
|
20
|
-
**3. Sign from the balance chain.** If the balance went down, it was a debit,
|
|
21
|
-
regardless of whether a minus glyph survived extraction.
|
|
22
|
-
|
|
23
|
-
**4. It refuses to bluff.** With nothing to check against, output is `UNVERIFIED` —
|
|
24
|
-
never a silent pass.
|
|
25
|
-
|
|
26
|
-
## Verdicts
|
|
27
|
-
|
|
28
|
-
| verdict | meaning |
|
|
29
|
-
|---|---|
|
|
30
|
-
| `VERIFIED` | transactions reproduce the statement's own balances |
|
|
31
|
-
| `FAILED` | they do not — **with the offending row named** |
|
|
32
|
-
| `UNVERIFIED` | statement carries no balances to check against |
|
|
33
|
-
|
|
34
|
-
## What it CANNOT catch — read this
|
|
35
|
-
|
|
36
|
-
The check is **arithmetic consistency**, not correctness. It cannot see errors that do
|
|
37
|
-
not disturb the arithmetic:
|
|
38
|
-
|
|
39
|
-
- junk rows with a `0.00` amount (page headers picked up as transactions)
|
|
40
|
-
- wrong dates
|
|
41
|
-
- garbled or truncated descriptions
|
|
42
|
-
- two errors that cancel out
|
|
43
|
-
|
|
44
|
-
**"Provably arithmetically consistent" is the honest claim. "Provably correct" is not,
|
|
45
|
-
and is not made here.**
|
|
46
|
-
|
|
47
|
-
## Free test mode — try it on your own statement
|
|
48
|
-
|
|
49
|
-
```bash
|
|
50
|
-
python -m statementproof YOUR_STATEMENT.pdf # validate, print a report
|
|
51
|
-
python -m statementproof YOUR_STATEMENT.pdf --csv out.csv
|
|
52
|
-
python -m statementproof YOUR_STATEMENT.pdf --diagnostic # shareable layout report
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
**It runs entirely on your machine. Nothing is uploaded, nothing is stored, no file is
|
|
56
|
-
written unless you name one with `--csv`.**
|
|
57
|
-
|
|
58
|
-
That is not a policy, it is a property of the code, and it is tested:
|
|
59
|
-
`tests/test_privacy.py` parses every module's AST and **fails the build if any
|
|
60
|
-
networking library is imported anywhere in the package.**
|
|
61
|
-
|
|
62
|
-
### The `--diagnostic` flag, and why it exists
|
|
63
|
-
|
|
64
|
-
The single thing that would most improve this tool is a library of real statement
|
|
65
|
-
*layouts*. A layout can be described without describing anyone's money, so
|
|
66
|
-
`--diagnostic` prints exactly that: column positions, column density, date-token
|
|
67
|
-
**shapes** (`DD/DD`, not `10/02`), and where extraction broke.
|
|
68
|
-
|
|
69
|
-
It contains **no amounts, no balances, no descriptions, no dates, no account numbers,
|
|
70
|
-
no names, and not even the filename.** It prints to your screen so you can read the
|
|
71
|
-
whole thing before deciding whether to share it. The tool never sends it anywhere —
|
|
72
|
-
there is no code that could.
|
|
73
|
-
|
|
74
|
-
Those exclusions are asserted by tests against a known statement, not just intended.
|
|
75
|
-
|
|
76
|
-
## Status
|
|
77
|
-
|
|
78
|
-
Early, and scoped to **text-layer PDFs only** — statements downloaded from a bank
|
|
79
|
-
portal. Scans and photographs are not supported; the tool detects them and says so
|
|
80
|
-
rather than producing garbage.
|
|
81
|
-
|
|
82
|
-
**7/7 layouts extracted exactly, 0 false assurances.** Six are synthetic; the seventh
|
|
83
|
-
is reproduced from a real bank's published specimen and is the useful one — it found
|
|
84
|
-
three bugs the synthetic set never could, including `MM/DD` dates with no year, which
|
|
85
|
-
alone produced **0/21 extracted** while the synthetic suite still reported 6/6.
|
|
86
|
-
|
|
87
|
-
⚠️ **Passing a test suite written by the author of the code under test is worth very
|
|
88
|
-
little.** Six invented layouts passed while a real bank's date format extracted
|
|
89
|
-
nothing. **No real customer file has been processed yet** — which is what the free
|
|
90
|
-
test mode above is for.
|
|
91
|
-
|
|
92
|
-
python statementproof/tests/make_statements.py # build synthetic corpus
|
|
93
|
-
python statementproof/tests/make_real_derived.py # build real-bank-derived layout
|
|
94
|
-
python statementproof/tests/score.py # score extraction
|
|
95
|
-
python statementproof/tests/test_failure_modes.py # validator behaviour
|
|
96
|
-
python statementproof/tests/test_privacy.py # privacy promises
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: statementproof
|
|
3
|
-
Version: 0.1.0
|
|
4
|
-
Summary: Extract transactions from bank statement PDFs -- and prove the extraction is right, or say it isn't.
|
|
5
|
-
License: MIT
|
|
6
|
-
Keywords: bank-statement,pdf,csv,bookkeeping,accounting,reconciliation,extraction,converter,quickbooks,xero
|
|
7
|
-
Classifier: Development Status :: 3 - Alpha
|
|
8
|
-
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
9
|
-
Classifier: Topic :: Office/Business :: Financial :: Accounting
|
|
10
|
-
Classifier: Topic :: Text Processing :: Filters
|
|
11
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
-
Classifier: Programming Language :: Python :: 3
|
|
13
|
-
Classifier: Operating System :: OS Independent
|
|
14
|
-
Requires-Python: >=3.9
|
|
15
|
-
Description-Content-Type: text/markdown
|
|
16
|
-
License-File: LICENSE
|
|
17
|
-
Requires-Dist: pdfplumber>=0.10
|
|
18
|
-
Provides-Extra: dev
|
|
19
|
-
Requires-Dist: reportlab>=4.0; extra == "dev"
|
|
20
|
-
Dynamic: license-file
|
|
21
|
-
|
|
22
|
-
# statementproof
|
|
23
|
-
|
|
24
|
-
Bank statement PDF → CSV extraction that **tells you when it got it wrong.**
|
|
25
|
-
|
|
26
|
-
Most converters hand you output with no way to know if it is correct. A bank
|
|
27
|
-
statement is one of the few documents carrying its own checksum — the balances.
|
|
28
|
-
|
|
29
|
-
## What it does differently
|
|
30
|
-
|
|
31
|
-
**1. Geometry, not regex.** The most-cited converter failure is *"columns shift,
|
|
32
|
-
debit and credit values land in the wrong places."* That happens because
|
|
33
|
-
`extract_text()` flattens a 2-D layout and discards x-position — the only signal that
|
|
34
|
-
distinguishes a debit column from a credit column. This reads word coordinates and
|
|
35
|
-
clusters money columns by their right edges.
|
|
36
|
-
|
|
37
|
-
**2. Column roles from arithmetic, not headers.** Which column is the running balance
|
|
38
|
-
is decided by behaviour, not by header text — header text differs across banks and is
|
|
39
|
-
often missing on continuation pages.
|
|
40
|
-
|
|
41
|
-
**3. Sign from the balance chain.** If the balance went down, it was a debit,
|
|
42
|
-
regardless of whether a minus glyph survived extraction.
|
|
43
|
-
|
|
44
|
-
**4. It refuses to bluff.** With nothing to check against, output is `UNVERIFIED` —
|
|
45
|
-
never a silent pass.
|
|
46
|
-
|
|
47
|
-
## Verdicts
|
|
48
|
-
|
|
49
|
-
| verdict | meaning |
|
|
50
|
-
|---|---|
|
|
51
|
-
| `VERIFIED` | transactions reproduce the statement's own balances |
|
|
52
|
-
| `FAILED` | they do not — **with the offending row named** |
|
|
53
|
-
| `UNVERIFIED` | statement carries no balances to check against |
|
|
54
|
-
|
|
55
|
-
## What it CANNOT catch — read this
|
|
56
|
-
|
|
57
|
-
The check is **arithmetic consistency**, not correctness. It cannot see errors that do
|
|
58
|
-
not disturb the arithmetic:
|
|
59
|
-
|
|
60
|
-
- junk rows with a `0.00` amount (page headers picked up as transactions)
|
|
61
|
-
- wrong dates
|
|
62
|
-
- garbled or truncated descriptions
|
|
63
|
-
- two errors that cancel out
|
|
64
|
-
|
|
65
|
-
**"Provably arithmetically consistent" is the honest claim. "Provably correct" is not,
|
|
66
|
-
and is not made here.**
|
|
67
|
-
|
|
68
|
-
## Free test mode — try it on your own statement
|
|
69
|
-
|
|
70
|
-
```bash
|
|
71
|
-
python -m statementproof YOUR_STATEMENT.pdf # validate, print a report
|
|
72
|
-
python -m statementproof YOUR_STATEMENT.pdf --csv out.csv
|
|
73
|
-
python -m statementproof YOUR_STATEMENT.pdf --diagnostic # shareable layout report
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
**It runs entirely on your machine. Nothing is uploaded, nothing is stored, no file is
|
|
77
|
-
written unless you name one with `--csv`.**
|
|
78
|
-
|
|
79
|
-
That is not a policy, it is a property of the code, and it is tested:
|
|
80
|
-
`tests/test_privacy.py` parses every module's AST and **fails the build if any
|
|
81
|
-
networking library is imported anywhere in the package.**
|
|
82
|
-
|
|
83
|
-
### The `--diagnostic` flag, and why it exists
|
|
84
|
-
|
|
85
|
-
The single thing that would most improve this tool is a library of real statement
|
|
86
|
-
*layouts*. A layout can be described without describing anyone's money, so
|
|
87
|
-
`--diagnostic` prints exactly that: column positions, column density, date-token
|
|
88
|
-
**shapes** (`DD/DD`, not `10/02`), and where extraction broke.
|
|
89
|
-
|
|
90
|
-
It contains **no amounts, no balances, no descriptions, no dates, no account numbers,
|
|
91
|
-
no names, and not even the filename.** It prints to your screen so you can read the
|
|
92
|
-
whole thing before deciding whether to share it. The tool never sends it anywhere —
|
|
93
|
-
there is no code that could.
|
|
94
|
-
|
|
95
|
-
Those exclusions are asserted by tests against a known statement, not just intended.
|
|
96
|
-
|
|
97
|
-
## Status
|
|
98
|
-
|
|
99
|
-
Early, and scoped to **text-layer PDFs only** — statements downloaded from a bank
|
|
100
|
-
portal. Scans and photographs are not supported; the tool detects them and says so
|
|
101
|
-
rather than producing garbage.
|
|
102
|
-
|
|
103
|
-
**7/7 layouts extracted exactly, 0 false assurances.** Six are synthetic; the seventh
|
|
104
|
-
is reproduced from a real bank's published specimen and is the useful one — it found
|
|
105
|
-
three bugs the synthetic set never could, including `MM/DD` dates with no year, which
|
|
106
|
-
alone produced **0/21 extracted** while the synthetic suite still reported 6/6.
|
|
107
|
-
|
|
108
|
-
⚠️ **Passing a test suite written by the author of the code under test is worth very
|
|
109
|
-
little.** Six invented layouts passed while a real bank's date format extracted
|
|
110
|
-
nothing. **No real customer file has been processed yet** — which is what the free
|
|
111
|
-
test mode above is for.
|
|
112
|
-
|
|
113
|
-
python statementproof/tests/make_statements.py # build synthetic corpus
|
|
114
|
-
python statementproof/tests/make_real_derived.py # build real-bank-derived layout
|
|
115
|
-
python statementproof/tests/score.py # score extraction
|
|
116
|
-
python statementproof/tests/test_failure_modes.py # validator behaviour
|
|
117
|
-
python statementproof/tests/test_privacy.py # privacy promises
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|