diff --git a/backend/api/account/client/views.py b/backend/api/account/client/views.py index 9e66d5f..318f930 100644 --- a/backend/api/account/client/views.py +++ b/backend/api/account/client/views.py @@ -18,12 +18,13 @@ from .serializers import RouteSerializer, CreateRouteSerializer, CitySerializer, from api.auth.serializers import UserResponseSerializer from api.models import UserProfile from routes.models import Route, City, Country, Leads -from sitemanagement.models import Pricing, RoutePromotionLog +from sitemanagement.models import Pricing, RoutePromotionLog, Transactions from api.utils.decorators import handle_exceptions from api.utils.emailSender import send_email from api.utils.permissionChecker import check_monthly_limit + class UserDataView(ViewSet): """Эндпоинт для наполнения стора фронта данными""" permission_classes = [IsAuthenticated] @@ -175,20 +176,41 @@ class CountryView(ViewSet): class ChangeUserMembership(ViewSet): """Меняем тарифный план пользователя""" - - @action(detail=False, methods=['post']) + permission_classes = [IsAuthenticated] + + @action(detail=False, methods=['patch']) @handle_exceptions def change_plan(self, request): """Меняем пользователю тарифный план""" user = request.user user_profile = get_object_or_404(UserProfile, user=user) + # преобразуем plan в account_type если нужно + if 'plan' in request.data and 'account_type' not in request.data: + request.data['account_type'] = request.data['plan'] + serializer = PlanChangeSerializer(user_profile, data=request.data) if serializer.is_valid(): - serializer.save() - return Response({"message": "Тариф успешно изменен"}, status=status.HTTP_200_OK) - + # получаем объект тарифного плана + new_plan = get_object_or_404(Pricing, plan=serializer.validated_data['account_type']) + + # создаем транзакцию + transaction = Transactions.objects.create( + user=user, + plan=new_plan, + amount=new_plan.price, + status='success' + ) + + # если транзакция успешно создана, меняем тариф + if transaction: + serializer.save() + return Response({ + "message": "Тариф успешно изменен", + "account_type": serializer.validated_data['account_type'] + }, status=status.HTTP_200_OK) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) class GetMembershipData(ViewSet): diff --git a/backend/api/utils/permissionChecker.py b/backend/api/utils/permissionChecker.py index d63ea52..123f2ce 100644 --- a/backend/api/utils/permissionChecker.py +++ b/backend/api/utils/permissionChecker.py @@ -1,29 +1,47 @@ from django.utils.timezone import now from datetime import timedelta from django.core.exceptions import ObjectDoesNotExist -from sitemanagement.models import RoutePromotionLog, Pricing +from sitemanagement.models import RoutePromotionLog, Pricing, Transactions from api.models import UserProfile def check_monthly_limit(user, route, action_type): try: - month_ago = now() - timedelta(days=30) - # получаем профиль пользователя и его тарифный план user_profile = UserProfile.objects.get(user=user) pricing_plan = Pricing.objects.get(plan=user_profile.account_type) + # получаем последнюю успешную транзакцию пользователя + last_transaction = Transactions.objects.filter( + user=user, + plan=pricing_plan, + status='success' # предполагаем, что успешные транзакции имеют статус 'success' + ).order_by('-created_at').first() + + if not last_transaction: + return False + + # определяем период действия подписки + subscription_start = last_transaction.created_at + subscription_period = timedelta(hours=pricing_plan.duration_hours) + subscription_end = subscription_start + subscription_period + + # проверяем, не истекла ли подписка + if now() > subscription_end: + return False + # определяем лимит в зависимости от типа действия и тарифного плана if action_type == 'highlight': action_limit = pricing_plan.highlight_limit else: # rising action_limit = pricing_plan.rising_limit - # проверяем количество действий за последний месяц + # проверяем количество действий за текущий период подписки actions_count = RoutePromotionLog.objects.filter( user=user, route=route, action_type=action_type, - created_at__gte=month_ago + created_at__gte=subscription_start, + created_at__lte=subscription_end ).count() return actions_count < action_limit