statementproof 0.2.0__tar.gz → 0.2.2__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.
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: statementproof
3
- Version: 0.2.0
4
- Summary: Extract transactions from bank statement PDFs -- and prove the extraction is right, or say it isn't.
3
+ Version: 0.2.2
4
+ Summary: Convert bank statement PDFs to CSV for QuickBooks or Xero, then prove the conversion is right against the statement's own balances -- or say it isn't.
5
5
  License: MIT
6
6
  Project-URL: Homepage, https://github.com/OrbitalKeyAi/statementproof
7
7
  Project-URL: Documentation, https://orbitalkeyai.github.io/statementproof/
8
8
  Project-URL: Source, https://github.com/OrbitalKeyAi/statementproof
9
9
  Project-URL: Issues, https://github.com/OrbitalKeyAi/statementproof/issues
10
- Keywords: bank-statement,pdf,csv,bookkeeping,accounting,reconciliation,extraction,converter,quickbooks,xero
10
+ Keywords: bank-statement,bank-statement-converter,pdf-to-csv,pdf-to-excel,statement-to-csv,quickbooks,xero,qbo,ofx,bookkeeping,accounting,reconciliation,audit-trail,extraction,converter,pdf,csv,finance,cli
11
11
  Classifier: Development Status :: 3 - Alpha
12
12
  Classifier: Intended Audience :: Financial and Insurance Industry
13
13
  Classifier: Topic :: Office/Business :: Financial :: Accounting
@@ -52,6 +52,9 @@ And when a row is misread:
52
52
  534.66 +37.07 should give 571.73, statement shows 497.59 (off by -74.14)
53
53
  ```
54
54
 
55
+ **[See the actual output before installing →](https://orbitalkeyai.github.io/statementproof/demo.html)**
56
+ Verified, silently-failing and batch runs, copied verbatim from real runs.
57
+
55
58
  ## Install
56
59
 
57
60
  ```bash
@@ -4,14 +4,17 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "statementproof"
7
- version = "0.2.0"
8
- description = "Extract transactions from bank statement PDFs -- and prove the extraction is right, or say it isn't."
7
+ version = "0.2.2"
8
+ description = "Convert bank statement PDFs to CSV for QuickBooks or Xero, then prove the conversion is right against the statement's own balances -- or say it isn't."
9
9
  readme = "statementproof/README.md"
10
10
  requires-python = ">=3.9"
11
11
  license = { text = "MIT" }
12
12
  keywords = [
13
- "bank-statement", "pdf", "csv", "bookkeeping", "accounting",
14
- "reconciliation", "extraction", "converter", "quickbooks", "xero",
13
+ # The words a bookkeeper types, not the words we would use to describe the design.
14
+ "bank-statement", "bank-statement-converter", "pdf-to-csv", "pdf-to-excel",
15
+ "statement-to-csv", "quickbooks", "xero", "qbo", "ofx", "bookkeeping",
16
+ "accounting", "reconciliation", "audit-trail", "extraction", "converter",
17
+ "pdf", "csv", "finance", "cli",
15
18
  ]
16
19
  classifiers = [
17
20
  "Development Status :: 3 - Alpha",
@@ -27,6 +27,9 @@ And when a row is misread:
27
27
  534.66 +37.07 should give 571.73, statement shows 497.59 (off by -74.14)
28
28
  ```
29
29
 
30
+ **[See the actual output before installing →](https://orbitalkeyai.github.io/statementproof/demo.html)**
31
+ Verified, silently-failing and batch runs, copied verbatim from real runs.
32
+
30
33
  ## Install
31
34
 
32
35
  ```bash
@@ -1,2 +1,2 @@
1
1
  """statementproof - verifiable bank statement extraction."""
2
- __version__ = "0.2.0"
2
+ __version__ = "0.2.2"
@@ -70,6 +70,27 @@ def licence_holder() -> str | None:
70
70
  return v or None
71
71
 
72
72
 
73
+ _SCOPE = {
74
+ "VERIFIED":
75
+ "A VERIFIED verdict means the extracted transactions reproduce this statement's "
76
+ "own opening and closing balances. It does not certify that descriptions or dates "
77
+ "are correct, and it does not detect errors that leave the totals unchanged.",
78
+ "FAILED":
79
+ "A FAILED verdict means the extracted transactions do NOT reproduce this "
80
+ "statement's own balances. The findings above name where the running total stops "
81
+ "following. This record is evidence that the extraction was checked and did not "
82
+ "reconcile -- it is not evidence of an error in the statement itself.",
83
+ "UNVERIFIED":
84
+ "An UNVERIFIED verdict means this statement does not carry enough balance "
85
+ "information to check the extraction against. The extracted figures may be "
86
+ "correct; nothing here demonstrates that they are, so nothing is claimed.",
87
+ }
88
+
89
+
90
+ def _scope(verdict: str) -> str:
91
+ return _SCOPE.get(verdict, _SCOPE["UNVERIFIED"])
92
+
93
+
73
94
  def build(pdf_path: str, txns, res, opening, closing, diag=None, holder=None) -> dict:
74
95
  """One record for one statement. Pure data; rendering is separate."""
75
96
  now = dt.datetime.now(dt.timezone.utc)
@@ -103,18 +124,27 @@ def build(pdf_path: str, txns, res, opening, closing, diag=None, holder=None) ->
103
124
  "verification": {
104
125
  "verdict": res.verdict,
105
126
  "checks_run": list(res.checks_run),
127
+ # p.message, not str(p): Problem is a plain dataclass with no __str__, so
128
+ # str() yields its repr -- and the one document a firm files as evidence of
129
+ # review would have read `Problem(kind='chain_break', row=7, message=...)`.
130
+ # `where` mirrors validate.Result.report() so the record and the terminal
131
+ # describe the same finding the same way; an aggregate problem has no row
132
+ # and belongs to the statement as a whole.
106
133
  "problems": [
107
- {"kind": p.kind, "row": getattr(p, "row", None), "detail": str(p)[:200]}
134
+ {"kind": p.kind,
135
+ "row": p.row,
136
+ "where": ("row %d" % p.row) if p.row is not None else "statement",
137
+ "detail": p.message,
138
+ "expected": fmt(p.expected_cents) if p.expected_cents is not None else None,
139
+ "found": fmt(p.found_cents) if p.found_cents is not None else None}
108
140
  for p in res.problems
109
141
  ],
110
142
  },
111
143
  # Said in the record itself, not only in the docs, because a record that
112
- # overstates what it proves is worse than no record.
113
- "scope_of_assurance":
114
- "A VERIFIED verdict means the extracted transactions reproduce this "
115
- "statement's own opening and closing balances. It does not certify that "
116
- "descriptions or dates are correct, and it does not detect errors that "
117
- "leave the totals unchanged.",
144
+ # overstates what it proves is worse than no record. The wording follows the
145
+ # verdict -- a FAILED record explaining what VERIFIED would have meant is
146
+ # answering a question nobody asked while leaving the real one unanswered.
147
+ "scope_of_assurance": _scope(res.verdict),
118
148
  }
119
149
 
120
150
 
@@ -198,10 +228,10 @@ def _one(rec: dict, heading: bool = True) -> str:
198
228
 
199
229
  probs = rec["verification"]["problems"]
200
230
  if probs:
201
- L.append("<table><tr><th>Row</th><th>Finding</th></tr>")
231
+ L.append("<table><tr><th>Where</th><th>Finding</th></tr>")
202
232
  for p in probs[:40]:
203
233
  L.append("<tr><td>%s</td><td>%s</td></tr>"
204
- % (_e(p["row"] if p["row"] is not None else "-"), _e(p["detail"])))
234
+ % (_e(p.get("where") or "statement"), _e(p["detail"])))
205
235
  L.append("</table>")
206
236
  if len(probs) > 40:
207
237
  L.append("<p class='sub'>… and %d more.</p>" % (len(probs) - 40))
@@ -255,7 +285,10 @@ def to_html(rec: dict) -> str:
255
285
 
256
286
  for r in rec["statements"]:
257
287
  L.append(_one(r))
258
- scope = rec["statements"][0]["scope_of_assurance"] if rec["statements"] else ""
288
+ # Every verdict present in the batch, not just the first statement's -- a mixed
289
+ # batch whose first file happened to verify would otherwise print only the
290
+ # VERIFIED wording over a page that also contains failures.
291
+ scope = " ".join(_SCOPE[v] for v in sorted(s["by_verdict"]) if v in _SCOPE)
259
292
  else:
260
293
  L.append(_one(rec, heading=False))
261
294
  scope = rec["scope_of_assurance"]
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: statementproof
3
- Version: 0.2.0
4
- Summary: Extract transactions from bank statement PDFs -- and prove the extraction is right, or say it isn't.
3
+ Version: 0.2.2
4
+ Summary: Convert bank statement PDFs to CSV for QuickBooks or Xero, then prove the conversion is right against the statement's own balances -- or say it isn't.
5
5
  License: MIT
6
6
  Project-URL: Homepage, https://github.com/OrbitalKeyAi/statementproof
7
7
  Project-URL: Documentation, https://orbitalkeyai.github.io/statementproof/
8
8
  Project-URL: Source, https://github.com/OrbitalKeyAi/statementproof
9
9
  Project-URL: Issues, https://github.com/OrbitalKeyAi/statementproof/issues
10
- Keywords: bank-statement,pdf,csv,bookkeeping,accounting,reconciliation,extraction,converter,quickbooks,xero
10
+ Keywords: bank-statement,bank-statement-converter,pdf-to-csv,pdf-to-excel,statement-to-csv,quickbooks,xero,qbo,ofx,bookkeeping,accounting,reconciliation,audit-trail,extraction,converter,pdf,csv,finance,cli
11
11
  Classifier: Development Status :: 3 - Alpha
12
12
  Classifier: Intended Audience :: Financial and Insurance Industry
13
13
  Classifier: Topic :: Office/Business :: Financial :: Accounting
@@ -52,6 +52,9 @@ And when a row is misread:
52
52
  534.66 +37.07 should give 571.73, statement shows 497.59 (off by -74.14)
53
53
  ```
54
54
 
55
+ **[See the actual output before installing →](https://orbitalkeyai.github.io/statementproof/demo.html)**
56
+ Verified, silently-failing and batch runs, copied verbatim from real runs.
57
+
55
58
  ## Install
56
59
 
57
60
  ```bash
File without changes
File without changes
File without changes