invoice_extractor_arca 0.2.0
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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +49 -0
- data/LICENSE.txt +21 -0
- data/README.md +631 -0
- data/exe/arca-invoice-extract +6 -0
- data/lib/invoice_extractor_arca/catalogs/copy_types.json +5 -0
- data/lib/invoice_extractor_arca/catalogs/currencies.json +65 -0
- data/lib/invoice_extractor_arca/catalogs/document_types.json +40 -0
- data/lib/invoice_extractor_arca/catalogs/iva_types.json +13 -0
- data/lib/invoice_extractor_arca/catalogs/payment_methods.json +10 -0
- data/lib/invoice_extractor_arca/catalogs/units_measure.json +47 -0
- data/lib/invoice_extractor_arca/catalogs/voucher_types.json +99 -0
- data/lib/invoice_extractor_arca/catalogs.rb +34 -0
- data/lib/invoice_extractor_arca/cli.rb +247 -0
- data/lib/invoice_extractor_arca/command_runner.rb +18 -0
- data/lib/invoice_extractor_arca/configuration.rb +42 -0
- data/lib/invoice_extractor_arca/dependencies/resolver.rb +118 -0
- data/lib/invoice_extractor_arca/error.rb +6 -0
- data/lib/invoice_extractor_arca/error_record.rb +39 -0
- data/lib/invoice_extractor_arca/errors.rb +34 -0
- data/lib/invoice_extractor_arca/extractor.rb +381 -0
- data/lib/invoice_extractor_arca/final_payload_builder.rb +67 -0
- data/lib/invoice_extractor_arca/ocr/rapidocr_extract.py +198 -0
- data/lib/invoice_extractor_arca/ocr/rapidocr_text_extractor.rb +117 -0
- data/lib/invoice_extractor_arca/pdf/ocr_text_extractor.rb +131 -0
- data/lib/invoice_extractor_arca/pdf/renderer.rb +97 -0
- data/lib/invoice_extractor_arca/pdf/text_extractor.rb +182 -0
- data/lib/invoice_extractor_arca/qr/payload_parser.rb +124 -0
- data/lib/invoice_extractor_arca/qr/reader.rb +53 -0
- data/lib/invoice_extractor_arca/qr/result_builder.rb +229 -0
- data/lib/invoice_extractor_arca/qr_extractor.rb +156 -0
- data/lib/invoice_extractor_arca/result.rb +94 -0
- data/lib/invoice_extractor_arca/scanners/factory.rb +88 -0
- data/lib/invoice_extractor_arca/scanners/qreader_scan.py +102 -0
- data/lib/invoice_extractor_arca/scanners/qreader_scanner.rb +131 -0
- data/lib/invoice_extractor_arca/scanners/scanner_chain.rb +73 -0
- data/lib/invoice_extractor_arca/scanners/zbar_scanner.rb +52 -0
- data/lib/invoice_extractor_arca/text/invoice_parser.rb +517 -0
- data/lib/invoice_extractor_arca/text/layout_table_parser.rb +218 -0
- data/lib/invoice_extractor_arca/text/locale_value_normalizer.rb +53 -0
- data/lib/invoice_extractor_arca/text/normalizer.rb +31 -0
- data/lib/invoice_extractor_arca/validation/reconciler.rb +53 -0
- data/lib/invoice_extractor_arca/version.rb +5 -0
- data/lib/invoice_extractor_arca/voucher_validator.rb +169 -0
- data/lib/invoice_extractor_arca.rb +117 -0
- data/requirements-ocr.txt +2 -0
- data/sig/invoice_extractor_arca.rbs +4 -0
- metadata +135 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 16278ffa86026380d3f66d0fdd3d028217583262f84747f6c0abb9fe9ff9a0ee
|
|
4
|
+
data.tar.gz: fb9ee435a5d1d0783955c9650494dcc683c7a50a4f73eb8e9cd46b115cc6f906
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: '09bada94fdc09cb05f364b1e195002f217f9fb9791a6d35b2457dd7d9b920f0a37821f01f3dc1aa5bd941382b778803ed43a4d716f9b404771f2470c8ba822c4'
|
|
7
|
+
data.tar.gz: d46cc254d2a855408511427eae31da7802b45005e8689cb98e28603406983e5ad0911d09536861fe67e576faeb2352f85d999d0c918cc69ef2236762b885e339
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## [0.2.0] - 2026-09-04
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Command-line interface through `arca-invoice-extract`.
|
|
10
|
+
- Compact and pretty JSON output.
|
|
11
|
+
- Documented CLI exit codes.
|
|
12
|
+
- CLI options for strict mode, enrichment, page selection, rendering resolution, QR scanner selection, multiple QR handling, and dependency paths.
|
|
13
|
+
- QR scanner fallback chains using ZBar and QReader.
|
|
14
|
+
- RapidOCR-based text extraction for invoice images.
|
|
15
|
+
- PDF text extraction with page selection.
|
|
16
|
+
- Regex-based invoice field enrichment.
|
|
17
|
+
- Layout-aware extraction of product and service rows.
|
|
18
|
+
- Reconciliation between QR-derived and text-derived invoice values.
|
|
19
|
+
- ARCA catalogs for voucher types, currencies, document types, IVA conditions, payment methods, copy types, and units of measure.
|
|
20
|
+
- Unit and integration tests for the CLI, OCR, enrichment, reconciliation, scanners, and PDF processing.
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
|
|
24
|
+
- Expanded extraction results with `text`, `enrichment`, and `validation` sections.
|
|
25
|
+
- Improved multiple-QR handling by distinguishing duplicate payloads from distinct payloads.
|
|
26
|
+
- QR scanner selection is now configurable.
|
|
27
|
+
- Image extraction can optionally enrich invoice data using OCR.
|
|
28
|
+
- Structured diagnostics now distinguish errors from warnings.
|
|
29
|
+
|
|
30
|
+
### Fixed
|
|
31
|
+
|
|
32
|
+
- Preserved actual PDF page numbers in QR candidates.
|
|
33
|
+
- Improved handling of URL-safe Base64 QR payloads.
|
|
34
|
+
- Normalized Argentine decimal values, dates, document numbers, and invoice codes.
|
|
35
|
+
- Ensured temporary rendered PDF pages are removed after processing.
|
|
36
|
+
|
|
37
|
+
### Security
|
|
38
|
+
|
|
39
|
+
- External commands are executed using argument arrays rather than shell command strings.
|
|
40
|
+
|
|
41
|
+
## [0.1.0] - 2026-07-28
|
|
42
|
+
|
|
43
|
+
### Added
|
|
44
|
+
|
|
45
|
+
- Initial release.
|
|
46
|
+
- QR-first extraction from PDF and image invoices.
|
|
47
|
+
- ARCA QR payload decoding and voucher validation.
|
|
48
|
+
- Structured result and error objects.
|
|
49
|
+
- PDF rendering and QR scanning with ZBar.
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Juan Manuel Llaury
|
|
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
|
|
13
|
+
all 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
|
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,631 @@
|
|
|
1
|
+
# InvoiceExtractorArca
|
|
2
|
+
|
|
3
|
+
A Ruby gem for extracting structured data from Argentine ARCA electronic invoices.
|
|
4
|
+
|
|
5
|
+
The gem follows a **QR-first** approach:
|
|
6
|
+
|
|
7
|
+
1. Detect and decode the ARCA QR code from an image or PDF.
|
|
8
|
+
2. Validate and normalize the QR payload.
|
|
9
|
+
3. Return a structured result object.
|
|
10
|
+
4. Optionally extract text from PDFs or images.
|
|
11
|
+
5. Enrich the result with invoice fields and service rows.
|
|
12
|
+
6. Reconcile extracted text values against the authoritative QR payload.
|
|
13
|
+
|
|
14
|
+
## Features
|
|
15
|
+
|
|
16
|
+
- Extract ARCA invoice data from:
|
|
17
|
+
- PDF files
|
|
18
|
+
- PNG
|
|
19
|
+
- JPG / JPEG
|
|
20
|
+
- WEBP
|
|
21
|
+
- BMP
|
|
22
|
+
- TIFF
|
|
23
|
+
- QR-first extraction strategy
|
|
24
|
+
- ARCA payload validation
|
|
25
|
+
- Voucher normalization
|
|
26
|
+
- Currency validation
|
|
27
|
+
- Document type validation
|
|
28
|
+
- Multiple QR detection
|
|
29
|
+
- PDF text extraction
|
|
30
|
+
- Structured error reporting
|
|
31
|
+
- Strict and permissive modes
|
|
32
|
+
- Multiple QR scanner backends:
|
|
33
|
+
- zbarimg
|
|
34
|
+
- QReader (Python)
|
|
35
|
+
- Fallback chains
|
|
36
|
+
- PDF text extraction with `pdftotext`
|
|
37
|
+
- Image OCR enrichment with RapidOCR
|
|
38
|
+
- Regex-based invoice field enrichment
|
|
39
|
+
- Service-row extraction from invoice tables
|
|
40
|
+
- QR-to-text reconciliation
|
|
41
|
+
- Command-line interface with JSON output
|
|
42
|
+
- Configurable page selection and rendering resolution
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Installation
|
|
46
|
+
|
|
47
|
+
Add to your Gemfile:
|
|
48
|
+
|
|
49
|
+
```ruby
|
|
50
|
+
gem "invoice_extractor_arca"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
and run:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
bundle install
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Or install directly:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
gem install invoice_extractor_arca
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## External Dependencies
|
|
68
|
+
|
|
69
|
+
The gem relies on external tools:
|
|
70
|
+
|
|
71
|
+
### Required
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
pdftoppm
|
|
75
|
+
pdftotext
|
|
76
|
+
zbarimg
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Optional
|
|
80
|
+
|
|
81
|
+
For the QReader backend:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
python3
|
|
85
|
+
opencv-python
|
|
86
|
+
qreader
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
### OCR enrichment for images
|
|
92
|
+
|
|
93
|
+
Image enrichment uses RapidOCR through Python.
|
|
94
|
+
|
|
95
|
+
Install the optional OCR dependencies:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
python3 -m venv .venv-ocr
|
|
99
|
+
.venv-ocr/bin/pip install -r requirements-ocr.txt
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Pass the virtual-environment interpreter when using the Ruby API:
|
|
103
|
+
|
|
104
|
+
```ruby
|
|
105
|
+
result = InvoiceExtractorArca.extract_image(
|
|
106
|
+
"invoice.png",
|
|
107
|
+
dependency_paths: {
|
|
108
|
+
python3: ".venv-ocr/bin/python"
|
|
109
|
+
}
|
|
110
|
+
)
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Or with the command-line interface:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
arca-invoice-extract \
|
|
117
|
+
--dependency python3=.venv-ocr/bin/python \
|
|
118
|
+
invoice.png
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Verify Dependencies
|
|
122
|
+
|
|
123
|
+
```ruby
|
|
124
|
+
InvoiceExtractorArca.check_dependencies
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Example:
|
|
128
|
+
|
|
129
|
+
```ruby
|
|
130
|
+
{
|
|
131
|
+
pdftoppm: {
|
|
132
|
+
available: true,
|
|
133
|
+
path: "/usr/bin/pdftoppm"
|
|
134
|
+
},
|
|
135
|
+
pdftotext: {
|
|
136
|
+
available: true,
|
|
137
|
+
path: "/usr/bin/pdftotext"
|
|
138
|
+
},
|
|
139
|
+
zbarimg: {
|
|
140
|
+
available: true,
|
|
141
|
+
path: "/usr/bin/zbarimg"
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
To raise if dependencies are missing:
|
|
147
|
+
|
|
148
|
+
```ruby
|
|
149
|
+
InvoiceExtractorArca.check_dependencies!
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Basic Usage
|
|
155
|
+
|
|
156
|
+
### Extract from PDF
|
|
157
|
+
|
|
158
|
+
```ruby
|
|
159
|
+
result = InvoiceExtractorArca.extract("invoice.pdf")
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Extract from Image
|
|
163
|
+
|
|
164
|
+
```ruby
|
|
165
|
+
result = InvoiceExtractorArca.extract("invoice.jpg")
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### PDF-only API
|
|
169
|
+
|
|
170
|
+
```ruby
|
|
171
|
+
result = InvoiceExtractorArca.extract_pdf("invoice.pdf")
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Image-only API
|
|
175
|
+
|
|
176
|
+
```ruby
|
|
177
|
+
result = InvoiceExtractorArca.extract_image("invoice.png")
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## Successful Result
|
|
183
|
+
|
|
184
|
+
```ruby
|
|
185
|
+
result.success?
|
|
186
|
+
# => true
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Example:
|
|
190
|
+
|
|
191
|
+
```ruby
|
|
192
|
+
result.voucher[:normalized]
|
|
193
|
+
|
|
194
|
+
{
|
|
195
|
+
version: 1,
|
|
196
|
+
issued_on: "2024-06-30",
|
|
197
|
+
issuer_cuit: "30712345678",
|
|
198
|
+
point_of_sale: "00001",
|
|
199
|
+
voucher_type_code: "006",
|
|
200
|
+
voucher_type_description: "FACTURA B",
|
|
201
|
+
voucher_number: "00000123",
|
|
202
|
+
invoice_number: "00001-00000123",
|
|
203
|
+
amount: "1500.00",
|
|
204
|
+
currency_code: "PES",
|
|
205
|
+
currency_description: "PESOS"
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## Strict Mode
|
|
212
|
+
|
|
213
|
+
By default, the gem returns structured errors without raising exceptions.
|
|
214
|
+
|
|
215
|
+
```ruby
|
|
216
|
+
result = InvoiceExtractorArca.extract("invoice.pdf")
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Enable strict mode:
|
|
220
|
+
|
|
221
|
+
```ruby
|
|
222
|
+
InvoiceExtractorArca.extract(
|
|
223
|
+
"invoice.pdf",
|
|
224
|
+
strict: true
|
|
225
|
+
)
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Possible exceptions:
|
|
229
|
+
|
|
230
|
+
```ruby
|
|
231
|
+
InvoiceExtractorArca::Errors::UnreadableFile
|
|
232
|
+
InvoiceExtractorArca::Errors::QrNotFound
|
|
233
|
+
InvoiceExtractorArca::Errors::MultipleQrFound
|
|
234
|
+
InvoiceExtractorArca::Errors::InvalidVoucherSchema
|
|
235
|
+
InvoiceExtractorArca::Errors::MissingDependency
|
|
236
|
+
InvoiceExtractorArca::Errors::UnsupportedFileType
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## Configuring QR Scanners
|
|
242
|
+
|
|
243
|
+
### Default
|
|
244
|
+
|
|
245
|
+
```ruby
|
|
246
|
+
qr_scanner: :zbar_then_qreader
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### Available Options
|
|
250
|
+
|
|
251
|
+
```ruby
|
|
252
|
+
:zbar
|
|
253
|
+
:qreader
|
|
254
|
+
:zbar_then_qreader
|
|
255
|
+
:qreader_then_zbar
|
|
256
|
+
:all
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
Example:
|
|
260
|
+
|
|
261
|
+
```ruby
|
|
262
|
+
InvoiceExtractorArca.extract(
|
|
263
|
+
"invoice.pdf",
|
|
264
|
+
qr_scanner: :all
|
|
265
|
+
)
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
## Multiple QR Handling
|
|
271
|
+
|
|
272
|
+
Default:
|
|
273
|
+
|
|
274
|
+
```ruby
|
|
275
|
+
multiple_qr: :first_valid
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
Available options:
|
|
279
|
+
|
|
280
|
+
```ruby
|
|
281
|
+
:first_valid
|
|
282
|
+
:error
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
Example:
|
|
286
|
+
|
|
287
|
+
```ruby
|
|
288
|
+
InvoiceExtractorArca.extract(
|
|
289
|
+
"invoice.pdf",
|
|
290
|
+
multiple_qr: :error
|
|
291
|
+
)
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
When multiple distinct ARCA payloads are found:
|
|
295
|
+
|
|
296
|
+
```ruby
|
|
297
|
+
result.success?
|
|
298
|
+
# => false
|
|
299
|
+
|
|
300
|
+
result.errors
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
## PDF Processing Options
|
|
306
|
+
|
|
307
|
+
### Specific Page
|
|
308
|
+
|
|
309
|
+
```ruby
|
|
310
|
+
InvoiceExtractorArca.extract(
|
|
311
|
+
"invoice.pdf",
|
|
312
|
+
page_range: 3
|
|
313
|
+
)
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
### Page Range
|
|
317
|
+
|
|
318
|
+
```ruby
|
|
319
|
+
InvoiceExtractorArca.extract(
|
|
320
|
+
"invoice.pdf",
|
|
321
|
+
page_range: 1..5
|
|
322
|
+
)
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### Non-consecutive Pages
|
|
326
|
+
|
|
327
|
+
```ruby
|
|
328
|
+
InvoiceExtractorArca.extract(
|
|
329
|
+
"invoice.pdf",
|
|
330
|
+
page_range: [1, 3, 5]
|
|
331
|
+
)
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### Custom Resolution
|
|
335
|
+
|
|
336
|
+
```ruby
|
|
337
|
+
InvoiceExtractorArca.extract(
|
|
338
|
+
"invoice.pdf",
|
|
339
|
+
resolution: 400
|
|
340
|
+
)
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
---
|
|
344
|
+
|
|
345
|
+
## PDF Text Extraction
|
|
346
|
+
|
|
347
|
+
Text extraction is enabled by default.
|
|
348
|
+
|
|
349
|
+
```ruby
|
|
350
|
+
result.text
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
Example:
|
|
354
|
+
|
|
355
|
+
```ruby
|
|
356
|
+
{
|
|
357
|
+
extracted: true,
|
|
358
|
+
source: "pdftotext",
|
|
359
|
+
raw: "...",
|
|
360
|
+
normalized: "..."
|
|
361
|
+
}
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
Disable text extraction:
|
|
365
|
+
|
|
366
|
+
```ruby
|
|
367
|
+
InvoiceExtractorArca.extract(
|
|
368
|
+
"invoice.pdf",
|
|
369
|
+
enrichment: false
|
|
370
|
+
)
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
---
|
|
374
|
+
|
|
375
|
+
## Result Structure
|
|
376
|
+
|
|
377
|
+
```ruby
|
|
378
|
+
result.to_h
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
```ruby
|
|
382
|
+
{
|
|
383
|
+
source: {},
|
|
384
|
+
qr: {},
|
|
385
|
+
voucher: {},
|
|
386
|
+
text: {},
|
|
387
|
+
enrichment: {},
|
|
388
|
+
validation: {},
|
|
389
|
+
errors: [],
|
|
390
|
+
metadata: {}
|
|
391
|
+
}
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
---
|
|
395
|
+
|
|
396
|
+
## Invoice enrichment
|
|
397
|
+
|
|
398
|
+
When enrichment is enabled, the extractor attempts to identify additional invoice fields from PDF text or image OCR.
|
|
399
|
+
|
|
400
|
+
Examples include:
|
|
401
|
+
|
|
402
|
+
- Issuer and recipient information
|
|
403
|
+
- Invoice dates
|
|
404
|
+
- Payment method
|
|
405
|
+
- Subtotal, taxes, and total
|
|
406
|
+
- Authorization code and expiration date
|
|
407
|
+
- Product or service rows
|
|
408
|
+
|
|
409
|
+
Each extracted field includes metadata such as:
|
|
410
|
+
|
|
411
|
+
```ruby
|
|
412
|
+
{
|
|
413
|
+
raw: "611388,00",
|
|
414
|
+
normalized: "611388.00",
|
|
415
|
+
source: "pdf_text",
|
|
416
|
+
method: "label_regex",
|
|
417
|
+
confidence: "high"
|
|
418
|
+
}
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
Fields that cannot be identified are returned with a `nil` normalized value and a diagnostic warning.
|
|
422
|
+
|
|
423
|
+
## QR reconciliation
|
|
424
|
+
|
|
425
|
+
QR values are treated as the authoritative invoice values. Text and OCR values are compared against selected QR fields.
|
|
426
|
+
|
|
427
|
+
```ruby
|
|
428
|
+
result.validation
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
A comparison can have one of these statuses:
|
|
432
|
+
|
|
433
|
+
- `match`
|
|
434
|
+
- `mismatch`
|
|
435
|
+
- `not_extracted`
|
|
436
|
+
|
|
437
|
+
A mismatch produces a warning but does not overwrite the QR-derived voucher data.
|
|
438
|
+
|
|
439
|
+
## Error Handling
|
|
440
|
+
|
|
441
|
+
Example:
|
|
442
|
+
|
|
443
|
+
```ruby
|
|
444
|
+
unless result.success?
|
|
445
|
+
result.errors.each do |error|
|
|
446
|
+
puts "#{error.code}: #{error.message}"
|
|
447
|
+
end
|
|
448
|
+
end
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
---
|
|
452
|
+
|
|
453
|
+
## Supported ARCA Fields
|
|
454
|
+
|
|
455
|
+
The gem validates and normalizes:
|
|
456
|
+
|
|
457
|
+
- ver
|
|
458
|
+
- fecha
|
|
459
|
+
- cuit
|
|
460
|
+
- ptoVta
|
|
461
|
+
- tipoCmp
|
|
462
|
+
- nroCmp
|
|
463
|
+
- importe
|
|
464
|
+
- moneda
|
|
465
|
+
- ctz
|
|
466
|
+
- tipoDocRec
|
|
467
|
+
- nroDocRec
|
|
468
|
+
- tipoCodAut
|
|
469
|
+
- codAut
|
|
470
|
+
|
|
471
|
+
It also validates against built-in ARCA catalogs for:
|
|
472
|
+
|
|
473
|
+
- Voucher types
|
|
474
|
+
- Currencies
|
|
475
|
+
- Recipient document types
|
|
476
|
+
|
|
477
|
+
---
|
|
478
|
+
|
|
479
|
+
## Command-line interface
|
|
480
|
+
|
|
481
|
+
The gem installs the `arca-invoice-extract` executable.
|
|
482
|
+
|
|
483
|
+
### Basic extraction
|
|
484
|
+
|
|
485
|
+
```bash
|
|
486
|
+
arca-invoice-extract invoice.pdf
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
The command writes the complete extraction result as JSON to standard output.
|
|
490
|
+
|
|
491
|
+
### Pretty JSON output
|
|
492
|
+
|
|
493
|
+
```bash
|
|
494
|
+
arca-invoice-extract --pretty invoice.pdf
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
### Disable text and OCR enrichment
|
|
498
|
+
|
|
499
|
+
```bash
|
|
500
|
+
arca-invoice-extract --no-enrichment invoice.pdf
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
### Strict mode
|
|
504
|
+
|
|
505
|
+
```bash
|
|
506
|
+
arca-invoice-extract --strict invoice.pdf
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
Strict mode raises known extraction errors instead of returning them in the result.
|
|
510
|
+
|
|
511
|
+
### Select one PDF page
|
|
512
|
+
|
|
513
|
+
```bash
|
|
514
|
+
arca-invoice-extract --page 2 invoice.pdf
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
### Select a PDF page range
|
|
518
|
+
|
|
519
|
+
```bash
|
|
520
|
+
arca-invoice-extract --pages 2-5 invoice.pdf
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
Page numbers must be positive, and the first page must not be greater than the last page.
|
|
524
|
+
|
|
525
|
+
### Set PDF rendering resolution
|
|
526
|
+
|
|
527
|
+
```bash
|
|
528
|
+
arca-invoice-extract --resolution 400 invoice.pdf
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
The default resolution is 300 DPI.
|
|
532
|
+
|
|
533
|
+
### Select a QR scanner
|
|
534
|
+
|
|
535
|
+
```bash
|
|
536
|
+
arca-invoice-extract --qr-scanner zbar invoice.pdf
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
Available values:
|
|
540
|
+
|
|
541
|
+
- `zbar`
|
|
542
|
+
- `qreader`
|
|
543
|
+
- `zbar_then_qreader`
|
|
544
|
+
- `qreader_then_zbar`
|
|
545
|
+
- `all`
|
|
546
|
+
|
|
547
|
+
### Handle multiple QR payloads
|
|
548
|
+
|
|
549
|
+
Use the first valid payload:
|
|
550
|
+
|
|
551
|
+
```bash
|
|
552
|
+
arca-invoice-extract --multiple-qr first_valid invoice.pdf
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
Return an extraction failure when multiple distinct payloads are found:
|
|
556
|
+
|
|
557
|
+
```bash
|
|
558
|
+
arca-invoice-extract --multiple-qr error invoice.pdf
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
### Configure dependency paths
|
|
562
|
+
|
|
563
|
+
The option may be repeated:
|
|
564
|
+
|
|
565
|
+
```bash
|
|
566
|
+
arca-invoice-extract \
|
|
567
|
+
--dependency pdftoppm=/usr/local/bin/pdftoppm \
|
|
568
|
+
--dependency pdftotext=/usr/local/bin/pdftotext \
|
|
569
|
+
--dependency zbarimg=/usr/local/bin/zbarimg \
|
|
570
|
+
invoice.pdf
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
### Display help
|
|
574
|
+
|
|
575
|
+
```bash
|
|
576
|
+
arca-invoice-extract --help
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
### Exit codes
|
|
580
|
+
|
|
581
|
+
| Exit code | Meaning |
|
|
582
|
+
|---:|---|
|
|
583
|
+
| `0` | Extraction succeeded |
|
|
584
|
+
| `1` | Extraction failed or a known extraction error was raised |
|
|
585
|
+
| `2` | Invalid command-line arguments |
|
|
586
|
+
| `3` | Runtime or operating-system error |
|
|
587
|
+
|
|
588
|
+
Extraction results are written to standard output. CLI usage errors and raised exceptions are written to standard error.
|
|
589
|
+
|
|
590
|
+
## Development
|
|
591
|
+
|
|
592
|
+
Install dependencies:
|
|
593
|
+
|
|
594
|
+
```bash
|
|
595
|
+
bin/setup
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
Run tests:
|
|
599
|
+
|
|
600
|
+
```bash
|
|
601
|
+
rake test
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
Run linting:
|
|
605
|
+
|
|
606
|
+
```bash
|
|
607
|
+
bundle exec standardrb
|
|
608
|
+
```
|
|
609
|
+
|
|
610
|
+
Run all checks:
|
|
611
|
+
|
|
612
|
+
```bash
|
|
613
|
+
rake
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
---
|
|
617
|
+
|
|
618
|
+
## Roadmap
|
|
619
|
+
|
|
620
|
+
Planned improvements:
|
|
621
|
+
|
|
622
|
+
- Broader integration coverage across different ARCA invoice layouts
|
|
623
|
+
- Synthetic and privacy-safe invoice fixtures
|
|
624
|
+
- Improved OCR and table-parsing resilience
|
|
625
|
+
- Expanded RBS type definitions
|
|
626
|
+
|
|
627
|
+
---
|
|
628
|
+
|
|
629
|
+
## License
|
|
630
|
+
|
|
631
|
+
Released under the MIT License.
|