diff --git a/management/templates/management/member_detail.html b/management/templates/management/member_detail.html
index 5f0dee0..436599e 100644
--- a/management/templates/management/member_detail.html
+++ b/management/templates/management/member_detail.html
@@ -28,6 +28,16 @@
{% trans "Emergency phone" %}
{{ member.emergency_phone.as_international|default:"-" }}
+ {% for guardian in guardians %}
+
+
{% trans "Parent phone" %} — {{ guardian.get_full_name }}
+ {{ guardian.phone.as_international|default:"-" }}
+
+
+
{% trans "Parent emergency phone" %} — {{ guardian.get_full_name }}
+ {{ guardian.emergency_phone.as_international|default:"-" }}
+
+ {% endfor %}
+
+ {% if guardians %}
+
+
+ {% lucide "users" size=12 %} {% trans "Parent/guardian contact" %}
+
+ {% for guardian in guardians %}
+ {% if guardian.phone or guardian.emergency_phone %}
+
+ {% endif %}
+ {% endfor %}
+ {% endif %}
diff --git a/management/tests.py b/management/tests.py
index 493cbc1..d61d7c1 100644
--- a/management/tests.py
+++ b/management/tests.py
@@ -1087,6 +1087,37 @@ class MemberFamilyAttachDetachTests(ManagementTestBase):
self.assertNotIn(family, response.context["attach_to_family_form"].fields["family"].queryset)
+ def test_a_childs_page_shows_their_guardians_phone_numbers(self):
+ family = Family.objects.create()
+ parent = Member.objects.create(first_name="Pat", last_name="Parent", phone="+32470000001", emergency_phone="+32470000002")
+ FamilyMembership.objects.create(family=family, member=self.standalone, role=FamilyMembership.FamilyRole.CHILD)
+ FamilyMembership.objects.create(family=family, member=parent, role=FamilyMembership.FamilyRole.PARENT)
+
+ response = self.club_get("member_detail", self.standalone.pk)
+
+ self.assertIn(parent, response.context["guardians"])
+ self.assertContains(response, "Pat Parent")
+ self.assertContains(response, "tel:+32 470 00 00 01")
+ self.assertContains(response, "tel:+32 470 00 00 02")
+
+ def test_a_parents_page_does_not_show_guardian_numbers(self):
+ # self.standalone has no CHILD membership anywhere -- the section must not appear.
+ response = self.club_get("member_detail", self.standalone.pk)
+
+ self.assertEqual(len(response.context["guardians"]), 0)
+ self.assertNotContains(response, "Parent/guardian contact")
+
+ def test_a_guardian_with_no_phone_numbers_gets_no_dial_buttons(self):
+ family = Family.objects.create()
+ parent = Member.objects.create(first_name="Pat", last_name="Parent")
+ FamilyMembership.objects.create(family=family, member=self.standalone, role=FamilyMembership.FamilyRole.CHILD)
+ FamilyMembership.objects.create(family=family, member=parent, role=FamilyMembership.FamilyRole.PARENT)
+
+ response = self.club_get("member_detail", self.standalone.pk)
+
+ self.assertContains(response, "Pat Parent")
+ self.assertNotContains(response, "tel:")
+
class MemberDeleteTests(ManagementTestBase):
def setUp(self):
diff --git a/management/views.py b/management/views.py
index 6da6707..4ad1e76 100644
--- a/management/views.py
+++ b/management/views.py
@@ -590,6 +590,10 @@ class MemberDetailView(ClubStaffRequiredMixin, DetailView):
attach_to_family_form=AttachToFamilyForm(club=self.request.club, member=self.object),
current_membership=ClubMembership.objects.filter(club=self.request.club, member=self.object, season=current_season(self.request.club)).first(),
membership_history=ClubMembership.objects.filter(club=self.request.club, member=self.object).select_related("season").order_by("-season__start_date"),
+ # Non-empty only when `member` is a CHILD in some family -- that's the same
+ # signal the Personal information card uses to decide whether to show parent
+ # contact numbers at all.
+ guardians=self.object.guardians,
**kwargs,
)