From 91841708cf2ee78d633a02275d46238e235c3ff5 Mon Sep 17 00:00:00 2001 From: Horilla Date: Thu, 21 Dec 2023 17:15:25 +0530 Subject: [PATCH] [ADD] RECRUITMENT: Mail template setup --- base/methods.py | 9 +- recruitment/admin.py | 2 + recruitment/forms.py | 17 +++ recruitment/models.py | 47 +++++- .../templates/offerletter/create_letter.html | 4 + .../templates/offerletter/htmx/form.html | 32 ++++ .../templates/offerletter/view_letter.html | 4 + .../templates/offerletter/view_templates.html | 75 ++++++++++ recruitment/templates/pipeline/nav.html | 9 -- recruitment/templates/pipeline/pipeline.html | 3 + .../pipeline_components/send_mail.html | 137 ++++++++++++++---- .../mail_templates/offer_letter.html | 102 +++++++++++++ recruitment/urls.py | 25 +++- recruitment/views/mail_templates.py | 91 ++++++++++++ templates/sidebar.html | 13 +- 15 files changed, 523 insertions(+), 47 deletions(-) create mode 100644 recruitment/templates/offerletter/create_letter.html create mode 100644 recruitment/templates/offerletter/htmx/form.html create mode 100644 recruitment/templates/offerletter/view_letter.html create mode 100644 recruitment/templates/offerletter/view_templates.html create mode 100644 recruitment/templates/recruitment/mail_templates/offer_letter.html create mode 100644 recruitment/views/mail_templates.py diff --git a/base/methods.py b/base/methods.py index 9b104be21..1a1459309 100644 --- a/base/methods.py +++ b/base/methods.py @@ -450,8 +450,11 @@ def check_owner(employee, instance): return False -def generate_pdf(template_path, context): - html = render_to_string(template_path, context) +def generate_pdf(template_path, context, path=True,title=None): + html = template_path + title = f"""{context.get("employee")}'s payslip for {context.get("range")}.pdf""" if not title else title + if path: + html = render_to_string(template_path, context) result = io.BytesIO() pdf = pisa.pisaDocument(io.BytesIO(html.encode("utf-8")), result) @@ -460,6 +463,6 @@ def generate_pdf(template_path, context): response = HttpResponse(result.getvalue(), content_type="application/pdf") response[ "Content-Disposition" - ] = f'''attachment;filename="{context.get("employee")}'s payslip for {context.get("range")}.pdf"''' + ] = f'''attachment;filename="{title}"''' return response return None diff --git a/recruitment/admin.py b/recruitment/admin.py index f4e40515f..372e6a030 100644 --- a/recruitment/admin.py +++ b/recruitment/admin.py @@ -10,6 +10,7 @@ from recruitment.models import ( Candidate, RecruitmentSurvey, RecruitmentSurveyAnswer, + RecruitmentMailTemplate ) @@ -21,3 +22,4 @@ admin.site.register(Recruitment) admin.site.register(Candidate) admin.site.register(RecruitmentSurveyAnswer) admin.site.register(RecruitmentSurvey) +admin.site.register(RecruitmentMailTemplate) diff --git a/recruitment/forms.py b/recruitment/forms.py index 2c6d07dfb..0081ace40 100644 --- a/recruitment/forms.py +++ b/recruitment/forms.py @@ -33,10 +33,12 @@ from recruitment.models import ( StageNote, JobPosition, RecruitmentSurvey, + RecruitmentMailTemplate, ) from recruitment import widgets from base.methods import reload_queryset + class ModelForm(forms.ModelForm): """ Overriding django default model form to apply some styles @@ -575,3 +577,18 @@ class CandidateExportForm(forms.Form): "joining_date", ], ) + + +class OfferLetterForm(ModelForm): + """ + OfferLetterForm + """ + + class Meta: + model = RecruitmentMailTemplate + fields = "__all__" + widgets = { + "body": forms.Textarea( + attrs={"data-summernote": "", "style": "display:none;"} + ), + } diff --git a/recruitment/models.py b/recruitment/models.py index 23d7474c6..049c1c358 100644 --- a/recruitment/models.py +++ b/recruitment/models.py @@ -302,6 +302,16 @@ class Candidate(models.Model): ], ) sequence = models.IntegerField(null=True, default=0) + offerletter_status = models.CharField( + max_length=20, + choices=[ + ("not_sent", "Not sent"), + ("waiting", "Waiting Confirmation"), + ("accepted", "Accepted / Confirmed"), + ("rejected", "Rejected / Canceled"), + ], + default="not_sent", + ) objects = HorillaCompanyManager(related_company_field="recruitment_id__company_id") def __str__(self): @@ -328,6 +338,28 @@ class Candidate(models.Model): return url + def get_company(self): + """ + This method is used to return the company + """ + return getattr( + getattr(getattr(self, "recruitment_id", None), "company_id", None), + "company", + None, + ) + + def get_job_position(self): + """ + This method is used to return the job position of the candidate + """ + return self.job_position_id.job_position + + def get_email(self): + """ + Return email + """ + return self.email + def tracking(self): """ This method is used to return the tracked history of the instance @@ -374,7 +406,9 @@ class StageNote(models.Model): description = models.TextField(verbose_name=_("Description")) stage_id = models.ForeignKey(Stage, on_delete=models.CASCADE) updated_by = models.ForeignKey(Employee, on_delete=models.CASCADE) - objects = HorillaCompanyManager(related_company_field="candidate_id__recruitment_id__company_id") + objects = HorillaCompanyManager( + related_company_field="candidate_id__recruitment_id__company_id" + ) def __str__(self) -> str: return f"{self.description}" @@ -464,3 +498,14 @@ class RecruitmentSurveyAnswer(models.Model): def __str__(self) -> str: return f"{self.candidate_id.name}-{self.recruitment_id}" + + +class RecruitmentMailTemplate(models.Model): + title = models.CharField(max_length=25, unique=True) + body = models.TextField() + company_id = models.ForeignKey( + Company, null=True, blank=True, on_delete=models.CASCADE,verbose_name="Company" + ) + + def __str__(self) -> str: + return self.title diff --git a/recruitment/templates/offerletter/create_letter.html b/recruitment/templates/offerletter/create_letter.html new file mode 100644 index 000000000..cb10b49dd --- /dev/null +++ b/recruitment/templates/offerletter/create_letter.html @@ -0,0 +1,4 @@ +{% extends "index.html" %} +{% block content %} +{{form}} +{% endblock content %} \ No newline at end of file diff --git a/recruitment/templates/offerletter/htmx/form.html b/recruitment/templates/offerletter/htmx/form.html new file mode 100644 index 000000000..564b37fba --- /dev/null +++ b/recruitment/templates/offerletter/htmx/form.html @@ -0,0 +1,32 @@ +{% if form.instance.id %} +
+{% else %} + +{% endif %} +
+
+
+
+
+ + {{ form.title }} +
+
+ + {{ form.body }} +
+
+ + {{ form.company_id }} +
+
+
+
+
+ +
+ \ No newline at end of file diff --git a/recruitment/templates/offerletter/view_letter.html b/recruitment/templates/offerletter/view_letter.html new file mode 100644 index 000000000..2b227a224 --- /dev/null +++ b/recruitment/templates/offerletter/view_letter.html @@ -0,0 +1,4 @@ +{% extends "index.html" %} +{% block content %} +{{instance.body}} +{% endblock content %} \ No newline at end of file diff --git a/recruitment/templates/offerletter/view_templates.html b/recruitment/templates/offerletter/view_templates.html new file mode 100644 index 000000000..60e9a4ac1 --- /dev/null +++ b/recruitment/templates/offerletter/view_templates.html @@ -0,0 +1,75 @@ +{% extends 'index.html' %} +{% block content %} + + +
+
+

Mail Templates

+
+
+ Add +
+
+ +
+ {% for template in templates %} +
+

{{ template.title }}

+
{{ template.body|safe }}
+

+ View Template +
+ {% endfor %} +
+ + + +{% endblock %} diff --git a/recruitment/templates/pipeline/nav.html b/recruitment/templates/pipeline/nav.html index 18c833d8d..af62ff915 100644 --- a/recruitment/templates/pipeline/nav.html +++ b/recruitment/templates/pipeline/nav.html @@ -1,13 +1,4 @@ {% load i18n %} -{% if messages %} -
- {% for message in messages %} -
- {{ message }} -
- {% endfor %} -
- {% endif %} {% if recruitment_form.errors %}
diff --git a/recruitment/templates/pipeline/pipeline.html b/recruitment/templates/pipeline/pipeline.html index 32f1bbc6f..53fee1d41 100644 --- a/recruitment/templates/pipeline/pipeline.html +++ b/recruitment/templates/pipeline/pipeline.html @@ -1,4 +1,7 @@ {% extends 'index.html' %} {% load i18n %} {% block content %} {% load static %} {% load recruitmentfilters %} +
+ +