63 lines
2.6 KiB
Python
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",)
|