From 589f02f575afda93e3bceb24eca20ba521795f31 Mon Sep 17 00:00:00 2001 From: gowtham Date: Sat, 30 Apr 2022 22:27:49 +0530 Subject: [PATCH] Changes for Deadline changes and email sending --- CDC_Backend/APIs/adminViews.py | 8 ++-- CDC_Backend/APIs/companyViews.py | 46 +++++++++++++++---- CDC_Backend/APIs/constants.py | 2 +- CDC_Backend/APIs/serializers.py | 34 +++++++------- CDC_Backend/APIs/studentViews.py | 17 ++++--- CDC_Backend/APIs/utils.py | 17 ++++++- CDC_Backend/CDC_Backend/settings.py | 30 ++++++------ .../templates/company_opening_submitted.html | 41 ++++++++++++++++- README.md | 5 +- dev.env | 6 +-- 10 files changed, 148 insertions(+), 58 deletions(-) diff --git a/CDC_Backend/APIs/adminViews.py b/CDC_Backend/APIs/adminViews.py index 014d79c..872bd0e 100644 --- a/CDC_Backend/APIs/adminViews.py +++ b/CDC_Backend/APIs/adminViews.py @@ -54,9 +54,9 @@ def markStatus(request, id, email, user_type): def getDashboard(request, id, email, user_type): try: placements = Placement.objects.all().order_by('-created_at') - ongoing = placements.filter(deadline_datetime__gt=datetime.datetime.now(), offer_accepted__isnull=False) + ongoing = placements.filter(deadline_datetime__gt=datetime.datetime.now(), offer_accepted=True) previous = placements.exclude(deadline_datetime__gt=datetime.datetime.now()).filter( - offer_accepted__isnull=False) + offer_accepted=True) new = placements.filter(offer_accepted__isnull=True) ongoing = PlacementSerializerForAdmin(ongoing, many=True).data previous = PlacementSerializerForAdmin(previous, many=True).data @@ -102,8 +102,10 @@ def updateDeadline(request, id, email, user_type): def updateOfferAccepted(request, id, email, user_type): try: data = request.data + print(data) opening = get_object_or_404(Placement, pk=data[OPENING_ID]) - opening.offer_accepted = True if data[OFFER_ACCEPTED] == "true" else False + opening.offer_accepted = True if data[OFFER_ACCEPTED] == True else False + print(opening.offer_accepted) opening.save() return Response({'action': "Update Offer Accepted", 'message': "Offer Accepted Updated"}, status=status.HTTP_200_OK) diff --git a/CDC_Backend/APIs/companyViews.py b/CDC_Backend/APIs/companyViews.py index c03f695..979ce62 100644 --- a/CDC_Backend/APIs/companyViews.py +++ b/CDC_Backend/APIs/companyViews.py @@ -1,6 +1,5 @@ -import json - from rest_framework.decorators import api_view +from django.forms.models import model_to_dict from .models import * from .utils import * @@ -231,6 +230,7 @@ def addPlacement(request): def verifyEmail(request): try: data = request.data + send_email_to_company = None token = data[TOKEN] # decode token decoded_token = jwt.decode(token, os.environ.get("EMAIL_VERIFICATION_SECRET_KEY"), algorithms=['HS256']) @@ -243,18 +243,48 @@ def verifyEmail(request): opening = get_object_or_404(Placement, id=opening_id) if email != opening.email: raise ValueError("Invalid Email") - opening.email_verified = True + if not opening.email_verified: + opening.email_verified = True + send_email_to_company = True + else: + send_email_to_company = False opening.save() + else: + raise ValueError('Invalid opening type') + + if send_email_to_company: + # Email sending part. + details = model_to_dict(opening, fields=[field.name for field in Placement._meta.fields], + exclude=['id', 'is_company_details_pdf', 'offer_accepted', 'is_description_pdf', + 'is_compensation_details_pdf', 'is_selection_procedure_details_pdf', + 'email_verified']) + keys = list(details.keys()) + newdetails = {} + for key in keys: + if isinstance(details[key], list): + details[key] = {"details": details[key], "type": ["list"]} + if key in ['website', 'company_details_pdf_names', 'description_pdf_names', + 'compensation_details_pdf_names', 'selection_procedure_pdf_names']: + if key == 'website': + details[key] = {"details": details[key], "type": ["link"]} + else: + details[key] = {"details": details[key]["details"], "type": ["list", "link"], + "link": LINK_TO_STORAGE_COMPANY_ATTACHMENT + opening.id + "/"} + new_key = key.replace('_', ' ') + if key == 'company_details_pdf_names': + new_key = 'company details pdf' + newdetails[new_key] = details[key] data = { "designation": opening.designation, "opening_type": PLACEMENT, "opening_link": PLACEMENT_OPENING_URL.format(id=opening.id), # Some Changes here too - "company_name": opening.company_name + "company_name": opening.company_name, + "data": newdetails } - sendEmail(opening.email, COMPANY_OPENING_SUBMITTED_TEMPLATE_SUBJECT.format(id=opening.id), data, + json_data = json.dumps(data, default=str) + sendEmail(opening.email, COMPANY_OPENING_SUBMITTED_TEMPLATE_SUBJECT.format(id=opening.id), json_data, COMPANY_OPENING_SUBMITTED_TEMPLATE) - else: - raise ValueError('Invalid opening type') + return Response({'action': "Verify Email", 'message': "Email Verified Successfully"}, status=status.HTTP_200_OK) except Http404: @@ -266,4 +296,4 @@ def verifyEmail(request): except: logger.warning("Verify Email: " + str(sys.exc_info())) return Response({'action': "Verify Email", 'message': "Something went wrong"}, - status=status.HTTP_400_BAD_REQUEST) + status=status.HTTP_400_BAD_REQUEST) \ No newline at end of file diff --git a/CDC_Backend/APIs/constants.py b/CDC_Backend/APIs/constants.py index 0fca0ae..38cb2f9 100644 --- a/CDC_Backend/APIs/constants.py +++ b/CDC_Backend/APIs/constants.py @@ -43,7 +43,7 @@ PLACEMENT_OPENING_URL = "https://www.googleapis.com/auth/adwords/{id}" # On fron LINK_TO_STORAGE_COMPANY_ATTACHMENT = "https://storage.googleapis.com/cdc-backend-attachments/company_attachments/" LINK_TO_STORAGE_RESUME = "https://storage.googleapis.com/cdc-backend-attachments/resume/" LINK_TO_APPLICATIONS_CSV = "https://storage.googleapis.com/cdc-backend-attachments/applications-csv/" -LINK_TO_EMAIl_VERIFICATION_API = "https://api.sendgrid.com/v3/mail/send?token={token}" +LINK_TO_EMAIl_VERIFICATION_API = "http://localhost:3000/company/verifyEmail?token={token}" EMAIL = "email" diff --git a/CDC_Backend/APIs/serializers.py b/CDC_Backend/APIs/serializers.py index 98608a3..51d56f6 100644 --- a/CDC_Backend/APIs/serializers.py +++ b/CDC_Backend/APIs/serializers.py @@ -34,15 +34,15 @@ class StudentSerializer(serializers.ModelSerializer): model = Student exclude = ['resumes'] + class PlacementSerializerForStudent(serializers.ModelSerializer): company_details_pdf_links = serializers.SerializerMethodField() description_pdf_links = serializers.SerializerMethodField() compensation_pdf_links = serializers.SerializerMethodField() selection_procedure_details_pdf_links = serializers.SerializerMethodField() - def get_company_details_pdf_links(self, obj): - links =[] + links = [] for pdf_name in obj.company_details_pdf_names: ele = {} link = LINK_TO_STORAGE_COMPANY_ATTACHMENT + urllib.parse.quote_plus(obj.id + "/" + pdf_name) @@ -52,7 +52,7 @@ class PlacementSerializerForStudent(serializers.ModelSerializer): return links def get_description_pdf_links(self, obj): - links =[] + links = [] for pdf_name in obj.description_pdf_names: ele = {} link = LINK_TO_STORAGE_COMPANY_ATTACHMENT + urllib.parse.quote_plus(obj.id + "/" + pdf_name) @@ -62,7 +62,7 @@ class PlacementSerializerForStudent(serializers.ModelSerializer): return links def get_compensation_pdf_links(self, obj): - links =[] + links = [] for pdf_name in obj.compensation_details_pdf_names: ele = {} link = LINK_TO_STORAGE_COMPANY_ATTACHMENT + urllib.parse.quote_plus(obj.id + "/" + pdf_name) @@ -72,7 +72,7 @@ class PlacementSerializerForStudent(serializers.ModelSerializer): return links def get_selection_procedure_details_pdf_links(self, obj): - links =[] + links = [] for pdf_name in obj.selection_procedure_details_pdf_names: ele = {} link = LINK_TO_STORAGE_COMPANY_ATTACHMENT + urllib.parse.quote_plus(obj.id + "/" + pdf_name) @@ -81,23 +81,23 @@ class PlacementSerializerForStudent(serializers.ModelSerializer): links.append(ele) return links - - class Meta: model = Placement exclude = [CONTACT_PERSON_NAME, PHONE_NUMBER, EMAIL, COMPANY_DETAILS_PDF_NAMES, DESCRIPTION_PDF_NAMES, - COMPENSATION_DETAILS_PDF_NAMES, SELECTION_PROCEDURE_DETAILS_PDF_NAMES, OFFER_ACCEPTED, EMAIL_VERIFIED] + COMPENSATION_DETAILS_PDF_NAMES, SELECTION_PROCEDURE_DETAILS_PDF_NAMES, OFFER_ACCEPTED, + EMAIL_VERIFIED, + ] depth = 1 + class PlacementSerializerForAdmin(serializers.ModelSerializer): company_details_pdf_links = serializers.SerializerMethodField() description_pdf_links = serializers.SerializerMethodField() compensation_pdf_links = serializers.SerializerMethodField() selection_procedure_details_pdf_links = serializers.SerializerMethodField() - def get_company_details_pdf_links(self, obj): - links =[] + links = [] for pdf_name in obj.company_details_pdf_names: ele = {} link = LINK_TO_STORAGE_COMPANY_ATTACHMENT + urllib.parse.quote_plus(obj.id + "/" + pdf_name) @@ -107,7 +107,7 @@ class PlacementSerializerForAdmin(serializers.ModelSerializer): return links def get_description_pdf_links(self, obj): - links =[] + links = [] for pdf_name in obj.description_pdf_names: ele = {} link = LINK_TO_STORAGE_COMPANY_ATTACHMENT + urllib.parse.quote_plus(obj.id + "/" + pdf_name) @@ -117,7 +117,7 @@ class PlacementSerializerForAdmin(serializers.ModelSerializer): return links def get_compensation_pdf_links(self, obj): - links =[] + links = [] for pdf_name in obj.compensation_details_pdf_names: ele = {} link = LINK_TO_STORAGE_COMPANY_ATTACHMENT + urllib.parse.quote_plus(obj.id + "/" + pdf_name) @@ -127,7 +127,7 @@ class PlacementSerializerForAdmin(serializers.ModelSerializer): return links def get_selection_procedure_details_pdf_links(self, obj): - links =[] + links = [] for pdf_name in obj.selection_procedure_details_pdf_names: ele = {} link = LINK_TO_STORAGE_COMPANY_ATTACHMENT + urllib.parse.quote_plus(obj.id + "/" + pdf_name) @@ -136,12 +136,10 @@ class PlacementSerializerForAdmin(serializers.ModelSerializer): links.append(ele) return links - - class Meta: model = Placement exclude = [COMPANY_DETAILS_PDF_NAMES, DESCRIPTION_PDF_NAMES, - COMPENSATION_DETAILS_PDF_NAMES, SELECTION_PROCEDURE_DETAILS_PDF_NAMES] + COMPENSATION_DETAILS_PDF_NAMES, SELECTION_PROCEDURE_DETAILS_PDF_NAMES] depth = 1 @@ -159,11 +157,11 @@ class PlacementApplicationSerializer(serializers.ModelSerializer): ele['name'] = obj.resume return ele - class Meta: model = PlacementApplication exclude = [STUDENT, 'resume'] + class PlacementApplicationSerializerForAdmin(serializers.ModelSerializer): student_details = serializers.SerializerMethodField() resume_link = serializers.SerializerMethodField() @@ -178,4 +176,4 @@ class PlacementApplicationSerializerForAdmin(serializers.ModelSerializer): class Meta: model = PlacementApplication - exclude = ['placement', 'resume'] \ No newline at end of file + exclude = ['placement', 'resume'] diff --git a/CDC_Backend/APIs/studentViews.py b/CDC_Backend/APIs/studentViews.py index 946e52f..623a9a0 100644 --- a/CDC_Backend/APIs/studentViews.py +++ b/CDC_Backend/APIs/studentViews.py @@ -1,5 +1,7 @@ import json -from datetime import datetime +# from datetime import datetime +import datetime +import traceback from rest_framework.decorators import api_view @@ -72,13 +74,11 @@ def getDashboard(request, id, email, user_type): placements = Placement.objects.filter(allowed_batch__contains=[studentDetails.batch], allowed_branch__contains=[studentDetails.branch], - deadline_datetime__gte=datetime.now(), - offer_accepted=True, email_verified=True).order_by('deadline_datetime') + deadline_datetime__gte=datetime.datetime.now(), + offer_accepted=True, email_verified=True).order_by('deadline_datetime') placementsdata = PlacementSerializerForStudent(placements, many=True).data - placementApplications = PlacementApplication.objects.filter(student_id=id) placementApplications = PlacementApplicationSerializer(placementApplications, many=True).data - return Response( {'action': "Get Dashboard - Student", 'message': "Data Found", "placements": placementsdata, 'placementApplication': placementApplications}, @@ -88,6 +88,8 @@ def getDashboard(request, id, email, user_type): status=status.HTTP_404_NOT_FOUND) except: logger.warning("Get Dashboard -Student: " + str(sys.exc_info())) + print(sys.exc_info()) + return Response({'action': "Get Dashboard - Student", 'message': "Something Went Wrong"}, status=status.HTTP_400_BAD_REQUEST) @@ -140,7 +142,7 @@ def submitApplication(request, id, email, user_type): opening = get_object_or_404(Placement, id=data[OPENING_ID], allowed_batch__contains=[student.batch], allowed_branch__contains=[student.branch], - deadline_datetime__gte=datetime.now().date() + deadline_datetime__gte=datetime.datetime.now().date() ) if not opening.offer_accepted or not opening.email_verified: raise PermissionError("Placement Not Approved") @@ -192,5 +194,8 @@ def submitApplication(request, id, email, user_type): status=status.HTTP_404_NOT_FOUND) except: logger.warning("Submit Application: " + str(sys.exc_info())) + print(traceback.format_exc()) + + print(sys.exc_info()) return Response({'action': "Submit Application", 'message': "Something Went Wrong"}, status=status.HTTP_400_BAD_REQUEST) diff --git a/CDC_Backend/APIs/utils.py b/CDC_Backend/APIs/utils.py index fc17705..959fdc6 100644 --- a/CDC_Backend/APIs/utils.py +++ b/CDC_Backend/APIs/utils.py @@ -5,8 +5,9 @@ import random import re import string import sys +import traceback from os import path, remove - +import json import background_task import jwt from django.conf import settings @@ -135,6 +136,8 @@ def saveFile(file, location): @background_task.background(schedule=10) def sendEmail(email_to, subject, data, template): try: + if not isinstance(data, dict): + data = json.loads(data) html_content = render_to_string(template, data) # render with dynamic value text_content = strip_tags(html_content) @@ -156,7 +159,9 @@ def PlacementApplicationConditions(student, placement): selected_companies = PlacementApplication.objects.filter(student=student, selected=True) selected_companies_PSU = [i for i in selected_companies if i.placement.tier == 'psu'] PPO = PrePlacementOffer.objects.filter(student=student, accepted=True) - + # find lenght of PPO + print(PPO) + print(len(PPO), "ere") if len(selected_companies) + len(PPO) >= MAX_OFFERS_PER_STUDENT: raise PermissionError("Max Applications Reached for the Season") @@ -177,6 +182,8 @@ def PlacementApplicationConditions(student, placement): return False, e except: print(sys.exc_info()) + print(traceback.format_exc()) + logger.warning("Utils - PlacementApplicationConditions: " + str(sys.exc_info())) return False, "_" @@ -237,15 +244,21 @@ def generateOneTimeVerificationLink(email, opening_id, opening_type): def verify_recaptcha(request): try: + print(settings.RECAPTCHA_SECRET_KEY) data = { 'secret': settings.RECAPTCHA_SECRET_KEY, 'response': request } + print(data) r = rq.post('https://www.google.com/recaptcha/api/siteverify', data=data) result = r.json() # logger.info("Recaptcha Response: " + str(result)+"request: "+str(data)) + + print(result, "Result") return result['success'] except: + # get exception line number print(sys.exc_info()) + print(traceback.format_exc()) logger.warning("Utils - verify_recaptcha: " + str(sys.exc_info())) return False, "_" \ No newline at end of file diff --git a/CDC_Backend/CDC_Backend/settings.py b/CDC_Backend/CDC_Backend/settings.py index c96c4d8..9a09b88 100644 --- a/CDC_Backend/CDC_Backend/settings.py +++ b/CDC_Backend/CDC_Backend/settings.py @@ -83,23 +83,23 @@ WSGI_APPLICATION = 'CDC_Backend.wsgi.application' # https://docs.djangoproject.com/en/2.2/ref/settings/#databases DATABASES = { - # 'default': { - # 'ENGINE': 'django.db.backends.postgresql_psycopg2', - # 'NAME': os.environ.get("DB_NAME"), - # 'USER': os.environ.get("DB_USER"), - # 'PASSWORD': os.environ.get("DB_PASSWORD"), - # 'HOST': os.environ.get("DB_HOST"), - # 'PORT': os.environ.get("DB_PORT"), - # }, - 'default': { 'ENGINE': 'django.db.backends.postgresql_psycopg2', - 'NAME': 'd84i5cbjig5rrf', - 'USER': 'hbkullcdjbxuwh', - 'PASSWORD': '45d990da00e2cc96d7d4e2e5e308d4b07a387883f70c40e090a6252175cb634e', - 'HOST': 'ec2-54-163-97-228.compute-1.amazonaws.com', - 'PORT': '5432', - } + 'NAME': os.environ.get("DB_NAME"), + 'USER': os.environ.get("DB_USER"), + 'PASSWORD': os.environ.get("DB_PASSWORD"), + 'HOST': os.environ.get("DB_HOST"), + 'PORT': os.environ.get("DB_PORT"), + }, + # + # 'default': { + # 'ENGINE': 'django.db.backends.postgresql_psycopg2', + # 'NAME': 'd84i5cbjig5rrf', + # 'USER': 'hbkullcdjbxuwh', + # 'PASSWORD': '45d990da00e2cc96d7d4e2e5e308d4b07a387883f70c40e090a6252175cb634e', + # 'HOST': 'ec2-54-163-97-228.compute-1.amazonaws.com', + # 'PORT': '5432', + # } } # Password validation diff --git a/CDC_Backend/templates/company_opening_submitted.html b/CDC_Backend/templates/company_opening_submitted.html index a37c107..31d6214 100644 --- a/CDC_Backend/templates/company_opening_submitted.html +++ b/CDC_Backend/templates/company_opening_submitted.html @@ -21,6 +21,14 @@ table, td, div, h1, p { font-family: 'Roboto', sans-serif; } + #details_table tr:nth-child(even) {background: #FFF} + #details_table tr:nth-child(odd) {background: #f9f9f9} + #details_table td {padding: 10px} + #details_table{ + border: #334878 1px solid; + border-collapse: collapse; + } + @@ -47,13 +55,44 @@ We have received your {{ opening_type }} notification for a {{ designation }} offer at {{ company_name }}. Click here to view your notification.

-

We will keep you informed with the updates. If you have any queries, please feel to write to cdc@iitdh.ac.in

+ + {% for key, value in data.items %} + + + + + {% endfor %} +
+ {{ key }} + + {% if 'list' in value.type %} + + {% for item in value.details %} +
  • + {% if 'link' in value.type and value.link %} + {{ item }} + {% elif 'link' in value.type %} + {{ item }} + {% else %} + {{ item }} + {% endif %} +
  • + {% endfor %} + {% else %} + {% if 'link' in value.type %} + {{ value.details }} + {% else %} + {{ value }} + {% endif %} + {% endif %} + +
    diff --git a/README.md b/README.md index b863ab5..78a53cf 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# CDC - Backend +python# CDC - Backend --- @@ -34,6 +34,9 @@ 1. Add the hosted domain name in `ALLOWED_HOSTS` in [settings.py](./CDC_Backend/CDC_Backend/settings.py) 2. Update the `CORS_ORIGIN_WHITELIST` list and `CORS_ORIGIN_ALLOW_ALL` variable +### Starting the Email Server +Run the following command to start the email backend process
    +`python manage.py process_tasks` ### API Reference Check [here](./CDC_Backend/README.md) for Api Reference diff --git a/dev.env b/dev.env index 4c6d245..fff40b9 100644 --- a/dev.env +++ b/dev.env @@ -1,12 +1,12 @@ HOSTING_URL=http://localhost:8000/ DEBUG=True EMAIL=saisurya3127@gmail.com -EMAIL_PASSWORD=yeylqcnsyjfpzsew +EMAIL_PASSWORD=lvryxwieedpervtv SECRET_KEY=%2e!&f6(ib^690y48z=)&w6fczhwukzzp@3y*^*7u+7%4s-mie EMAIL_VERIFICATION_SECRET_KEY=b'<\xa3\xaf&(*|\x0e\xbces\x07P\xf7\xd6\xa9sf\x19$\x96\xb7\x90\x8b\x88\x84\x0e\x191\xde,M\x90\x17(\xf7\nG\x13"\x8d$\x9f&\xb0\xcd\xa4\xaf\xa9\x1b\x15\x02B\x8a\xaf\xff\x0c\x1e\xd5\xb3\x06\xb8\xa6\x9bQ\xa0TR\xe8\x98\x9ae\xe0n}\xcc/[\xdaFz\x18\xfeX\xaf\xbd\xd0\x88\xeal\xe3\xd2\xe3\xb8\x8c\x199{\xf3<\xb0\xc5\xd0\xe7*Rv\xda\xbb \x1d\x85~\xff%>\x1e\xb8\xa7\xbf\xbc\xb2\x06\x86X\xc3\x9f\x13<\x9fd\xea\xb5"\\5&\x01\xa4\x7f=\xa0\x1b\x8bO\x01h\xe8\xfd\x1f\xfe\xba\xbeg\\\xc2\xcb\xc3\xd1~\xff\xd5/9d\xa8\xa7x{\x16\xdb\\\xbb\x08\rI\xcd\x9e7\x8c~\x0f\x1d\x81rXZD\xf0\xf7\x87K\x8f\xfb,\xf4\xf0\xa5\x9e\xde^\xca\xae\x80|9b\x9b\xaaE"\xba\xfb\xdf\x80\xb1\x99\x83e[\xf8\xce&Rq\x99\xdb}\xeeO\xd5\x18\x8d\x0bv\xe7\xab\xf9\xb9{\xb5u\xce\xcf\x90\xa6HE\xc5\x92p\x00\x158\xdf\x1d' DB_NAME=cdc DB_USER=postgres -DB_PASSWORD=root +DB_PASSWORD=postgres DB_HOST=localhost DB_PORT=5432 -RECAPTCHA_SECRET_KEY=6LdXXj4fAAAAADRZvwwsznKPEI-StyN6s_4glHLj +RECAPTCHA_SECRET_KEY=6Lcv-mEfAAAAAOxM3pzPc-9W96yPlkWnn6v41fLl