from django.contrib import admin from django.utils.translation import gettext_lazy as _ from django.utils.html import format_html from django.contrib import messages from unfold.admin import ModelAdmin, StackedInline, TabularInline from unfold.decorators import display from apps.transaction.models import TransactionParticipant, ParticipantInfo, TransactionReceipt from apps.course.models import Participant from utils.admin import project_admin_site class ParticipantInfoInline(StackedInline): model = ParticipantInfo extra = 1 fields = ['fullname', 'email', 'phone_number', 'gender', 'birthdate'] # readonly_fields = ['email', 'phone_number'] classes = ['collapse'] tab = True show_change_link = True class TransactionReceiptInline(TabularInline): model = TransactionReceipt extra = 0 fields = ['file', 'description', 'uploaded_at'] readonly_fields = ['uploaded_at'] classes = ['collapse'] tab = True show_change_link = True verbose_name = _('Payment Receipt') verbose_name_plural = _('Payment Receipts') @admin.register(TransactionParticipant) class TransactionParticipantAdmin(ModelAdmin): list_display = ('user', 'course', 'payment_status', 'price_display', 'participant_status', 'receipts_count', 'created_at', 'updated_at') list_filter = ('status', 'course', 'created_at') search_fields = ('user__email', 'course__title') readonly_fields = ['created_at', 'updated_at'] inlines = [ParticipantInfoInline, TransactionReceiptInline] autocomplete_fields = ['user',] show_change_link = True ordering = ('-created_at',) fieldsets = ( (None, { 'fields': ('user', 'course', 'status', 'price') }), (_('Timestamps'), { 'fields': ('created_at', 'updated_at'), 'classes': ('collapse',) }), ) @display(description=_("Payment Status"), ordering="status") def payment_status(self, obj): if obj.status == 'success': return format_html('Paid') elif obj.status == 'failed': return format_html('Failed') elif obj.status == 'waiting_approval': return format_html('Waiting Approval') return format_html('Pending') @display(description=_("Receipts Count")) def receipts_count(self, obj): """Display count of uploaded receipts""" count = obj.receipts.count() if count > 0: return format_html('{} receipts', count) return format_html('No receipts') @display(description=_("Price"), ordering="price") def price_display(self, obj): return format_html('${}', obj.price) @display(description=_("Course Participant Status")) def participant_status(self, obj): """نمایش وضعیت شرکت‌کننده در دوره""" if obj.status == TransactionParticipant.TransactionStatus.SUCCESS: participant_exists = Participant.objects.filter( student=obj.user, course=obj.course ).exists() if participant_exists: return format_html('✓ Enrolled') else: return format_html('⚠ Not Enrolled') else: return format_html('- Not Applicable') def save_model(self, request, obj, form, change): """Override save_model to show messages when participant is created""" if change: # Store the old status before saving old_obj = TransactionParticipant.objects.get(pk=obj.pk) old_status = old_obj.status # Save the object super().save_model(request, obj, form, change) # Check if status changed to SUCCESS if (old_status != TransactionParticipant.TransactionStatus.SUCCESS and obj.status == TransactionParticipant.TransactionStatus.SUCCESS): participant_exists = Participant.objects.filter( student=obj.user, course=obj.course ).exists() if participant_exists: messages.success( request, f"Transaction status updated to SUCCESS. User {obj.user.email} is now enrolled in course '{obj.course.title}'." ) else: messages.warning( request, f"Transaction status updated to SUCCESS, but there was an issue enrolling user {obj.user.email} in course '{obj.course.title}'. Please check the logs." ) else: super().save_model(request, obj, form, change) def get_queryset(self, request): # Filter out deleted transactions return super().get_queryset(request).filter(is_deleted=False) project_admin_site.register(TransactionParticipant, TransactionParticipantAdmin) @admin.register(TransactionReceipt) class TransactionReceiptAdmin(ModelAdmin): list_display = ('transaction', 'file', 'uploaded_at', 'description_preview') list_filter = ('uploaded_at', 'transaction__status') search_fields = ('transaction__user__email', 'transaction__course__title', 'description') readonly_fields = ['uploaded_at'] autocomplete_fields = ['transaction'] ordering = ('-uploaded_at',) fieldsets = ( (None, { 'fields': ('transaction', 'file', 'description') }), (_('Timestamps'), { 'fields': ('uploaded_at',), 'classes': ('collapse',) }), ) @display(description=_("Description")) def description_preview(self, obj): """Display truncated description""" if obj.description: return obj.description[:50] + '...' if len(obj.description) > 50 else obj.description return '-' project_admin_site.register(TransactionReceipt, TransactionReceiptAdmin)