Skip to content

PEOPLE: Meine Betreuungen #281

Description

@richardjubla

Aktuelles Verhalten

Für Coaches und Leiterkursbetreuer betreute Kurse werden auf der Personenübersicht angezeigt. (Siehe #103 )

Nun ist es aber so, dass jeder Kurs/Lager in meine Betreuungen angezeigt wird, ach wenn das Profil/User gar nicht Coach oder LKB ist. Fehler: Ein angemeldetes Profil hat einen Event in mein Event UND meine Betreuungen.

event_coach → nur bei Lager (Event::Camp::Role::Coach)
event_advisor → nur bei Kurs (Event::Course::Role::Advisor, = LKB)

Der "asside" im Profil der Personenübersicht (was steht an?) deckt vermutlich nicht mehr die aktuellen Bedürfnisse der Benutzerinnen ab. (Elternzugang, Coach, Kurskoodinatorin, etc.)
Mögliche Verbindungen und Komplexität über den Core bis zum jubla-Wagon vermutet. (Die Jubla hat sich seit Jahren nicht mehr damit befasst?)

Gewünschtes Verhalten

Im Profil der Personenübersicht (asside), werden alle relevanten Events (Kurs, Lager, Anlass) für das Profil angezeigt. Ich gehe von folgendem Bedürfnis aus:

  • Meine nächsten Kurse
    Liste aller aktuellen Kurse, in denen ich angemeldet (in Teilnehmerliste) bin
  • Meine nächsten Lager
    Liste aller aktuellen Lager, in denen ich angemeldet (in Teilnehmerliste) bin
  • Meine nächsten Anlässe
    Liste aller aktuellen Anlässe, in denen ich angemeldet (in Teilnehmerliste) bin
  • Meine Betreuungen
    Liste aller aktuellen Events (Kurse/Lager) in denen ich eine Event-Rolle (LKB, Coach, ec.)
    Alternative: Meine Betreuungen entfernen und Event-Rolle in den jeweiligen Events (Kurse, Lager) anzeigen (analog pbs).
  • Anlässe verwalteter Profile
    Liste aller aktuellen Events in denen meine Kinder (verwalteten Profile) angemeldet (in Teilnehmerliste) sind
Image

Schritte zu reproduzieren

Bug 1: Fremde Coach-/LKB-Zuweisung erscheint in der eigenen "Meine Betreuungen"-Liste
Voraussetzung: Ein Kurs oder Lager mit mindestens zwei Personen.

  1. Kurs/Lager öffnen → bearbeiten
  2. Person A als LKB (bei Kurs) bzw. Coach (bei Lager) im entsprechenden Feld eintragen und speichern
  3. Zum selben Kurs/Lager zurück → Reiter "Teilnehmende" → Person B (irgendeine andere Person) ganz normal als Teilnehmer*in oder mit einer beliebigen anderen Rolle hinzufügen
  4. Zum Profil von Person B wechseln (nicht der LKB/Coach!)
  5. Im Profil den Bereich "Meine Betreuungen" ansehen
  6. Erwartet: Der Kurs/das Lager erscheint dort nicht, da Person B keine LKB-/Coach-Rolle hat.
  7. Tatsächlich (Bug): Der Kurs/das Lager erscheint trotzdem in Person B's "Meine Betreuungen".

Bug 2: Eigene LKB-/Coach-Zuweisung erscheint zusätzlich (doppelt) in "Meine nächsten Kurse"/"Meine nächsten Lager"
Voraussetzung: Ein Kurs oder Lager, das zeitlich noch bevorsteht (nicht in der Vergangenheit).

  1. Kurs/Lager öffnen → bearbeiten
  2. Eine Person als LKB (Kurs) bzw. Coach (Lager) eintragen und speichern
  3. Zum Profil dieser Person wechseln
  4. Bereich "Meine Betreuungen" ansehen → Kurs/Lager erscheint dort korrekt
  5. Zusätzlich Bereich "Meine nächsten Kurse" (bei Kurs-LKB) bzw. "Meine nächsten Lager" (bei Lager-Coach) ansehen
  6. Erwartet: Der Kurs/das Lager erscheint dort nicht, da er/sie bereits unter "Meine Betreuungen" korrekt aufgeführt ist.
  7. Tatsächlich (Bug): Derselbe Kurs/dasselbe Lager erscheint zusätzlich auch dort – also doppelt an zwei Stellen im Profil.

Hinweis zur Reproduzierbarkeit: Beide Bugs treten unabhängig vom Rollentyp auf (sowohl bei LKB/Kurs als auch bei Coach/Lager) – bei den Tests hier bestätigt für beide Varianten.

Wann ist der Fehler aufgetreten?

jubla only, Verbindungen zum core

hitobito version

2.10

Organisation

Jubla

Screenshots, weiterer Kontext

Fix: "Meine Betreuungen" zeigt falsche/fehlende Anlässe

Zusammenfassung

Der Bereich "Meine Betreuungen" im Personenprofil (zeigt Kurse/Lager, in denen die Person LKB oder Coach ist) hat zwei voneinander unabhängige Bugs, die beide auf denselben Konstruktionsfehler zurückgehen: Zwei ähnlich benannte, aber unterschiedliche Datenbankabfragen wurden nicht konsistent behandelt.

Zusätzlich fehlte eine Möglichkeit, die Anlässe von verknüpften/verwalteten Profilen (z. B. Kindern via Eltern-Kind-Verknüpfung) separat einzusehen.

Hinweis: Diese Analyse und der vorgeschlagene Fix wurden mit KI/LLM-Unterstützung erarbeitet und gegen eine lokale Entwicklungsumgebung mit echten Testdaten verifiziert (siehe Testplan unten). Kein Teil davon wurde bereits eingereicht oder committet.


Bug 1: "Meine Betreuungen" zeigt fremde Zuweisungen

Symptom: Ist man selbst normale/r Teilnehmer*in (oder Leitung, Küche, etc.) in einem Kurs/Lager, und eine andere Person in diesem Kurs/Lager ist LKB oder Coach, erscheint dieser Kurs/dieses Lager fälschlicherweise auch in der eigenen "Meine Betreuungen"-Liste.

Ursache: In Jubla::Person::EventQueries#coached_events wird person.events.joins(participations: :roles) verwendet. Person und Event verwenden für dieselbe zugrundeliegende Tabelle (event_participations) unterschiedliche Assoziationsnamen (event_participations bzw. participations). Rails erzeugt dadurch zwei unabhängige SQL-Joins statt eines gemeinsamen – die Rollen-Bedingung wird nicht mehr an dieselbe Anmeldung der Person gebunden, sondern prüft nur noch "existiert irgendwo in diesem Event eine Coach-/LKB-Rolle".

Der Fehler steckt unverändert seit Einführung des Features im Jahr 2016 im Code (Commit 1b81ae2). Die bestehende Testsuite (spec/domain/jubla/person/event_queries_spec.rb) deckt diesen Fall nicht ab, da nie getestet wird, dass eine andere Person die Coach-/LKB-Rolle hält.

Live-Nachweis (Dev-Datenbank): Person 101 hält ausschliesslich die Rolle "Hauptleitung" in Event 3; eine andere Person ist dort LKB. Vor dem Fix lieferte coached_events für Person 101 dieses Event dennoch zurück.

Bild nach Fix von 101

Image

Bug 2: LKB/Coach erscheinen zusätzlich (doppelt) in "Meine nächsten Kurse/Lager"

Symptom: Die reguläre Liste "Meine nächsten Kurse"/"Meine nächsten Lager" soll laut Absicht keine LKB-/Coach-Zuweisungen zeigen (dafür gibt es "Meine Betreuungen"). Tatsächlich tut sie das aber doch – eine LKB-/Coach-Zuweisung erscheint dadurch doppelt.

Ursache: Der bestehende Ausschluss-Mechanismus patcht nur unordered_upcoming_events (via alias_method_chain :unordered_upcoming_events, :coached). Die tatsächlich für "Meine nächsten Kurse/Lager" verwendete Methode ist aber upcoming_participations (aus dem hitobito-Core, gerendert über upcoming_participations_grouped) – eine andere, nie gepatchte Methode.

Live-Nachweis: Für den echten LKB aus Bug 1 lieferte upcoming_events korrekt kein Ergebnis für Event 3 (Ausschluss funktioniert dort), upcoming_participations lieferte es aber trotzdem.


Zusatz: Anlässe verwalteter Profile

Das System kennt eine Eltern-Kind/Verwalter-Verknüpfung (Person#manageds, Feature-Flag people.people_managers). Es gab bisher keine Stelle im Profil, die zeigt, für welche Anlässe die verwalteten Profile angemeldet sind (unabhängig von deren Rolle). Neuer, vierter Bereich "Anlässe verwalteter Profile" ergänzt – bewusst getrennt von "Meine Betreuungen", da letztere ausschliesslich die eigenen LKB-/Coach-Zuweisungen zeigen soll.


Änderungen

app/domain/jubla/person/event_queries.rb

  • coached_events: Neu aufgebaut, ausgehend von person.event_participations statt person.events, damit die Rollen-Bedingung korrekt an dieselbe Anmeldung gebunden bleibt. Rückgabetyp geändert von Event zu Event::Participation (nötig für Fix des Anzeigeformats, siehe unten).
  • upcoming_participations_with_coached (neu, via alias_method_chain :upcoming_participations, :coached): Schliesst LKB/Coach-Anmeldungen aus der regulären Kurs-/Lager-Liste aus, analog zum bereits bestehenden Muster bei unordered_upcoming_events_with_coached.
  • managed_events (neu): Liefert alle Anmeldungen (unabhängig von der Rolle) der verwalteten Profile (person.manageds).

app/decorators/jubla/person_decorator.rb

  • coached_events: Dekoriert jetzt mit Event::ParticipationDecorator statt EventDecorator (Konsequenz aus dem geänderten Rückgabetyp).
  • managed_events (neu): Analog dekoriert.

app/views/people/_show_event_jubla.html.haml

  • Nutzt jetzt den Partial participation_aside statt event_aside – dadurch wird pro Zeile zusätzlich zu Name und Datum auch Gruppe und die konkrete Rolle (verlinkt zur Anmeldung) angezeigt, im selben Format wie bei "Meine nächsten Kurse/Lager".
  • Neuer, bedingt gerenderter Abschnitt "Anlässe verwalteter Profile" (nur sichtbar, wenn Feature aktiv und tatsächlich verwaltete Profile vorhanden sind).

config/locales/views.de.yml

  • Neuer Übersetzungsschlüssel people.show_event_jubla.managed_events: Anlässe verwalteter Profile.

Hinweis: Die fehlende Übersetzung der Rollennamen selbst (LKB/Coach erscheinen als generischer Platzhalter "Anlass Rolle" statt als eigener Rollenname) ist ein separates Thema und nicht Teil dieses Fixes – siehe eigener Bug Report zu hitobito_jubla#272.


Diff

--- a/app/domain/jubla/person/event_queries.rb
+++ b/app/domain/jubla/person/event_queries.rb
@@ -9,18 +9,43 @@ module Jubla
 
     included do
       alias_method_chain :unordered_upcoming_events, :coached
+      alias_method_chain :upcoming_participations, :coached
     end
 
     def coached_events
-      person.events
-        .up_to_a_month_ago
-        .merge(::Event::Participation.active)
-        .joins(participations: :roles)
-        .where(event_roles: {type: [::Event::Camp::Role::Coach.sti_name,
-          ::Event::Course::Role::Advisor.sti_name]})
-        .distinct
-        .includes(:groups)
-        .preload_all_dates
+      midnight = Time.zone.now.midnight
+      ::Event::Participation.select("*").from(
+        ::Event::Participation
+          .where(participant: person)
+          .merge(::Event::Participation.active)
+          .joins(:roles, event: :dates)
+          .where(event_roles: {type: [::Event::Camp::Role::Coach.sti_name,
+            ::Event::Course::Role::Advisor.sti_name]})
+          .where("event_dates.start_at >= ? OR event_dates.finish_at >= ?",
+            midnight - 1.month, midnight - 1.month)
+          .distinct
+          .includes(:roles, event: [:translations, :dates, :groups])
+      ).tap do |participations|
+        ::Event::PreloadAllDates.for(participations.collect(&:event))
+      end
+    end
+
+    # All upcoming events (any role) of managed profiles (e.g. children),
+    # shown separately so a manager can see what their managed profiles
+    # are registered for, without mixing it into their own coached_events.
+    def managed_events
+      ::Event::Participation.select("*").from(
+        ::Event::Participation
+          .where(participant: person.manageds)
+          .merge(::Event::Participation.upcoming)
+          .active
+          .joins(event: :dates)
+          .select("event_participations.*", "event_dates.start_at")
+          .distinct_on(:id)
+          .includes(:roles, event: [:translations, :dates, :groups])
+      ).order(:start_at).tap do |participations|
+        ::Event::PreloadAllDates.for(participations.collect(&:event))
+      end
     end
 
     def unordered_upcoming_events_with_coached
@@ -29,5 +54,25 @@ module Jubla
         .where.not(event_roles: {type: [::Event::Camp::Role::Coach,
           ::Event::Course::Role::Advisor].map(&:sti_name)})
     end
+
+    def upcoming_participations_with_coached
+      ::Event::Participation.select("*").from(
+        person
+          .event_participations
+          .merge(::Event::Participation.upcoming)
+          .active
+          .joins(event: :dates)
+          .where.not(id: ::Event::Participation
+            .joins(:roles)
+            .where(event_roles: {type: [::Event::Camp::Role::Coach.sti_name,
+              ::Event::Course::Role::Advisor.sti_name]})
+            .select(:id))
+          .select("event_participations.*", "event_dates.start_at")
+          .distinct_on(:id)
+          .includes(:roles, event: [:translations, :dates, :groups])
+      ).order(:start_at).tap do |participations|
+        ::Event::PreloadAllDates.for(participations.collect(&:event))
+      end
+    end
   end
 end
--- a/app/decorators/jubla/person_decorator.rb
+++ b/app/decorators/jubla/person_decorator.rb
@@ -21,7 +21,11 @@ module Jubla::PersonDecorator
   end
 
   def coached_events
-    @coached_events ||= EventDecorator.decorate_collection(event_queries.coached_events)
+    @coached_events ||= Event::ParticipationDecorator.decorate_collection(event_queries.coached_events)
+  end
+
+  def managed_events
+    @managed_events ||= Event::ParticipationDecorator.decorate_collection(event_queries.managed_events)
   end
 
   private
--- a/app/views/people/_show_event_jubla.html.haml
+++ b/app/views/people/_show_event_jubla.html.haml
@@ -1 +1,4 @@
-= render 'event_aside', title: t('.coached'), collection: entry.coached_events
+= render 'participation_aside', title: t('.coached'), collection: entry.coached_events
+
+- if FeatureGate.enabled?('people.people_managers') && entry.manageds.any?
+  = render 'participation_aside', title: t('.managed_events'), collection: entry.managed_events
--- a/config/locales/views.de.yml
+++ b/config/locales/views.de.yml
@@ -81,6 +81,7 @@ de:
       info_alumnus_contactable: "Mit dem Setzen eines Häkchens erlaubst du folgenden Ebenen, dich zu kontaktieren und dir Informationen zu senden:"
     show_event_jubla:
       coached: Meine Betreuungen
+      managed_events: Anlässe verwalteter Profile
     privacy_policy_acceptance_field:

Testplan

Manuell gegen eine lokale Dev-Datenbank mit echten Testdaten verifiziert (jeweils in einer Transaktion mit anschliessendem Rollback, keine dauerhaften Datenänderungen):

  • Person mit einer fremden Rolle (Hauptleitung) im selben Event wie eine LKB/Coach-Zuweisung sieht dieses Event nicht mehr unter "Meine Betreuungen" (vorher: fälschlich sichtbar)
  • Echte LKB-/Coach-Zuweisung sieht ihr eigenes Event weiterhin korrekt unter "Meine Betreuungen"
  • Echte LKB-/Coach-Zuweisung sieht ihr Event nicht mehr zusätzlich unter "Meine nächsten Kurse/Lager" (vorher: doppelt sichtbar)
  • Normale/r Teilnehmer*in sieht die eigene reguläre Anmeldung weiterhin korrekt unter "Meine nächsten Kurse/Lager"
  • Verwaltendes Profil (Elternteil) sieht die reguläre (nicht-Betreuungs-)Anmeldung eines verwalteten Profils (Kind) unter dem neuen Bereich "Anlässe verwalteter Profile"
  • Eigene "Meine Betreuungen" bleibt leer, wenn nur ein verwaltetes Profil (nicht man selbst) eine Coach-/LKB-Rolle hat
  • Bestehende RSpec-Suite (spec/domain/jubla/person/event_queries_spec.rb) konnte in dieser Umgebung nicht ausgeführt werden (Konflikt mit der laufenden Dev-Datenbank, die vom Testlauf purged werden wollte) – sollte vor Merge reinstalliert bzw. erweitert werden, insbesondere um einen Testfall "andere Person hat Coach/LKB-Rolle im selben Event" zu ergänzen, der den ursprünglichen Bug abgedeckt hätte.

Offene Punkte für die Umsetzung

  1. Neue/erweiterte Testfälle für event_queries_spec.rb fehlen noch (bewusst ausgeklammert, siehe oben).
  2. Die fehlende Rollen-Übersetzung ("Anlass Rolle" statt "LKB"/"Coach") ist separat zu behandeln, siehe hitobito_jubla#272.

ToDos

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions