Debug: Purge-Details im Alert anzeigen (Status-Breakdown pro Collection)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
30
app.py
30
app.py
@@ -1313,6 +1313,7 @@ def purge_all_orphans():
|
|||||||
"""
|
"""
|
||||||
token = request.headers.get("Authorization", "")
|
token = request.headers.get("Authorization", "")
|
||||||
removed = 0
|
removed = 0
|
||||||
|
details = []
|
||||||
|
|
||||||
for junc_col, fk_field, item_col in [
|
for junc_col, fk_field, item_col in [
|
||||||
("questions_objects", "questions_id", "questions"),
|
("questions_objects", "questions_id", "questions"),
|
||||||
@@ -1322,16 +1323,21 @@ def purge_all_orphans():
|
|||||||
f"/items/{junc_col}?fields=id,{fk_field}&limit=10000", token)
|
f"/items/{junc_col}?fields=id,{fk_field}&limit=10000", token)
|
||||||
rows = junc_data.get("data") or []
|
rows = junc_data.get("data") or []
|
||||||
|
|
||||||
# collect all unique FK values
|
|
||||||
fk_ids = list({row[fk_field] for row in rows if row.get(fk_field)})
|
fk_ids = list({row[fk_field] for row in rows if row.get(fk_field)})
|
||||||
if not fk_ids:
|
if not fk_ids:
|
||||||
|
details.append({"collection": junc_col, "junction_rows": 0, "existing": 0, "orphans": 0})
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# fetch which IDs still exist AND are not archived
|
# fetch existing AND check all statuses (fetch without status filter first)
|
||||||
ids_param = ",".join(fk_ids)
|
ids_param = urllib.parse.quote(",".join(fk_ids), safe="")
|
||||||
existing_data, _ = _directus("GET",
|
all_data, _ = _directus("GET",
|
||||||
f"/items/{item_col}?filter[id][_in]={ids_param}&filter[status][_neq]=archived&fields=id&limit=10000", token)
|
f"/items/{item_col}?filter[id][_in]={ids_param}&fields=id,status&limit=10000", token)
|
||||||
existing_ids = {e["id"] for e in (existing_data.get("data") or [])}
|
all_items = all_data.get("data") or []
|
||||||
|
existing_ids = {e["id"] for e in all_items if e.get("status") not in ("archived", "deleted")}
|
||||||
|
status_summary = {}
|
||||||
|
for e in all_items:
|
||||||
|
s = e.get("status", "unknown")
|
||||||
|
status_summary[s] = status_summary.get(s, 0) + 1
|
||||||
|
|
||||||
orphan_junc_ids = [row["id"] for row in rows
|
orphan_junc_ids = [row["id"] for row in rows
|
||||||
if row.get(fk_field) and row[fk_field] not in existing_ids]
|
if row.get(fk_field) and row[fk_field] not in existing_ids]
|
||||||
@@ -1339,7 +1345,17 @@ def purge_all_orphans():
|
|||||||
_directus("DELETE", f"/items/{junc_col}", token, orphan_junc_ids)
|
_directus("DELETE", f"/items/{junc_col}", token, orphan_junc_ids)
|
||||||
removed += len(orphan_junc_ids)
|
removed += len(orphan_junc_ids)
|
||||||
|
|
||||||
return jsonify({"ok": True, "orphans_removed": removed})
|
details.append({
|
||||||
|
"collection": junc_col,
|
||||||
|
"junction_rows": len(rows),
|
||||||
|
"fk_unique": len(fk_ids),
|
||||||
|
"items_found": len(all_items),
|
||||||
|
"status_breakdown": status_summary,
|
||||||
|
"existing_active": len(existing_ids),
|
||||||
|
"orphans_removed": len(orphan_junc_ids),
|
||||||
|
})
|
||||||
|
|
||||||
|
return jsonify({"ok": True, "orphans_removed": removed, "details": details})
|
||||||
|
|
||||||
|
|
||||||
@app.route("/api/fix-distractor-field", methods=["POST"])
|
@app.route("/api/fix-distractor-field", methods=["POST"])
|
||||||
|
|||||||
@@ -351,7 +351,12 @@ export default function GenerateIt() {
|
|||||||
if (!confirm('Alle verwaisten Junction-Einträge (gelöschte Fragen/Wörter) global bereinigen?')) return
|
if (!confirm('Alle verwaisten Junction-Einträge (gelöschte Fragen/Wörter) global bereinigen?')) return
|
||||||
try {
|
try {
|
||||||
const r = await purgeAllOrphans(token)
|
const r = await purgeAllOrphans(token)
|
||||||
alert(`Bereinigt: ${r.orphans_removed} verwaiste Einträge entfernt`)
|
const det = (r as {orphans_removed: number; details?: {collection:string; junction_rows?:number; orphans_removed?:number; items_found?:number; status_breakdown?:Record<string,number>}[]}).details
|
||||||
|
const detStr = det ? '\n\n' + det.map(d =>
|
||||||
|
`${d.collection}: ${d.junction_rows ?? 0} Zeilen, ${d.items_found ?? 0} Items gefunden, ${d.orphans_removed ?? 0} entfernt` +
|
||||||
|
(d.status_breakdown ? ' | Status: ' + JSON.stringify(d.status_breakdown) : '')
|
||||||
|
).join('\n') : ''
|
||||||
|
alert(`Bereinigt: ${r.orphans_removed} verwaiste Einträge entfernt${detStr}`)
|
||||||
if (selectedObjId) await reloadQW(selectedObjId)
|
if (selectedObjId) await reloadQW(selectedObjId)
|
||||||
} catch (e: unknown) {
|
} catch (e: unknown) {
|
||||||
alert(`Fehler: ${e instanceof Error ? e.message : e}`)
|
alert(`Fehler: ${e instanceof Error ? e.message : e}`)
|
||||||
|
|||||||
Reference in New Issue
Block a user