Steuerkram/tests/11_KontierungsvorschlagTest.php

74 lines
3.2 KiB
PHP

<?php
declare(strict_types=1);
use Steuerkram\Database;
use Steuerkram\Models\Beleg;
use Steuerkram\Services\KontierungsvorschlagService;
class KontierungsvorschlagTest extends TestCase
{
protected string $testName = 'Test 11: KI-Kontierungsvorschlag';
public function run(): void
{
// 1. Einstellung deaktiviert → isEnabled() muss false zurückgeben
Database::execute('UPDATE company_settings SET ki_vorschlag_aktiv = 0');
$svc = new KontierungsvorschlagService();
$this->assert(!$svc->isEnabled(), 'ki_vorschlag_aktiv sollte per Default 0 sein');
// 2. saveKiVorschlag speichert und liest korrekt zurück
$belegId = $this->createTestBeleg();
$vorschlag = [
'buchungstyp' => 'Ausgabe',
'kategorie_konto_id' => 42,
'zahlungskonto_id' => 10,
'ust_satz' => 19,
'betrag_netto' => 33.64,
'buchungstext' => 'Testrechnung',
];
Beleg::saveKiVorschlag($belegId, $vorschlag);
$beleg = Beleg::find($belegId);
$this->assertNotEmpty($beleg['ki_vorschlag'], 'ki_vorschlag sollte gespeichert sein');
$this->assertNotEmpty($beleg['ki_vorschlag_at'], 'ki_vorschlag_at sollte gesetzt sein');
$decoded = json_decode($beleg['ki_vorschlag'], true);
$this->assertEquals('Ausgabe', $decoded['buchungstyp'], 'buchungstyp korrekt gespeichert');
$this->assertEquals(19, $decoded['ust_satz'], 'ust_satz korrekt gespeichert');
$this->assertEquals(33.64, $decoded['betrag_netto'], 'betrag_netto korrekt gespeichert');
// 3. saveKiVorschlag(null) löscht den Vorschlag
Beleg::saveKiVorschlag($belegId, null);
$beleg = Beleg::find($belegId);
$this->assert($beleg['ki_vorschlag'] === null, 'ki_vorschlag sollte nach Reset null sein');
// 4. JSON-Extraktion: Prosa vor JSON wird korrekt extrahiert
$this->testJsonExtraktion();
}
private function createTestBeleg(): int
{
Database::execute(
"INSERT INTO belege (beleg_nr, filename, storage_path, mime_type, file_hash, belegtyp)
VALUES ('TEST-KI-0001', 'test.pdf', 'static/uploads/test/test.pdf', 'application/pdf',
SHA2('test', 256), 'Eingangsrechnung')"
);
return (int)Database::lastInsertId();
}
private function testJsonExtraktion(): void
{
// Simuliert die Regex-Extraktion aus einer LLM-Antwort mit vorangehendem Text
$antwort = "Hier ist mein Kontierungsvorschlag:\n{\"buchungstyp\":\"Ausgabe\",\"kategorie_konto_id\":5,\"zahlungskonto_id\":2,\"ust_satz\":19,\"betrag_netto\":100.00,\"buchungstext\":\"Test\"}";
preg_match('/\{[^{}]*\}/s', $antwort, $m);
$data = json_decode($m[0] ?? '{}', true);
$this->assertEquals('Ausgabe', $data['buchungstyp'] ?? '', 'JSON-Extraktion aus LLM-Antwort mit Prosa');
$this->assertEquals(19, $data['ust_satz'] ?? -1, 'ust_satz aus extrahiertem JSON');
// Antwort ohne JSON
preg_match('/\{[^{}]*\}/s', 'Keine Angabe möglich.', $m2);
$this->assert(empty($m2), 'Keine JSON-Extraktion ohne JSON-Block');
}
}