Steuerkram/scripts/ki-batch.php

104 lines
3.2 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* KI-Kontierungsvorschlag – Batch-Verarbeitung (CLI-Einstiegspunkt).
*
* Verarbeitet EINEN ausstehenden Beleg pro Aufruf (ki_vorschlag IS NULL, locked = 0).
* Verhindert so, dass mehrere Vision-Model-Anfragen parallel an Ollama geschickt werden.
*
* Voraussetzung: ki_vorschlag_aktiv = 1 in den Einstellungen, Ollama erreichbar.
*
* Aufruf:
* docker compose exec web php scripts/ki-batch.php
*
* Für optionalen eigenen Cronjob (manuelle Uploads ohne Nextcloud):
* *\/5 * * * * docker compose -f /opt/steuerkram/docker-compose.yml exec -T web \
* php scripts/ki-batch.php >> /var/log/steuerkram-ki.log 2>&1
*/
declare(strict_types=1);
chdir(dirname(__DIR__));
// DB-Zugangsdaten aus .env laden (für CLI-Kontext ohne Apache-Umgebung)
if (file_exists('.env')) {
foreach (file('.env', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) as $line) {
if (str_starts_with(trim($line), '#') || !str_contains($line, '=')) {
continue;
}
[$key, $value] = explode('=', $line, 2);
$key = trim($key);
$value = trim($value, " \t\n\r\0\x0B\"'");
if (!array_key_exists($key, $_ENV)) {
$_ENV[$key] = $value;
putenv("{$key}={$value}");
}
}
}
require_once 'vendor/autoload.php';
use Steuerkram\Config;
use Steuerkram\Database;
use Steuerkram\Models\Beleg;
use Steuerkram\Models\Setting;
use Steuerkram\Services\KontierungsvorschlagService;
Config::load();
$tag = '[ki-batch]';
// KI-Erkennung in den Einstellungen aktiv?
$settings = Setting::get();
if (empty($settings['ki_vorschlag_aktiv'])) {
echo "{$tag} KI-Erkennung ist in den Einstellungen deaktiviert – nichts zu tun." . PHP_EOL;
exit(0);
}
$svc = new KontierungsvorschlagService();
if (!$svc->isEnabled()) {
echo "{$tag} LLM nicht erreichbar – Abbruch." . PHP_EOL;
exit(1);
}
// Optionale Beleg-ID als CLI-Argument: php ki-batch.php 123
$argId = isset($argv[1]) && ctype_digit((string)$argv[1]) ? (int)$argv[1] : null;
// Beleg holen: wenn ID angegeben, diesen direkt verarbeiten; sonst ältesten ausstehenden
$row = $argId !== null
? Database::fetchOne('SELECT id FROM belege WHERE id = ? AND ki_vorschlag IS NULL AND locked = 0', [$argId])
: Database::fetchOne('SELECT id FROM belege WHERE ki_vorschlag IS NULL AND locked = 0 ORDER BY id ASC LIMIT 1');
if (!$row) {
echo "{$tag} Kein ausstehender Beleg gefunden." . PHP_EOL;
exit(0);
}
$belegId = (int)$row['id'];
$beleg = Beleg::find($belegId);
if (!$beleg) {
echo "{$tag} Beleg #{$belegId} nicht ladbar – Abbruch." . PHP_EOL;
exit(1);
}
echo "{$tag} Verarbeite Beleg #{$belegId} ({$beleg['beleg_nr']}) ..." . PHP_EOL;
$start = microtime(true);
$result = $svc->generateForBeleg($beleg);
if ($result === null) {
echo "{$tag} Beleg #{$belegId}: Kein Vorschlag generiert (nicht unterstützter Typ oder LLM-Fehler)." . PHP_EOL;
// Leeres Array speichern damit der Beleg nicht erneut verarbeitet wird
Beleg::saveKiVorschlag($belegId, []);
exit(0);
}
Beleg::saveKiVorschlag($belegId, $result);
$elapsed = round(microtime(true) - $start, 1);
$zeilen = count($result);
echo "{$tag} Beleg #{$belegId}: {$zeilen} Buchungszeile(n) generiert in {$elapsed}s." . PHP_EOL;
exit(0);