Files
shopship/apps/messaging/api/views.py
T
2026-08-24 15:54:08 +03:30

93 lines
3.9 KiB
Python

from django.db.models import Count
from rest_framework import status
from rest_framework.exceptions import NotFound, ValidationError
from rest_framework.generics import RetrieveAPIView
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from apps.banker.models import ContactGroup
from apps.billing.permissions import HasActiveFeature
from apps.messaging.models import BulkMessage, MessageRecipient
from .serializers import BulkMessageSerializer, SendBulkMessageSerializer
from .services import BulkMessageService
class SendBulkMessageView(APIView):
"""POST: می‌سازد و بلافاصله dispatch می‌کند (پیامک/کانال‌های Business-API-دار
خودکار، بقیه needs_manual برای صف deep-link سمت اپ)."""
permission_classes = [IsAuthenticated, HasActiveFeature]
feature_key = "sms_bank"
throttle_scope = "messaging_send"
def post(self, request):
serializer = SendBulkMessageSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
data = serializer.validated_data
if data["group_id"] and not ContactGroup.objects.filter(user=request.user, id=data["group_id"]).exists():
raise ValidationError({"group_id": "گروه یافت نشد."})
bulk = BulkMessageService.create_and_dispatch(
user=request.user,
channels=data["channels"],
group_id=data["group_id"],
contact_ids=data["contact_ids"],
template_id=data["template_id"],
body_override=data["body_override"],
)
return Response(BulkMessageSerializer(bulk).data, status=status.HTTP_201_CREATED)
class BulkMessageDetailView(RetrieveAPIView):
serializer_class = BulkMessageSerializer
permission_classes = [IsAuthenticated]
def get_queryset(self):
return BulkMessage.objects.filter(user=self.request.user)
class MessagingStatsView(APIView):
"""آمار ارسال: چند پیام موفق به گیت‌وی/API فرستاده شده، چند تا ناموفق
بوده، چند تا نیاز به تایید دستی داشته/دارد — بر اساس MessageRecipient
(نه رسید تحویل واقعی گوشی، چون آن نیاز به webhook از سرویس‌دهنده‌ی
پیامک دارد که در این نسخه وصل نشده؛ «ارسال‌شده» یعنی سرور با موفقیت آن
را به API/گیت‌وی تحویل داده)."""
permission_classes = [IsAuthenticated, HasActiveFeature]
feature_key = "sms_bank"
def get(self, request):
rows = (
MessageRecipient.objects.filter(bulk_message__user=request.user)
.values("status")
.annotate(count=Count("id"))
)
counts = {row["status"]: row["count"] for row in rows}
total = sum(counts.values())
return Response(
{
"total": total,
"sent": counts.get(MessageRecipient.Status.SENT, 0),
"failed": counts.get(MessageRecipient.Status.FAILED, 0),
"needs_manual": counts.get(MessageRecipient.Status.NEEDS_MANUAL, 0),
"manual_confirmed": counts.get(MessageRecipient.Status.MANUAL_CONFIRMED, 0),
}
)
class ConfirmManualSendView(APIView):
"""اپ بعد از این‌که کاربر دستی در واتساپ/تلگرام/بله/ایتا زد «ارسال»، این را صدا می‌زند."""
permission_classes = [IsAuthenticated, HasActiveFeature]
feature_key = "sms_bank"
def post(self, request, bulk_id, recipient_id):
try:
recipient = BulkMessageService.confirm_manual(request.user, bulk_id, recipient_id)
except MessageRecipient.DoesNotExist:
raise NotFound("گیرنده یافت نشد.")
return Response({"success": True, "status": recipient.status})