From 9a349c7aa05bd360d1f0a9e8077c959ff99f410e Mon Sep 17 00:00:00 2001 From: Horilla Date: Tue, 15 Oct 2024 17:06:39 +0530 Subject: [PATCH] [UPDT] HORILLA API: Clock out method update --- horilla_api/api_decorators/base/decorators.py | 23 +++++++ horilla_api/api_views/attendance/views.py | 55 ++++++--------- horilla_api/api_views/base/views.py | 63 +---------------- horilla_api/api_views/employee/views.py | 26 +++---- horilla_api/api_views/payroll/views.py | 68 +++++-------------- 5 files changed, 73 insertions(+), 162 deletions(-) diff --git a/horilla_api/api_decorators/base/decorators.py b/horilla_api/api_decorators/base/decorators.py index 959b20f86..5368df153 100644 --- a/horilla_api/api_decorators/base/decorators.py +++ b/horilla_api/api_decorators/base/decorators.py @@ -1,11 +1,16 @@ from functools import wraps +from django.contrib import messages +from django.http import HttpResponse +from django.shortcuts import render from rest_framework import status from rest_framework.permissions import BasePermission from rest_framework.response import Response from base.models import MultipleApprovalManagers from employee.models import EmployeeWorkInformation +from horilla.horilla_middlewares import _thread_locals +from horilla_views.cbv_methods import decorator_with_arguments class ManagerPermission(BasePermission): @@ -120,3 +125,21 @@ def check_approval_status(model, perm): return wrapper return decorator + + +@decorator_with_arguments +def permission_required(function, perm): + """ + Decorator to validate user permissions + """ + + def _function(self, *args, **kwargs): + request = getattr(_thread_locals, "request") + if not getattr(self, "request", None): + self.request = request + if request.user.has_perm(perm): + return function(self, *args, **kwargs) + else: + return Response({"message": "No permission"}, status=401) + + return _function diff --git a/horilla_api/api_views/attendance/views.py b/horilla_api/api_views/attendance/views.py index 81545adae..5fbfa09db 100644 --- a/horilla_api/api_views/attendance/views.py +++ b/horilla_api/api_views/attendance/views.py @@ -2,7 +2,6 @@ from datetime import date, datetime, timedelta, timezone from django import template from django.conf import settings -from django.contrib.auth.decorators import permission_required from django.core.mail import EmailMessage from django.db.models import Case, CharField, F, Value, When from django.http import QueryDict @@ -15,6 +14,7 @@ from rest_framework.views import APIView from attendance.models import Attendance, AttendanceActivity, EmployeeShiftDay from attendance.views.clock_in_out import * +from attendance.views.clock_in_out import clock_out from attendance.views.dashboard import ( find_expected_attendances, find_late_come, @@ -26,7 +26,10 @@ from base.methods import generate_pdf, is_reportingmanager from employee.filters import EmployeeFilter from recruitment.models import RecruitmentMailTemplate -from ...api_decorators.base.decorators import manager_permission_required +from ...api_decorators.base.decorators import ( + manager_permission_required, + permission_required, +) from ...api_methods.base.methods import groupby_queryset, permission_based_queryset from ...api_serializers.attendance.serializers import ( AttendanceActivitySerializer, @@ -130,38 +133,24 @@ class ClockOutAPIView(APIView): permission_classes = [IsAuthenticated] def post(self, request): - datetime_now = datetime.now() - if request.__dict__.get("datetime"): - datetime_now = request.datetime - employee, work_info = employee_exists(request) - shift = work_info.shift_id - date_today = date.today() - if request.__dict__.get("date"): - date_today = request.date - day = date_today.strftime("%A").lower() - day = EmployeeShiftDay.objects.get(day=day) - attendance = ( - Attendance.objects.filter(employee_id=employee) - .order_by("id", "attendance_date") - .last() - ) - if attendance is not None: - day = attendance.attendance_day - now = datetime.now().strftime("%H:%M") - if request.__dict__.get("time"): - now = request.time.strftime("%H:%M") - minimum_hour, start_time_sec, end_time_sec = shift_schedule_today( - day=day, shift=shift - ) - early_out_instance = attendance.late_come_early_out.filter(type="early_out") - if not early_out_instance.exists(): - early_out( - attendance=attendance, start_time=start_time_sec, end_time=end_time_sec - ) - clock_out_attendance_and_activity( - employee=employee, date_today=date_today, now=now, out_datetime=datetime_now - ) + current_date = date.today() + current_time = datetime.now().time() + current_datetime = datetime.now() + + try: + clock_out( + Request( + user=request.user, + date=current_date, + time=current_time, + datetime=current_datetime, + ) + ) + return Response({"message": "Clocked-Out"}, status=200) + + except Exception as error: + logger.error("Got an error in clock_out", error) return Response({"message": "Clocked-Out"}, status=200) diff --git a/horilla_api/api_views/base/views.py b/horilla_api/api_views/base/views.py index e7628ddda..1e4f575c1 100644 --- a/horilla_api/api_views/base/views.py +++ b/horilla_api/api_views/base/views.py @@ -34,13 +34,13 @@ from base.views import ( work_type_request_export, ) from employee.models import Actiontype, Employee -from horilla.decorators import permission_required from notifications.signals import notify from ...api_decorators.base.decorators import ( check_approval_status, manager_or_owner_permission_required, manager_permission_required, + permission_required, ) from ...api_methods.base.methods import groupby_queryset, permission_based_queryset from ...api_serializers.base.serializers import ( @@ -518,63 +518,6 @@ class WorkTypeRequestExport(APIView): return work_type_request_export(request) -class RotatingWorkTypeView(APIView): - - serializer_class = RotatingWorkTypeSerializer - permission_classes = [IsAuthenticated] - - def get_queryset(self, request): - queryset = RotatingWorkType.objects.all() - user = request.user - # checking user level permissions - perm = "base.view_rotatingworktype" - queryset = permission_based_queryset(user, perm, queryset) - return queryset - - def get(self, request, pk=None): - if pk: - rotating_work_type = object_check(RotatingWorkType, pk) - if rotating_work_type is None: - return Response({"error": "RotatingWorkType not found"}, status=404) - serializer = self.serializer_class(rotating_work_type) - return Response(serializer.data, status=200) - - rotating_work_types = self.get_queryset(request) - serializer = self.serializer_class(rotating_work_types, many=True) - return Response(serializer.data, status=200) - - @method_decorator(permission_required("base.add_rotatingworktype"), name="dispatch") - def post(self, request): - serializer = self.serializer_class(data=request.data) - if serializer.is_valid(): - serializer.save() - return Response(serializer.data, status=201) - return Response(serializer.errors, status=400) - - @method_decorator( - permission_required("base.change_rotatingworktype"), name="dispatch" - ) - def put(self, request, pk): - rotating_work_type = object_check(RotatingWorkType, pk) - if rotating_work_type is None: - return Response({"error": "RotatingWorkType not found"}, status=404) - serializer = self.serializer_class(rotating_work_type, data=request.data) - if serializer.is_valid(): - serializer.save() - return Response(serializer.data, status=200) - return Response(serializer.errors, status=400) - - @method_decorator( - permission_required("base.delete_rotatingworktype"), name="dispatch" - ) - def delete(self, request, pk): - rotating_work_type = object_check(RotatingWorkType, pk) - if rotating_work_type is None: - return Response({"error": "RotatingWorkType not found"}, status=404) - response, status_code = object_delete(RotatingWorkType, pk) - return Response(response, status=status_code) - - class IndividualRotatingWorktypesView(APIView): serializer_class = RotatingWorkTypeAssignSerializer permission_classes = [IsAuthenticated] @@ -1035,9 +978,7 @@ class RotatingWorkTypeView(APIView): serializer_class = RotatingWorkTypeSerializer permission_classes = [IsAuthenticated] - @method_decorator( - permission_required("base.view_rotatingworktype"), name="dispatch" - ) + @method_decorator(permission_required("base.view_rotatingworktype")) def get(self, request, pk=None): if pk: rotating_work_type = object_check(RotatingWorkType, pk) diff --git a/horilla_api/api_views/employee/views.py b/horilla_api/api_views/employee/views.py index 0b8c8cc0f..796b33136 100644 --- a/horilla_api/api_views/employee/views.py +++ b/horilla_api/api_views/employee/views.py @@ -1,4 +1,3 @@ -from django.contrib.auth.decorators import permission_required from django.db.models import ProtectedError, Q from django.http import Http404 from django.utils.decorators import method_decorator @@ -24,6 +23,7 @@ from employee.models import ( ) from employee.views import work_info_export, work_info_import from horilla.decorators import owner_can_enter +from horilla_api.api_decorators.base.decorators import permission_required from horilla_api.api_methods.employee.methods import get_next_badge_id from horilla_documents.models import Document, DocumentRequest from notifications.signals import notify @@ -113,7 +113,7 @@ class EmployeeAPIView(APIView): serializer = EmployeeSerializer(page, many=True) return paginator.get_paginated_response(serializer.data) - @manager_permission_required("employee.change_employee") + @method_decorator(permission_required("employee.add_employee")) def post(self, request): serializer = EmployeeSerializer(data=request.data) if serializer.is_valid(): @@ -124,14 +124,10 @@ class EmployeeAPIView(APIView): def put(self, request, pk): user = request.user employee = Employee.objects.get(pk=pk) - is_manager = EmployeeWorkInformation.objects.filter( - reporting_manager_id=user.employee_get - ).first() if ( - employee == user.employee_get - or is_manager - or user.has_perm("employee.change_employee") - ): + employee + in [user.employee_get, request.user.employee_get.get_reporting_manager()] + ) or user.has_perm("employee.change_employee"): serializer = EmployeeSerializer(employee, data=request.data, partial=True) if serializer.is_valid(): serializer.save() @@ -621,9 +617,7 @@ class DocumentRequestAPIView(APIView): return Response(serializer.data) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) - @method_decorator( - permission_required("employee.delete_employee", raise_exception=True) - ) + @method_decorator(permission_required("employee.delete_employee")) def delete(self, request, pk): document_request = self.get_object(pk) document_request.delete() @@ -733,9 +727,7 @@ class DocumentBulkApproveRejectAPIView(APIView): class EmployeeBulkArchiveView(APIView): permission_classes = [IsAuthenticated] - @method_decorator( - permission_required("employee.delete_employee", raise_exception=True) - ) + @method_decorator(permission_required("employee.delete_employee")) def post(self, request, is_active): ids = request.data.get("ids") error = [] @@ -757,9 +749,7 @@ class EmployeeBulkArchiveView(APIView): class EmployeeArchiveView(APIView): permission_classes = [IsAuthenticated] - @method_decorator( - permission_required("employee.delete_employee", raise_exception=True) - ) + @method_decorator(permission_required("employee.delete_employee")) def post(self, request, id, is_active): employee = Employee.objects.get(id=id) employee.is_active = is_active diff --git a/horilla_api/api_views/payroll/views.py b/horilla_api/api_views/payroll/views.py index 88eff84ca..32a3e62f6 100644 --- a/horilla_api/api_views/payroll/views.py +++ b/horilla_api/api_views/payroll/views.py @@ -88,7 +88,7 @@ class PayslipDownloadView(APIView): class PayslipSendMailView(APIView): permission_classes = [IsAuthenticated] - @method_decorator(permission_required("payroll.add_payslip", raise_exception=True)) + @method_decorator(permission_required("payroll.add_payslip")) def post(self, request): email_backend = ConfiguredEmailBackend() if not getattr( @@ -135,7 +135,7 @@ class ContractView(APIView): serializer = ContractSerializer(page, many=True) return pagination.get_paginated_response(serializer.data) - @method_decorator(permission_required("payroll.add_contract", raise_exception=True)) + @method_decorator(permission_required("payroll.add_contract")) def post(self, request): serializer = ContractSerializer(data=request.data) if serializer.is_valid(): @@ -143,9 +143,7 @@ class ContractView(APIView): return Response(serializer.data, status=200) return Response(serializer.errors, status=400) - @method_decorator( - permission_required("payroll.change_contract", raise_exception=True) - ) + @method_decorator(permission_required("payroll.change_contract")) def put(self, request, pk): contract = Contract.objects.get(id=pk) serializer = ContractSerializer(instance=contract, data=request.data) @@ -154,9 +152,7 @@ class ContractView(APIView): return Response(serializer.data, status=200) return Response(serializer.errors, status=400) - @method_decorator( - permission_required("payroll.delete_contract", raise_exception=True) - ) + @method_decorator(permission_required("payroll.delete_contract")) def delete(self, request, pk): contract = Contract.objects.get(id=pk) contract.delete() @@ -166,9 +162,7 @@ class ContractView(APIView): class AllowanceView(APIView): permission_classes = [IsAuthenticated] - @method_decorator( - permission_required("payroll.view_allowance", raise_exception=True) - ) + @method_decorator(permission_required("payroll.view_allowance")) def get(self, request, pk=None): if pk: allowance = Allowance.objects.get(id=pk) @@ -181,9 +175,7 @@ class AllowanceView(APIView): serializer = AllowanceSerializer(page, many=True) return pagination.get_paginated_response(serializer.data) - @method_decorator( - permission_required("payroll.add_allowance", raise_exception=True) - ) + @method_decorator(permission_required("payroll.add_allowance")) def post(self, request): serializer = AllowanceSerializer(data=request.data) if serializer.is_valid(): @@ -191,9 +183,7 @@ class AllowanceView(APIView): return Response(serializer.data, status=200) return Response(serializer.errors, status=400) - @method_decorator( - permission_required("payroll.change_allowance", raise_exception=True) - ) + @method_decorator(permission_required("payroll.change_allowance")) def put(self, request, pk): contract = Allowance.objects.get(id=pk) serializer = AllowanceSerializer(instance=contract, data=request.data) @@ -202,9 +192,7 @@ class AllowanceView(APIView): return Response(serializer.data, status=200) return Response(serializer.errors, status=400) - @method_decorator( - permission_required("payroll.delete_allowance", raise_exception=True) - ) + @method_decorator(permission_required("payroll.delete_allowance")) def delete(self, request, pk): contract = Allowance.objects.get(id=pk) contract.delete() @@ -214,9 +202,7 @@ class AllowanceView(APIView): class DeductionView(APIView): permission_classes = [IsAuthenticated] - @method_decorator( - permission_required("payroll.view_deduction", raise_exception=True) - ) + @method_decorator(permission_required("payroll.view_deduction")) def get(self, request, pk=None): if pk: deduction = Deduction.objects.get(id=pk) @@ -229,9 +215,7 @@ class DeductionView(APIView): serializer = DeductionSerializer(page, many=True) return pagination.get_paginated_response(serializer.data) - @method_decorator( - permission_required("payroll.add_deduction", raise_exception=True) - ) + @method_decorator(permission_required("payroll.add_deduction")) def post(self, request): serializer = DeductionSerializer(data=request.data) if serializer.is_valid(): @@ -239,9 +223,7 @@ class DeductionView(APIView): return Response(serializer.data, status=200) return Response(serializer.errors, status=400) - @method_decorator( - permission_required("payroll.change_deduction", raise_exception=True) - ) + @method_decorator(permission_required("payroll.change_deduction")) def put(self, request, pk): contract = Deduction.objects.get(id=pk) serializer = DeductionSerializer(instance=contract, data=request.data) @@ -250,9 +232,7 @@ class DeductionView(APIView): return Response(serializer.data, status=200) return Response(serializer.errors, status=400) - @method_decorator( - permission_required("payroll.delete_deduction", raise_exception=True) - ) + @method_decorator(permission_required("payroll.delete_deduction")) def delete(self, request, pk): contract = Deduction.objects.get(id=pk) contract.delete() @@ -262,9 +242,7 @@ class DeductionView(APIView): class LoanAccountView(APIView): permission_classes = [IsAuthenticated] - @method_decorator( - permission_required("payroll.add_loanaccount", raise_exception=True) - ) + @method_decorator(permission_required("payroll.add_loanaccount")) def post(self, request): serializer = LoanAccountSerializer(data=request.data) if serializer.is_valid(): @@ -272,9 +250,7 @@ class LoanAccountView(APIView): return Response(serializer.data, status=200) return Response(serializer.errors, status=400) - @method_decorator( - permission_required("payroll.view_loanaccount", raise_exception=True) - ) + @method_decorator(permission_required("payroll.view_loanaccount")) def get(self, request, pk=None): if pk: loan_account = LoanAccount.objects.get(id=pk) @@ -286,9 +262,7 @@ class LoanAccountView(APIView): serializer = LoanAccountSerializer(page, many=True) return pagination.get_paginated_response(serializer.data) - @method_decorator( - permission_required("payroll.change_loanaccount", raise_exception=True) - ) + @method_decorator(permission_required("payroll.change_loanaccount")) def put(self, request, pk): loan_account = LoanAccount.objects.get(id=pk) serializer = LoanAccountSerializer(loan_account, data=request.data) @@ -297,9 +271,7 @@ class LoanAccountView(APIView): return Response(serializer.data, status=200) return Response(serializer.errors, status=400) - @method_decorator( - permission_required("payroll.delete_loanaccount", raise_exception=True) - ) + @method_decorator(permission_required("payroll.delete_loanaccount")) def delete(self, request, pk): loan_account = LoanAccount.objects.get(id=pk) loan_account.delete() @@ -337,9 +309,7 @@ class ReimbursementView(APIView): return Response(serializer.data, status=200) return Response(serializer.errors, status=400) - @method_decorator( - permission_required("payroll.change_reimbursement", raise_exception=True) - ) + @method_decorator(permission_required("payroll.change_reimbursement")) def put(self, request, pk): reimbursement = Reimbursement.objects.get(id=pk) serializer = self.serializer_class(instance=reimbursement, data=request.data) @@ -348,9 +318,7 @@ class ReimbursementView(APIView): return Response(serializer.data, status=200) return Response(serializer.errors, status=400) - @method_decorator( - permission_required("payroll.delete_reimbursement", raise_exception=True) - ) + @method_decorator(permission_required("payroll.delete_reimbursement")) def delete(self, request, pk): reimbursement = Reimbursement.objects.get(id=pk) reimbursement.delete()