dattos 0.2.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,9 @@
1
+ __pycache__/
2
+ *.pyc
3
+ *.pyo
4
+ *.egg-info/
5
+ dist/
6
+ build/
7
+ .pytest_cache/
8
+ .env
9
+ .dattos/
dattos-0.2.0/PKG-INFO ADDED
@@ -0,0 +1,529 @@
1
+ Metadata-Version: 2.4
2
+ Name: dattos
3
+ Version: 0.2.0
4
+ Summary: CLI for the Dattos reconciliation platform
5
+ Project-URL: Homepage, https://dattos.com.br
6
+ Classifier: Environment :: Console
7
+ Classifier: Intended Audience :: Developers
8
+ Classifier: Operating System :: OS Independent
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Classifier: Topic :: Office/Business :: Financial
14
+ Requires-Python: >=3.11
15
+ Requires-Dist: httpx<1,>=0.27
16
+ Requires-Dist: typer<1,>=0.12
17
+ Provides-Extra: dev
18
+ Requires-Dist: build; extra == 'dev'
19
+ Requires-Dist: pytest; extra == 'dev'
20
+ Requires-Dist: twine; extra == 'dev'
21
+ Description-Content-Type: text/markdown
22
+
23
+ # dattos
24
+
25
+ CLI for the [Dattos](https://dattos.com.br) reconciliation platform — designed as an **agent-native interface** for AI agents (Claude Code, custom agents) to operate Dattos programmatically.
26
+
27
+ All output is **JSON to stdout**, errors go to **stderr**, making it trivially parseable by both humans and machines.
28
+
29
+ ## Installation
30
+
31
+ Requires **Python 3.11+**.
32
+
33
+ ```bash
34
+ pip install dattos
35
+
36
+ # Verify
37
+ dattos version
38
+ # {"version": "0.2.0"}
39
+ ```
40
+
41
+ ### From source (development)
42
+
43
+ ```bash
44
+ git clone git@bitbucket.org:dattos/dattos-cli.git
45
+ cd dattos-cli
46
+ pip install -e .
47
+ ```
48
+
49
+ ## Authentication
50
+
51
+ The CLI authenticates via API key + organization ID. Configure using **environment variables** or the **config file** (`~/.dattos/config.json`).
52
+
53
+ ### Environment Variables
54
+
55
+ ```bash
56
+ export DATTOS_API_URL="https://your-instance.dattos.com.br/dattos.api"
57
+ export DATTOS_API_KEY="api-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
58
+ export DATTOS_ORG_ID="1"
59
+ export DATTOS_FOLDER_ID="2473" # optional, default folder for all commands
60
+ ```
61
+
62
+ ### Config File
63
+
64
+ ```bash
65
+ dattos config set api-url "https://your-instance.dattos.com.br/dattos.api"
66
+ dattos config set api-key "api-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
67
+ dattos config set org-id "1"
68
+ ```
69
+
70
+ Saved to `~/.dattos/config.json`. Environment variables take precedence over the config file.
71
+
72
+ ### Folder ID
73
+
74
+ Most Dattos API endpoints require a **folder context**. There are three ways to set it (in priority order):
75
+
76
+ ```bash
77
+ # 1. Per-command flag (highest priority)
78
+ dattos analyses list --folder-id 2473
79
+
80
+ # 2. Environment variable
81
+ export DATTOS_FOLDER_ID="2473"
82
+ dattos analyses list
83
+
84
+ # 3. Config file (persistent, recommended)
85
+ dattos config set folder-id "2473"
86
+ dattos analyses list
87
+ ```
88
+
89
+ To discover available folder IDs, use `dattos folders list`:
90
+
91
+ ```bash
92
+ # Full tree (raw JSON)
93
+ dattos folders list
94
+
95
+ # Flat list with id, name, and full path (easier to read)
96
+ dattos folders list --flat
97
+ ```
98
+
99
+ ## Commands
100
+
101
+ ### `dattos analyses` — Manage analyses
102
+
103
+ ```bash
104
+ # List analyses (with pagination and search)
105
+ dattos analyses list --page-size 10
106
+ # {"data": [{"analysisId": 5192, "analysisCode": "PRD-7728", "analysisName": "Reconciliação Bancária", ...}], "totalItems": 42}
107
+
108
+ dattos analyses list --search "RECON-001" --folder-id 2473
109
+ dattos analyses list --inactive # include inactive/archived
110
+
111
+ # Get analysis by ID
112
+ dattos analyses get 5192 --folder-id 2473
113
+ # {"analysisId": 5192, "analysisCode": "PRD-7728", "analysisName": "Reconciliação Bancária", "isActive": true, ...}
114
+
115
+ # Get analysis by code
116
+ dattos analyses get-by-code "ETL-1" --folder-id 2473
117
+ # {"analysisId": 4137, "analysisCode": "ETL-1", ...}
118
+
119
+ # List data sources and connector info
120
+ dattos analyses datasources 5192 --folder-id 2473
121
+ # [{"id": 101, "name": "Extrato Bancário", "connectorType": "Excel", ...}]
122
+
123
+ # Check execution status at a reference date
124
+ dattos analyses execution-status 5192 --date 2025-12-20 --folder-id 2473
125
+ # {"executionJobId": "89625", "status": "Loaded", "completedPercent": 100.0, ...}
126
+ # Status values: NoLoad, Loading, Loaded, Error, Inactive, InvalidPreparation
127
+
128
+ # Start an analysis execution (default: replace mode)
129
+ dattos analyses start 5192 --date 2026-03-08
130
+ # {"status": "started", "analysisId": 5192, "referenceDate": "2026-03-08"}
131
+
132
+ # Start with file upload (auto-uploads, then starts)
133
+ dattos analyses start 5192 --date 2026-03-08 --file data.csv
134
+ # Supported: .csv, .edi, .ofx, .pdf, .rem, .ret, .txt, .xlsx, .xls, .xlsb, .xml
135
+
136
+ # Start and wait for completion (polls every 5s)
137
+ dattos analyses start 5192 --date 2026-03-08 --wait
138
+
139
+ # Incremental import (preserves existing data, adds new)
140
+ dattos analyses start 5192 --date 2026-03-08 --incremental
141
+ ```
142
+
143
+ ### `dattos loads` — Query analysis loads
144
+
145
+ ```bash
146
+ # Get load details for a reference date (returns load ID + dataset IDs)
147
+ dattos loads get 5192 2025-12-20 --folder-id 2473
148
+ # {"id": 3248, "referenceDate": "2025-12-20", "datasets": [{"id": 2476, "name": "Extrato", "columns": [...]}]}
149
+
150
+ # List all reference dates with loaded data
151
+ dattos loads list-dates 4137 --from 2025-01-01 --to 2026-12-31 --folder-id 2473
152
+ # ["2025-12-09T00:00:00", "2025-12-10T00:00:00", "2025-12-11T00:00:00"]
153
+
154
+ # List available views for a load
155
+ dattos loads views 5192 3248 --folder-id 2473
156
+ # [{"id": 1, "name": "Summary"}, {"id": 2, "name": "Detail"}]
157
+ ```
158
+
159
+ ### `dattos datasets` — Query dataset rows
160
+
161
+ ```bash
162
+ # Search rows in a dataset (requires analysis ID, load ID, dataset ID)
163
+ dattos datasets search 5192 3248 2476 --page-size 10 --folder-id 2473
164
+ # {"rows": {"data": [{"id": 1, "valor": 1500.00, "data": "2025-12-20", ...}]}, "totalRows": 1523}
165
+
166
+ # With pagination (default page-size is 50)
167
+ dattos datasets search 5192 3248 2476 --page-size 50 --page 2
168
+
169
+ # With filter (JSON string)
170
+ dattos datasets search 5192 3248 2476 --filter '{"column": "status", "value": "active"}'
171
+ ```
172
+
173
+ ### `dattos matching` — Reconciliation results
174
+
175
+ ```bash
176
+ # Get matching execution info
177
+ dattos matching get 5192 3248 2475 --folder-id 2473
178
+ # {"id": 1, "status": "Completed", "matchedCount": 1523, ...}
179
+
180
+ # Get totals by status (matched, unmatched, pending)
181
+ dattos matching status 5192 3248 2475 --folder-id 2473
182
+ # {"Matched": 1523, "Unmatched": 47, "Pending": 0}
183
+
184
+ # Get matching summary report
185
+ dattos matching summary 5192 3248 2475 --folder-id 2473
186
+ # [{"column": "Account", "matched": 100, "unmatched": 5}, ...]
187
+ ```
188
+
189
+ ### `dattos reports` — Generate and download reports
190
+
191
+ ```bash
192
+ # Generate a report (async — returns report ID to poll)
193
+ dattos reports generate 5192 --load-id 3248 --dataset-id 2476 --format csv
194
+ # {"id": 99, "status": "Processing"}
195
+
196
+ dattos reports generate 5192 --load-id 3248 --dataset-id 2476 --format xlsx
197
+ # Note: >1M rows only supports CSV format
198
+
199
+ # Check report generation status
200
+ dattos reports status 5192 --load-id 3248 --dataset-id 2476
201
+ # {"id": 99, "status": "Completed", "downloadUrl": "..."}
202
+
203
+ # Download a generated report
204
+ dattos reports download 5192 99 --output report.csv
205
+ # {"status": "downloaded", "file": "report.csv"}
206
+ ```
207
+
208
+ ### `dattos workflows` — Manage and execute workflows
209
+
210
+ ```bash
211
+ # List workflows
212
+ dattos workflows list --page-size 10
213
+ dattos workflows list --name "Daily Recon"
214
+ # {"data": [{"Workflow": {"Id": 1, "Name": "Daily Recon"}, "ExecutionWorkflow": {...}}, ...], "totalItems": 5}
215
+
216
+ # Get workflow details
217
+ dattos workflows get 1
218
+ # {"Workflow": {"Id": 1, "Name": "Daily Recon", "IsActive": true}, "ExecutionWorkflow": {"Status": "Done", ...}}
219
+
220
+ # Start a workflow for a reference date
221
+ dattos workflows start 1 --date 2026-03-08
222
+ # {"status": "started", "workflowId": 1, "referenceDate": "2026-03-08"}
223
+
224
+ # Stop a running workflow execution
225
+ dattos workflows stop 10 # uses execution ID, not workflow ID
226
+ # {"status": "stopped", "executionId": 10}
227
+
228
+ # View execution history
229
+ dattos workflows history 1 --page-size 20
230
+ # {"data": [{"Id": 10, "Status": "Done", "ReferenceDate": "2026-03-07"}, ...], "totalItems": 15}
231
+
232
+ # View task logs
233
+ dattos workflows logs 55 # uses task ID from execution
234
+ # [{"message": "Starting import", "timestamp": "2026-03-07T10:00:00"}, ...]
235
+ ```
236
+
237
+ ### `dattos imports` — Monitor and manage imports
238
+
239
+ ```bash
240
+ # List imports (with optional filters)
241
+ dattos imports list
242
+ dattos imports list --from 2026-01-01 --to 2026-03-31
243
+ dattos imports list --status Error
244
+ dattos imports list --include-canceled
245
+ # {"data": [{"Id": 1, "Status": "Success", "TotalSuccess": 100, ...}], "totalItems": 25}
246
+
247
+ # Get import details
248
+ dattos imports get 1
249
+ # {"Id": 1, "Status": "Success", "TotalSuccess": 100, "TotalRejections": 0, ...}
250
+
251
+ # View rejection details
252
+ dattos imports results 1
253
+ # {"data": [{"line": 5, "reason": "Invalid date format"}], "totalItems": 1}
254
+
255
+ # View import logs
256
+ dattos imports logs 1
257
+ # {"data": [{"message": "Processing started", "timestamp": "..."}], "totalItems": 3}
258
+
259
+ # Cancel an import
260
+ dattos imports cancel 1
261
+ # {"status": "canceled", "importId": 1}
262
+ ```
263
+
264
+ ### `dattos folders` — List and inspect folders
265
+
266
+ ```bash
267
+ # List all folders as a tree (raw JSON)
268
+ dattos folders list
269
+
270
+ # Flat list — easier to find folder IDs
271
+ dattos folders list --flat
272
+ # [{"id": 2473, "code": "SIR", "name": "sirio", "fullPath": "Engenharia / sirio", "depth": 1}, ...]
273
+ ```
274
+
275
+ ### `dattos config` — Manage configuration
276
+
277
+ ```bash
278
+ # Set config values (saved to ~/.dattos/config.json)
279
+ dattos config set api-url "https://your-instance.dattos.com.br/dattos.api"
280
+ dattos config set api-key "api-xxxxxxxx"
281
+ dattos config set org-id "1"
282
+ dattos config set folder-id "2473"
283
+ # {"key": "folder-id", "status": "saved"}
284
+
285
+ # Show current resolved configuration (API key is masked)
286
+ dattos config show
287
+ # {"api_url": "https://your-instance.dattos.com.br/dattos.api", "api_key": "api-xxxx...", "org_id": "1", "folder_id": "2473"}
288
+ ```
289
+
290
+ ### `dattos version`
291
+
292
+ ```bash
293
+ dattos version
294
+ # {"version": "0.1.0"}
295
+ ```
296
+
297
+ ## Usage Examples
298
+
299
+ ### Example 1: First-time setup
300
+
301
+ ```bash
302
+ # Configure credentials
303
+ dattos config set api-url "https://your-instance.dattos.com.br/dattos.api"
304
+ dattos config set api-key "api-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
305
+ dattos config set org-id "1"
306
+
307
+ # Discover your folders
308
+ dattos folders list --flat | jq '.[] | "\(.id) — \(.fullPath)"'
309
+ # "2473 — Engenharia / sirio"
310
+ # "2474 — Engenharia / delta"
311
+
312
+ # Set a default folder
313
+ dattos config set folder-id "2473"
314
+
315
+ # Verify everything works
316
+ dattos config show
317
+ dattos analyses list --page-size 5
318
+ ```
319
+
320
+ ### Example 2: Inspect reconciliation results
321
+
322
+ ```bash
323
+ # Find the analysis by code
324
+ dattos analyses get-by-code "RECON-BANK"
325
+ # Note the analysisId (e.g., 5192)
326
+
327
+ # Check if data is loaded for a date
328
+ dattos analyses execution-status 5192 --date 2026-03-01
329
+ # {"status": "Loaded", "completedPercent": 100.0, ...}
330
+
331
+ # Get the load (returns load ID and dataset IDs)
332
+ dattos loads get 5192 2026-03-01
333
+ # Note loadId (3248) and datasetId (2476)
334
+
335
+ # Browse the data
336
+ dattos datasets search 5192 3248 2476 --page-size 10
337
+
338
+ # Check matching results
339
+ dattos matching status 5192 3248 2475
340
+ # {"Matched": 1523, "Unmatched": 47, "Pending": 0}
341
+ ```
342
+
343
+ ### Example 3: Export data for external analysis
344
+
345
+ ```bash
346
+ # Generate a CSV report
347
+ dattos reports generate 5192 --load-id 3248 --dataset-id 2476 --format csv
348
+ # {"id": 99, "status": "Processing"}
349
+
350
+ # Wait for it to complete
351
+ dattos reports status 5192 --load-id 3248 --dataset-id 2476
352
+ # {"id": 99, "status": "Completed"}
353
+
354
+ # Download the file
355
+ dattos reports download 5192 99 --output reconciliation_2026-03-01.csv
356
+ # {"status": "downloaded", "file": "reconciliation_2026-03-01.csv"}
357
+ ```
358
+
359
+ ### Example 4: Find loaded dates for an analysis
360
+
361
+ ```bash
362
+ # Which dates have data loaded?
363
+ dattos loads list-dates 4137 --from 2026-01-01 --to 2026-03-31 | jq -r '.[]'
364
+ # 2026-01-15T00:00:00
365
+ # 2026-02-15T00:00:00
366
+ # 2026-03-15T00:00:00
367
+ ```
368
+
369
+ ### Example 5: Composing with jq
370
+
371
+ ```bash
372
+ # List analysis names and codes
373
+ dattos analyses list --page-size 100 | jq '.data[] | {code: .analysisCode, name: .analysisName}'
374
+
375
+ # Count unmatched items
376
+ dattos matching status 5192 3248 2475 | jq '.Unmatched'
377
+
378
+ # Get dataset column names
379
+ dattos loads get 5192 2026-03-01 | jq '.datasets[].columns[].name'
380
+
381
+ # Check if execution is done (useful in scripts)
382
+ STATUS=$(dattos analyses execution-status 5192 --date 2026-03-01 | jq -r '.status')
383
+ if [ "$STATUS" = "Loaded" ]; then echo "Ready"; fi
384
+ ```
385
+
386
+ ## Typical Agent Workflow
387
+
388
+ A typical AI agent workflow to inspect reconciliation results:
389
+
390
+ ```bash
391
+ # 0. First time: discover folders and set default
392
+ dattos folders list --flat
393
+ dattos config set folder-id "2473"
394
+
395
+ # 1. List analyses
396
+ dattos analyses list --page-size 10
397
+
398
+ # 2. Check execution status
399
+ dattos analyses execution-status 5192 --date 2025-12-20
400
+
401
+ # 3. Get load details (returns load ID + dataset IDs)
402
+ dattos loads get 5192 2025-12-20
403
+
404
+ # 4. Search dataset rows
405
+ dattos datasets search 5192 3248 2476 --page-size 50
406
+
407
+ # 5. Check matching results
408
+ dattos matching status 5192 3248 2475
409
+
410
+ # 6. Export a report
411
+ dattos reports generate 5192 --load-id 3248 --dataset-id 2476 --format csv
412
+ ```
413
+
414
+ ## Output Format
415
+
416
+ All commands output **JSON to stdout**. Errors output structured JSON to **stderr**.
417
+
418
+ ```bash
419
+ # Success — JSON to stdout
420
+ dattos analyses get 5192
421
+ # {"analysisId": 5192, "analysisCode": "PRD-7728", ...}
422
+
423
+ # Error — JSON to stderr, non-zero exit code
424
+ dattos analyses get 99999
425
+ # {"error": "not_found", "message": "A entidade procurada não existe.", "status": 404}
426
+ ```
427
+
428
+ ### Exit Codes
429
+
430
+ | Code | Meaning |
431
+ |------|---------|
432
+ | `0` | Success |
433
+ | `1` | API error (4xx/5xx) |
434
+ | `2` | Auth/config error (missing API key, invalid credentials) |
435
+
436
+ ### Piping and Filtering
437
+
438
+ Because output is JSON, it composes naturally with `jq`:
439
+
440
+ ```bash
441
+ # Get just the analysis names
442
+ dattos analyses list --folder-id 2473 | jq '.data[].analysisName'
443
+
444
+ # Get loaded dates as plain text
445
+ dattos loads list-dates 4137 --from 2025-01-01 --to 2026-12-31 --folder-id 2473 | jq -r '.[]'
446
+
447
+ # Check if execution is complete
448
+ dattos analyses execution-status 5192 --date 2025-12-20 | jq -r '.status'
449
+ ```
450
+
451
+ ## Error Handling
452
+
453
+ The CLI handles common API errors with descriptive messages:
454
+
455
+ | HTTP Status | Error Type | Description |
456
+ |-------------|------------|-------------|
457
+ | `401` | `auth_error` | Invalid or expired API key |
458
+ | `403` | `forbidden` | Insufficient permissions |
459
+ | `404` | `not_found` | Resource does not exist |
460
+ | `429` | `rate_limited` | Too many requests (auto-retried up to 3 times) |
461
+ | Other | `api_error` | General API error |
462
+
463
+ Rate limiting (HTTP 429) is handled automatically with exponential backoff (5s, 10s, 20s, max 30s).
464
+
465
+ ## Project Structure
466
+
467
+ ```
468
+ dattos-cli/
469
+ ├── src/dattos_cli/
470
+ │ ├── __init__.py # Version
471
+ │ ├── main.py # Typer app, client factory, error handling
472
+ │ ├── client.py # HTTP client (httpx) with retry logic
473
+ │ ├── config.py # Config loading (env vars + ~/.dattos/config.json)
474
+ │ ├── output.py # JSON output helpers (stdout/stderr)
475
+ │ └── commands/
476
+ │ ├── analyses.py # dattos analyses *
477
+ │ ├── loads.py # dattos loads *
478
+ │ ├── datasets.py # dattos datasets *
479
+ │ ├── matching.py # dattos matching *
480
+ │ ├── reports.py # dattos reports *
481
+ │ ├── folders.py # dattos folders *
482
+ │ ├── workflows.py # dattos workflows *
483
+ │ ├── imports.py # dattos imports *
484
+ │ └── config_cmd.py # dattos config *
485
+ ├── tests/ # 53 unit + integration tests
486
+ ├── docs/plans/ # Design and implementation docs
487
+ ├── pyproject.toml
488
+ └── .gitignore
489
+ ```
490
+
491
+ ## Development
492
+
493
+ ### Branch Workflow
494
+
495
+ All development happens on `develop`. The `main` branch is protected — changes require a PR.
496
+
497
+ ```bash
498
+ git checkout develop
499
+ # make changes...
500
+ git push origin develop
501
+ # create PR: develop → main
502
+ ```
503
+
504
+ ### Setup
505
+
506
+ ```bash
507
+ pip install -e .
508
+ pip install pytest
509
+
510
+ # Run tests
511
+ pytest -v
512
+
513
+ # Run a specific test
514
+ pytest tests/test_analyses.py -v
515
+ ```
516
+
517
+ ### Tech Stack
518
+
519
+ - **Python 3.11+**
520
+ - **[Typer](https://typer.tiangolo.com/)** — CLI framework with type hints and auto-generated help
521
+ - **[httpx](https://www.python-httpx.org/)** — HTTP client with MockTransport for testing
522
+ - **[hatchling](https://hatch.pypa.io/)** — Build backend
523
+
524
+ ## Roadmap
525
+
526
+ - ~~**v0.2** — Execution commands~~ ✅ Done (analyses start, workflows, imports)
527
+ - **v0.3** — Configuration commands (create/edit analyses, datasources, connectors)
528
+ - **v0.4** — Database connection info (for massive data access via direct DB queries)
529
+ - **Future** — Interactive login, shell completion, table output format