Features: 1) Add LimitsType GraphQL object and payments_limits query to expose deposit limits; 2) Introduce LimitsSerializer and LimitsAPIView for retrieving minimal and maximal deposit amounts; 3) Implement get_limits utility to calculate deposit boundaries dynamically;

Fixes: 1) Add missing `LimitsSerializer` import in `drf.views` module;

Extra: 1) Update `.gitignore` to exclude `queries`; 2) Refactor schema and views to integrate new limits functionality.
This commit is contained in:
Egor Pavlovich Gorbunov 2025-12-08 10:48:22 +03:00
parent 5b3a8aedbe
commit 87ba06ff0c
8 changed files with 67 additions and 5 deletions

3
.gitignore vendored
View file

@ -167,4 +167,5 @@ cypress/screenshots/
test.ipynb
# Production stuff
.initialized
.initialized
queries

View file

@ -83,6 +83,8 @@ from engine.core.utils import get_project_parameters
from engine.core.utils.languages import get_flag_by_language
from engine.core.utils.messages import permission_denied_message
from engine.payments.graphene.mutations import Deposit
from engine.payments.graphene.object_types import LimitsType
from engine.payments.utils.gateways import get_limits
from engine.vibes_auth.filters import UserFilter
from engine.vibes_auth.graphene.mutations import (
ActivateUser,
@ -105,6 +107,7 @@ logger = logging.getLogger(__name__)
class Query(ObjectType):
parameters = Field(ConfigType)
languages = List(LanguageType)
payments_limits = Field(LimitsType)
products = DjangoFilterConnectionField(ProductType, filterset_class=ProductFilter)
orders = DjangoFilterConnectionField(OrderType, filterset_class=OrderFilter)
users = DjangoFilterConnectionField(UserType, filterset_class=UserFilter)
@ -140,6 +143,11 @@ class Query(ObjectType):
return languages
@staticmethod
def resolve_payments_limits(_parent, _info):
min_amount, max_amount = get_limits()
return {"min_amount": min_amount, "max_amount": max_amount}
@staticmethod
def resolve_products(_parent, info, **kwargs):
if info.context.user.is_authenticated and kwargs.get("uuid"):

View file

@ -3,7 +3,7 @@ from drf_spectacular.utils import extend_schema
from rest_framework import status
from engine.core.docs.drf import error
from engine.payments.serializers import DepositSerializer, TransactionProcessSerializer
from engine.payments.serializers import DepositSerializer, TransactionProcessSerializer, LimitsSerializer
DEPOSIT_SCHEMA = {
"post": extend_schema(
@ -20,3 +20,17 @@ DEPOSIT_SCHEMA = {
},
),
}
LIMITS_SCHEMA = {
"get": extend_schema(
tags=[
"payments",
],
summary=_("payment limits"),
description=_("retrieve minimal and maximal allowed deposit amounts across available gateways"),
responses={
status.HTTP_200_OK: LimitsSerializer,
status.HTTP_401_UNAUTHORIZED: error,
},
),
}

View file

@ -7,6 +7,11 @@ from graphene_django import DjangoObjectType
from engine.payments.models import Balance, Transaction
class LimitsType(graphene.ObjectType):
min_amount = graphene.Float()
max_amount = graphene.Float()
class TransactionType(DjangoObjectType):
process = GenericScalar()

View file

@ -29,3 +29,8 @@ class TransactionProcessSerializer(ModelSerializer): # type: ignore [type-arg]
model = Transaction
fields = ("process", "order_hr_id", "order_uuid")
read_only_fields = ("process", "order_hr_id", "order_uuid")
class LimitsSerializer(Serializer): # type: ignore [type-arg]
min_amount = FloatField(read_only=True)
max_amount = FloatField(read_only=True)

View file

@ -1,7 +1,7 @@
from django.urls import include, path
from rest_framework.routers import DefaultRouter
from engine.payments.views import CallbackAPIView, DepositView
from engine.payments.views import CallbackAPIView, DepositView, LimitsAPIView
from engine.payments.viewsets import TransactionViewSet
app_name = "payments"
@ -12,5 +12,6 @@ payment_router.register(prefix=r"transactions", viewset=TransactionViewSet, base
urlpatterns = [
path(r"", include(payment_router.urls)),
path(r"deposit/", DepositView.as_view()),
path(r"limits/", LimitsAPIView.as_view()),
path(r"<str:uuid>/callback/", CallbackAPIView.as_view()),
]

View file

@ -14,3 +14,18 @@ def get_gateways_integrations(name: str | None = None) -> list[Type[AbstractGate
class_name = gateway.integration_path.split(".")[-1]
gateways_integrations.append(create_object(module_name, class_name))
return gateways_integrations
def get_limits() -> tuple[float, float]:
from django.db.models import Min, Max
qs = Gateway.objects.can_be_used().filter(can_be_used=True)
if not qs.exists():
return 0.0, 0.0
agg = qs.aggregate(min_limit=Min("minimum_transaction_amount"), max_limit=Max("maximum_transaction_amount"))
min_limit = float(agg.get("min_limit") or 0.0)
max_limit = float(agg.get("max_limit") or 0.0)
return min_limit, max_limit

View file

@ -9,10 +9,11 @@ from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.views import APIView
from engine.payments.docs.drf.views import DEPOSIT_SCHEMA
from engine.payments.docs.drf.views import DEPOSIT_SCHEMA, LIMITS_SCHEMA
from engine.payments.gateways import UnknownGatewayError
from engine.payments.models import Transaction
from engine.payments.serializers import DepositSerializer, TransactionProcessSerializer
from engine.payments.serializers import DepositSerializer, TransactionProcessSerializer, LimitsSerializer
from engine.payments.utils.gateways import get_limits
logger = logging.getLogger(__name__)
@ -67,3 +68,15 @@ class CallbackAPIView(APIView):
return Response(
status=status.HTTP_500_INTERNAL_SERVER_ERROR, data={"error": str(e), "detail": traceback.format_exc()}
)
@extend_schema_view(**LIMITS_SCHEMA)
class LimitsAPIView(APIView):
__doc__ = _( # type: ignore [assignment]
"This endpoint returns minimal and maximal allowed deposit amounts across available gateways."
)
def get(self, request: Request, *args: list[Any], **kwargs: dict[Any, Any]) -> Response:
min_amount, max_amount = get_limits()
data = {"min_amount": min_amount, "max_amount": max_amount}
return Response(LimitsSerializer(data).data, status=status.HTTP_200_OK)