[UPDT] HORILLA_API: Employee and attendance view with permsn

This commit is contained in:
Horilla
2025-08-02 16:23:04 +05:30
parent ff93e22886
commit 757fdcd372
5 changed files with 142 additions and 56 deletions

View File

@@ -210,3 +210,15 @@ class MailTemplateSerializer(serializers.ModelSerializer):
class Meta:
model = HorillaMailTemplate
fields = "__all__"
class UserAttendanceListSerializer(serializers.ModelSerializer):
class Meta:
model = Attendance
fields = [
"id",
"attendance_date",
"attendance_clock_in",
"attendance_clock_out",
"attendance_worked_hour",
]

View File

@@ -55,4 +55,6 @@ urlpatterns = [
path("offline-employee-mail-send", OfflineEmployeeMailsend.as_view()),
path("converted-mail-template", ConvertedMailTemplateConvert.as_view()),
path("mail-templates", MailTemplateView.as_view()),
path("my-attendance/", UserAttendanceView.as_view()),
path("attendance-type-check/", AttendanceTypeAccessCheck.as_view()),
]

View File

@@ -3,7 +3,7 @@ from django.urls import path
from ...api_views.employee import views as views
urlpatterns = [
path("employees/", views.EmployeeAPIView.as_view(), name="api-employees-list"),
# path('employees/', views.EmployeeAPIView.as_view(), name='api-employees-list'),
path(
"employees/<int:pk>/",
views.EmployeeAPIView.as_view(),

View File

@@ -7,6 +7,7 @@ from django.db.models import Case, CharField, F, Value, When
from django.http import QueryDict
from django.shortcuts import get_object_or_404
from django.utils.decorators import method_decorator
from rest_framework import status
from rest_framework.pagination import PageNumberPagination
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
@@ -38,6 +39,7 @@ from ...api_serializers.attendance.serializers import (
AttendanceRequestSerializer,
AttendanceSerializer,
MailTemplateSerializer,
UserAttendanceListSerializer,
)
# Create your views here.
@@ -65,7 +67,6 @@ 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:
@@ -158,7 +159,6 @@ class ClockOutAPIView(APIView):
except:
pass
if request.user.employee_get.check_online():
print("----------------")
current_date = date.today()
current_time = datetime.now().time()
current_datetime = datetime.now()
@@ -722,6 +722,7 @@ class OfflineEmployeesCountView(APIView):
permission_classes = [IsAuthenticated]
@method_decorator(permission_required("employee.view_employee"))
def get(self, request):
count = (
EmployeeFilter({"not_in_yet": date.today()})
@@ -742,6 +743,7 @@ class OfflineEmployeesListView(APIView):
permission_classes = [IsAuthenticated]
@method_decorator(permission_required("employee.view_employee"))
def get(self, request):
queryset = (
EmployeeFilter({"not_in_yet": date.today()})
@@ -972,3 +974,46 @@ class OfflineEmployeeMailsend(APIView):
return Response(f"Email not set for {employee.get_full_name()}")
except Exception as e:
return Response("Something went wrong")
class UserAttendanceView(APIView):
permission_classes = [IsAuthenticated]
serializer_class = UserAttendanceListSerializer
def get(self, request):
employee_id = request.user.employee_get.id
attendance_queryset = Attendance.objects.filter(
employee_id=employee_id
).order_by("-id")
paginator = PageNumberPagination()
paginator.page_size = 20
page = paginator.paginate_queryset(attendance_queryset, request)
serializer = self.serializer_class(page, many=True)
return paginator.get_paginated_response(serializer.data)
class AttendanceTypeAccessCheck(APIView):
permission_classes = [IsAuthenticated]
def get(self, request):
user = request.user
employee_id = user.employee_get.id
if user.has_perm("attendance.view_attendance"):
return Response(status=200)
is_manager = (
EmployeeWorkInformation.objects.filter(reporting_manager_id=employee_id)
.only("id")
.exists()
)
if is_manager:
return Response(status=200)
return Response(
{"error": "Permission denied"}, status=status.HTTP_403_FORBIDDEN
)

View File

@@ -93,49 +93,61 @@ class EmployeeTypeAPIView(APIView):
class EmployeeAPIView(APIView):
"""
Handles CRUD operations for employees.
Methods:
get(request, pk=None):
- Retrieves a single employee by pk if provided.
- Retrieves and filters all employees if pk is not provided.
post(request):
- Creates a new employee if the user has the 'employee.change_employee' permission.
put(request, pk):
- Updates an existing employee if the user is the employee, a manager, or has 'employee.change_employee' permission.
delete(request, pk):
- Deletes an employee if the user has the 'employee.delete_employee' permission.
"""
filter_backends = [DjangoFilterBackend]
filterset_class = EmployeeFilter
permission_classes = [IsAuthenticated]
def get(self, request, pk=None):
if pk:
try:
employee = Employee.objects.get(pk=pk)
except Employee.DoesNotExist:
return Response(
{"error": "Employee does not exist"},
status=status.HTTP_404_NOT_FOUND,
)
def get(self, request, pk):
user = request.user
try:
employee = Employee.objects.only(
"id",
"employee_first_name",
"employee_last_name", # include only needed fields
).get(pk=pk)
except Employee.DoesNotExist:
return Response(
{"error": "Employee does not exist"}, status=status.HTTP_404_NOT_FOUND
)
# If user has global view permission
if user.has_perm("employee.view_employee"):
serializer = EmployeeSerializer(employee)
return Response(serializer.data)
paginator = PageNumberPagination()
employees_queryset = Employee.objects.all()
employees_filter_queryset = self.filterset_class(
request.GET, queryset=employees_queryset
).qs
field_name = request.GET.get("groupby_field", None)
if field_name:
url = request.build_absolute_uri()
return groupby_queryset(request, url, field_name, employees_filter_queryset)
page = paginator.paginate_queryset(employees_filter_queryset, request)
serializer = EmployeeSerializer(page, many=True)
return paginator.get_paginated_response(serializer.data)
# If employee is in user's subordinates
subordinates = user.employee_get.get_subordinate_employees()
if subordinates.filter(pk=pk).exists():
serializer = EmployeeSerializer(employee)
return Response(serializer.data)
# If requesting own data
if employee.pk == user.employee_get.id:
serializer = EmployeeSerializer(employee)
return Response(serializer.data)
return Response(
{"error": "Permission denied"}, status=status.HTTP_403_FORBIDDEN
)
# paginator = PageNumberPagination()
# if request.user.has_perm('employee.view_employee'):
# employees_queryset = Employee.objects.all()
# elif request.user.employee_get.get_subordinate_employees():
# employees_queryset = request.user.employee_get.get_subordinate_employees()
# else:
# employees_queryset = [request.user.employee_get]
# employees_filter_queryset = self.filterset_class(
# request.GET, queryset=employees_queryset).qs
# field_name = request.GET.get("groupby_field", None)
# if field_name:
# url = request.build_absolute_uri()
# return groupby_queryset(request, url, field_name, employees_filter_queryset)
# page = paginator.paginate_queryset(employees_filter_queryset, request)
# serializer = EmployeeSerializer(page, many=True)
# return paginator.get_paginated_response(serializer.data)
@method_decorator(permission_required("employee.add_employee"))
def post(self, request):
@@ -176,27 +188,42 @@ class EmployeeAPIView(APIView):
class EmployeeListAPIView(APIView):
"""
Retrieves a paginated list of employees with optional search functionality.
Methods:
get(request):
- Returns a paginated list of employees.
- Optionally filters employees based on a search query in the first or last name.
"""
permission_classes = [IsAuthenticated]
def get(self, request):
paginator = PageNumberPagination()
paginator.page_size = 13
search = request.query_params.get("search", None)
user = request.user
search = request.query_params.get("search")
# Start with a base queryset with only required fields
employees_queryset = Employee.objects.only(
"id", "employee_first_name", "employee_last_name"
)
# Permission-based filtering
if user.has_perm("employee.view_employee"):
pass # employees_queryset is already all employees
else:
subordinate_qs = user.employee_get.get_subordinate_employees()
if subordinate_qs.exists():
employees_queryset = subordinate_qs.only(
"id", "employee_first_name", "employee_last_name"
)
else:
employees_queryset = employees_queryset.filter(id=user.employee_get.id)
# Apply search filter if provided
if search:
employees_queryset = Employee.objects.filter(
employees_queryset = employees_queryset.filter(
Q(employee_first_name__icontains=search)
| Q(employee_last_name__icontains=search)
)
else:
employees_queryset = Employee.objects.all()
# Paginate
paginator = PageNumberPagination()
page = paginator.paginate_queryset(employees_queryset, request)
serializer = EmployeeListSerializer(page, many=True)
return paginator.get_paginated_response(serializer.data)
@@ -386,14 +413,14 @@ class EmployeeWorkInfoImportView(APIView):
class EmployeeBulkUpdateView(APIView):
"""
Endpoint for bulk updating employee and work information.
Endpoint for bulk updating employee and work information.
Permissions:
- Requires authentication and "change_employee" permission.
0
Methods:
put(request):
- Updates multiple employees and their work information.
Permissions:
- Requires authentication and "change_employee" permission.
Methods:
put(request):
- Updates multiple employees and their work information.
"""
permission_classes = [IsAuthenticated]