The invoice scanning module lets admins upload a supplier invoice (PDF or image) and have Ferromax ERP automatically extract product codes, quantities, and unit prices using OCR — eliminating manual data entry for high-volume stock ingestion. The module is accessible atDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/DragonesMagicos/ferromax_v0.8/llms.txt
Use this file to discover all available pages before exploring further.
/ingreso-factura and is restricted to the ADMIN role.
How It Works
Navigate to the invoice upload page
The admin opens
/ingreso-factura. The page displays a drag-and-drop upload zone (ZonaDrop component) alongside three feature tiles explaining the supported input types: digital PDF, scanned photo, and automatic line-item detection.Upload a PDF or image file
The admin drags a file onto the drop zone or clicks it to open the file picker. Accepted types are
application/pdf, image/jpeg, image/png, and image/webp. Files larger than 20 MB are rejected client-side before any network request is made.Frontend calls the analysis endpoint
On file selection, The multipart field name for the file is
IngresoFacturaPage.jsx calls facturaService.analizar(file), which sends:archivo.While the backend processes the document, the UI switches to an “Analizando factura con IA…” loading state with a spinner and the filename.Backend extracts text from the document
FacturaService.analizarFactura() branches on content type:application/pdf— Apache PDFBox (Loader.loadPDF+PDFTextStripper) extracts raw text with positional sorting enabled. This path is fast and highly accurate for digitally generated PDFs.- Image files (
image/jpeg,image/png, etc.) — The image is base64-encoded and submitted to the OCR.space API (https://api.ocr.space/parse/image) withlanguage=spa,isTable=true, andOCREngine=2for best photo accuracy. The extractedParsedTextis then parsed character-by-character to handle JSON escaping correctly without regex backtracking issues.
Line items are parsed and returned
The extracted text is parsed by Each
FacturaService.parsearTexto() using token-based analysis (not complex regex) to identify:- Supplier name — the first non-date, non-header line near the top of the document
- Invoice number — matched against patterns like
0001-00012345orFactura N° ... - Line items — each row is parsed for a product code (short alphanumeric token), quantity (integer), description, and unit price (Argentine decimal format:
1.234,56)
- Exact SKU match (
codigoSku↔producto.sku) - Keyword match across the item description against
producto.nombre
FacturaIngreso draft with status BORRADOR and returned as FacturaAnalisisResponse:ItemFacturaDTO carries descripcion, codigoSku, cantidad, precioUnitario, and — if matched — productoId and productoNombre.Admin reviews and edits extracted items
The UI enters the revision stage, showing an editable table (
TablaItems component). Every cell in the table is directly editable — description, SKU, quantity, and unit price can all be corrected inline. A BadgeMatch indicator on each row shows whether the item was automatically linked (green), linked by code only (blue), or unmatched (amber).Items without a product link show a Vincular dropdown that searches the product catalog by name or SKU and assigns the match. Only linked items are included in the final confirmation payload. The panel also shows running counts of total items, linked items, and unlinked items.Admin confirms the ingestion
When satisfied, the admin clicks Confirmar ingreso. The frontend sends:Items with neither
FacturaConfirmarRequest body:productoId nor codigoSku are silently skipped.Stock is updated and the draft is confirmed
For each confirmed item,
FacturaService.confirmarIngreso() calls RecepcionService.recibirMercaderia() internally, which increases stockActual on the product, creates a MovimientoStock record, and triggers a low-stock alert check. The FacturaIngreso record is updated from BORRADOR to CONFIRMADA with a confirmadoAt timestamp. The response is a List<RecepcionResponse> showing before/after stock for each product.Supported File Types
| Format | Extraction method | Notes |
|---|---|---|
| PDF (text-based) | Apache PDFBox | Highest accuracy; recommended for supplier-generated digital invoices |
| PDF (scanned image) | PDFBox text extraction may return empty; consider uploading the page as an image instead | — |
| JPEG / JPG | OCR.space API (Engine 2, Spanish) | Accuracy depends on print quality and image resolution |
| PNG | OCR.space API (Engine 2, Spanish) | Same as JPEG |
| WEBP | OCR.space API (Engine 2, Spanish) | Same as JPEG |
File Size Limit
The maximum upload size is 20 MB per file. This is enforced both client-side (inZonaDrop) and by the Spring Boot multipart configuration:
application.properties if your supplier invoices routinely exceed this limit.
OCR Configuration
Image-based extraction uses the OCR.space cloud API. The API key is configured inapplication.properties and injected into FacturaService via @Value:
| Parameter | Value | Reason |
|---|---|---|
language | spa | Spanish invoice text |
isTable | true | Improves column alignment detection |
OCREngine | 2 | Better performance on photographs |
Invoice History
Past invoice ingestions are listed on the upload page (/ingreso-factura) whenever no active upload session is in progress. History is fetched with pagination:
FacturaIngresoResumenDTO entry in content includes: id, numeroFactura, proveedorNombre, archivoNombre, cantidadItems, estado (BORRADOR | CONFIRMADA | CANCELADA), and createdAt.