Fix #55: Verbindungsfehler-Fallback – kein Retry-Loop, spezifische Fehlermeldung
This commit is contained in:
parent
54f7d9bd38
commit
1a23b3e11d
4 changed files with 78 additions and 2 deletions
|
|
@ -8,6 +8,8 @@
|
|||
- **`LlmService`:** `probeOllama()` schreibt bei cURL-Fehlern jetzt einen Eintrag ins PHP-Fehlerlog (`docker compose logs web`)
|
||||
- **Einstellungsseite:** Neuer Button „Verbindung testen" im KI-Abschnitt; zeigt bei Erfolg verfügbare Modelle, bei Fehler cURL-Fehler, URL und Firewall-Hinweis an
|
||||
- **Route:** `POST /settings/llm-test` → `SettingsController::llmTest()`
|
||||
- **`BelegController`:** Bei Verbindungsfehler wird jetzt `[]` statt `null` gespeichert (verhindert endlose Auto-Retry-Schleife); Fehlermeldung differenziert zwischen „Ollama nicht erreichbar" und „kein Vorschlag generiert"
|
||||
- **Beleg-Detailseite:** Zeigt bei Verbindungsfehler spezifische Meldung „Ollama nicht erreichbar" mit Link zu den Einstellungen statt der generischen Warnung
|
||||
|
||||
## 2026-06-01 – Fix: EN16931-Validierungsfehler in ZUGFeRD-Rechnungen
|
||||
|
||||
|
|
|
|||
|
|
@ -378,8 +378,17 @@ class BelegController extends BaseController
|
|||
|
||||
$svc = new KontierungsvorschlagService();
|
||||
$vorschlag = $svc->generateForBeleg($beleg);
|
||||
Beleg::saveKiVorschlag($id, $vorschlag);
|
||||
echo json_encode($vorschlag ?? ['error' => 'Kein Vorschlag generiert']);
|
||||
// [] = "verarbeitet, kein Ergebnis"; null würde endlose Auto-Retry-Schleife auslösen
|
||||
Beleg::saveKiVorschlag($id, $vorschlag ?? []);
|
||||
if ($vorschlag === null) {
|
||||
$llm = new \Steuerkram\Services\LlmService();
|
||||
echo json_encode($llm->isReachable()
|
||||
? ['error' => 'Kein Vorschlag generiert']
|
||||
: ['connection_error' => true]
|
||||
);
|
||||
return;
|
||||
}
|
||||
echo json_encode($vorschlag);
|
||||
}
|
||||
|
||||
public function resetVorschlag(array $params): void
|
||||
|
|
|
|||
|
|
@ -1101,6 +1101,16 @@ function _showKiBadgeError() {
|
|||
'<button class="btn btn-secondary btn-sm" onclick="_startKiAnalyse()">Erneut versuchen</button></div>';
|
||||
}
|
||||
|
||||
function _showKiBadgeConnectionError() {
|
||||
const neuBtn = _kiAktiv
|
||||
? ' <button class="btn btn-secondary btn-sm" onclick="_startKiAnalyse()">Erneut versuchen</button>'
|
||||
: '';
|
||||
document.getElementById('ki-badge').innerHTML =
|
||||
'<div class="flash flash-warning">Ollama nicht erreichbar.' + neuBtn +
|
||||
' <a href="/settings" style="color:inherit;text-decoration:underline">Einstellungen / Verbindung testen</a>' +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
// Normalisiert _kiVorschlag zu einem Array (Objekt oder Array aus DB möglich).
|
||||
// Gibt null zurück wenn kein Ergebnis vorhanden.
|
||||
// Gibt leeres Array [] zurück wenn verarbeitet aber kein Ergebnis erzeugt.
|
||||
|
|
@ -1119,6 +1129,7 @@ async function _startKiAnalyse() {
|
|||
try {
|
||||
const r = await fetch('/belege/' + _belegId + '/vorschlag/generate', {method: 'POST'});
|
||||
const raw = await r.json();
|
||||
if (raw && raw.connection_error) { _showKiBadgeConnectionError(); return; }
|
||||
const arr = _normalizeKiArr(raw);
|
||||
if (arr && arr.length > 0) { _applyKiVorschlag(arr[0]); _showKiBadgeDone(arr); }
|
||||
else _showKiBadgeNoResult();
|
||||
|
|
|
|||
54
tests/43_KiConnectionFallbackTest.php
Normal file
54
tests/43_KiConnectionFallbackTest.php
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Steuerkram\Database;
|
||||
use Steuerkram\Models\Beleg;
|
||||
|
||||
class KiConnectionFallbackTest extends TestCase
|
||||
{
|
||||
protected string $testName = 'Test 43: KI-Verbindungsfehler-Fallback';
|
||||
|
||||
public function run(): void
|
||||
{
|
||||
$belegId = $this->createTestBeleg();
|
||||
|
||||
// [] = "verarbeitet, kein Ergebnis" – verhindert endlose Auto-Retry-Schleife
|
||||
Beleg::saveKiVorschlag($belegId, []);
|
||||
$beleg = Beleg::find($belegId);
|
||||
$this->assertNotEmpty($beleg['ki_vorschlag'], 'Leeres Array muss als JSON gespeichert werden, nicht als SQL NULL');
|
||||
|
||||
$decoded = json_decode($beleg['ki_vorschlag'], true);
|
||||
$this->assert(is_array($decoded) && count($decoded) === 0, 'Gespeicherter Wert muss leeres Array sein');
|
||||
|
||||
// null = "noch nicht verarbeitet" – löst Auto-Retry auf der Beleg-Seite aus
|
||||
Beleg::saveKiVorschlag($belegId, null);
|
||||
$beleg = Beleg::find($belegId);
|
||||
$this->assert($beleg['ki_vorschlag'] === null, 'saveKiVorschlag(null) muss SQL NULL ergeben');
|
||||
|
||||
// Nicht-leeres Array wird korrekt gespeichert und zurückgelesen
|
||||
$vorschlag = [[
|
||||
'buchungstyp' => 'Ausgabe',
|
||||
'kategorie_konto_id' => 5,
|
||||
'zahlungskonto_id' => 2,
|
||||
'ust_satz' => 19,
|
||||
'betrag_netto' => 99.00,
|
||||
'buchungstext' => 'Fallback-Test',
|
||||
]];
|
||||
Beleg::saveKiVorschlag($belegId, $vorschlag);
|
||||
$beleg = Beleg::find($belegId);
|
||||
$decoded = json_decode($beleg['ki_vorschlag'], true);
|
||||
$this->assert(is_array($decoded) && count($decoded) === 1, 'Vorschlag-Array korrekt gespeichert');
|
||||
$this->assertEquals('Ausgabe', $decoded[0]['buchungstyp'], 'buchungstyp korrekt');
|
||||
}
|
||||
|
||||
private function createTestBeleg(): int
|
||||
{
|
||||
Database::execute(
|
||||
"INSERT INTO belege (beleg_nr, filename, storage_path, mime_type, file_hash, belegtyp)
|
||||
VALUES ('TEST-KI-FALLBACK-001', 'test.pdf', 'static/uploads/test/test.pdf', 'application/pdf',
|
||||
SHA2('fallback-test', 256), 'Eingangsrechnung')"
|
||||
);
|
||||
return (int)Database::lastInsertId();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue