@fuzzle/opencode-accountant 0.0.12 → 0.0.13

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,252 @@
1
+ # import-statements Tool
2
+
3
+ The `import-statements` tool imports classified CSV bank statements into hledger using rules files. It operates in two modes:
4
+
5
+ - **Check mode** (`checkOnly: true`, default): Validates transactions and reports any that cannot be categorized
6
+ - **Import mode** (`checkOnly: false`): Imports validated transactions and moves processed files to the done directory
7
+
8
+ ## Arguments
9
+
10
+ | Argument | Type | Default | Description |
11
+ | ----------- | ------- | ------- | ------------------------------------------- |
12
+ | `provider` | string | - | Filter by provider (e.g., `revolut`, `ubs`) |
13
+ | `currency` | string | - | Filter by currency (e.g., `chf`, `eur`) |
14
+ | `checkOnly` | boolean | `true` | If true, only validate without importing |
15
+
16
+ ## Output Format
17
+
18
+ **Note on paths:** All file paths in the examples below use `{paths.*}` variables. These are configured in `config/import/providers.yaml`. Default values are:
19
+
20
+ - `{paths.pending}` = `import/pending`
21
+ - `{paths.done}` = `import/done`
22
+ - `{paths.rules}` = `ledger/rules`
23
+
24
+ ### Check Mode - All Transactions Matched
25
+
26
+ When all transactions have matching rules:
27
+
28
+ ```json
29
+ {
30
+ "success": true,
31
+ "files": [
32
+ {
33
+ "csv": "{paths.pending}/ubs/chf/transactions-ubs-0235-90250546.0.csv",
34
+ "rulesFile": "{paths.rules}/ubs-0235-90250546.0.rules",
35
+ "transactions": 25,
36
+ "unknownPostings": []
37
+ }
38
+ ],
39
+ "summary": {
40
+ "filesProcessed": 1,
41
+ "totalTransactions": 25,
42
+ "matched": 25,
43
+ "unknown": 0
44
+ },
45
+ "message": "All transactions matched. Ready to import with checkOnly: false"
46
+ }
47
+ ```
48
+
49
+ ### Check Mode - Unknown Postings Found
50
+
51
+ When transactions don't match any `if` pattern in the rules file, the tool returns the full CSV row data for each unknown posting to provide context for classification:
52
+
53
+ ```json
54
+ {
55
+ "success": false,
56
+ "files": [
57
+ {
58
+ "csv": "{paths.pending}/ubs/chf/transactions-ubs-0235-90250546.0.csv",
59
+ "rulesFile": "{paths.rules}/ubs-0235-90250546.0.rules",
60
+ "transactions": 25,
61
+ "unknownPostings": [
62
+ {
63
+ "date": "2026-01-16",
64
+ "description": "Connor, John",
65
+ "amount": "CHF95.25",
66
+ "account": "income:unknown",
67
+ "csvRow": {
68
+ "trade_date": "2026-01-16",
69
+ "trade_time": "",
70
+ "booking_date": "2026-01-16",
71
+ "value_date": "2026-01-16",
72
+ "currency": "CHF",
73
+ "debit": "",
74
+ "credit": "95.25",
75
+ "individual_amount": "",
76
+ "balance": "4746.23",
77
+ "transaction_no": "ABC123",
78
+ "description1": "Connor, John",
79
+ "description2": "Twint deposit",
80
+ "description3": "Ref: TW-12345",
81
+ "footnotes": ""
82
+ }
83
+ },
84
+ {
85
+ "date": "2026-01-30",
86
+ "description": "Balance closing of service prices",
87
+ "amount": "CHF-10.00",
88
+ "account": "expenses:unknown",
89
+ "csvRow": {
90
+ "trade_date": "2026-01-30",
91
+ "trade_time": "",
92
+ "booking_date": "2026-01-30",
93
+ "value_date": "2026-01-30",
94
+ "currency": "CHF",
95
+ "debit": "10.00",
96
+ "credit": "",
97
+ "individual_amount": "",
98
+ "balance": "2364.69",
99
+ "transaction_no": "DEF456",
100
+ "description1": "Balance closing of service prices",
101
+ "description2": "",
102
+ "description3": "",
103
+ "footnotes": ""
104
+ }
105
+ }
106
+ ]
107
+ }
108
+ ],
109
+ "summary": {
110
+ "filesProcessed": 1,
111
+ "totalTransactions": 25,
112
+ "matched": 23,
113
+ "unknown": 2
114
+ }
115
+ }
116
+ ```
117
+
118
+ ### Check Mode - Missing Rules File
119
+
120
+ When a CSV file has no matching rules file:
121
+
122
+ ```json
123
+ {
124
+ "success": false,
125
+ "files": [
126
+ {
127
+ "csv": "{paths.pending}/ubs/chf/transactions.csv",
128
+ "error": "No matching rules file found. Create a rules file with 'source' directive pointing to this CSV."
129
+ }
130
+ ],
131
+ "summary": {
132
+ "filesProcessed": 1,
133
+ "filesWithoutRules": 1
134
+ }
135
+ }
136
+ ```
137
+
138
+ ### Import Mode - Success
139
+
140
+ When importing with all transactions matched:
141
+
142
+ ```json
143
+ {
144
+ "success": true,
145
+ "files": [
146
+ {
147
+ "csv": "{paths.pending}/ubs/chf/transactions.csv",
148
+ "rulesFile": "{paths.rules}/ubs.rules",
149
+ "imported": true,
150
+ "movedTo": "{paths.done}/ubs/chf/transactions.csv"
151
+ }
152
+ ],
153
+ "summary": {
154
+ "filesProcessed": 1,
155
+ "filesImported": 1,
156
+ "totalTransactions": 25
157
+ },
158
+ "message": "Successfully imported 1 file(s)"
159
+ }
160
+ ```
161
+
162
+ ### Import Mode - Blocked by Unknown Postings
163
+
164
+ Import mode runs a check first and aborts if any unknowns exist:
165
+
166
+ ```json
167
+ {
168
+ "success": false,
169
+ "error": "Cannot import: 2 transactions have unknown accounts. Run with checkOnly: true to see details and add rules.",
170
+ "hint": "Run with checkOnly: true first to identify and fix unknown postings"
171
+ }
172
+ ```
173
+
174
+ ## Unknown Posting Types
175
+
176
+ hledger assigns transactions to `income:unknown` or `expenses:unknown` based on the direction:
177
+
178
+ | Transaction Type | Account Assigned |
179
+ | -------------------------- | ------------------ |
180
+ | Money coming in (positive) | `income:unknown` |
181
+ | Money going out (negative) | `expenses:unknown` |
182
+
183
+ ## Fixing Unknown Postings
184
+
185
+ When the tool reports unknown postings, the `csvRow` field contains all available data from the original CSV to help determine the correct account. This includes additional description fields, transaction references, and other metadata that may help with classification.
186
+
187
+ Add `if` rules to the appropriate rules file based on the posting details:
188
+
189
+ ```
190
+ # Example: Categorize a friend's reimbursement
191
+ # (csvRow showed description2: "Twint deposit" confirming it's a payment app transfer)
192
+ if Connor, John
193
+ account1 income:reimbursements
194
+
195
+ # Example: Categorize bank service charges
196
+ if Balance closing of service prices
197
+ account1 expenses:fees:bank
198
+ ```
199
+
200
+ Then run the tool again with `checkOnly: true` to verify the rules work.
201
+
202
+ ### CSV Row Field Names
203
+
204
+ The `csvRow` object uses field names from the `fields` directive in the rules file. Common fields include:
205
+
206
+ | Field | Description |
207
+ | ---------------- | ------------------------------------------------------- |
208
+ | `trade_date` | When the transaction occurred |
209
+ | `booking_date` | When it was booked |
210
+ | `description1` | Primary description |
211
+ | `description2` | Secondary description (often useful for classification) |
212
+ | `description3` | Additional reference information |
213
+ | `transaction_no` | Unique transaction identifier |
214
+ | `debit` | Debit amount (money out) |
215
+ | `credit` | Credit amount (money in) |
216
+
217
+ The exact field names depend on your rules file configuration.
218
+
219
+ ## Error Handling
220
+
221
+ ### hledger Errors
222
+
223
+ If hledger fails to parse a CSV or rules file:
224
+
225
+ ```json
226
+ {
227
+ "success": false,
228
+ "files": [
229
+ {
230
+ "csv": "{paths.pending}/ubs/chf/transactions.csv",
231
+ "rulesFile": "{paths.rules}/ubs.rules",
232
+ "error": "hledger error: Parse error at line 5: invalid date format"
233
+ }
234
+ ],
235
+ "summary": {
236
+ "filesProcessed": 1,
237
+ "filesWithErrors": 1
238
+ }
239
+ }
240
+ ```
241
+
242
+ ### Configuration Errors
243
+
244
+ If the config file is missing or invalid:
245
+
246
+ ```json
247
+ {
248
+ "success": false,
249
+ "error": "Failed to load configuration: Configuration file not found: config/import/providers.yaml",
250
+ "hint": "Ensure config/import/providers.yaml exists with a 'rules' path configured"
251
+ }
252
+ ```