[ADD] GEOFENCING & FACEDETECTION: Add modules for geofencing and facedetection app api's for mobile app (beta)

This commit is contained in:
Horilla
2025-04-28 17:39:24 +05:30
parent c5ccc04416
commit 0113e84548
19 changed files with 312 additions and 0 deletions

View File

7
facedetection/admin.py Normal file
View File

@@ -0,0 +1,7 @@
from django.contrib import admin
from .models import *
# Register your models here.
admin.site.register(FaceDetection)
admin.site.register(EmployeeFaceDetection)

15
facedetection/apps.py Normal file
View File

@@ -0,0 +1,15 @@
from django.apps import AppConfig
class FacedetectionConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'facedetection'
def ready(self):
from django.urls import include, path
from horilla.urls import urlpatterns
urlpatterns.append(
path("api/facedetection/", include("facedetection.urls")),
)
super().ready()

View File

20
facedetection/models.py Normal file
View File

@@ -0,0 +1,20 @@
from django.db import models
# Create your models here.
class FaceDetection(models.Model):
company_id = models.OneToOneField("base.Company", related_name="face_detection", on_delete=models.CASCADE)
start = models.BooleanField(default=False)
class EmployeeFaceDetection(models.Model):
employee_id = models.OneToOneField("employee.Employee", related_name="face_detection", on_delete=models.CASCADE)
image = models.ImageField()

View File

@@ -0,0 +1,8 @@
from rest_framework import serializers
from .models import *
class EmployeeFaceDetectionSerializer(serializers.ModelSerializer):
class Meta:
model = EmployeeFaceDetection
fields = '__all__'

3
facedetection/tests.py Normal file
View File

@@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

7
facedetection/urls.py Normal file
View File

@@ -0,0 +1,7 @@
from django.urls import path
from .views import *
urlpatterns = [
path("setup/", FaceDetectionGetPostAPIView.as_view())
]

30
facedetection/views.py Normal file
View File

@@ -0,0 +1,30 @@
from django.shortcuts import render
from rest_framework.views import APIView
from .serializers import *
from rest_framework.response import Response
from rest_framework import status
from rest_framework.permissions import IsAuthenticated
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator
from django.http import QueryDict
class FaceDetectionGetPostAPIView(APIView):
permission_classes = [IsAuthenticated]
@method_decorator(csrf_exempt)
def dispatch(self, *args, **kwargs):
return super().dispatch(*args, **kwargs)
def post(self, request):
employee_id = request.user.employee_get.id
data = request.data
if isinstance(data, QueryDict):
data = data.dict()
data["employee_id"] = employee_id
serializer = EmployeeFaceDetectionSerializer(data=data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

0
geofencing/__init__.py Normal file
View File

5
geofencing/admin.py Normal file
View File

@@ -0,0 +1,5 @@
from django.contrib import admin
from .models import GeoFencing
# Register your models here.
admin.site.register(GeoFencing)

15
geofencing/apps.py Normal file
View File

@@ -0,0 +1,15 @@
from django.apps import AppConfig
class GeofencingConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'geofencing'
def ready(self):
from django.urls import include, path
from horilla.urls import urlpatterns
urlpatterns.append(
path("api/geofencing/", include("geofencing.urls")),
)
super().ready()

View File

31
geofencing/models.py Normal file
View File

@@ -0,0 +1,31 @@
from django.db import models
from base.models import Company
from django.core.exceptions import ValidationError
from geopy.geocoders import Nominatim
class GeoFencing(models.Model):
latitude = models.FloatField(max_length=100)
longitude = models.FloatField(max_length=100)
radius_in_meters = models.IntegerField()
company_id = models.OneToOneField("base.Company", related_name="geo_fencing", on_delete=models.CASCADE, blank=True, null=True)
start = models.BooleanField(default=False)
def clean(self):
geolocator = Nominatim(user_agent="geo_checker") # Use a unique user-agent
try:
location = geolocator.reverse((self.latitude, self.longitude), exactly_one=True)
if location:
pass
else:
raise ValidationError("Invalid Location")
except Exception as e:
raise ValidationError(e)
return super().clean()
def save_base(self, raw = ..., force_insert = ..., force_update = ..., using = ..., update_fields = ...):
self.clean()
return super().save_base(raw, force_insert, force_update, using, update_fields)

27
geofencing/serializers.py Normal file
View File

@@ -0,0 +1,27 @@
from rest_framework import serializers
from .models import GeoFencing
from geopy.geocoders import Nominatim
class GeoFencingSetupSerializer(serializers.ModelSerializer):
class Meta:
model = GeoFencing
fields = '__all__'
def validate(self, data):
geolocator = Nominatim(user_agent="geo_checker") # Use a unique user-agent
try:
latitude = data.get("latitude")
longitude = data.get("longitude")
location = geolocator.reverse((latitude, longitude), exactly_one=True)
if not location:
raise serializers.ValidationError("Invalid Location")
except Exception as e:
raise serializers.ValidationError(e)
return data
class EmployeeLocationSerializer(serializers.ModelSerializer):
class Meta:
model = GeoFencing
fields = ['latitude', 'longitude']

3
geofencing/tests.py Normal file
View File

@@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

9
geofencing/urls.py Normal file
View File

@@ -0,0 +1,9 @@
from django.urls import path
from .views import *
urlpatterns = [
path("setup/", GeoFencingSetupGetPostAPIView.as_view()),
path("setup/<int:pk>/", GeoFencingSetupPutDeleteAPIView.as_view()),
path("setup-check/", GeoFencingSetUpPermissionCheck.as_view()),
]

128
geofencing/views.py Normal file
View File

@@ -0,0 +1,128 @@
from geopy.distance import geodesic
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import GeoFencing
from .serializers import *
from rest_framework.permissions import IsAuthenticated
from rest_framework.pagination import PageNumberPagination
from django.contrib.auth.decorators import permission_required
from django.utils.decorators import method_decorator
from django.http import QueryDict
class GeoFencingSetupGetPostAPIView(APIView):
permission_classes = [IsAuthenticated]
@method_decorator(
permission_required("geofencing.view_geofencing", raise_exception=True), name="dispatch"
)
def get(self, request):
if request.user.is_superuser:
location = GeoFencing.objects.all()
else:
company = request.user.employee_get.get_company()
location = company.geo_fencing.all()
paginator = PageNumberPagination()
page = paginator.paginate_queryset(location, request)
serializer = GeoFencingSetupSerializer(page, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
@method_decorator(
permission_required("geofencing.add_geofencing", raise_exception=True), name="dispatch"
)
def post(self, request):
data = request.data
if not request.user.is_superuser:
if isinstance(data, QueryDict):
data = data.dict()
company = request.user.employee_get.get_company()
if company:
data["company_id"] = company.id
serializer = GeoFencingSetupSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class GeoFencingSetupPutDeleteAPIView(APIView):
permission_classes = [IsAuthenticated]
def get_location(self, pk):
try:
return GeoFencing.objects.get(pk=pk)
except Exception as e:
raise serializers.ValidationError(e)
@method_decorator(
permission_required("geofencing.change_geofencing", raise_exception=True), name="dispatch"
)
def put(self, request, pk):
location = self.get_location(pk)
company = request.user.employee_get.get_company()
if request.user.is_superuser or company == location.company_id:
serializer = GeoFencingSetupSerializer(location, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
raise serializers.ValidationError("Access Denied..")
@method_decorator(
permission_required("geofencing.delete_geofencing", raise_exception=True), name="dispatch"
)
def delete(self, request, pk):
location = self.get_location(pk)
company = request.user.employee_get.get_company()
if request.user.is_superuser or company == location.company_id:
location.delete()
return Response({"message": "GeoFencing location deleted successfully"}, status=status.HTTP_204_NO_CONTENT)
raise serializers.ValidationError("Access Denied..")
class GeoFencingEmployeeLocationCheckAPIView(APIView):
permission_classes = [IsAuthenticated]
def get_company(self, request):
try:
company = request.user.employee_get.get_company()
return company
except Exception as e:
raise serializers.ValidationError(e)
def get_company_location(self, request):
company = self.get_company(request)
try:
location = GeoFencing.objects.get(company_id=company)
return location
except Exception as e:
raise serializers.ValidationError(e)
def post(self, request):
serializer = EmployeeLocationSerializer(data=request.data)
if serializer.is_valid():
company_location = self.get_company_location(request)
geofence_center = (company_location.latitude, company_location.longitude)
employee_location = (request.data.get("latitude"), request.data.get("longitude"))
distance = geodesic(geofence_center, employee_location).meters
if distance <= company_location.radius_in_meters:
return Response({"message": "Inside the geofence"}, status=status.HTTP_200_OK)
return Response({"message": "Outside the geofence"}, status=status.HTTP_400_BAD_REQUEST)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class GeoFencingSetUpPermissionCheck(APIView):
permission_classes = [IsAuthenticated]
def get(self, request):
geo_fencing = GeoFencingSetupGetPostAPIView()
if geo_fencing.get(request).status_code == 200:
return Response(status=200)
return Response(status=400)

View File

@@ -0,0 +1,4 @@
from horilla.settings import INSTALLED_APPS
INSTALLED_APPS.append("geofencing")
INSTALLED_APPS.append("facedetection")