feat: Diagnose-Skript für fehlende Schlagwörter
Die Kategorie-Liste zeigt nur manuelle, einer bestehenden Kategorie zugeordnete Regeln. Bleibt sie leer, obwohl Regeln in der Datenbank stehen, sagt das Skript warum: Es schlüsselt den Bestand nach source, kind und is_transfer auf, zählt Regeln ohne Kategorie sowie solche, deren Kategorie nicht mehr existiert, und nennt die Zahl der tatsächlich sichtbaren. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Executable
+66
@@ -0,0 +1,66 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Zeigt, warum Schlagwörter in der Oberfläche fehlen könnten.
|
||||
|
||||
Die Liste einer Kategorie zeigt nur Regeln mit ``source='manual'``, die einer
|
||||
Kategorie zugeordnet und keine Transfer-Regel sind. Automatisch gelernte Regeln
|
||||
tauchen dort bewusst nicht auf. Dieses Skript schlüsselt den Bestand danach auf.
|
||||
|
||||
Aufruf: pruefe_schlagwoerter.py [pfad/zur/app.db]
|
||||
"""
|
||||
import sqlite3
|
||||
import sys
|
||||
from collections import Counter
|
||||
|
||||
DB = sys.argv[1] if len(sys.argv) > 1 else "/var/lib/certain-finance/app.db"
|
||||
con = sqlite3.connect(f"file:{DB}?mode=ro", uri=True)
|
||||
con.row_factory = sqlite3.Row
|
||||
|
||||
|
||||
def spalten(tabelle: str) -> set[str]:
|
||||
return {r["name"] for r in con.execute(f"PRAGMA table_info({tabelle})")}
|
||||
|
||||
|
||||
vorhanden = spalten("categorization_rules")
|
||||
print(f"Datenbank: {DB}")
|
||||
print(f"Spalten in categorization_rules: {', '.join(sorted(vorhanden))}\n")
|
||||
|
||||
gesamt = con.execute("SELECT COUNT(*) FROM categorization_rules").fetchone()[0]
|
||||
print(f"Regeln insgesamt: {gesamt}")
|
||||
|
||||
for feld in ("source", "kind", "is_transfer", "match_field"):
|
||||
if feld not in vorhanden:
|
||||
print(f" {feld:<12} – Spalte fehlt")
|
||||
continue
|
||||
verteilung = Counter(
|
||||
r[0] for r in con.execute(f"SELECT {feld} FROM categorization_rules")
|
||||
)
|
||||
print(f" {feld:<12} {dict(verteilung)}")
|
||||
|
||||
ohne_kat = con.execute(
|
||||
"SELECT COUNT(*) FROM categorization_rules WHERE category_id IS NULL"
|
||||
).fetchone()[0]
|
||||
verwaist = con.execute(
|
||||
"SELECT COUNT(*) FROM categorization_rules r WHERE r.category_id IS NOT NULL"
|
||||
" AND NOT EXISTS (SELECT 1 FROM categories c WHERE c.id = r.category_id)"
|
||||
).fetchone()[0]
|
||||
print(f" ohne Kategorie: {ohne_kat}")
|
||||
print(f" Kategorie zeigt ins Leere: {verwaist} <-- solche erscheinen nirgends")
|
||||
|
||||
# Genau die Bedingung, die die Oberfläche für die Kategorie-Liste nutzt.
|
||||
sichtbar = con.execute(
|
||||
"SELECT COUNT(*) FROM categorization_rules r"
|
||||
" JOIN categories c ON c.id = r.category_id"
|
||||
" WHERE r.source = 'manual' AND r.is_transfer = 0"
|
||||
).fetchone()[0]
|
||||
print(f"\nIn der Kategorie-Liste sichtbar: {sichtbar} von {gesamt}")
|
||||
|
||||
print("\nBeispiele (die ersten 12):")
|
||||
print(f" {'Muster':<26}{'source':<10}{'kind':<10}{'transfer':<9}{'Kategorie'}")
|
||||
for r in con.execute(
|
||||
"SELECT r.pattern, r.source, r.kind, r.is_transfer, c.name AS kat"
|
||||
" FROM categorization_rules r LEFT JOIN categories c ON c.id = r.category_id"
|
||||
" ORDER BY r.id LIMIT 12"
|
||||
):
|
||||
print(f" {r['pattern'][:24]:<26}{str(r['source']):<10}{str(r['kind']):<10}"
|
||||
f"{str(r['is_transfer']):<9}{r['kat'] or '— fehlt —'}")
|
||||
con.close()
|
||||
Reference in New Issue
Block a user