from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status from .models import UserData, AIKey, AppVersion, Contact from django.shortcuts import get_object_or_404 from .serializers import ContactSerializer, ExpenseRequestSerializer from rest_framework.generics import CreateAPIView, GenericAPIView import uuid from .models import ExpenseLog from django.apps import apps import re class UserDataPostView(APIView): def post(self, request): user_id = request.data.get("user_id") if not user_id: return Response( {"error": "user_id is required"}, status=status.HTTP_400_BAD_REQUEST, ) obj, created = UserData.objects.get_or_create(user_id=user_id) # Always regenerate backup key obj.data_backup_key = str(uuid.uuid4()) updated = False for key in ["expenses", "salary", "category", "user_data"]: if key in request.data and getattr(obj, key) != request.data[key]: setattr(obj, key, request.data[key]) updated = True obj.save() # Save once after changes # AI key logic if obj.has_ai_access: AI_KEY = get_object_or_404(AIKey, isActive=True).aikey else: AI_KEY = None return Response( { "message": ( "Data created successfully" if created else "Data updated successfully" if updated else "No changes made" ), "app_version": get_object_or_404(AppVersion, isActive=True).version, "has_music_url_access": obj.has_music_url_access, "has_ai_access": obj.has_ai_access, "ai_key": AI_KEY, "data_backup_key": obj.data_backup_key, }, status=status.HTTP_201_CREATED if created else status.HTTP_200_OK, ) class GetFieldView(APIView): def get(self, request, field, identifier): # identifier can be user_id OR data_backup_key obj = ( UserData.objects.filter(user_id=identifier).first() or UserData.objects.filter(data_backup_key=identifier).first() ) if not obj: return Response({"error": "User not found"}, status=404) if field == "all": data = { "userData": obj.user_data, "expenseData": obj.expenses, "categoryData": obj.category, "salaryData": obj.salary, } return Response(data) if hasattr(obj, field): return Response({field: getattr(obj, field)}) return Response({"error": "Invalid field"}, status=status.HTTP_400_BAD_REQUEST) class ContactList1(CreateAPIView): queryset = Contact.objects.all() serializer_class = ContactSerializer def create(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) if serializer.is_valid(): serializer.save() return Response( {"message": "Contact saved successfully"}, status=status.HTTP_201_CREATED, ) return Response( {"message": "Validation failed", "errors": serializer.errors}, status=status.HTTP_400_BAD_REQUEST, ) class CategorizeExpenseView(GenericAPIView): # 2. Assign the serializer class to automatically populate the Swagger schema serializer_class = ExpenseRequestSerializer def post(self, request): # 3. Validate input using the serializer serializer = self.get_serializer(data=request.data) if not serializer.is_valid(): return Response(serializer.errors, status=400) expense_text = serializer.validated_data["text"] # 4. Extract Amount using Regex # Matches formats like 150, 1,500, 150.50, 1,500.50 amount_match = re.search(r"\d+(?:,\d+)*(?:\.\d+)?", expense_text) extracted_amount = ( float(amount_match.group().replace(",", "")) if amount_match else None ) # 5. Use the safe Django app registry to fetch the pre-loaded AI model api_config = apps.get_app_config("api") result = api_config.classifier( expense_text, candidate_labels=api_config.categories, hypothesis_template="This expense is for {}.", ) top_category = result["labels"][0] confidence_score = result["scores"][0] # 6. Save to database ExpenseLog.objects.create( text=expense_text, amount=extracted_amount, predicted_category=top_category, confidence_score=confidence_score, ) return Response( { "expense": expense_text, "amount": extracted_amount, "category": top_category, "confidence": round(confidence_score * 100, 2), } )