Fixes: 1) Default to a usable `Gateway` when processing new transactions if none is specified. Extra: 1) Add missing import for `GatewayManager` in `payments.models`; 2) Refactor gateway availability logic into the manager and query set for cleaner code organization.
44 lines
1.7 KiB
Python
44 lines
1.7 KiB
Python
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()
|