Files
testpoint/accounts/admin.py
T
2026-07-29 10:47:40 +00:00

63 lines
2.6 KiB
Python

from django.contrib import admin
from django.utils import timezone
from unfold.admin import ModelAdmin
from .access import has_lifetime_premium
from .models import DailyMissionClaim, PremiumEntitlement, StudentProfile
@admin.register(StudentProfile)
class StudentProfileAdmin(ModelAdmin):
list_display = ("user", "premium_status", "target_band", "daily_goal", "xp", "streak")
search_fields = ("user__username", "user__email", "user__first_name", "user__last_name")
list_filter = ("target_band", "daily_goal")
actions = ("grant_lifetime_premium", "revoke_lifetime_premium")
@admin.display(description="Membership", boolean=True)
def premium_status(self, obj):
return has_lifetime_premium(obj.user)
@admin.action(description="Grant Lifetime Premium")
def grant_lifetime_premium(self, request, queryset):
granted = 0
for profile in queryset.select_related("user"):
entitlement, created = PremiumEntitlement.objects.get_or_create(
user=profile.user,
defaults={"source": PremiumEntitlement.SOURCE_ADMIN},
)
if entitlement.revoked_at is not None:
entitlement.revoked_at = None
entitlement.save(update_fields=["revoked_at"])
if created or entitlement.is_active:
granted += 1
self.message_user(request, f"Lifetime Premium is active for {granted} user(s).")
@admin.action(description="Revoke Lifetime Premium")
def revoke_lifetime_premium(self, request, queryset):
updated = PremiumEntitlement.objects.filter(
user__studentprofile__in=queryset,
revoked_at__isnull=True,
).update(revoked_at=timezone.now())
self.message_user(request, f"Revoked Lifetime Premium for {updated} user(s).")
@admin.register(PremiumEntitlement)
class PremiumEntitlementAdmin(ModelAdmin):
list_display = ("user", "status", "source", "order_reference", "granted_at", "revoked_at")
list_filter = ("source", "revoked_at", "granted_at")
search_fields = ("user__username", "user__email", "order_reference")
readonly_fields = ("granted_at",)
list_select_related = ("user",)
@admin.display(description="Status")
def status(self, obj):
return "Active" if obj.is_active else "Revoked"
@admin.register(DailyMissionClaim)
class DailyMissionClaimAdmin(ModelAdmin):
list_display = ("user", "mission_key", "completed_on", "xp_awarded", "claimed_at")
list_filter = ("mission_key", "completed_on")
search_fields = ("user__username", "user__email")
readonly_fields = ("claimed_at",)