From b95b46da769f7e0ceb67a8752b071e1dfedb798c Mon Sep 17 00:00:00 2001 From: Horilla Date: Thu, 21 Dec 2023 16:37:23 +0530 Subject: [PATCH] [ADD] ONBOARDING: Added templates as attachment feature --- .../templates/onboarding/candidates_view.html | 193 +++++++++--------- onboarding/views.py | 51 ++++- recruitment/views/views.py | 92 ++++++--- 3 files changed, 207 insertions(+), 129 deletions(-) diff --git a/onboarding/templates/onboarding/candidates_view.html b/onboarding/templates/onboarding/candidates_view.html index 2db07584c..7300cb973 100644 --- a/onboarding/templates/onboarding/candidates_view.html +++ b/onboarding/templates/onboarding/candidates_view.html @@ -19,38 +19,17 @@

{% trans "Hired Candidates" %}

- - + +
{% if candidates %} -
- - +
+ +
@@ -61,25 +40,15 @@
- - +
{% endif %}
- + {% trans "Create" %} @@ -88,77 +57,105 @@
- + Joining Set - + Joining Not-Set - + Portal Not-Sent - + Portal Sent +
+
+
{% if candidates %} {% include 'onboarding/candidates.html' %} {% else %} -
-
- Page not found. 404. -
{% trans "At present, There are no Candidates onboarding." %}
-
-
+
+
+ Page not found. 404. +
{% trans "At present, There are no Candidates onboarding." %}
+
+
{% endif %}
+ -{% endblock content %} +{% endblock content %} \ No newline at end of file diff --git a/onboarding/views.py b/onboarding/views.py index 52b355cce..4e7a4db12 100644 --- a/onboarding/views.py +++ b/onboarding/views.py @@ -13,6 +13,7 @@ provide the main entry points for interacting with the application's functionali from urllib.parse import parse_qs import json, contextlib, random, secrets +from django import template from django.core.mail import EmailMessage from django.template.loader import render_to_string from django.core.mail import send_mail @@ -30,8 +31,8 @@ from notifications.signals import notify from horilla import settings from horilla.decorators import login_required, hx_request_required from horilla.decorators import permission_required -from base.methods import get_key_instances -from recruitment.models import Candidate, Recruitment +from base.methods import generate_pdf, get_key_instances +from recruitment.models import Candidate, Recruitment, RecruitmentMailTemplate from recruitment.filters import CandidateFilter from employee.models import Employee, EmployeeWorkInformation, EmployeeBankDetails from django.db.models import ProtectedError @@ -481,6 +482,7 @@ def candidates_view(request): previous_data = request.GET.urlencode() page_number = request.GET.get("page") page_obj = paginator_qry(queryset, page_number) + mail_templates = RecruitmentMailTemplate.objects.all() return render( request, "onboarding/candidates_view.html", @@ -488,6 +490,8 @@ def candidates_view(request): "candidates": page_obj, "form": candidate_filter_obj.form, "pd": previous_data, + "mail_templates": mail_templates, + "hired_candidates": queryset, }, ) @@ -556,9 +560,44 @@ def email_send(request): """ host = request.get_host() protocol = "https" if request.is_secure() else "http" - candidates = request.GET.getlist("ids") + candidates = request.POST.getlist("ids") + other_attachments = request.FILES.getlist("other_attachments") + template_attachment_ids = request.POST.getlist("template_attachment_ids") + print(candidates) + if not candidates: + messages.info(request, "Please choose chandidates") + return HttpResponse("") + + bodys = list( + RecruitmentMailTemplate.objects.filter( + id__in=template_attachment_ids + ).values_list("body", flat=True) + ) + + if not candidates: + messages.info(request, "Please choose candidates") + + attachments_other = [] + for file in other_attachments: + attachments_other.append((file.name, file.read(), file.content_type)) + file.close() for cand_id in candidates: + attachments = list(set(attachments_other) | set([])) candidate = Candidate.objects.get(id=cand_id) + for html in bodys: + # due to not having solid template we first need to pass the context + template_bdy = template.Template(html) + context = template.Context( + {"instance": candidate, "self": request.user.employee_get} + ) + render_bdy = template_bdy.render(context) + attachments.append( + ( + "Document", + generate_pdf(render_bdy, {}, path=False, title="Document").content, + "application/pdf", + ) + ) token = secrets.token_hex(15) existing_portal = OnboardingPortal.objects.filter(candidate_id=candidate) if existing_portal.exists(): @@ -584,16 +623,16 @@ def email_send(request): [candidate.email], ) email.content_subtype = "html" + email.attachments = attachments try: email.send() # to check ajax or not - if not request.headers.get("x-requested-with") == "XMLHttpRequest": - messages.success(request, "Portal link sent to the candidate") + messages.success(request, "Portal link sent to the candidate") except: messages.error(request, f"Mail not send to {candidate.name}") candidate.start_onboard = True candidate.save() - return redirect(candidates_view) + return HttpResponse("") @login_required diff --git a/recruitment/views/views.py b/recruitment/views/views.py index f9107bd2b..6f00543ff 100644 --- a/recruitment/views/views.py +++ b/recruitment/views/views.py @@ -11,7 +11,8 @@ This module is part of the recruitment project and is intended to provide the main entry points for interacting with the application's functionality. """ -from datetime import date, datetime +from django import template +from django.core.mail import EmailMessage import os import json import contextlib @@ -21,18 +22,22 @@ from django.db.models import Q from django.http import JsonResponse, HttpResponse, HttpResponseRedirect from django.shortcuts import render, redirect from django.core import serializers -import pandas as pd from base.models import JobPosition from django.contrib import messages from django.views.decorators.http import require_http_methods -from django.core.mail import send_mail from django.utils.translation import gettext_lazy as _ from notifications.signals import notify from horilla import settings from horilla.decorators import permission_required, login_required, hx_request_required -from base.methods import export_data, get_key_instances +from base.methods import export_data, generate_pdf, get_key_instances from recruitment.views.paginator_qry import paginator_qry -from recruitment.models import Recruitment, Candidate, Stage, StageNote +from recruitment.models import ( + RecruitmentMailTemplate, + Recruitment, + Candidate, + Stage, + StageNote, +) from recruitment.filters import ( CandidateFilter, CandidateReGroup, @@ -998,8 +1003,11 @@ def form_send_mail(request, cand_id): This method is used to render the bootstrap modal content body form """ candidate_obj = Candidate.objects.get(id=cand_id) + templates = RecruitmentMailTemplate.objects.all() return render( - request, "pipeline/pipeline_components/send_mail.html", {"cand": candidate_obj} + request, + "pipeline/pipeline_components/send_mail.html", + {"cand": candidate_obj, "templates": templates}, ) @@ -1009,29 +1017,57 @@ def send_acknowledgement(request): """ This method is used to send acknowledgement mail to the candidate """ - with contextlib.suppress(Exception): - send_to = request.POST.get("to") - subject = request.POST.get("subject") - bdy = request.POST.get("body") - res = send_mail( - subject, bdy, settings.EMAIL_HOST_USER, [send_to], fail_silently=False - ) - if res == 1: - return HttpResponse( - """ -
-
Mail sent.
-
- """ - ) - return HttpResponse( - """ -
-
Sorry,\ - Something went wrong.
-
- """ + candidate_id = request.POST["id"] + subject = request.POST.get("subject") + bdy = request.POST.get("body") + other_attachments = request.FILES.getlist("other_attachments") + attachments = [ + (file.name, file.read(), file.content_type) for file in other_attachments + ] + host = settings.EMAIL_HOST_USER + candidate_obj = Candidate.objects.get(id=candidate_id) + template_attachment_ids = request.POST.getlist("template_attachments") + bodys = list( + RecruitmentMailTemplate.objects.filter( + id__in=template_attachment_ids + ).values_list("body", flat=True) ) + for html in bodys: + # due to not having solid template we first need to pass the context + template_bdy = template.Template(html) + context = template.Context( + {"instance": candidate_obj, "self": request.user.employee_get} + ) + render_bdy = template_bdy.render(context) + attachments.append( + ( + "Document", + generate_pdf(render_bdy, {}, path=False, title="Document").content, + "application/pdf", + ) + ) + + template_bdy = template.Template(bdy) + context = template.Context( + {"instance": candidate_obj, "self": request.user.employee_get} + ) + render_bdy = template_bdy.render(context) + + email = EmailMessage( + subject, + render_bdy, + host, + [candidate_obj.email], + ) + email.content_subtype = "html" + + email.attachments = attachments + try: + email.send() + messages.success(request, "Mail sent to candidate") + except Exception as e: + messages.error(request, "Something went wrong") + return HttpResponse("") @login_required