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__date__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)): # ty:ignore[unsupported-base] def get_queryset(self) -> QuerySet: return super().get_queryset().can_be_used()