from django.db.models import Count, F, Q EVENT_STATUS_LABELS = { "draft": "پیش‌نویس", "cancelled": "لغو شده", "completed": "برگزار شده", "in_progress": "در حال برگزاری", "registration_closed": "پایان ثبت‌نام", "full": "تکمیل ظرفیت", "registration_open": "در حال ثبت‌نام", "upcoming": "به‌زودی", } PUBLIC_EVENT_STATUSES = tuple(key for key in EVENT_STATUS_LABELS if key != "draft") def active_registration_count_annotation(*, now, relation="registrations"): return Count( relation, filter=Q(**{f"{relation}__is_deleted": False}) & ( Q(**{f"{relation}__status__in": ["confirmed", "attended"]}) | Q( **{ f"{relation}__status": "pending", f"{relation}__checkout_expires_at__gt": now, } ) ), distinct=True, ) def event_status_filter(status, *, now, prefix="", count_field="browse_registration_count"): """Return a queryset condition for a derived event status. The caller should restrict the queryset to published events and annotate the active registration count using ``count_field`` before applying this filter. """ def field(name): return f"{prefix}{name}" count = F(count_field) before_event_start = Q(**{f"{field('start_time')}__gt": now}) deadline_open = Q(**{f"{field('registration_end_date')}__isnull": True}) | Q( **{f"{field('registration_end_date')}__gt": now} ) if status == "cancelled": return Q(**{field("is_cancelled"): True}) if status == "completed": return Q(**{f"{field('end_time')}__lte": now}) & Q(**{field("is_cancelled"): False}) if status == "in_progress": return ( Q(**{f"{field('start_time')}__lte": now}) & Q(**{f"{field('end_time')}__gt": now}) & Q(**{field("is_cancelled"): False}) ) if status == "registration_closed": return ( before_event_start & Q(**{f"{field('registration_end_date')}__lte": now}) & Q(**{field("is_cancelled"): False}) ) if status == "full": return ( before_event_start & deadline_open & Q(**{f"{field('capacity')}__isnull": False}) & Q(**{f"{field('capacity')}__lte": count}) & Q(**{field("is_cancelled"): False}) ) if status == "registration_open": registration_started = Q(**{f"{field('registration_start_date')}__isnull": True}) | Q( **{f"{field('registration_start_date')}__lte": now} ) capacity_available = Q(**{f"{field('capacity')}__isnull": True}) | Q( **{f"{field('capacity')}__gt": count} ) return ( before_event_start & registration_started & deadline_open & capacity_available & Q(**{field("is_cancelled"): False}) ) if status == "upcoming": registration_not_started = Q(**{f"{field('registration_start_date')}__gt": now}) capacity_available = Q(**{f"{field('capacity')}__isnull": True}) | Q( **{f"{field('capacity')}__gt": count} ) return ( before_event_start & registration_not_started & deadline_open & capacity_available & Q(**{field("is_cancelled"): False}) ) raise ValueError(f"Unsupported event status: {status}")