| 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) |
|
|
| |
| 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() |
|
|
| |
| 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): |
| |
| 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): |
| |
| serializer_class = ExpenseRequestSerializer |
|
|
| def post(self, request): |
| |
| serializer = self.get_serializer(data=request.data) |
| if not serializer.is_valid(): |
| return Response(serializer.errors, status=400) |
|
|
| expense_text = serializer.validated_data["text"] |
|
|
| |
| |
| amount_match = re.search(r"\d+(?:,\d+)*(?:\.\d+)?", expense_text) |
| extracted_amount = ( |
| float(amount_match.group().replace(",", "")) if amount_match else None |
| ) |
|
|
| |
| 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] |
|
|
| |
| 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), |
| } |
| ) |
|
|