+ Aviso de confidencialidad:
+ Este correo electrónico y cualquier archivo adjunto son confidenciales y pueden contener información privilegiada. Si usted no es el destinatario correcto, por favor notifique al remitente respondiendo este mensaje y elimine inmediatamente este correo electrónico y cualquier archivo adjunto de su sistema. Si está usted recibiendo este correo electrónico por error, no debe copiar este mensaje o divulgar su contenido a ninguna persona.
+
+
+
+
+ Mensaje generado automáticamente, por favor no responder.
+
+
+
+ """
+
+ plain_signature = """
+ ---
+ C&C SERVICES S.A.S
+ https://cyc-bpo.com/
+ PBX: (601)7461166-Ext: 8081
+ Calle 19 #3-16 | Piso 3-CC Barichara
+ Bogotá D.C.-Colombia
+
+ Aviso de confidencialidad:
+ Este correo electrónico y cualquier archivo adjunto son confidenciales y pueden contener información privilegiada. Si usted no es el destinatario correcto, por favor notifique al remitente respondiendo este mensaje y elimine inmediatamente este correo electrónico y cualquier archivo adjunto de su sistema. Si está usted recibiendo este correo electrónico por error, no debe copiar este mensaje o divulgar su contenido a ninguna persona.
+
+ Mensaje generado automáticamente, por favor no responder.
+ """
+
+ if isinstance(message, EmailMultiAlternatives):
+ # Ensure HTML signature is added to the HTML alternative part
+ has_html_alternative = False
+ for i, (content, mime_type) in enumerate(message.alternatives):
+ if mime_type == "text/html":
+ message.alternatives[i] = (content + html_signature, mime_type)
+ has_html_alternative = True
+ if not has_html_alternative:
+ message.alternatives.append(
+ (message.body.replace("\n", " ") + html_signature, "text/html")
+ )
+ else:
+ # If no alternatives, ensure a plain text alternative is added
+ if message.content_subtype == "html":
+ message.alternatives = [
+ (message.body.replace("\n", " ") + html_signature, "text/html")
+ ]
+ else:
+ message.alternatives = [
+ (message.body.replace("\n", " ") + html_signature, "text/html"),
+ (message.body, "text/plain"),
+ ]
+
+ # Add the appropriate signature based on content_subtype
+ if message.content_subtype == "html":
+ message.body += html_signature
+ else:
+ message.body += plain_signature
+
+ # Ensure the message body is plain text if alternatives exist
+ if message.content_subtype == "html" and isinstance(
+ message, EmailMultiAlternatives
+ ):
+ message.body = (
+ message.body.replace(html_signature, "").strip() + plain_signature
+ )
+
def open(self):
if self.connection:
return False
@@ -30,7 +120,7 @@ def open(self):
if not self.fail_silently:
raise e
- # Override the send_messages method without changing his working
+ # Override the send_messages method without changing its functionality
def send_messages(self, email_messages):
if not email_messages:
return
@@ -44,14 +134,24 @@ def send_messages(self, email_messages):
num_sent = 0
for message in email_messages:
if ("test" in sys.argv or settings.DEBUG) and not (
- all("heibert" in str(email).lower() or "juan.carreno" in str(email).lower() for email in message.to)
+ all(
+ "heibert.mogollon@cyc-bpo.com" in str(email).lower()
+ or "carreno" in str(email).lower()
+ or "diego.martinez.p@cyc-bpo.com" in str(email).lower()
+ for email in message.to
+ )
):
-
raise Exception(f"Email {message.to} not allowed in test mode")
+ self.add_signature(message)
+
+ message.from_email = formataddr((self.display_name, self.username))
sent = self._send(message)
if sent:
num_sent += 1
+ self.outbox.append(message)
self.save_to_sent_folder(message)
+ else:
+ print("Email not sent")
if new_conn_created:
self.close()
diff --git a/INSIGHTSAPI/INSIGHTSAPI/settings.py b/INSIGHTSAPI/INSIGHTSAPI/settings.py
index cc0dc57..00377fa 100644
--- a/INSIGHTSAPI/INSIGHTSAPI/settings.py
+++ b/INSIGHTSAPI/INSIGHTSAPI/settings.py
@@ -12,12 +12,12 @@
from datetime import timedelta, datetime
from pathlib import Path
+import sys
import os
import ssl
-import ldap # type: ignore
-from django_auth_ldap.config import LDAPSearch, LDAPSearchUnion # type: ignore
+import ldap
+from django_auth_ldap.config import LDAPSearch, LDAPSearchUnion
from dotenv import load_dotenv
-import sys
ENV_PATH = Path("/var/env/INSIGHTS.env")
@@ -28,7 +28,9 @@
load_dotenv(ENV_PATH)
# This allows to use the server with a self signed certificate
-ssl._create_default_https_context = ssl._create_unverified_context
+ssl._create_default_https_context = (
+ ssl._create_unverified_context
+) # pylint: disable=protected-access
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
@@ -38,24 +40,27 @@
SENDFILE_ROOT = MEDIA_ROOT
-# Quick-start development settings - unsuitable for production
-# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/
-
-# SECURITY WARNING: keep the secret key used in production secret!
+# keep the secret key used in production secret!
SECRET_KEY = os.getenv("SECRET_KEY")
-# SECURITY WARNING: don't run with debug turned on in production!
-DEBUG = True if os.getenv("DEBUG") is not None else False
-# DEBUG = False
+# don't run with debug turned on in production!
+DEBUG = os.getenv("DEBUG", "False") == "True"
-if DEBUG:
- ALLOWED_HOSTS = ["insights-api-dev.cyc-bpo.com"]
-else:
- ALLOWED_HOSTS = ["insights-api.cyc-bpo.com"]
+def str_to_bool(value: str) -> bool:
+ """Convert a string to a boolean."""
+ return value.lower() in ("true", "t", "1")
-# Application definition
+allowed_hosts_env = os.getenv("ALLOWED_HOSTS", "")
+
+# This is to avoid the error of having an empty string as an allowed host (This is a security risk)
+# If the environment variable is an empty string, return an empty list, otherwise split by comma
+ALLOWED_HOSTS = (
+ [host.strip() for host in allowed_hosts_env.split(",")] if allowed_hosts_env else []
+)
+
+# Application definition
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
@@ -84,6 +89,8 @@
"operational_risk",
"payslip",
"employment_management",
+ "vacation",
+ "notifications",
]
MIDDLEWARE = [
@@ -103,11 +110,8 @@
"DEFAULT_RENDERER_CLASSES": [
"rest_framework.renderers.JSONRenderer",
],
- "DEFAULT_AUTHENTICATION_CLASSES": ("api_token.cookie_JWT.CookieJWTAuthentication",),
+ "DEFAULT_AUTHENTICATION_CLASSES": ("api_token.cookie_jwt.CookieJWTAuthentication",),
"DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
- # 'DEFAULT_PERMISSION_CLASSES': [
- # 'rest_framework.permissions.IsAuthenticated',
- # ],
}
@@ -125,10 +129,13 @@
if not DEBUG:
- CORS_ALLOWED_ORIGINS = [
- "https://intranet.cyc-bpo.com",
- "https://staffnet-api.cyc-bpo.com",
- ]
+ cors_allowed_origins = os.getenv("CORS_ALLOWED_ORIGINS", "")
+ # This avoid the error of having an empty string as an allowed host (This is a security risk)
+ CORS_ALLOWED_ORIGINS = (
+ [cors.strip() for cors in cors_allowed_origins.split(",")]
+ if cors_allowed_origins
+ else []
+ )
ROOT_URLCONF = "INSIGHTSAPI.urls"
@@ -148,21 +155,34 @@
},
]
-ADMINS = [
- ("Heibert Mogollon", "heibert203@hotmail.com"),
- # ("Heibert Mogollon", "heibert.mogollon@gmail.com"),
- ("Heibert Mogollon", "heibert.mogollon@cyc-bpo.com"),
- ("Juan Carreño", "carrenosebastian54@gmail.com"),
-]
-SERVER_EMAIL = "no-reply@cyc-services.com.co"
+admins = os.getenv("ADMINS", "")
+
+if "test" in sys.argv or ALLOWED_HOSTS[0].find("-dev") != -1:
+ ADMINS = []
+else:
+ ADMINS = (
+ [tuple(admin.strip().split(":")) for admin in admins.split(",")]
+ if admins
+ else []
+ )
+
+SERVER_EMAIL = os.environ["SERVER_EMAIL"]
EMAIL_BACKEND = "INSIGHTSAPI.custom.custom_email_backend.CustomEmailBackend"
-EMAIL_HOST = "mail.cyc-services.com.co"
-EMAIL_PORT = 587
+EMAIL_HOST = os.environ["EMAIL_HOST"]
+EMAIL_PORT = int(os.getenv("EMAIL_PORT", "587"))
EMAIL_USE_TLS = True
-DEFAULT_FROM_EMAIL = "no-reply@cyc-services.com.co"
-EMAIL_HOST_USER = "no-reply@cyc-services.com.co"
-EMAIL_HOST_PASSWORD = os.environ["TecPlusLess"]
-EMAIL_TEST = "heibert.mogollon@cyc-bpo.com"
+DEFAULT_FROM_EMAIL = SERVER_EMAIL
+EMAIL_HOST_USER = SERVER_EMAIL
+EMAIL_HOST_PASSWORD = os.environ["EMAIL_HOST_PASSWORD"]
+EMAILS_ETHICAL_LINE = [
+ email.strip() for email in os.environ["EMAILS_ETHICAL_LINE"].split(",")
+]
+
+
+# This is the email where the test emails are going to be sent
+EMAIL_FOR_TEST = os.getenv("EMAIL_FOR_TEST", "").upper()
+# This cedula need to be in the StaffNet database it's used in many tests
+TEST_CEDULA = os.environ["TEST_CEDULA"]
# Database
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases
@@ -173,7 +193,7 @@
"HOST": os.environ["SERVER_DB"],
"PORT": "3306",
"USER": "INSIGHTSUSER",
- "PASSWORD": os.environ["INSIGHTSMYSQL"],
+ "PASSWORD": os.environ["INSIGHTS_DB_PASS"],
"NAME": "insights",
},
"staffnet": {
@@ -181,7 +201,7 @@
"HOST": os.environ["SERVER_DB"],
"PORT": "3306",
"USER": "INSIGHTSUSER",
- "PASSWORD": os.environ["INSIGHTSMYSQL"],
+ "PASSWORD": os.environ["INSIGHTS_DB_PASS"],
"NAME": "staffnet",
"TEST": {"MIRROR": "staffnet"},
},
@@ -239,7 +259,7 @@
AUTHENTICATION_BACKENDS = [
"django_auth_ldap.backend.LDAPBackend",
- "api_token.cookie_JWT.CustomAuthBackend",
+ "api_token.cookie_jwt.CustomAuthBackend",
"django.contrib.auth.backends.ModelBackend",
]
@@ -297,6 +317,7 @@
"mail_admins": {
"level": "ERROR",
"class": "django.utils.log.AdminEmailHandler",
+ "include_html": True,
},
"celery": {
"level": "INFO",
@@ -307,7 +328,7 @@
},
"loggers": {
"requests": {
- "handlers": ["response_file", "exception_file"],
+ "handlers": ["response_file", "exception_file", "mail_admins"],
"level": "DEBUG",
"propagate": True,
},
@@ -337,6 +358,10 @@
"propagate": True,
},
},
+ "root": {
+ "handlers": ["exception_file", "mail_admins"],
+ "level": "ERROR",
+ },
}
AUTH_USER_MODEL = "users.User"
@@ -344,7 +369,7 @@
# LDAP configuration
AUTH_LDAP_SERVER_URI = "ldap://CYC-SERVICES.COM.CO:389"
AUTH_LDAP_BIND_DN = "CN=StaffNet,OU=TECNOLOGÍA,OU=BOGOTA,DC=CYC-SERVICES,DC=COM,DC=CO"
-AUTH_LDAP_BIND_PASSWORD = os.getenv("Adminldap")
+AUTH_LDAP_BIND_PASSWORD = os.getenv("AdminLDAPPassword")
# AUTH_LDAP_USER_SEARCH = LDAPSearch(
# "OU=BOGOTA,DC=CYC-SERVICES,DC=COM,DC=CO", # Search base
@@ -383,9 +408,11 @@
AUTH_LDAP_ALWAYS_UPDATE_USER = False
# This works faster in ldap but i don't know how implement it with the sAMAcountName
-# AUTH_LDAP_USER_DN_TEMPLATE = 'CN=Heibert Steven Mogollon Mahecha,OU=IT,OU=BOGOTA,DC=CYC-SERVICES,DC=COM,DC=CO'
+# AUTH_LDAP_USER_DN_TEMPLATE =
+#'CN=Heibert Steven Mogollon Mahecha,OU=IT,OU=BOGOTA,DC=CYC-SERVICES,DC=COM,DC=CO'
-# AUTH_LDAP_USER_DN_TEMPLATE = '(sAMAccountName=%(user)s),OU=IT,OU=BOGOTA,DC=CYC-SERVICES,DC=COM,DC=CO'
+# AUTH_LDAP_USER_DN_TEMPLATE =
+#'(sAMAccountName=%(user)s),OU=IT,OU=BOGOTA,DC=CYC-SERVICES,DC=COM,DC=CO'
if DEBUG:
SENDFILE_BACKEND = "django_sendfile.backends.development"
@@ -400,7 +427,7 @@
"SLIDING_TOKEN_REFRESH_ON_LOGIN": True,
"SLIDING_TOKEN_REFRESH_ON_REFRESH": True,
"AUTH_COOKIE": "access-token",
- "USER_AUTHENTICATION_RULE": "api_token.cookie_JWT.always_true",
+ "USER_AUTHENTICATION_RULE": "api_token.cookie_jwt.always_true",
}
# Celery configuration for the tasks
diff --git a/INSIGHTSAPI/INSIGHTSAPI/tests.py b/INSIGHTSAPI/INSIGHTSAPI/tests.py
index 64c930b..2705d4b 100644
--- a/INSIGHTSAPI/INSIGHTSAPI/tests.py
+++ b/INSIGHTSAPI/INSIGHTSAPI/tests.py
@@ -1,10 +1,13 @@
"""This file contains the tests for the Celery app. """
-from django.test import TestCase
from celery import current_app
+from django.test import TestCase
+from django.conf import settings
from django.core.mail import get_connection
-from INSIGHTSAPI.tasks import add_numbers
+from django.test import override_settings
from django.core.mail import EmailMessage
+from django.urls import reverse
+from INSIGHTSAPI.tasks import add_numbers
class CeleryTestCase(TestCase):
@@ -25,22 +28,52 @@ def test_add_numbers_task(self):
task_result = result.get(timeout=5)
self.assertEqual(task_result, 7)
+
class CustomEmailBackendTestCase(TestCase):
"""Test case for the CustomEmailBackend class."""
+ @override_settings(
+ EMAIL_BACKEND="INSIGHTSAPI.custom.custom_email_backend.CustomEmailBackend",
+ )
def test_send_messages(self):
"""Test the send_messages method."""
+ # By default in a test environment, the email is not sent
+ backend = get_connection()
+ email = EmailMessage(
+ "Subject here",
+ "Here is the message.",
+ None,
+ [settings.EMAIL_FOR_TEST],
+ connection=backend,
+ )
+ email.send()
+ self.assertEqual(len(backend.outbox), 1)
+
+ def test_send_messages_to_wrong_email(self):
+ """Test the send_messages method."""
+ # By default in a test environment, the email is not sent
backend = "INSIGHTSAPI.custom.custom_email_backend.CustomEmailBackend"
- # Create an EmailMessage instance using your custom backend
try:
email = EmailMessage(
"Subject here",
"Here is the message.",
None,
["not_allowed_email@not_allowed.com"],
- connection=get_connection(backend=backend)
+ connection=get_connection(backend=backend),
)
email.send()
self.fail("Email should not be sent.")
except Exception as e:
self.assertIn("not allowed in test mode", str(e))
+
+ @override_settings(
+ ADMINS=[("Heibert Mogollon", settings.EMAIL_FOR_TEST)],
+ DEBUG=False, # Ensure DEBUG is False to enable email sending on errors
+ EMAIL_BACKEND="INSIGHTSAPI.custom.custom_email_backend.CustomEmailBackend",
+ )
+ def test_admin_email_on_server_error(self):
+ """Test that an email is sent to the admins on a server error."""
+ with self.assertRaises(Exception) as context:
+ self.client.get(reverse("trigger_error"))
+
+ self.assertIn("Test error", str(context.exception))
diff --git a/INSIGHTSAPI/INSIGHTSAPI/urls.py b/INSIGHTSAPI/INSIGHTSAPI/urls.py
index e1a9c80..40961a8 100644
--- a/INSIGHTSAPI/INSIGHTSAPI/urls.py
+++ b/INSIGHTSAPI/INSIGHTSAPI/urls.py
@@ -41,6 +41,8 @@
path("payslips/", include("payslip.urls")),
path("employment-management/", include("employment_management.urls")),
path("users/", include("users.urls")),
+ path("vacation/", include("vacation.urls")),
+ path("notifications/", include("notifications.urls")),
]
handler500 = "rest_framework.exceptions.server_error"
diff --git a/INSIGHTSAPI/api_token/cookie_JWT.py b/INSIGHTSAPI/api_token/cookie_JWT.py
index dd3c419..2a7a91d 100644
--- a/INSIGHTSAPI/api_token/cookie_JWT.py
+++ b/INSIGHTSAPI/api_token/cookie_JWT.py
@@ -1,6 +1,8 @@
"""
-This module contains the CookieJWTAuthentication class, which is used to authenticate requests through a JSON web token.
+This module contains the CookieJWTAuthentication class,
+which is used to authenticate requests through a JSON web token.
"""
+
import logging
from rest_framework_simplejwt.authentication import JWTAuthentication
from django.contrib.auth import get_user_model
@@ -15,10 +17,10 @@ class CustomAuthBackend(ModelBackend):
def authenticate(self, request, username=None, password=None, **kwargs):
"""Authenticate the superusers."""
if not request:
- UserModel = get_user_model()
+ user_model = get_user_model()
try:
- user = UserModel.objects.get(username=username)
- except UserModel.DoesNotExist:
+ user = user_model.objects.get(username=username)
+ except user_model.DoesNotExist:
return None
# Check if the user is a superuser
@@ -30,11 +32,11 @@ def authenticate(self, request, username=None, password=None, **kwargs):
return jwt_authentication.authenticate(request)
def get_user(self, user_id):
- UserModel = get_user_model()
+ user_model = get_user_model()
try:
- return UserModel.objects.get(pk=user_id)
- except UserModel.DoesNotExist:
+ return user_model.objects.get(pk=user_id)
+ except user_model.DoesNotExist:
return None
diff --git a/INSIGHTSAPI/api_token/tests.py b/INSIGHTSAPI/api_token/tests.py
index 0bf5a26..28e4d1e 100644
--- a/INSIGHTSAPI/api_token/tests.py
+++ b/INSIGHTSAPI/api_token/tests.py
@@ -66,6 +66,10 @@ def test_token_obtain(self):
response.data["permissions"],
user.get_all_permissions(),
)
+ self.assertEqual(response.data["cedula"], user.cedula)
+ self.assertEqual(response.data["cargo"], user.job_position.name)
+ self.assertEqual(response.data["email"], user.email)
+ self.assertEqual(response.data["rango"], user.job_position.rank)
def test_token_obtain_fail(self):
"""Test that the token obtain endpoint works correctly."""
diff --git a/INSIGHTSAPI/api_token/views.py b/INSIGHTSAPI/api_token/views.py
index 3ba22e9..e04f42d 100644
--- a/INSIGHTSAPI/api_token/views.py
+++ b/INSIGHTSAPI/api_token/views.py
@@ -46,8 +46,9 @@ def post(self, request, *args, **kwargs):
user = User.objects.get(username=username)
response.data["permissions"] = user.get_all_permissions()
response.data["cedula"] = user.cedula
- response.data["cargo"] = user.job_title
+ response.data["cargo"] = user.job_position.name
response.data["email"] = user.email
+ response.data["rango"] = user.job_position.rank
return response
diff --git a/INSIGHTSAPI/contracts/tests.py b/INSIGHTSAPI/contracts/tests.py
index 42f062b..af75995 100644
--- a/INSIGHTSAPI/contracts/tests.py
+++ b/INSIGHTSAPI/contracts/tests.py
@@ -1,7 +1,16 @@
"""This module defines the tests for the contracts app."""
+
from services.tests import BaseTestCase
from users.models import User
from django.contrib.auth.models import Permission
+from django.test import TestCase
+from django.core.management import call_command
+from django.utils import timezone
+from io import StringIO
+from django.conf import settings
+from django.test import override_settings
+from contracts.models import Contract
+from datetime import timedelta
from .models import Contract
@@ -124,3 +133,72 @@ def test_delete_contract(self):
response = self.client.delete(f"/contracts/{self.contract.id}/")
self.assertEqual(response.status_code, 204, response.data)
self.assertEqual(Contract.objects.count(), 0)
+
+
+@override_settings(
+ EMAIL_BACKEND="INSIGHTSAPI.custom.custom_email_backend.CustomEmailBackend"
+)
+class SchedulerTest(TestCase):
+ """Test for scheduler."""
+
+ def test_scheduler(self):
+ """Test scheduler."""
+
+ contract_data = {
+ "name": "Contract 30 Days",
+ "city": "Bogota",
+ "description": "Test",
+ "expected_start_date": timezone.now().date(),
+ "value": 100000,
+ "monthly_cost": 10000,
+ "duration": timezone.now().date(),
+ "contact": "Test",
+ "contact_telephone": "123456789",
+ "start_date": timezone.now().date(),
+ "civil_responsibility_policy": "Test",
+ "compliance_policy": "Test",
+ "insurance_policy": "Test",
+ "renovation_date": timezone.now().date() + timedelta(days=30),
+ }
+
+ contract_30_days = Contract.objects.create(**contract_data)
+
+ # Create a contract with a renovation date 15 days from now
+ contract_data["name"] = "Contract 15 Days"
+ contract_data["renovation_date"] = timezone.now().date() + timedelta(days=15)
+ contract_15_days = Contract.objects.create(**contract_data)
+
+ # Create a contract with a renovation date 7 days from now
+ contract_data["name"] = "Contract 7 Days"
+ contract_data["renovation_date"] = timezone.now().date() + timedelta(days=7)
+ contract_7_days = Contract.objects.create(**contract_data)
+
+ # Create a contract with a renovation date today
+ contract_data["name"] = "Contract Today"
+ contract_data["renovation_date"] = timezone.now().date()
+ contract_today = Contract.objects.create(**contract_data)
+
+ # Run the logic to check for contract renewal
+ stdout = StringIO()
+ management_command_output = call_command("run_scheduler", stdout=stdout)
+
+ self.assertIn(
+ f"Email sent for contract {contract_30_days.name} to ['"
+ + settings.EMAIL_FOR_TEST,
+ stdout.getvalue(),
+ )
+ self.assertIn(
+ f"Email sent for contract {contract_15_days.name} to ['"
+ + settings.EMAIL_FOR_TEST,
+ stdout.getvalue(),
+ )
+ self.assertIn(
+ f"Email sent for contract {contract_7_days.name} to ['"
+ + settings.EMAIL_FOR_TEST,
+ stdout.getvalue(),
+ )
+ self.assertIn(
+ f"Email sent for contract {contract_today.name} to ['"
+ + settings.EMAIL_FOR_TEST,
+ stdout.getvalue(),
+ )
diff --git a/INSIGHTSAPI/employment_management/serializers.py b/INSIGHTSAPI/employment_management/serializers.py
index 13ea77d..8a8e474 100644
--- a/INSIGHTSAPI/employment_management/serializers.py
+++ b/INSIGHTSAPI/employment_management/serializers.py
@@ -7,6 +7,11 @@
class EmploymentCertificationSerializer(serializers.ModelSerializer):
"""Employment certification serializer."""
+ def to_representation(self, instance):
+ representation = super().to_representation(instance)
+ representation["cedula"] = instance.user.cedula
+ return representation
+
class Meta:
model = EmploymentCertification
- fields = "__all__"
\ No newline at end of file
+ fields = "__all__"
diff --git a/INSIGHTSAPI/employment_management/tests.py b/INSIGHTSAPI/employment_management/tests.py
index 4d81cb2..f084d54 100644
--- a/INSIGHTSAPI/employment_management/tests.py
+++ b/INSIGHTSAPI/employment_management/tests.py
@@ -1,6 +1,9 @@
+"""Tests for the employment management app."""
+
+from django.conf import settings
+from django.contrib.auth.models import Permission
from django.urls import reverse
from services.tests import BaseTestCase
-from django.contrib.auth.models import Permission
from payslip.models import Payslip
from .models import EmploymentCertification
@@ -13,7 +16,7 @@ def setUp(self):
super().setUp()
self.payslip_data = {
"title": "title",
- "identification": "1000065648",
+ "identification": settings.TEST_CEDULA,
"name": "name",
"area": "area",
"job_title": "job_title",
@@ -42,17 +45,17 @@ def setUp(self):
def test_get_my_employment_certification(self):
"""Tests that the user can get the simple employment certification don't need months."""
- self.user.cedula = "1000065648"
+ self.user.cedula = self.payslip_data["identification"]
# self.user.cedula = "1001185389"
self.user.save()
response = self.client.post(reverse("send-employment-certification"))
self.assertEqual(response.status_code, 200, response.content)
- self.assertEqual(response.data["email"], "HEIBERT.MOGOLLON@GMAIL.COM")
+ self.assertEqual(response.data["email"], self.user.email)
self.assertEqual(EmploymentCertification.objects.count(), 1)
def test_get_my_employment_certification_with_months(self):
"""Tests that the user can get the employment certification with months."""
- self.user.cedula = "1000065648"
+ self.user.cedula = self.payslip_data["identification"]
self.user.save()
Payslip.objects.create(**self.payslip_data)
response = self.client.post(
@@ -62,7 +65,7 @@ def test_get_my_employment_certification_with_months(self):
self.assertEqual(EmploymentCertification.objects.count(), 1)
def test_get_my_employment_certification_without_have_the_months(self):
- """Tests that the user can get the employment certification with months."""
+ """Tests that the user can't get the employment certification with months."""
response = self.client.post(
reverse("send-employment-certification"), {"months": 6}
)
@@ -75,7 +78,8 @@ def test_get_another_employment_certification_with_identification(self):
self.user.user_permissions.add(get_permission)
self.user.save()
response = self.client.post(
- reverse("send-employment-certification"), {"identification": "1000065648"}
+ reverse("send-employment-certification"),
+ {"identification": self.payslip_data["identification"]},
)
self.assertEqual(response.status_code, 200, response.content)
self.assertEqual(EmploymentCertification.objects.count(), 1)
@@ -90,7 +94,7 @@ def test_get_another_employment_certification_with_months_and_identification(sel
Payslip.objects.create(**self.payslip_data)
response = self.client.post(
reverse("send-employment-certification"),
- {"months": 6, "identification": "1000065648"},
+ {"months": 6, "identification": self.payslip_data["identification"]},
)
self.assertEqual(response.status_code, 200, response.content)
self.assertEqual(EmploymentCertification.objects.count(), 1)
@@ -104,10 +108,35 @@ def test_get_employment_certification_without_login(self):
def test_get_another_employment_certification_without_permission(self):
"""Tests that the user cannot get another user's employment certification without permission."""
response = self.client.post(
- reverse("send-employment-certification"), {"identification": "1000065648"}
+ reverse("send-employment-certification"),
+ {"identification": self.payslip_data["identification"]},
)
self.assertEqual(response.status_code, 403, response.content)
- # def test_something(self):
- # response = self.client.get(reverse("upload-old-certifications"))
- # self.assertEqual(response.status_code, 200)
+ def test_list_employment_certifications(self):
+ """Tests that the user can list the employment certifications."""
+ self.create_demo_user()
+ get_permission = Permission.objects.get(codename="get_employment_certification")
+ self.user.user_permissions.add(get_permission)
+ self.user.save()
+ for _ in range(6):
+ EmploymentCertification.objects.create(
+ user=self.user,
+ start_date="2023-09-01",
+ position=self.payslip_data["job_title"],
+ salary=self.payslip_data["salary"],
+ bonuses=self.payslip_data["bonus_paycheck"],
+ contract_type="Contrato de trabajo",
+ expedition_city="Bogotá",
+ )
+ response = self.client.get(reverse("get-employment-certifications"))
+ self.assertEqual(response.status_code, 200, response.content)
+ self.assertEqual(len(response.data), EmploymentCertification.objects.count())
+ self.assertEqual(response.data[0]["cedula"], self.user.cedula)
+ self.assertEqual(response.data[0]["position"], self.payslip_data["job_title"])
+ self.assertEqual(response.data[0]["salary"], str(self.payslip_data["salary"]))
+ self.assertEqual(
+ response.data[0]["bonuses"], str(self.payslip_data["bonus_paycheck"])
+ )
+ self.assertEqual(response.data[0]["contract_type"], "Contrato de trabajo")
+ self.assertEqual(response.data[0]["expedition_city"], "Bogotá")
diff --git a/INSIGHTSAPI/goals/tests.py b/INSIGHTSAPI/goals/tests.py
index 7a382c2..d20f13f 100644
--- a/INSIGHTSAPI/goals/tests.py
+++ b/INSIGHTSAPI/goals/tests.py
@@ -1,10 +1,11 @@
"""This module contains the tests for the goals app."""
from django.db.models import Q
+from django.conf import settings
+from django.contrib.auth.models import Permission
+from django.core.files.uploadedfile import SimpleUploadedFile
from django.utils import timezone
from django.urls import reverse
-from django.core.files.uploadedfile import SimpleUploadedFile
-from django.contrib.auth.models import Permission
from services.tests import BaseTestCase
from rest_framework import status
from users.models import User
@@ -248,7 +249,7 @@ def test_patch_goal_delivery(self):
# Create a goal object
Goals.objects.create(
- cedula="1000065648",
+ cedula=settings.TEST_CEDULA,
name="Heibert",
campaign_goal="Base Test Goal",
result="50",
@@ -268,7 +269,7 @@ def test_patch_goal_delivery(self):
"accepted": True,
}
# Send a PATCH request to the update-goal view
- response = self.client.patch("/goals/1000065648/", data=payload)
+ response = self.client.patch("/goals/" + str(settings.TEST_CEDULA) +"/", data=payload)
# Assert the response status code and content
self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)
# Assert that the goal was updated with the new data
@@ -402,7 +403,7 @@ def test_patch_goal_delivery_claro(self):
for data in table_info_data:
TableInfo.objects.create(**data)
goal = Goals.objects.create(
- cedula="1000065648",
+ cedula=settings.TEST_CEDULA,
name="Heibert",
campaign_goal="Base Test Goal",
result="50",
@@ -437,7 +438,7 @@ def test_patch_goal_execution(self):
"""Test the update-goal view."""
# Get the first goal from the database
goal = Goals.objects.create(
- cedula="1000065648",
+ cedula=settings.TEST_CEDULA,
name="Heibert",
campaign_goal="Base Test Goal",
result="50",
@@ -471,7 +472,7 @@ def test_patch_goal_denied(self):
"""Test the update-goal view."""
# Get the first goal from the database
goal = Goals.objects.create(
- cedula="1000065648",
+ cedula=settings.TEST_CEDULA,
name="Heibert",
campaign_goal="Base Test Goal",
result="50",
diff --git a/INSIGHTSAPI/goals/views.py b/INSIGHTSAPI/goals/views.py
index 809e537..f716d6b 100644
--- a/INSIGHTSAPI/goals/views.py
+++ b/INSIGHTSAPI/goals/views.py
@@ -1,10 +1,7 @@
"""This view allow to upload an Excel file with the goals of the staff and save them in the db."""
-import base64
-import email
import logging
import re
-import ssl
import locale
from django.core.exceptions import ValidationError
from django.db import transaction
@@ -14,8 +11,7 @@
from rest_framework import status as framework_status
from rest_framework import viewsets
from rest_framework.response import Response
-from services.emails import send_email
-from rest_framework.exceptions import PermissionDenied
+from django.core.mail import send_mail
from services.permissions import CustomizableGetDjangoModelViewPermissions
@@ -58,6 +54,7 @@ def partial_update(self, request, *args, **kwargs):
table_info = TableInfo.objects.filter(name=instance.table_goal)
accepted_state = "aceptada" if request.data["accepted"] else "rechazada"
table_data = ""
+ table_data_plain = ""
for table in table_info:
table_data += f"""