feat: derive event lifecycle status from dates and flags
Replace persisted event statuses with publication and cancellation flags, and compute public lifecycle labels from event timing and registration capacity. Keep filters, registration checks, and profile responses aligned with the derived status.
This commit is contained in:
@@ -14,11 +14,11 @@ from apps.events.checkout import cancel_event_checkouts
|
||||
class EventAdmin(BaseModelAdmin, ImportExportModelAdmin):
|
||||
resource_class = EventResource
|
||||
list_display = (
|
||||
'title', 'event_type', 'start_time_display', 'end_time_display', 'status',
|
||||
'title', 'event_type', 'start_time_display', 'end_time_display', 'status_display',
|
||||
'price_display', 'capacity_display', 'attendees_display', 'is_registration_open_display',
|
||||
)
|
||||
list_filter = (
|
||||
'event_type', 'status', 'is_deleted', 'start_time', 'end_time',
|
||||
'event_type', 'is_published', 'is_cancelled', 'is_deleted', 'start_time', 'end_time',
|
||||
'registration_start_date', 'registration_end_date', SoftDeleteListFilter,
|
||||
)
|
||||
search_fields = ('title', 'description', 'address')
|
||||
@@ -27,7 +27,8 @@ class EventAdmin(BaseModelAdmin, ImportExportModelAdmin):
|
||||
filter_horizontal = ('gallery_images',)
|
||||
fieldsets = (
|
||||
('Event Details', {'fields': ('title', 'slug', 'description', 'featured_image')}),
|
||||
('Timing & Type', {'fields': ('start_time', 'end_time', 'event_type', 'status')}),
|
||||
('Timing & Type', {'fields': ('start_time', 'end_time', 'event_type')}),
|
||||
('Publication', {'fields': ('is_published', 'is_cancelled')}),
|
||||
('Location & Online', {
|
||||
'fields': ('address', 'location', 'online_link'),
|
||||
'description': 'For On-Site or Hybrid events, provide address and select on map. For Online events, provide a link.',
|
||||
@@ -41,9 +42,13 @@ class EventAdmin(BaseModelAdmin, ImportExportModelAdmin):
|
||||
)
|
||||
readonly_fields = ('deleted_at',)
|
||||
actions = BaseModelAdmin.actions + [
|
||||
'make_published', 'make_draft', 'make_cancelled', 'make_completed', 'restore_events',
|
||||
'make_published', 'make_draft', 'make_cancelled', 'restore_events',
|
||||
]
|
||||
|
||||
@admin.display(description='Status')
|
||||
def status_display(self, obj):
|
||||
return obj.status_label
|
||||
|
||||
@admin.display(description='Price')
|
||||
def price_display(self, obj):
|
||||
return obj.price if obj.price is not None else 'رایگان'
|
||||
@@ -70,30 +75,25 @@ class EventAdmin(BaseModelAdmin, ImportExportModelAdmin):
|
||||
|
||||
@admin.action(description='Mark selected events as published')
|
||||
def make_published(self, request, queryset):
|
||||
queryset.update(status=Event.StatusChoices.PUBLISHED)
|
||||
self.message_user(request, f'Published {queryset.count()} events.')
|
||||
count = queryset.update(is_published=True)
|
||||
self.message_user(request, f'Published {count} events.')
|
||||
|
||||
@admin.action(description='Mark selected events as draft')
|
||||
def make_draft(self, request, queryset):
|
||||
queryset.update(status=Event.StatusChoices.DRAFT)
|
||||
self.message_user(request, f'Marked {queryset.count()} events as draft.')
|
||||
count = queryset.update(is_published=False)
|
||||
self.message_user(request, f'Marked {count} events as draft.')
|
||||
|
||||
@admin.action(description='Mark selected events as cancelled')
|
||||
def make_cancelled(self, request, queryset):
|
||||
count = 0
|
||||
for event in queryset:
|
||||
if event.status != Event.StatusChoices.CANCELLED:
|
||||
event.status = Event.StatusChoices.CANCELLED
|
||||
event.save(update_fields=['status'])
|
||||
if not event.is_cancelled:
|
||||
event.is_cancelled = True
|
||||
event.save(update_fields=['is_cancelled', 'updated_at'])
|
||||
cancel_event_checkouts(event.pk)
|
||||
count += 1
|
||||
self.message_user(request, f'Cancelled {count} events.')
|
||||
|
||||
@admin.action(description='Mark selected events as completed')
|
||||
def make_completed(self, request, queryset):
|
||||
queryset.update(status=Event.StatusChoices.COMPLETED)
|
||||
self.message_user(request, f'Completed {queryset.count()} events.')
|
||||
|
||||
@admin.action(description='Restore selected events')
|
||||
def restore_events(self, request, queryset):
|
||||
for event in queryset:
|
||||
@@ -101,11 +101,11 @@ class EventAdmin(BaseModelAdmin, ImportExportModelAdmin):
|
||||
self.message_user(request, f'Restored {queryset.count()} events.')
|
||||
|
||||
def save_model(self, request, obj, form, change):
|
||||
previous_status = None
|
||||
was_cancelled = None
|
||||
if change and obj.pk:
|
||||
previous_status = Event.all_objects.filter(pk=obj.pk).values_list("status", flat=True).first()
|
||||
was_cancelled = Event.all_objects.filter(pk=obj.pk).values_list("is_cancelled", flat=True).first()
|
||||
super().save_model(request, obj, form, change)
|
||||
if previous_status != Event.StatusChoices.CANCELLED and obj.status == Event.StatusChoices.CANCELLED:
|
||||
if was_cancelled is False and obj.is_cancelled:
|
||||
cancel_event_checkouts(obj.pk)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user