diff --git a/backend/api/account/client/views.py b/backend/api/account/client/views.py index d006d18..9e66d5f 100644 --- a/backend/api/account/client/views.py +++ b/backend/api/account/client/views.py @@ -9,17 +9,20 @@ from django.core.validators import validate_email from django.core.exceptions import ValidationError from django.db import models from django.db.models import Q -from datetime import datetime, timedelta -from django.utils import timezone +from datetime import timedelta +from rest_framework.exceptions import PermissionDenied +from django.utils.timezone import now as timezone_now + from .serializers import RouteSerializer, CreateRouteSerializer, CitySerializer, CountrySerializer, PlanChangeSerializer, PricingSerializer, LeadSerializer, LeadResponseSerializer from api.auth.serializers import UserResponseSerializer from api.models import UserProfile from routes.models import Route, City, Country, Leads -from sitemanagement.models import Pricing +from sitemanagement.models import Pricing, RoutePromotionLog 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): """Эндпоинт для наполнения стора фронта данными""" @@ -314,32 +317,54 @@ class LeadViewSet(ViewSet): ) class PremiumMembershipActionsView(ViewSet): - """Выделение объявления""" - + """Выделение и поднятие объявления""" + @action(detail=False, methods=['patch']) @handle_exceptions def highlight_route(self, request): """Выделяем объявление""" route_id = request.data.get('route_id') route = get_object_or_404(Route, id=route_id) - + + if not check_monthly_limit(request.user, route, 'highlight'): + raise PermissionDenied("Превышен лимит выделений за месяц") + # подсвечиваем объявление на 24 часа - now = timezone.now() + now = timezone_now() route.highlight_end_DT = now + timedelta(days=1) route.is_highlighted = True route.save() - + + # логируем действие + RoutePromotionLog.objects.create( + user=request.user, + route=route, + action_type='highlight' + ) + return Response({ "message": "Объявление выделено", "is_highlighted": route.is_highlighted }, status=status.HTTP_200_OK) - + @action(detail=False, methods=['patch']) @handle_exceptions def upper_route(self, request): """Поднимаем объявление""" route_id = request.data.get('route_id') route = get_object_or_404(Route, id=route_id) - route.rising_DT = datetime.now() + + if not check_monthly_limit(request.user, route, 'rising'): + raise PermissionDenied("Превышен лимит поднятий за месяц") + + route.rising_DT = timezone_now() route.save() - return Response({"message": "Объявление поднято"}, status=status.HTTP_200_OK) \ No newline at end of file + + # логируем действие + RoutePromotionLog.objects.create( + user=request.user, + route=route, + action_type='rising' + ) + + return Response({"message": "Объявление поднято"}, status=status.HTTP_200_OK) \ No newline at end of file diff --git a/backend/api/utils/permissionChecker.py b/backend/api/utils/permissionChecker.py new file mode 100644 index 0000000..75e2450 --- /dev/null +++ b/backend/api/utils/permissionChecker.py @@ -0,0 +1,14 @@ +from django.utils.timezone import now +from datetime import timedelta +from sitemanagement.models import RoutePromotionLog + +MAX_ACTIONS_PER_MONTH = 5 + +def check_monthly_limit(user, route, action_type): + month_ago = now() - timedelta(days=30) + return RoutePromotionLog.objects.filter( + user=user, + route=route, + action_type=action_type, + created_at__gte=month_ago + ).count() < MAX_ACTIONS_PER_MONTH \ No newline at end of file diff --git a/backend/sitemanagement/models.py b/backend/sitemanagement/models.py index 50a4664..516bc49 100644 --- a/backend/sitemanagement/models.py +++ b/backend/sitemanagement/models.py @@ -7,6 +7,7 @@ from django.dispatch import receiver from transliterate import translit from routes.constants.account_types import account_types from django.contrib.auth.models import User +from routes.models import Route class FAQ (models.Model): title = models.CharField(max_length=250) @@ -89,4 +90,17 @@ class Transactions(models.Model): def __str__(self): return f'{self.user} - {self.amount}' - \ No newline at end of file + +class RoutePromotionLog(models.Model): + ACTION_CHOICES = [ + ('highlight', 'Выделение'), + ('rising', 'Поднятие'), + ] + + route = models.ForeignKey(Route, on_delete=models.CASCADE, related_name='promotion_logs') + user = models.ForeignKey(User, on_delete=models.CASCADE) + action_type = models.CharField(max_length=20, choices=ACTION_CHOICES) + created_at = models.DateTimeField(auto_now_add=True) + + def __str__(self): + return f"{self.user} - {self.action_type} for route {self.route.id} at {self.created_at}" \ No newline at end of file