You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

165 lines
6.8 KiB

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('<span class="unfold-badge unfold-badge--success">{}</span>', _("Paid"))
elif obj.status == 'failed':
return format_html('<span class="unfold-badge unfold-badge--danger">{}</span>', _("Failed"))
elif obj.status == 'waiting_approval':
return format_html('<span class="unfold-badge unfold-badge--info">{}</span>', _("Waiting Approval"))
return format_html('<span class="unfold-badge unfold-badge--warning">{}</span>', _("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('<span class="unfold-badge unfold-badge--info">{} {}</span>', count, _("receipts"))
return format_html('<span class="unfold-badge unfold-badge--secondary">{}</span>', _("No receipts"))
@display(description=_("Price"), ordering="price")
def price_display(self, obj):
return format_html('<span class="unfold-badge unfold-badge--info">${}</span>', 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('<span class="unfold-badge unfold-badge--success">✓ {}</span>', _("Enrolled"))
else:
return format_html('<span class="unfold-badge unfold-badge--warning">⚠ {}</span>', _("Not Enrolled"))
else:
return format_html('<span class="unfold-badge unfold-badge--secondary">- {}</span>', _("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,
_("Transaction status updated to SUCCESS. User {user_email} is now enrolled in course '{course_title}'.").format(
user_email=obj.user.email,
course_title=obj.course.title
)
)
else:
messages.warning(
request,
_("Transaction status updated to SUCCESS, but there was an issue enrolling user {user_email} in course '{course_title}'. Please check the logs.").format(
user_email=obj.user.email,
course_title=obj.course.title
)
)
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)