Skip to content

Commit

Permalink
Vacation almost working 2
Browse files Browse the repository at this point in the history
  • Loading branch information
Heibert committed Nov 1, 2024
1 parent 2188ac1 commit 9665ab5
Show file tree
Hide file tree
Showing 4 changed files with 183 additions and 55 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Generated by Django 5.0.8 on 2024-11-01 16:36

import django.db.models.deletion
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('hierarchy', '0008_area_manager'),
('vacation', '0020_remove_vacationrequest_request_file_and_more'),
]

operations = [
migrations.AddField(
model_name='vacationrequest',
name='user_job_position',
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.PROTECT, related_name='vacation_requests', to='hierarchy.jobposition'),
preserve_default=False,
),
]
7 changes: 6 additions & 1 deletion INSIGHTSAPI/vacation/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,13 @@ class VacationRequest(models.Model):
default="PENDIENTE",
)
comment = models.TextField(null=True, blank=True)
# this column is deprecated, but needs to be kept for backwards compatibility
created_at = models.DateTimeField(auto_now_add=True)
# this column is used to store the job position of the user at the time of the request
user_job_position = models.ForeignKey(
"hierarchy.JobPosition",
related_name="vacation_requests",
on_delete=models.PROTECT,
)

class Meta:
"""Meta class for the vacation request model."""
Expand Down
41 changes: 33 additions & 8 deletions INSIGHTSAPI/vacation/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ def setUp(self):
self.test_user = self.create_demo_user()
self.user.job_position.rank = 2
self.user.job_position.save()
self.user.area = self.test_user.area
self.user.save()
self.permission = Permission.objects.get(codename="payroll_approval")
self.vacation_request = {
"start_date": "2024-01-02",
Expand Down Expand Up @@ -123,12 +125,9 @@ def test_vacation_list_user(self):
VacationRequest.objects.create(**self.vacation_request_user)
self.vacation_request_user["user"] = self.user
VacationRequest.objects.create(**self.vacation_request_user)
self.user.job_position.rank = 1
self.user.job_position.save()
response = self.client.get(reverse("vacation-list"))
vacation_requests = VacationRequest.objects.filter(user=self.user)
serializer = VacationRequestSerializer(vacation_requests, many=True)
self.assertEqual(
response.data, serializer.data, (response.data, serializer.data)
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(len(response.data), 1)

Expand Down Expand Up @@ -167,10 +166,12 @@ def test_vacation_list_manager_multiple_areas(self):
"""Test listing all vacations endpoint for a manager with multiple areas."""
self.test_user.area.manager = self.user
self.test_user.area.save()
self.user.area = Area.objects.create(name="Test Area 2", manager=self.user)
self.user.save()
# Check that the user has a different area than the manager
self.assertNotEqual(self.test_user.area, self.user.area)
VacationRequest.objects.create(**self.vacation_request_user)
demo_user = self.create_demo_user()
self.create_demo_user()
Area.objects.create(name="Test Area", manager=self.user)
VacationRequest.objects.create(**self.vacation_request_user)
response = self.client.get(reverse("vacation-list"))
Expand Down Expand Up @@ -531,11 +532,35 @@ def test_validate_vacation_request_more_than_15_days(self):
"No puedes solicitar más de 15 días de vacaciones.",
)

def test_get_vacation_pdf(self):
def test_get_vacation_request(self):
"""Test getting the vacation request PDF."""
self.user.user_permissions.add(self.permission)
vacation_object = VacationRequest.objects.create(**self.vacation_request_user)
response = self.client.get(
reverse("vacation-get-request", kwargs={"pk": vacation_object.pk})
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response["Content-Type"], "application/pdf")

def test_get_vacation_request_no_permission(self):
"""Test getting the vacation request PDF without permission."""
self.user.job_position.rank = 1
self.user.job_position.save()
vacation_object = VacationRequest.objects.create(**self.vacation_request_user)
response = self.client.get(
reverse("vacation-get-request", kwargs={"pk": vacation_object.pk})
)
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)

def test_get_vacation_request_manager(self):
"""Test getting the vacation request PDF as a manager."""
self.user.job_position.rank = 5
self.user.job_position.save()
self.test_user.area.manager = self.user
self.test_user.area.save()
vacation_object = VacationRequest.objects.create(**self.vacation_request_user)
response = self.client.get(
reverse("vacation-get-pdf", kwargs={"pk": vacation_object.pk})
reverse("vacation-get-request", kwargs={"pk": vacation_object.pk})
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response["Content-Type"], "application/pdf")
Expand Down
169 changes: 123 additions & 46 deletions INSIGHTSAPI/vacation/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,46 @@ class VacationRequestViewSet(viewsets.ModelViewSet):
serializer_class = VacationRequestSerializer
permission_classes = [IsAuthenticated]

def get_queryset(self):
# Restrict queryset based on user permissions
user = self.request.user

# If the user is a manager of HR
if user.job_position.name == "GERENTE DE GESTION HUMANA":
return self.queryset

# If the user has payroll approval permissions
elif user.has_perm("vacation.payroll_approval"):
return self.queryset

# If the user has a management position with rank >= 2
elif user.job_position.rank >= 2:
children = user.area.get_children()

# Check if the user is a manager of their area
if children and user.area.manager == user:
return self.queryset.filter(
Q(user=user)
| Q(user__area__manager=user)
| Q(user__area__in=children)
| (
Q(user__job_position__rank__lt=user.job_position.rank)
& Q(user__area=user.area)
)
)
else:
return self.queryset.filter(
Q(user=user)
| Q(user__area__manager=user)
| (
Q(user__job_position__rank__lt=user.job_position.rank)
& Q(user__area=user.area)
)
)

# If the user is a regular employee
return self.queryset.filter(user=user)

def create(self, request, *args, **kwargs):
response = super().create(request, *args, **kwargs)
if response.status_code == status.HTTP_201_CREATED and response.data:
Expand Down Expand Up @@ -123,43 +163,43 @@ def create(self, request, *args, **kwargs):
)
return response

def list(self, request, *args, **kwargs):
if request.user.job_position.name == "GERENTE DE GESTION HUMANA":
queryset = self.queryset.all()
# Check if the user is in payroll
elif request.user.has_perm("vacation.payroll_approval"):
queryset = self.queryset.all()
# Check if the user has employee management permissions
elif request.user.job_position.rank >= 2:
children = self.request.user.area.get_children()
# Check if the user is a manager
if children and request.user.area.manager == request.user:
queryset = self.queryset.filter(
# Check if the user is the owner
(Q(user=request.user))
# Check if the user is a manager of the area
| (Q(user__area__manager=request.user))
# Check if the user is a manager of a child area
| (Q(user__area__in=children))
| (
Q(user__job_position__rank__lt=request.user.job_position.rank)
& Q(user__area=request.user.area)
)
)
else:
queryset = self.queryset.filter(
Q(user=request.user)
| (Q(user__area__manager=request.user))
| (
Q(user__job_position__rank__lt=request.user.job_position.rank)
& Q(user__area=request.user.area)
)
)
# The user is a regular employee
else:
queryset = self.queryset.filter(Q(user=request.user))
serializer = self.serializer_class(queryset, many=True)
return Response(serializer.data)
# def list(self, request, *args, **kwargs):
# if request.user.job_position.name == "GERENTE DE GESTION HUMANA":
# queryset = self.queryset.all()
# # Check if the user is in payroll
# elif request.user.has_perm("vacation.payroll_approval"):
# queryset = self.queryset.all()
# # Check if the user has employee management permissions
# elif request.user.job_position.rank >= 2:
# children = self.request.user.area.get_children()
# # Check if the user is a manager
# if children and request.user.area.manager == request.user:
# queryset = self.queryset.filter(
# # Check if the user is the owner
# (Q(user=request.user))
# # Check if the user is a manager of the area
# | (Q(user__area__manager=request.user))
# # Check if the user is a manager of a child area
# | (Q(user__area__in=children))
# | (
# Q(user__job_position__rank__lt=request.user.job_position.rank)
# & Q(user__area=request.user.area)
# )
# )
# else:
# queryset = self.queryset.filter(
# Q(user=request.user)
# | (Q(user__area__manager=request.user))
# | (
# Q(user__job_position__rank__lt=request.user.job_position.rank)
# & Q(user__area=request.user.area)
# )
# )
# # The user is a regular employee
# else:
# queryset = self.queryset.filter(Q(user=request.user))
# serializer = self.serializer_class(queryset, many=True)
# return Response(serializer.data)

def partial_update(self, request, *args, **kwargs):

Expand Down Expand Up @@ -192,7 +232,7 @@ def partial_update(self, request, *args, **kwargs):
return response
create_notification(
"Una solicitud necesita tu aprobación",
f"{request.user.get_full_name()} ha aprobado la solicitud de vacaciones de {response.data['user']}. Ahora necesita tu aprobación.",
f"{request.user.get_full_name()} ha aprobado la solicitud de vacaciones de {response.data['username']}. Ahora necesita tu aprobación.",
manager_user,
)
return response
Expand Down Expand Up @@ -236,7 +276,7 @@ def partial_update(self, request, *args, **kwargs):
hr_message = f"""
Hola {hr_user.get_full_name()} 👋,
{request.user.get_full_name()} ha aprobado la solicitud de vacaciones de {response.data["user"]} la cual fue solicitada para el {datetime.datetime.strptime(response.data["start_date"], "%Y-%m-%d").strftime("%d de %B del %Y")} al {datetime.datetime.strptime(response.data["end_date"], "%Y-%m-%d").strftime("%d de %B del %Y")}.
{request.user.get_full_name()} ha aprobado la solicitud de vacaciones de {response.data["username"]} la cual fue solicitada para el {datetime.datetime.strptime(response.data["start_date"], "%Y-%m-%d").strftime("%d de %B del %Y")} al {datetime.datetime.strptime(response.data["end_date"], "%Y-%m-%d").strftime("%d de %B del %Y")}.
Ahora esta a la espera de tu aprobación. Por favor revisa la solicitud y apruébala si estas de acuerdo con las fechas solicitadas.
"""
Expand All @@ -257,13 +297,13 @@ def partial_update(self, request, *args, **kwargs):
return response
create_notification(
"Una solicitud de vacaciones ha sido aprobada por un gerente",
f"La solicitud de vacaciones de {response.data['user']} ha sido aprobada por {request.user.get_full_name()}. Ahora sera revisada por la Gerencia de Recursos Humanos.",
f"La solicitud de vacaciones de {response.data['username']} ha sido aprobada por {request.user.get_full_name()}. Ahora sera revisada por la Gerencia de Recursos Humanos.",
payroll_user,
)
payroll_message = f"""
Hola {payroll_user.get_full_name()} 👋,
{request.user.get_full_name()} ha aprobado la solicitud de vacaciones de {response.data["user"]} la cual fue solicitada para el {datetime.datetime.strptime(response.data["start_date"], "%Y-%m-%d").strftime("%d de %B del %Y")} al {datetime.datetime.strptime(response.data["end_date"], "%Y-%m-%d").strftime("%d de %B del %Y")}.
{request.user.get_full_name()} ha aprobado la solicitud de vacaciones de {response.data["username"]} la cual fue solicitada para el {datetime.datetime.strptime(response.data["start_date"], "%Y-%m-%d").strftime("%d de %B del %Y")} al {datetime.datetime.strptime(response.data["end_date"], "%Y-%m-%d").strftime("%d de %B del %Y")}.
Ahora esta a la espera de la aprobación de la Gerencia de Recursos Humanos.
"""
Expand Down Expand Up @@ -308,13 +348,13 @@ def partial_update(self, request, *args, **kwargs):
return response
create_notification(
"Una solicitud de vacaciones necesita tu aprobación",
f"La Gerencia de Recursos Humanos ha aprobado la solicitud de vacaciones de {response.data['user']}. Ahora necesita tu aprobación.",
f"La Gerencia de Recursos Humanos ha aprobado la solicitud de vacaciones de {response.data['username']}. Ahora necesita tu aprobación.",
payroll_user,
)
payroll_message = f"""
Hola {payroll_user.get_full_name()} 👋,
La Gerencia de Recursos Humanos ha aprobado la solicitud de vacaciones de {response.data["user"]} la cual fue solicitada para el {datetime.datetime.strptime(response.data["start_date"], "%Y-%m-%d").strftime("%d de %B del %Y")} al {datetime.datetime.strptime(response.data["end_date"], "%Y-%m-%d").strftime("%d de %B del %Y")}.
La Gerencia de Recursos Humanos ha aprobado la solicitud de vacaciones de {response.data["username"]} la cual fue solicitada para el {datetime.datetime.strptime(response.data["start_date"], "%Y-%m-%d").strftime("%d de %B del %Y")} al {datetime.datetime.strptime(response.data["end_date"], "%Y-%m-%d").strftime("%d de %B del %Y")}.
Ahora esta a la espera de tu aprobación final. Por favor revisa la solicitud y apruébala si estas de acuerdo con las fechas solicitadas.
"""
Expand Down Expand Up @@ -356,9 +396,11 @@ def partial_update(self, request, *args, **kwargs):
status=status.HTTP_403_FORBIDDEN,
)

# Example link: http://localhost:8000/vacation/1/get-pdf/
@action(detail=True, methods=["get"], url_path="get-pdf", url_name="get-pdf")
def generate_pdf(self, request, pk=None):
# Example link: http://localhost:8000/vacation/1/get-request/
@action(
detail=True, methods=["get"], url_path="get-request", url_name="get-request"
)
def generate_request(self, request, pk=None):
context = {
"vacation": self.get_object(),
"current_date": timezone.now().strftime("%d de %B de %Y").capitalize(),
Expand Down Expand Up @@ -389,3 +431,38 @@ def generate_pdf(self, request, pk=None):
)
)
return response

@action(
detail=True, methods=["get"], url_path="get-response", url_name="get-response"
)
def generate_response(self, request, pk=None):
context = {
"vacation": self.get_object(),
"current_date": timezone.now().strftime("%d de %B de %Y").capitalize(),
"company_logo": base64.b64encode(
open("static/images/just_logo.png", "rb").read()
).decode("utf-8"),
}
# Import the html template
rendered_template = render_to_string(
"vacation_response.html",
context,
)
# PDF options
options = {
"page-size": "Letter",
"orientation": "portrait",
"encoding": "UTF-8",
"margin-top": "0mm",
"margin-right": "0mm",
"margin-bottom": "0mm",
"margin-left": "0mm",
}
pdf = pdfkit.from_string(rendered_template, False, options=options)
response = HttpResponse(pdf, content_type="application/pdf")
response["Content-Disposition"] = (
'inline; filename="Respuesta a solicitud de vacaciones - {}.pdf"'.format(
self.get_object().user.get_full_name()
)
)
return response

0 comments on commit 9665ab5

Please sign in to comment.