from rest_framework import generics, status from rest_framework.exceptions import ValidationError from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from rest_framework.views import APIView from apps.banker.models import ( Contact, ContactField, ContactGroup, MessageTemplate, StructuredTemplate, StructuredTemplateField, ) from apps.billing.permissions import HasActiveFeature from .crud_serializers import ( ContactCrudSerializer, ContactFieldCrudSerializer, ContactGroupCrudSerializer, MessageTemplateCrudSerializer, StructuredTemplateCrudSerializer, StructuredTemplateFieldCrudSerializer, ) from .serializers import BackupSerializer from .services import BackupService, GroupService class BackupView(APIView): """ پشتیبان‌گیری/بازیابی کامل مخاطبین، فیلدهای دلخواه، گروه‌ها و قالب‌های کاربر. GET -> آخرین نسخه‌ی ذخیره‌شده روی سرور را برمی‌گرداند (برای بازیابی روی گوشی جدید) POST -> دیتای فعلی اپ را می‌فرستد و کامل جایگزین نسخه‌ی قبلی روی سرور می‌شود (منبع حقیقت خود اپ روی گوشی است، نه سرور) """ # عمداً HasActiveFeature ندارد — بک‌آپ صادرات/وارد کردن خامِ داده‌ی خود # کاربر است (مثلا موقع عوض‌کردن گوشی)، نه استفاده از ریزاپ؛ گروگان‌گرفتن # دیتای کاربر پشت پولی‌بودن اشتراک درست نیست. permission_classes = [IsAuthenticated] throttle_scope = "backup" def get(self, request): snapshot = BackupService.build_snapshot(request.user) return Response({"success": True, "data": snapshot}) def post(self, request): serializer = BackupSerializer(data=request.data) serializer.is_valid(raise_exception=True) snapshot = BackupService.replace_snapshot(request.user, serializer.validated_data) return Response( {"success": True, "message": "پشتیبان‌گیری با موفقیت انجام شد.", "data": snapshot}, status=status.HTTP_200_OK, ) # -------------------- CRUD واقعی (تکی، نه replace کامل) -------------------- # همه‌ی ویوهای زیر روی request.user فیلتر می‌شوند و مالکیت رکورد را # مستقل از ورودی کاربر تضمین می‌کنند. class ContactGroupListCreateView(generics.ListCreateAPIView): """GET: لیست گروه‌های کاربر (گروه عمومی هم اگر نبود ساخته می‌شود). POST: گروه جدید.""" serializer_class = ContactGroupCrudSerializer permission_classes = [IsAuthenticated, HasActiveFeature] feature_key = "sms_bank" def get_queryset(self): GroupService.get_or_create_general(self.request.user) return ContactGroup.objects.filter(user=self.request.user) def perform_create(self, serializer): serializer.save(user=self.request.user) class ContactGroupDetailView(generics.RetrieveUpdateDestroyAPIView): serializer_class = ContactGroupCrudSerializer permission_classes = [IsAuthenticated, HasActiveFeature] feature_key = "sms_bank" def get_queryset(self): return ContactGroup.objects.filter(user=self.request.user) def perform_destroy(self, instance): if instance.is_general: raise ValidationError({"detail": "گروه عمومی قابل حذف نیست."}) instance.delete() class GroupFieldListCreateView(generics.ListCreateAPIView): """فیلدهای سفارشی یک گروه مشخص — /groups//fields/""" serializer_class = ContactFieldCrudSerializer permission_classes = [IsAuthenticated, HasActiveFeature] feature_key = "sms_bank" def get_queryset(self): return ContactField.objects.filter( user=self.request.user, group_id=self.kwargs["group_id"] ) def perform_create(self, serializer): serializer.save(user=self.request.user) class ContactFieldDetailView(generics.RetrieveUpdateDestroyAPIView): serializer_class = ContactFieldCrudSerializer permission_classes = [IsAuthenticated, HasActiveFeature] feature_key = "sms_bank" def get_queryset(self): return ContactField.objects.filter(user=self.request.user) class ContactListCreateView(generics.ListCreateAPIView): serializer_class = ContactCrudSerializer permission_classes = [IsAuthenticated, HasActiveFeature] feature_key = "sms_bank" def get_queryset(self): return Contact.objects.filter(user=self.request.user) def perform_create(self, serializer): serializer.save(user=self.request.user) class ContactDetailView(generics.RetrieveUpdateDestroyAPIView): serializer_class = ContactCrudSerializer permission_classes = [IsAuthenticated, HasActiveFeature] feature_key = "sms_bank" def get_queryset(self): return Contact.objects.filter(user=self.request.user) class MessageTemplateListCreateView(generics.ListCreateAPIView): serializer_class = MessageTemplateCrudSerializer permission_classes = [IsAuthenticated, HasActiveFeature] feature_key = "sms_bank" def get_queryset(self): return MessageTemplate.objects.filter(user=self.request.user) def perform_create(self, serializer): serializer.save(user=self.request.user) class MessageTemplateDetailView(generics.RetrieveUpdateDestroyAPIView): serializer_class = MessageTemplateCrudSerializer permission_classes = [IsAuthenticated, HasActiveFeature] feature_key = "sms_bank" def get_queryset(self): return MessageTemplate.objects.filter(user=self.request.user) class StructuredTemplateListCreateView(generics.ListCreateAPIView): serializer_class = StructuredTemplateCrudSerializer permission_classes = [IsAuthenticated, HasActiveFeature] feature_key = "sms_bank" def get_queryset(self): return StructuredTemplate.objects.filter(user=self.request.user) def perform_create(self, serializer): serializer.save(user=self.request.user) class StructuredTemplateDetailView(generics.RetrieveUpdateDestroyAPIView): serializer_class = StructuredTemplateCrudSerializer permission_classes = [IsAuthenticated, HasActiveFeature] feature_key = "sms_bank" def get_queryset(self): return StructuredTemplate.objects.filter(user=self.request.user) class StructuredTemplateFieldListCreateView(generics.ListCreateAPIView): """فیلدهای یک قالب کلید-مقدار مشخص — /structured-templates//fields/""" serializer_class = StructuredTemplateFieldCrudSerializer permission_classes = [IsAuthenticated, HasActiveFeature] feature_key = "sms_bank" def get_queryset(self): return StructuredTemplateField.objects.filter( template__user=self.request.user, template_id=self.kwargs["template_id"] ) def perform_create(self, serializer): serializer.save() class StructuredTemplateFieldDetailView(generics.RetrieveUpdateDestroyAPIView): serializer_class = StructuredTemplateFieldCrudSerializer permission_classes = [IsAuthenticated, HasActiveFeature] feature_key = "sms_bank" def get_queryset(self): return StructuredTemplateField.objects.filter(template__user=self.request.user)