cashapply 0.1.0__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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 SybilGambleyyu
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,231 @@
1
+ Metadata-Version: 2.4
2
+ Name: cashapply
3
+ Version: 0.1.0
4
+ Summary: Deterministic cash application: match bank payments to open invoices with an auditable trail
5
+ Author: SybilGambleyyu
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/SybilGambleyyu/cashapply
8
+ Project-URL: Repository, https://github.com/SybilGambleyyu/cashapply
9
+ Project-URL: Issues, https://github.com/SybilGambleyyu/cashapply/issues
10
+ Keywords: accounting,accounts-receivable,cash-application,reconciliation,invoice-matching,remittance,open-item,bookkeeping
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Financial and Insurance Industry
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Office/Business :: Financial :: Accounting
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Requires-Python: >=3.10
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: rapidfuzz>=3.0
26
+ Provides-Extra: dev
27
+ Requires-Dist: pytest>=7.0; extra == "dev"
28
+ Requires-Dist: build; extra == "dev"
29
+ Requires-Dist: twine; extra == "dev"
30
+ Dynamic: license-file
31
+
32
+ # cashapply
33
+
34
+ **Deterministic cash application for accounts receivable.**
35
+
36
+ Match bank payments and remittance lines to open invoices — with a confidence score and a plain-English reason for every match. No black-box model: every suggestion is auditable.
37
+
38
+ Also includes **bank ↔ book (GL) reconciliation** for classic statement matching.
39
+
40
+ ```bash
41
+ pip install cashapply
42
+
43
+ cashapply apply -p payments.csv -i invoices.csv -o matches.csv
44
+ cashapply reconcile -b bank.csv -g book.csv -o pairs.csv
45
+ ```
46
+
47
+ ## Why this exists
48
+
49
+ AR clerks and controllers still burn hours every week on cash application:
50
+
51
+ 1. A payment hits the bank for `$1,650.00`
52
+ 2. The memo says something like `paying both open invoices` or `INV-1004`
53
+ 3. Someone hunts through the open AR aging to find which invoice(s) it covers
54
+
55
+ Enterprise tools (HighRadius, BlackLine, Versapay, …) automate this — at enterprise prices. Lightweight open-source matching engines you can drop into a script, a notebook, or a small firm’s workflow are scarce.
56
+
57
+ **cashapply** is that engine:
58
+
59
+ | Need | What cashapply does |
60
+ |------|---------------------|
61
+ | Memo says `INV-1001` | Reference extraction → high-confidence apply |
62
+ | One payment covers two invoices | Subset-sum multi-invoice match |
63
+ | Partial payment on account | Partial apply with customer-name check |
64
+ | Bank line vs GL line | Two-sided ledger reconciliation |
65
+ | Auditor asks “why?” | Every match has `reasons[]` and a score |
66
+
67
+ It is **not** a full ERP, lockbox OCR product, or ML remittance reader. It takes clean structured inputs (CSV / Python objects) and returns scored matches you can post or review.
68
+
69
+ ## Install
70
+
71
+ ```bash
72
+ pip install cashapply
73
+ ```
74
+
75
+ Requires Python 3.10+.
76
+
77
+ ## Quick start (CLI)
78
+
79
+ ### Cash application
80
+
81
+ **invoices.csv**
82
+
83
+ ```csv
84
+ id,amount,customer,invoice_date,due_date,reference
85
+ INV-1001,1500.00,Acme Corporation,2024-05-01,2024-05-31,PO-7781
86
+ INV-1002,275.50,Acme Corporation,2024-05-15,2024-06-14,
87
+ INV-1004,1200.00,Initech LLC,2024-06-10,2024-07-10,
88
+ INV-1005,450.00,Initech LLC,2024-06-12,2024-07-12,
89
+ ```
90
+
91
+ **payments.csv**
92
+
93
+ ```csv
94
+ id,amount,date,memo,payer
95
+ P-01,1500.00,2024-05-28,ACH BILL PAY INV-1001,Acme Corporation
96
+ P-04,1650.00,2024-07-15,paying both open invoices,Initech LLC
97
+ ```
98
+
99
+ ```bash
100
+ cashapply apply -p payments.csv -i invoices.csv -o matches.csv --json result.json
101
+ ```
102
+
103
+ Example summary:
104
+
105
+ ```
106
+ === Cash application summary ===
107
+ Payments: 2
108
+ Invoices: 4
109
+ Matches: 2 (auto-apply ≥0.85: 2)
110
+ ...
111
+ [AUTO] pay P-01 → INV-1001 $1500.00 conf=0.97 (reference_full)
112
+ • memo reference 'INV-1001' (known_id) → invoice INV-1001
113
+ [AUTO] pay P-04 → INV-1004, INV-1005 $1650.00 conf=0.93 (multi_invoice)
114
+ • multi-invoice: 1650.00 = sum of ['INV-1004', 'INV-1005'] (...)
115
+ ```
116
+
117
+ ### Bank ↔ book reconciliation
118
+
119
+ ```bash
120
+ cashapply reconcile -b bank.csv -g gl.csv -o pairs.csv
121
+ ```
122
+
123
+ ## Python API
124
+
125
+ ```python
126
+ from decimal import Decimal
127
+ from cashapply import Invoice, Payment, MatchConfig, match_payments
128
+
129
+ invoices = [
130
+ Invoice(id="INV-1001", amount=Decimal("1500.00"), customer="Acme Corporation"),
131
+ Invoice(id="INV-1002", amount=Decimal("275.50"), customer="Acme Corporation"),
132
+ ]
133
+ payments = [
134
+ Payment(id="P-01", amount=Decimal("1500.00"), memo="ACH INV-1001", payer="Acme Corp"),
135
+ ]
136
+
137
+ result = match_payments(payments, invoices)
138
+
139
+ for m in result.high_confidence(0.85):
140
+ print(m.payment_id, "→", m.invoice_ids, m.confidence, m.reasons)
141
+
142
+ # Full audit payload
143
+ print(result.to_dict())
144
+ ```
145
+
146
+ ### Bank / GL reconciliation
147
+
148
+ ```python
149
+ from cashapply.reconcile import LedgerLine, reconcile_ledgers
150
+ from datetime import date
151
+ from decimal import Decimal
152
+
153
+ bank = [LedgerLine("b1", Decimal("100"), date(2024, 5, 1), "ACME DEP")]
154
+ book = [LedgerLine("g1", Decimal("100"), date(2024, 5, 1), "Acme deposit")]
155
+ result = reconcile_ledgers(bank, book)
156
+ ```
157
+
158
+ ## How matching works
159
+
160
+ Matches are tried in order; each invoice is claimed at most once per run:
161
+
162
+ 1. **Reference** — invoice numbers / PO / refs extracted from the payment memo (and exact known-id scan)
163
+ 2. **Exact amount** — open balance equals payment; boosted by customer-name and date proximity; penalized when ambiguous
164
+ 3. **Multi-invoice** — payment equals the sum of a small set of open invoices (same customer preferred)
165
+ 4. **Partial** — payment is less than one larger invoice, only with reasonable customer-name agreement
166
+ 5. **Name + amount band** — strong name match with short-pay / near amount
167
+
168
+ Confidence is a number in `[0, 1]`. Default rule of thumb:
169
+
170
+ - **≥ 0.85** — safe to auto-post (still keep the reason trail)
171
+ - **0.40–0.85** — queue for human review
172
+ - **< 0.40** — not reported (stays unmatched)
173
+
174
+ Tune with `MatchConfig`:
175
+
176
+ ```python
177
+ cfg = MatchConfig(
178
+ amount_tolerance=Decimal("0.05"),
179
+ date_window_days=60,
180
+ allow_partial=True,
181
+ max_invoices_per_payment=5,
182
+ auto_apply_threshold=0.90,
183
+ min_report_confidence=0.50,
184
+ )
185
+ result = match_payments(payments, invoices, cfg)
186
+ ```
187
+
188
+ ## CSV columns
189
+
190
+ Flexible headers — any of these work:
191
+
192
+ | Role | Accepted column names |
193
+ |------|------------------------|
194
+ | Invoice id | `id`, `invoice_id`, `invoice`, `invoice_number`, `number` |
195
+ | Amount | `amount`, `open_amount`, `balance`, `total` |
196
+ | Customer | `customer`, `customer_name`, `name`, `client` |
197
+ | Payment id | `id`, `payment_id`, `txn_id`, `transaction_id` |
198
+ | Memo | `memo`, `description`, `narrative`, `reference`, `remittance` |
199
+ | Payer | `payer`, `customer`, `name`, `payor` |
200
+
201
+ ## Examples
202
+
203
+ This repo ships runnable samples:
204
+
205
+ ```bash
206
+ git clone https://github.com/SybilGambleyyu/cashapply
207
+ cd cashapply
208
+ pip install -e .
209
+ cashapply apply -p examples/payments.csv -i examples/invoices.csv
210
+ cashapply reconcile -b examples/bank.csv -g examples/book.csv
211
+ ```
212
+
213
+ ## What this is not
214
+
215
+ - Not OCR for PDF lockbox images (feed it structured data)
216
+ - Not a full AR suite (credit memos, deductions workflows, ERP posting adapters — bring your own)
217
+ - Not a neural net: accuracy comes from rules, fuzzy names, and combinatorial matching you can explain
218
+
219
+ If you need PDF remittance capture, pair cashapply with your existing extraction step and pass the resulting tables in.
220
+
221
+ ## Development
222
+
223
+ ```bash
224
+ python -m venv .venv && source .venv/bin/activate
225
+ pip install -e ".[dev]"
226
+ pytest -q
227
+ ```
228
+
229
+ ## License
230
+
231
+ MIT — use it in internal tools, products, and client work.
@@ -0,0 +1,200 @@
1
+ # cashapply
2
+
3
+ **Deterministic cash application for accounts receivable.**
4
+
5
+ Match bank payments and remittance lines to open invoices — with a confidence score and a plain-English reason for every match. No black-box model: every suggestion is auditable.
6
+
7
+ Also includes **bank ↔ book (GL) reconciliation** for classic statement matching.
8
+
9
+ ```bash
10
+ pip install cashapply
11
+
12
+ cashapply apply -p payments.csv -i invoices.csv -o matches.csv
13
+ cashapply reconcile -b bank.csv -g book.csv -o pairs.csv
14
+ ```
15
+
16
+ ## Why this exists
17
+
18
+ AR clerks and controllers still burn hours every week on cash application:
19
+
20
+ 1. A payment hits the bank for `$1,650.00`
21
+ 2. The memo says something like `paying both open invoices` or `INV-1004`
22
+ 3. Someone hunts through the open AR aging to find which invoice(s) it covers
23
+
24
+ Enterprise tools (HighRadius, BlackLine, Versapay, …) automate this — at enterprise prices. Lightweight open-source matching engines you can drop into a script, a notebook, or a small firm’s workflow are scarce.
25
+
26
+ **cashapply** is that engine:
27
+
28
+ | Need | What cashapply does |
29
+ |------|---------------------|
30
+ | Memo says `INV-1001` | Reference extraction → high-confidence apply |
31
+ | One payment covers two invoices | Subset-sum multi-invoice match |
32
+ | Partial payment on account | Partial apply with customer-name check |
33
+ | Bank line vs GL line | Two-sided ledger reconciliation |
34
+ | Auditor asks “why?” | Every match has `reasons[]` and a score |
35
+
36
+ It is **not** a full ERP, lockbox OCR product, or ML remittance reader. It takes clean structured inputs (CSV / Python objects) and returns scored matches you can post or review.
37
+
38
+ ## Install
39
+
40
+ ```bash
41
+ pip install cashapply
42
+ ```
43
+
44
+ Requires Python 3.10+.
45
+
46
+ ## Quick start (CLI)
47
+
48
+ ### Cash application
49
+
50
+ **invoices.csv**
51
+
52
+ ```csv
53
+ id,amount,customer,invoice_date,due_date,reference
54
+ INV-1001,1500.00,Acme Corporation,2024-05-01,2024-05-31,PO-7781
55
+ INV-1002,275.50,Acme Corporation,2024-05-15,2024-06-14,
56
+ INV-1004,1200.00,Initech LLC,2024-06-10,2024-07-10,
57
+ INV-1005,450.00,Initech LLC,2024-06-12,2024-07-12,
58
+ ```
59
+
60
+ **payments.csv**
61
+
62
+ ```csv
63
+ id,amount,date,memo,payer
64
+ P-01,1500.00,2024-05-28,ACH BILL PAY INV-1001,Acme Corporation
65
+ P-04,1650.00,2024-07-15,paying both open invoices,Initech LLC
66
+ ```
67
+
68
+ ```bash
69
+ cashapply apply -p payments.csv -i invoices.csv -o matches.csv --json result.json
70
+ ```
71
+
72
+ Example summary:
73
+
74
+ ```
75
+ === Cash application summary ===
76
+ Payments: 2
77
+ Invoices: 4
78
+ Matches: 2 (auto-apply ≥0.85: 2)
79
+ ...
80
+ [AUTO] pay P-01 → INV-1001 $1500.00 conf=0.97 (reference_full)
81
+ • memo reference 'INV-1001' (known_id) → invoice INV-1001
82
+ [AUTO] pay P-04 → INV-1004, INV-1005 $1650.00 conf=0.93 (multi_invoice)
83
+ • multi-invoice: 1650.00 = sum of ['INV-1004', 'INV-1005'] (...)
84
+ ```
85
+
86
+ ### Bank ↔ book reconciliation
87
+
88
+ ```bash
89
+ cashapply reconcile -b bank.csv -g gl.csv -o pairs.csv
90
+ ```
91
+
92
+ ## Python API
93
+
94
+ ```python
95
+ from decimal import Decimal
96
+ from cashapply import Invoice, Payment, MatchConfig, match_payments
97
+
98
+ invoices = [
99
+ Invoice(id="INV-1001", amount=Decimal("1500.00"), customer="Acme Corporation"),
100
+ Invoice(id="INV-1002", amount=Decimal("275.50"), customer="Acme Corporation"),
101
+ ]
102
+ payments = [
103
+ Payment(id="P-01", amount=Decimal("1500.00"), memo="ACH INV-1001", payer="Acme Corp"),
104
+ ]
105
+
106
+ result = match_payments(payments, invoices)
107
+
108
+ for m in result.high_confidence(0.85):
109
+ print(m.payment_id, "→", m.invoice_ids, m.confidence, m.reasons)
110
+
111
+ # Full audit payload
112
+ print(result.to_dict())
113
+ ```
114
+
115
+ ### Bank / GL reconciliation
116
+
117
+ ```python
118
+ from cashapply.reconcile import LedgerLine, reconcile_ledgers
119
+ from datetime import date
120
+ from decimal import Decimal
121
+
122
+ bank = [LedgerLine("b1", Decimal("100"), date(2024, 5, 1), "ACME DEP")]
123
+ book = [LedgerLine("g1", Decimal("100"), date(2024, 5, 1), "Acme deposit")]
124
+ result = reconcile_ledgers(bank, book)
125
+ ```
126
+
127
+ ## How matching works
128
+
129
+ Matches are tried in order; each invoice is claimed at most once per run:
130
+
131
+ 1. **Reference** — invoice numbers / PO / refs extracted from the payment memo (and exact known-id scan)
132
+ 2. **Exact amount** — open balance equals payment; boosted by customer-name and date proximity; penalized when ambiguous
133
+ 3. **Multi-invoice** — payment equals the sum of a small set of open invoices (same customer preferred)
134
+ 4. **Partial** — payment is less than one larger invoice, only with reasonable customer-name agreement
135
+ 5. **Name + amount band** — strong name match with short-pay / near amount
136
+
137
+ Confidence is a number in `[0, 1]`. Default rule of thumb:
138
+
139
+ - **≥ 0.85** — safe to auto-post (still keep the reason trail)
140
+ - **0.40–0.85** — queue for human review
141
+ - **< 0.40** — not reported (stays unmatched)
142
+
143
+ Tune with `MatchConfig`:
144
+
145
+ ```python
146
+ cfg = MatchConfig(
147
+ amount_tolerance=Decimal("0.05"),
148
+ date_window_days=60,
149
+ allow_partial=True,
150
+ max_invoices_per_payment=5,
151
+ auto_apply_threshold=0.90,
152
+ min_report_confidence=0.50,
153
+ )
154
+ result = match_payments(payments, invoices, cfg)
155
+ ```
156
+
157
+ ## CSV columns
158
+
159
+ Flexible headers — any of these work:
160
+
161
+ | Role | Accepted column names |
162
+ |------|------------------------|
163
+ | Invoice id | `id`, `invoice_id`, `invoice`, `invoice_number`, `number` |
164
+ | Amount | `amount`, `open_amount`, `balance`, `total` |
165
+ | Customer | `customer`, `customer_name`, `name`, `client` |
166
+ | Payment id | `id`, `payment_id`, `txn_id`, `transaction_id` |
167
+ | Memo | `memo`, `description`, `narrative`, `reference`, `remittance` |
168
+ | Payer | `payer`, `customer`, `name`, `payor` |
169
+
170
+ ## Examples
171
+
172
+ This repo ships runnable samples:
173
+
174
+ ```bash
175
+ git clone https://github.com/SybilGambleyyu/cashapply
176
+ cd cashapply
177
+ pip install -e .
178
+ cashapply apply -p examples/payments.csv -i examples/invoices.csv
179
+ cashapply reconcile -b examples/bank.csv -g examples/book.csv
180
+ ```
181
+
182
+ ## What this is not
183
+
184
+ - Not OCR for PDF lockbox images (feed it structured data)
185
+ - Not a full AR suite (credit memos, deductions workflows, ERP posting adapters — bring your own)
186
+ - Not a neural net: accuracy comes from rules, fuzzy names, and combinatorial matching you can explain
187
+
188
+ If you need PDF remittance capture, pair cashapply with your existing extraction step and pass the resulting tables in.
189
+
190
+ ## Development
191
+
192
+ ```bash
193
+ python -m venv .venv && source .venv/bin/activate
194
+ pip install -e ".[dev]"
195
+ pytest -q
196
+ ```
197
+
198
+ ## License
199
+
200
+ MIT — use it in internal tools, products, and client work.
@@ -0,0 +1,58 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "cashapply"
7
+ version = "0.1.0"
8
+ description = "Deterministic cash application: match bank payments to open invoices with an auditable trail"
9
+ readme = "README.md"
10
+ license = { text = "MIT" }
11
+ requires-python = ">=3.10"
12
+ authors = [
13
+ { name = "SybilGambleyyu" },
14
+ ]
15
+ keywords = [
16
+ "accounting",
17
+ "accounts-receivable",
18
+ "cash-application",
19
+ "reconciliation",
20
+ "invoice-matching",
21
+ "remittance",
22
+ "open-item",
23
+ "bookkeeping",
24
+ ]
25
+ classifiers = [
26
+ "Development Status :: 4 - Beta",
27
+ "Intended Audience :: Financial and Insurance Industry",
28
+ "Intended Audience :: Developers",
29
+ "License :: OSI Approved :: MIT License",
30
+ "Programming Language :: Python :: 3",
31
+ "Programming Language :: Python :: 3.10",
32
+ "Programming Language :: Python :: 3.11",
33
+ "Programming Language :: Python :: 3.12",
34
+ "Programming Language :: Python :: 3.13",
35
+ "Topic :: Office/Business :: Financial :: Accounting",
36
+ "Topic :: Software Development :: Libraries :: Python Modules",
37
+ ]
38
+ dependencies = [
39
+ "rapidfuzz>=3.0",
40
+ ]
41
+
42
+ [project.optional-dependencies]
43
+ dev = ["pytest>=7.0", "build", "twine"]
44
+
45
+ [project.scripts]
46
+ cashapply = "cashapply.cli:main"
47
+
48
+ [project.urls]
49
+ Homepage = "https://github.com/SybilGambleyyu/cashapply"
50
+ Repository = "https://github.com/SybilGambleyyu/cashapply"
51
+ Issues = "https://github.com/SybilGambleyyu/cashapply/issues"
52
+
53
+ [tool.setuptools.packages.find]
54
+ where = ["src"]
55
+
56
+ [tool.pytest.ini_options]
57
+ testpaths = ["tests"]
58
+ pythonpath = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,23 @@
1
+ """
2
+ cashapply — deterministic cash application and open-item matching.
3
+
4
+ Match bank payments (or remittance lines) to open invoices with scored,
5
+ auditable reasons. No ML black boxes: every match explains itself.
6
+ """
7
+
8
+ from cashapply.engine import MatchConfig, match_payments
9
+ from cashapply.models import Invoice, Match, MatchResult, Payment
10
+ from cashapply.reconcile import ReconcileConfig, reconcile_ledgers
11
+
12
+ __version__ = "0.1.0"
13
+ __all__ = [
14
+ "Invoice",
15
+ "Payment",
16
+ "Match",
17
+ "MatchResult",
18
+ "MatchConfig",
19
+ "match_payments",
20
+ "ReconcileConfig",
21
+ "reconcile_ledgers",
22
+ "__version__",
23
+ ]