Feature: Extrahierten Belegtext in beleg_text speichern (Migration 021)

This commit is contained in:
fds2610-bot 2026-04-10 16:36:29 +02:00
parent fa50de5c48
commit f737aff212
4 changed files with 43 additions and 6 deletions

View file

@ -2,6 +2,16 @@
--- ---
## 2026-04-10 – Belegtext-Speicherung für spätere Volltextsuche
### Neu
- Migration 021: Spalte `beleg_text MEDIUMTEXT` in `belege` – speichert den per `pdftotext` oder Tesseract-OCR extrahierten Volltext
- `KontierungsvorschlagService::extractText()`: neue public Methode zur Textextraktion (PDF + Bild), unabhängig vom KI-Vorschlag nutzbar
- Beim Generieren des KI-Vorschlags wird `beleg_text` automatisch befüllt (einmalig, nur wenn noch leer)
- `Beleg::saveBelegText()`: neue Methode im Model
---
## 2026-04-10 – OCR-Schalter unabhängig vom KI-Schalter ## 2026-04-10 – OCR-Schalter unabhängig vom KI-Schalter
### Neu ### Neu

View file

@ -0,0 +1,4 @@
-- Migration 021: Extrahierter Belegtext als durchsuchbares Metafeld
ALTER TABLE belege
ADD COLUMN IF NOT EXISTS beleg_text MEDIUMTEXT NULL
COMMENT 'Per pdftotext oder OCR extrahierter Volltext des Belegs (für Suche)';

View file

@ -218,6 +218,14 @@ class Beleg
); );
} }
public static function saveBelegText(int $id, string $text): void
{
Database::execute(
'UPDATE belege SET beleg_text = ? WHERE id = ?',
[$text !== '' ? $text : null, $id]
);
}
public static function verifyIntegrity(int $id): bool public static function verifyIntegrity(int $id): bool
{ {
$beleg = self::find($id); $beleg = self::find($id);

View file

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Steuerkram\Services; namespace Steuerkram\Services;
use Steuerkram\Models\Account; use Steuerkram\Models\Account;
use Steuerkram\Models\Beleg;
use Steuerkram\Models\Setting; use Steuerkram\Models\Setting;
use Steuerkram\Models\Supplier; use Steuerkram\Models\Supplier;
@ -29,19 +30,33 @@ class KontierungsvorschlagService
return (bool)($s['ocr_aktiv'] ?? 1); return (bool)($s['ocr_aktiv'] ?? 1);
} }
public function generateForBeleg(array $beleg): ?array public function extractText(array $beleg): string
{ {
$absPath = dirname(__DIR__, 2) . '/public/' . $beleg['storage_path']; $absPath = dirname(__DIR__, 2) . '/public/' . $beleg['storage_path'];
if (!file_exists($absPath)) return null; if (!file_exists($absPath)) return '';
// Inhalt extrahieren
$mime = strtolower($beleg['mime_type'] ?? ''); $mime = strtolower($beleg['mime_type'] ?? '');
if ($mime === 'application/pdf') { if ($mime === 'application/pdf') {
$text = $this->extractPdfText($absPath); return $this->extractPdfText($absPath);
} elseif (in_array($mime, ['image/jpeg', 'image/png', 'image/tiff'], true)) { } elseif (in_array($mime, ['image/jpeg', 'image/png', 'image/tiff'], true)) {
$text = $this->isOcrEnabled() ? $this->extractImageText($absPath) : ''; return $this->isOcrEnabled() ? $this->extractImageText($absPath) : '';
} else { }
return '';
}
public function generateForBeleg(array $beleg): ?array
{
$text = $this->extractText($beleg);
// Extrahierten Text dauerhaft am Beleg speichern (für spätere Suche)
if ($text !== '' && $beleg['beleg_text'] === null) {
Beleg::saveBelegText((int)$beleg['id'], $text);
}
$mime = strtolower($beleg['mime_type'] ?? '');
if (!in_array($mime, ['application/pdf', 'image/jpeg', 'image/png', 'image/tiff'], true)) {
return null; return null;
} }