diff --git a/app.py b/app.py index 712bf6f..3b8348a 100644 --- a/app.py +++ b/app.py @@ -637,10 +637,14 @@ def resolve_katalog_overrides(device_id: str) -> dict: """ Ermittelt für ein Gerät die OE-/Gruppen-Zwischenschicht des Auftragskatalogs (siehe Konfigurationsgruppen-Plan): pro Merkmal-ID ein - (aktiv, quelle)-Tupel, falls die OE-Kette oder eine Gruppe eine explizite - Meinung dazu hat - fehlt der Merkmal-Key im Ergebnis, hat weder OE-Kette - noch eine Gruppe eine Meinung, der Aufrufer fällt dann auf den - Workspace-Default zurück. + (aktiv, quelle, quelle_id)-Tupel, falls die OE-Kette oder eine Gruppe eine + explizite Meinung dazu hat - fehlt der Merkmal-Key im Ergebnis, hat weder + OE-Kette noch eine Gruppe eine Meinung, der Aufrufer fällt dann auf den + Workspace-Default zurück. quelle_id ist die konkrete oe_id/gruppe_id, die + das Ergebnis geliefert hat (fürs Kundenportal, Sprung von der + Herkunfts-Anzeige zur verantwortlichen OE/Gruppe) - bei mehreren + zustimmenden Gruppen wird eine davon genannt, kein Anspruch auf + vollständige Attribution aller Beitragenden. Reihenfolge: innerhalb der OE-Kette gewinnt die spezifischste OE (klassische Vererbung, von der eigenen OE aus nach oben zur Wurzel @@ -692,30 +696,36 @@ def resolve_katalog_overrides(device_id: str) -> dict: for oe_id_in_chain in oe_chain: for merkmal_id, aktiv in rows_by_oe.get(oe_id_in_chain, {}).items(): - oe_aktiv_by_merkmal.setdefault(merkmal_id, aktiv) + oe_aktiv_by_merkmal.setdefault(merkmal_id, (aktiv, oe_id_in_chain)) cur.execute( """ - SELECT gm.merkmal_id, gm.aktiv + SELECT gm.merkmal_id, gm.gruppe_id, gm.aktiv FROM device_gruppen dg JOIN gruppen_merkmale gm ON gm.gruppe_id = dg.gruppe_id WHERE dg.device_id = %s """, (device_id,), ) - gruppen_aktiv_by_merkmal = {} - for merkmal_id, aktiv in cur.fetchall(): - gruppen_aktiv_by_merkmal.setdefault(merkmal_id, []).append(aktiv) + gruppen_stimmen_by_merkmal = {} + for merkmal_id, gruppe_id, aktiv in cur.fetchall(): + gruppen_stimmen_by_merkmal.setdefault(merkmal_id, []).append((gruppe_id, aktiv)) ergebnis = {} - for merkmal_id in set(oe_aktiv_by_merkmal) | set(gruppen_aktiv_by_merkmal): - oe_aktiv = oe_aktiv_by_merkmal.get(merkmal_id) - gruppen_stimmen = gruppen_aktiv_by_merkmal.get(merkmal_id, []) + for merkmal_id in set(oe_aktiv_by_merkmal) | set(gruppen_stimmen_by_merkmal): + oe_aktiv, oe_id_gewinner = oe_aktiv_by_merkmal.get(merkmal_id, (None, None)) + gruppen_stimmen = gruppen_stimmen_by_merkmal.get(merkmal_id, []) + aktive_gruppen = [gruppe_id for gruppe_id, aktiv in gruppen_stimmen if aktiv] + inaktive_gruppen = [gruppe_id for gruppe_id, aktiv in gruppen_stimmen if not aktiv] - if oe_aktiv is True or True in gruppen_stimmen: - ergebnis[merkmal_id] = (True, "oe" if oe_aktiv is True else "gruppe") + if oe_aktiv is True or aktive_gruppen: + quelle = "oe" if oe_aktiv is True else "gruppe" + quelle_id = oe_id_gewinner if oe_aktiv is True else aktive_gruppen[0] + ergebnis[merkmal_id] = (True, quelle, quelle_id) else: - ergebnis[merkmal_id] = (False, "oe" if oe_aktiv is False else "gruppe") + quelle = "oe" if oe_aktiv is False else "gruppe" + quelle_id = oe_id_gewinner if oe_aktiv is False else inaktive_gruppen[0] + ergebnis[merkmal_id] = (False, quelle, quelle_id) return ergebnis @@ -774,7 +784,7 @@ def fetch_auftragskatalog_state(device_id: str): if device_override is not None: aktiv = device_override elif merkmal_id in overrides: - aktiv, _quelle = overrides[merkmal_id] + aktiv, _quelle, _quelle_id = overrides[merkmal_id] else: aktiv = workspace_default @@ -842,11 +852,11 @@ def fetch_auftragskatalog_listing(device_id: str): device_override, workspace_default, optionen, ) in rows: if device_override is not None: - aktiv, quelle = device_override, "geraet" + aktiv, quelle, quelle_id = device_override, "geraet", None elif merkmal_id in overrides: - aktiv, quelle = overrides[merkmal_id] + aktiv, quelle, quelle_id = overrides[merkmal_id] else: - aktiv, quelle = workspace_default, "workspace" + aktiv, quelle, quelle_id = workspace_default, "workspace", None ergebnis.append({ "merkmal": key, @@ -858,6 +868,7 @@ def fetch_auftragskatalog_listing(device_id: str): ), "state": "present" if aktiv else "absent", "quelle": quelle, + "quelle_id": str(quelle_id) if quelle_id is not None else None, "optionen": optionen, }) @@ -1381,9 +1392,10 @@ def fetch_all_devices(): cur.execute( """ SELECT d.id, d.hostname, d.device_fingerprint, d.agent_last_checkin, - d.organization_id, o.name, d.deprovisioned_at + d.organization_id, o.name, d.deprovisioned_at, d.oe_id, oe.name FROM devices d JOIN organizations o ON o.id = d.organization_id + LEFT JOIN organisationseinheiten oe ON oe.id = d.oe_id WHERE d.archived_at IS NULL ORDER BY o.name, d.hostname NULLS LAST, d.created_at """ @@ -1401,10 +1413,13 @@ def fetch_all_devices(): "deprovisioned_at": ( deprovisioned_at.isoformat() if deprovisioned_at is not None else None ), + "oe_id": str(oe_id) if oe_id is not None else None, + "oe_name": oe_name, } for ( device_id, hostname, fingerprint, last_checkin, organization_id, organization_name, deprovisioned_at, + oe_id, oe_name, ) in cur.fetchall() ]