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>
67 lines
2.5 KiB
Python
Executable File
67 lines
2.5 KiB
Python
Executable File
#!/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()
|