Remove OnboardingRequirement.order; restrict checklist actions to admin/MEMBER_ADMIN
Every active requirement blocks equally and there's no set order to complete them in, so the configurable "order" field (and its ordering-by-number) is gone -- requirements list alphabetically now, both in the admin UI and the Onboarding requirements settings page. Also closes a real permission gap found while checking this: marking a checklist item complete, bypassing it, or reopening it (management/views.py's MemberRequirementCompleteView/BypassView/IncompleteView) was open to *any* staff member with page access, not just admin/MEMBER_ADMIN, despite the member detail page's own Documents card implying otherwise. Switched all three to MemberAdminRequiredMixin and hid the corresponding buttons/dialog from anyone who can't use them. The Sign-up page's Bypass action was already admin-only end to end (the whole page is ClubAdminRequiredMixin-gated), so no change in practice there. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ECGMEwrc2k4D8VQuwjstj9
This commit is contained in:
@@ -67,10 +67,10 @@ class ClubRoleAdmin(admin.ModelAdmin):
|
||||
|
||||
@admin.register(OnboardingRequirement)
|
||||
class OnboardingRequirementAdmin(admin.ModelAdmin):
|
||||
list_display = ["name", "club", "requires_document", "is_active", "order"]
|
||||
list_display = ["name", "club", "requires_document", "is_active"]
|
||||
list_filter = ["club", "is_active", "requires_document"]
|
||||
search_fields = ["name", "club__name"]
|
||||
ordering = ["club", "order", "name"]
|
||||
ordering = ["club", "name"]
|
||||
|
||||
|
||||
@admin.register(MemberRequirementStatus)
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
# Generated by Django 6.0.6 on 2026-08-20 07:21
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('club', '0027_club_website'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='onboardingrequirement',
|
||||
options={'ordering': ['name'], 'verbose_name': 'onboarding requirement', 'verbose_name_plural': 'onboarding requirements'},
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='onboardingrequirement',
|
||||
name='order',
|
||||
),
|
||||
]
|
||||
@@ -422,12 +422,14 @@ class OnboardingRequirement(ClubScopedModel):
|
||||
requires_document = models.BooleanField(_("requires a document"), default=False, help_text=_("Staff can attach a file (e.g. the certificate itself) when marking this complete."))
|
||||
blocked_event_kinds = models.JSONField(_("blocks selection for"), default=list, blank=True, help_text=_("Event kinds a member can't be invited to or selected for while this is open. Empty means purely informational."))
|
||||
is_active = models.BooleanField(_("active"), default=True, help_text=_("Inactive requirements no longer apply to new memberships, but existing statuses are kept."))
|
||||
order = models.PositiveIntegerField(_("order"), default=0, help_text=_("Lower numbers show first on the checklist."))
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("onboarding requirement")
|
||||
verbose_name_plural = _("onboarding requirements")
|
||||
ordering = ["order", "name"]
|
||||
# Alphabetical, not a configurable sequence: every active requirement
|
||||
# blocks equally and there's no set order to complete them in, so
|
||||
# ordering here is purely for a stable, predictable listing.
|
||||
ordering = ["name"]
|
||||
constraints = [
|
||||
models.UniqueConstraint(fields=["club", "name"], name="unique_onboarding_requirement_name_per_club"),
|
||||
]
|
||||
|
||||
@@ -1817,8 +1817,8 @@ class OnboardingRequirementTests(TestCase):
|
||||
club=cls.club, member=cls.member, season=cls.season, status=ClubMembership.StatusChoices.ACTIVE, fee_status=ClubMembership.FeeStatus.PAID
|
||||
)
|
||||
cls.staff = get_user_model().objects.create_user(email="staff@example.com", password="pw-secret-123")
|
||||
cls.photo = OnboardingRequirement.objects.create(club=cls.club, name="Photo", order=1)
|
||||
cls.medical = OnboardingRequirement.objects.create(club=cls.club, name="Medical certificate", requires_document=True, order=2)
|
||||
cls.photo = OnboardingRequirement.objects.create(club=cls.club, name="Photo")
|
||||
cls.medical = OnboardingRequirement.objects.create(club=cls.club, name="Medical certificate", requires_document=True)
|
||||
|
||||
def test_a_membership_with_no_status_rows_has_every_requirement_open(self):
|
||||
self.assertEqual(self.membership.open_requirement_count, 2)
|
||||
|
||||
Reference in New Issue
Block a user