93 lines
3.9 KiB
Python
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})
|