[UPDT] ATTENDANCE: Geofencing and Facedetection settings page based on selected company

This commit is contained in:
Horilla
2025-05-22 15:48:58 +05:30
parent c0459e1f97
commit 3d857c8e1c
6 changed files with 73 additions and 25 deletions

View File

@@ -1,5 +1,6 @@
import os
from django.core.exceptions import ValidationError
from django.db import models
from django.db.models.signals import post_delete
from django.dispatch import receiver
@@ -9,10 +10,37 @@ from django.dispatch import receiver
class FaceDetection(models.Model):
company_id = models.OneToOneField(
"base.Company", related_name="face_detection", on_delete=models.CASCADE
"base.Company",
related_name="face_detection",
on_delete=models.CASCADE,
null=True,
blank=True,
)
start = models.BooleanField(default=False)
def clean(self):
if self.company_id is None:
qs = FaceDetection.objects.filter(company_id__isnull=True)
if self.pk:
qs = qs.exclude(pk=self.pk)
if qs.exists():
raise ValidationError(
"Only one FaceDetection can have a null company_id."
)
def save(self, *args, **kwargs):
self.full_clean() # Ensures `clean()` runs
super().save(*args, **kwargs)
class Meta:
constraints = [
models.UniqueConstraint(
fields=["company_id"],
name="unique_company_id_when_not_null_facedetection",
condition=~models.Q(company_id=None),
)
]
class EmployeeFaceDetection(models.Model):
employee_id = models.OneToOneField(

View File

@@ -10,6 +10,7 @@ from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from base.models import Company
from facedetection.forms import FaceDetectionSetupForm
from horilla.decorators import hx_request_required
@@ -34,10 +35,6 @@ class FaceDetectionConfigAPIView(APIView):
except Exception as e:
raise serializers.ValidationError(e)
@method_decorator(
permission_required("facedetection.view_facedetection", raise_exception=True),
name="dispatch",
)
def get(self, request):
serializer = FaceDetectionSerializer(self.get_facedetection(request))
return Response(serializer.data, status=status.HTTP_200_OK)
@@ -122,7 +119,10 @@ class EmployeeFaceDetectionGetPostAPIView(APIView):
def get_company(request):
try:
company = request.user.employee_get.get_company()
selected_company = request.session.get("selected_company")
if selected_company == "all":
return None
company = Company.objects.get(id=selected_company)
return company
except Exception as e:
raise serializers.ValidationError(e)

View File

@@ -1,11 +1,13 @@
from django.template.loader import render_to_string
from base.forms import ModelForm
from .models import GeoFencing
from django.template.loader import render_to_string
class GeoFencingSetupForm(ModelForm):
verbose_name = "Geofence Configuration"
class Meta:
model = GeoFencing
exclude = ["company_id"]
@@ -17,4 +19,3 @@ class GeoFencingSetupForm(ModelForm):
context = {"form": self}
table_html = render_to_string("common_form.html", context)
return table_html

View File

@@ -1,13 +1,12 @@
from django.core.exceptions import ValidationError
from django.db import models
from django.db.models import Q
from geopy.geocoders import Nominatim
from base.models import Company
class GeoFencing(models.Model):
latitude = models.FloatField(max_length=100)
longitude = models.FloatField(max_length=100)
latitude = models.FloatField()
longitude = models.FloatField()
radius_in_meters = models.IntegerField()
company_id = models.OneToOneField(
"base.Company",
@@ -19,21 +18,36 @@ class GeoFencing(models.Model):
start = models.BooleanField(default=False)
def clean(self):
geolocator = Nominatim(user_agent="geo_checker") # Use a unique user-agent
if self.company_id is None:
qs = GeoFencing.objects.filter(company_id__isnull=True)
if self.pk:
qs = qs.exclude(pk=self.pk)
if qs.exists():
raise ValidationError("Only one GeoFencing can have a null company_id.")
geolocator = Nominatim(
user_agent="geo_checker_unique"
) # Unique user-agent is important
try:
location = geolocator.reverse(
(self.latitude, self.longitude), exactly_one=True
)
if location:
pass
else:
raise ValidationError("Invalid Location")
if not location:
raise ValidationError("Invalid location coordinates.")
except Exception as e:
raise ValidationError(e)
raise ValidationError(f"Geolocation error: {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)
def save(self, *args, **kwargs):
self.full_clean() # Run clean before save
super().save(*args, **kwargs)
class Meta:
constraints = [
models.UniqueConstraint(
fields=["company_id"],
name="unique_company_id_when_not_null_geofencing",
condition=~Q(company_id=None),
)
]

View File

@@ -11,6 +11,7 @@ from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from base.models import Company
from geofencing.forms import GeoFencingSetupForm
from .models import GeoFencing
@@ -152,7 +153,10 @@ class GeoFencingSetUpPermissionCheck(APIView):
def get_company(request):
try:
company = request.user.employee_get.get_company()
selected_company = request.session.get("selected_company")
if selected_company == "all":
return None
company = Company.objects.get(id=selected_company)
return company
except Exception as e:
raise serializers.ValidationError(e)

View File

@@ -65,6 +65,7 @@ class ClockInAPIView(APIView):
permission_classes = [IsAuthenticated]
def post(self, request):
print("========", request.user.employee_get.check_online())
if not request.user.employee_get.check_online():
try:
if request.user.employee_get.get_company().geo_fencing.start: