diff --git a/app.py b/app.py index 4ac4c0d..aec330e 100644 --- a/app.py +++ b/app.py @@ -1313,6 +1313,7 @@ def purge_all_orphans(): """ token = request.headers.get("Authorization", "") removed = 0 + details = [] for junc_col, fk_field, item_col in [ ("questions_objects", "questions_id", "questions"), @@ -1322,16 +1323,21 @@ def purge_all_orphans(): f"/items/{junc_col}?fields=id,{fk_field}&limit=10000", token) 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)}) if not fk_ids: + details.append({"collection": junc_col, "junction_rows": 0, "existing": 0, "orphans": 0}) continue - # fetch which IDs still exist AND are not archived - ids_param = ",".join(fk_ids) - existing_data, _ = _directus("GET", - f"/items/{item_col}?filter[id][_in]={ids_param}&filter[status][_neq]=archived&fields=id&limit=10000", token) - existing_ids = {e["id"] for e in (existing_data.get("data") or [])} + # fetch existing AND check all statuses (fetch without status filter first) + ids_param = urllib.parse.quote(",".join(fk_ids), safe="") + all_data, _ = _directus("GET", + f"/items/{item_col}?filter[id][_in]={ids_param}&fields=id,status&limit=10000", token) + 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 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) 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"]) diff --git a/frontend/src/pages/GenerateIt.tsx b/frontend/src/pages/GenerateIt.tsx index b6c259c..5a50902 100644 --- a/frontend/src/pages/GenerateIt.tsx +++ b/frontend/src/pages/GenerateIt.tsx @@ -351,7 +351,12 @@ export default function GenerateIt() { if (!confirm('Alle verwaisten Junction-Einträge (gelöschte Fragen/Wörter) global bereinigen?')) return try { 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}[]}).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) } catch (e: unknown) { alert(`Fehler: ${e instanceof Error ? e.message : e}`)