from django.db.models import BooleanField, Case, F, Manager, Q, QuerySet, Sum, Value, When from django.db.models.functions import Coalesce from django.utils.timezone import now class GatewayQuerySet(QuerySet): def with_usage_sums(self) -> QuerySet: today = now().date() current_month_start = today.replace(day=1) return self.annotate( daily_sum=Coalesce(Sum("transactions__amount", filter=Q(transactions__created__date=today)), Value(0.0)), monthly_sum=Coalesce( Sum("transactions__amount", filter=Q(transactions__created__gte=current_month_start)), Value(0.0) ), ) def can_be_used(self) -> QuerySet: qs = self.with_usage_sums() qs = qs.annotate( daily_ok=Case( When(daily_limit=0, then=Value(True)), When(daily_sum__lt=F("daily_limit"), then=Value(True)), default=Value(False), output_field=BooleanField(), ), monthly_ok=Case( When(monthly_limit=0, then=Value(True)), When(monthly_sum__lt=F("monthly_limit"), then=Value(True)), default=Value(False), output_field=BooleanField(), ), ) return qs.annotate( can_be_used=Case( When(daily_ok=True, monthly_ok=True, is_active=True, then=Value(True)), default=Value(False), output_field=BooleanField(), ) ).order_by("-priority") class GatewayManager(Manager.from_queryset(GatewayQuerySet)): def get_queryset(self) -> QuerySet: return super().get_queryset().can_be_used()