diff --git a/CDC_Backend/APIs/admin.py b/CDC_Backend/APIs/admin.py
index 4c26bd9..eb4711c 100644
--- a/CDC_Backend/APIs/admin.py
+++ b/CDC_Backend/APIs/admin.py
@@ -1,9 +1,41 @@
from django.contrib import admin
from .models import *
+from django.contrib import admin
+from django.contrib.admin.templatetags.admin_urls import admin_urlname
+from django.shortcuts import resolve_url
+from django.utils.html import format_html
+from django.utils.safestring import SafeText
+from .models import *
admin.site.register(User)
-admin.site.register(Student)
+# admin.site.register(Student)
admin.site.register(Admin)
-admin.site.register(Placement)
+# admin.site.register(Placement)
admin.site.register(PlacementApplication)
admin.site.register(PrePlacementOffer)
+
+admin.site.site_header = "CDC Recruitment Portal"
+
+
+def model_admin_url(obj, name=None) -> str:
+ url = resolve_url(admin_urlname(obj._meta, SafeText("change")), obj.pk)
+ return format_html('{}', url, name or str(obj))
+
+
+@admin.register(Student)
+class Student(admin.ModelAdmin):
+ list_display = ("roll_no", "name", "batch", "branch", "phone_number")
+ search_fields = ("roll_no", "name","phone_number")
+ ordering = ("roll_no", "name", "batch", "branch", "phone_number")
+ list_filter = ("batch", "branch")
+
+
+@admin.register(Placement)
+class Placement(admin.ModelAdmin):
+ list_display = (COMPANY_NAME, CONTACT_PERSON_NAME, PHONE_NUMBER, 'tier', 'compensation_CTC')
+ search_fields = (COMPANY_NAME, CONTACT_PERSON_NAME)
+ ordering = (COMPANY_NAME, CONTACT_PERSON_NAME, 'tier', 'compensation_CTC')
+ list_filter = ('tier',)
+
+
+
diff --git a/CDC_Backend/APIs/adminUrls.py b/CDC_Backend/APIs/adminUrls.py
index 203c0dc..bd3d6e5 100644
--- a/CDC_Backend/APIs/adminUrls.py
+++ b/CDC_Backend/APIs/adminUrls.py
@@ -1,7 +1,15 @@
from django.urls import path
-from . import companyViews
+from . import adminViews
urlpatterns = [
-
+ path('markStatus/', adminViews.markStatus, name="Mark Status"),
+ path('getDashboard/', adminViews.getDashboard, name="Get Dashboard"),
+ path('updateDeadline/', adminViews.updateDeadline, name="Update Deadline"),
+ path('updateOfferAccepted/', adminViews.updateOfferAccepted, name="Update Offer Accepted"),
+ path('updateEmailVerified', adminViews.updateEmailVerified, name="Update Email Verified"),
+ path('updateAdditionalInfo/', adminViews.updateAdditionalInfo, name="Update Additional Info"),
+ path('getApplications/', adminViews.getApplications, name="Get Applications"),
+ path("submitApplication/", adminViews.submitApplication, name="Submit Application"),
+ path('generateCSV/', adminViews.generateCSV, name="Generate CSV"),
]
diff --git a/CDC_Backend/APIs/adminViews.py b/CDC_Backend/APIs/adminViews.py
index e69de29..845ecef 100644
--- a/CDC_Backend/APIs/adminViews.py
+++ b/CDC_Backend/APIs/adminViews.py
@@ -0,0 +1,299 @@
+import json
+from datetime import datetime
+
+from .utils import *
+from rest_framework.decorators import api_view
+import csv
+from .serializers import *
+
+
+@api_view(['POST'])
+@isAuthorized([ADMIN])
+@precheck([OPENING_ID, STUDENT_LIST])
+def markStatus(request, id, email, user_type):
+ try:
+ data = request.data
+ # Getting all application from db for this opening
+ applications = PlacementApplication.objects.filter(placement_id=data[OPENING_ID])
+ for i in data[STUDENT_LIST]:
+ application = applications.filter(student_id=i[STUDENT_ID]) # Filtering student's application
+ if len(application) > 0:
+ application = application[0]
+ application.selected = True if i[STUDENT_SELECTED] == "true" else False
+
+ email = str(application.student.roll_no) + "@iitdh.ac.in" # Only allowing for IITDh emails
+ subject = STUDENT_APPLICATION_STATUS_TEMPLATE_SUBJECT.format(company_name=application.placement.company_name,
+ id=application.id)
+ data = {
+ "company_name": application.placement.company_name,
+ "designation": application.placement.designation,
+ "student_name": application.student.name
+ }
+ if application.selected: # Sending corresponding email to students
+ sendEmail(email, subject, data, STUDENT_APPLICATION_STATUS_SELECTED_TEMPLATE)
+ else:
+ sendEmail(email, subject, data, STUDENT_APPLICATION_STATUS_NOT_SELECTED_TEMPLATE)
+ application.save()
+ else:
+ raise ValueError("Student - " + i[STUDENT_ID] + " didn't apply for this opening")
+ return Response({'action': "Mark Status", 'message': "Marked Status"},
+ status=status.HTTP_200_OK)
+
+ except ValueError as e:
+ return Response({'action': "Mark Status", 'message': str(e)},
+ status=status.HTTP_400_BAD_REQUEST)
+ except:
+ logger.warning("Mark Status: " + str(sys.exc_info()))
+ return Response({'action': "Mark Status", 'message': "Something went wrong"},
+ status=status.HTTP_400_BAD_REQUEST)
+
+
+@api_view(['GET'])
+@isAuthorized([ADMIN])
+def getDashboard(request, id, email, user_type):
+ try:
+ placements = Placement.objects.all().order_by('-created_at')
+ ongoing = placements.filter(deadline_datetime__gt=datetime.now())
+ previous = placements.exclude(deadline_datetime__gt=datetime.now())
+ ongoing = PlacementSerializerForAdmin(ongoing, many=True).data
+ previous = PlacementSerializerForAdmin(previous, many=True).data
+
+ return Response(
+ {'action': "Get Dashboard - Admin", 'message': "Data Found", "ongoing": ongoing, "previous": previous},
+ status=status.HTTP_200_OK)
+ except Http404:
+ return Response({'action': "Get Dashboard - Admin", 'message': 'Student Not Found'},
+ status=status.HTTP_404_NOT_FOUND)
+ except:
+ logger.warning("Get Dashboard - Admin: " + str(sys.exc_info()))
+ return Response({'action': "Get Dashboard - Admin", 'message': "Something went wrong"},
+ status=status.HTTP_400_BAD_REQUEST)
+
+
+@api_view(['POST'])
+@isAuthorized([ADMIN])
+@precheck([OPENING_ID, DEADLINE_DATETIME])
+def updateDeadline(request, id, email, user_type):
+ try:
+ data = request.data
+ opening = get_object_or_404(Placement, pk=data[OPENING_ID])
+ # Updating deadline date with correct format in datetime field
+ opening.deadline_datetime = datetime.strptime(data[DEADLINE_DATETIME], '%Y-%m-%d %H:%M:%S %z')
+ opening.save()
+ return Response({'action': "Update Deadline", 'message': "Deadline Updated"},
+ status=status.HTTP_200_OK)
+ except Http404:
+ return Response({'action': "Update Deadline", 'message': 'Opening Not Found'},
+ status=status.HTTP_404_NOT_FOUND)
+ except:
+ logger.warning("Update Deadline: " + str(sys.exc_info()))
+ return Response({'action': "Update Deadline", 'message': "Something went wrong"},
+ status=status.HTTP_400_BAD_REQUEST)
+
+@api_view(['POST'])
+@isAuthorized([ADMIN])
+@precheck([OPENING_ID, OFFER_ACCEPTED])
+def updateOfferAccepted(request, id, email, user_type):
+ try:
+ data = request.data
+ opening = get_object_or_404(Placement, pk=data[OPENING_ID])
+ opening.offer_accepted = True if data[OFFER_ACCEPTED] == "true" else False
+ opening.save()
+ return Response({'action': "Update Offer Accepted", 'message': "Offer Accepted Updated"},
+ status=status.HTTP_200_OK)
+ except Http404:
+ return Response({'action': "Update Offer Accepted", 'message': 'Opening Not Found'},
+ status=status.HTTP_404_NOT_FOUND)
+ except:
+ logger.warning("Update Offer Accepted: " + str(sys.exc_info()))
+ return Response({'action': "Update Offer Accepted", 'message': "Something went wrong"},
+ status=status.HTTP_400_BAD_REQUEST)
+
+@api_view(['POST'])
+@isAuthorized([ADMIN])
+@precheck([OPENING_ID, EMAIL_VERIFIED])
+def updateEmailVerified(request, id, email, user_type):
+ try:
+ data = request.data
+ opening = get_object_or_404(Placement, pk=data[OPENING_ID])
+ opening.email_verified = True if data[EMAIL_VERIFIED] == "true" else False
+ opening.save()
+ return Response({'action': "Update Email Verified", 'message': "Email Verified Updated"},
+ status=status.HTTP_200_OK)
+ except Http404:
+ return Response({'action': "Update Email Verified", 'message': 'Opening Not Found'},
+ status=status.HTTP_404_NOT_FOUND)
+ except:
+ logger.warning("Update Email Verified: " + str(sys.exc_info()))
+ return Response({'action': "Update Email Verified", 'message': "Something went wrong"},
+ status=status.HTTP_400_BAD_REQUEST)
+
+@api_view(['POST'])
+@isAuthorized([ADMIN])
+@precheck([OPENING_ID, ADDITIONAL_INFO])
+def updateAdditionalInfo(request, id, email, user_type):
+ try:
+ data = request.data
+ opening = get_object_or_404(Placement, pk=data[OPENING_ID])
+ if data[ADDITIONAL_INFO] == "":
+ opening.additional_info = []
+ elif isinstance(data[ADDITIONAL_INFO], list):
+ opening.additional_info = data[ADDITIONAL_INFO]
+ else:
+ raise ValueError("Additional Info must be a list")
+ opening.save()
+ return Response({'action': "Update Additional Info", 'message': "Additional Info Updated"},
+ status=status.HTTP_200_OK)
+ except Http404:
+ return Response({'action': "Update Additional Info", 'message': 'Opening Not Found'},
+ status=status.HTTP_404_NOT_FOUND)
+ except ValueError:
+ return Response({'action': "Update Additional Info", 'message': "Additional Info must be a list"},
+ status=status.HTTP_400_BAD_REQUEST)
+ except:
+ logger.warning("Update Additional Info: " + str(sys.exc_info()))
+ return Response({'action': "Update Additional Info", 'message': "Something went wrong"},
+ status=status.HTTP_400_BAD_REQUEST)
+
+
+@api_view(['GET'])
+@isAuthorized([ADMIN])
+@precheck([OPENING_ID])
+def getApplications(request, id, email, user_type):
+ try:
+ data = request.GET
+ opening = get_object_or_404(Placement, pk=data[OPENING_ID])
+ applications = PlacementApplication.objects.filter(placement=opening)
+ serializer = PlacementApplicationSerializerForAdmin(applications, many=True)
+ return Response({'action': "Get Applications", 'message': 'Data Found', 'applications':serializer.data},
+ status=status.HTTP_200_OK)
+ except Http404:
+ return Response({'action': "Get Applications", 'message': 'Opening Not Found'},
+ status=status.HTTP_404_NOT_FOUND)
+ except:
+ logger.warning("Get Applications: " + str(sys.exc_info()))
+ return Response({'action': "Get Applications", 'message': "Something went wrong"},
+ status=status.HTTP_400_BAD_REQUEST)
+
+
+
+@api_view(['POST'])
+@isAuthorized(allowed_users=[ADMIN])
+@precheck(required_data=[OPENING_TYPE, OPENING_ID, RESUME_FILE_NAME,
+ STUDENT_ID])
+def submitApplication(request, id, email, user_type):
+ try:
+ data = request.data
+ student = get_object_or_404(Student, roll_no=data[STUDENT_ID])
+ # Only Allowing Applications for Placements
+ if data[OPENING_TYPE] == PLACEMENT:
+ if not len(PlacementApplication.objects.filter(
+ student_id=student.id, placement_id=data[OPENING_ID])):
+ application = PlacementApplication()
+ 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()
+ )
+ if not opening.offer_accepted or not opening.email_verified:
+ raise PermissionError("Placement Not Approved")
+
+ cond_stat, cond_msg = PlacementApplicationConditions(student, opening)
+ if not cond_stat:
+ raise PermissionError(cond_msg)
+ application.placement = opening
+ else:
+ raise PermissionError("Application is already Submitted")
+ else:
+ raise ValueError(OPENING_TYPE + " is Invalid")
+
+ if data[RESUME_FILE_NAME] in student.resumes:
+ application.resume = data[RESUME_FILE_NAME]
+ else:
+ raise FileNotFoundError(RESUME_FILE_NAME + " Not Found")
+
+ application.student = student
+ application.id = generateRandomString()
+ additional_info = {}
+ for i in opening.additional_info:
+ if i not in data[ADDITIONAL_INFO]:
+ raise AttributeError(i + " not found in Additional Info")
+ else:
+ additional_info[i] = data[ADDITIONAL_INFO][i]
+
+ application.additional_info = json.dumps(additional_info)
+ data = {
+ "name": student.name,
+ "company_name": opening.company_name,
+ "application_type": data[OPENING_TYPE],
+ "additional_info": dict(json.loads(application.additional_info)),
+ }
+ subject = STUDENT_APPLICATION_SUBMITTED_TEMPLATE_SUBJECT.format(company_name=opening.company_name)
+ student_email = str(student.roll_no)+"@iitdh.ac.in"
+ sendEmail(student_email, subject, data, STUDENT_APPLICATION_SUBMITTED_TEMPLATE)
+
+ application.save()
+ return Response({'action': "Submit Application", 'message': "Application Submitted"},
+ status=status.HTTP_200_OK)
+ except Http404 as e:
+ return Response({'action': "Submit Application", 'message': str(e)},
+ status=status.HTTP_404_NOT_FOUND)
+ except PermissionError as e:
+ return Response({'action': "Submit Application", 'message': str(e)},
+ status=status.HTTP_403_FORBIDDEN)
+ except FileNotFoundError as e:
+ return Response({'action': "Submit Application", 'message': str(e)},
+ status=status.HTTP_404_NOT_FOUND)
+ except:
+ logger.warning("Submit Application: " + str(sys.exc_info()))
+ return Response({'action': "Submit Application", 'message': "Something Went Wrong"},
+ status=status.HTTP_400_BAD_REQUEST)
+
+
+
+@api_view(['POST'])
+@isAuthorized(allowed_users=[ADMIN])
+@precheck(required_data=[OPENING_ID])
+def generateCSV(request, id, email, user_type):
+ try:
+ data = request.data
+ placement = get_object_or_404(Placement, id=data[OPENING_ID])
+ applications = PlacementApplication.objects.filter(placement=placement)
+ filename = generateRandomString()
+ if not os.path.isdir(STORAGE_DESTINATION_APPLICATION_CSV):
+ os.mkdir(STORAGE_DESTINATION_APPLICATION_CSV)
+ destination_path = STORAGE_DESTINATION_APPLICATION_CSV + filename + ".csv"
+ f = open(destination_path, 'w')
+ writer = csv.writer(f)
+ header_row = APPLICATION_CSV_COL_NAMES.copy()
+
+ header_row.extend(placement.additional_info)
+ writer.writerow(header_row)
+ for apl in applications:
+ row_details=[]
+
+ row_details.append(apl.applied_at)
+ row_details.append(apl.student.roll_no)
+ row_details.append(apl.student.name)
+ row_details.append(str(apl.student.roll_no)+"@iitdh.ac.in")
+ row_details.append(apl.student.phone_number)
+ row_details.append(apl.student.branch)
+ row_details.append(apl.student.batch)
+ row_details.append(apl.student.cpi)
+ link = LINK_TO_STORAGE_RESUME + urllib.parse.quote_plus(apl.student.id + "/" + apl.resume)
+ row_details.append(link)
+ row_details.append(apl.selected)
+
+ for i in placement.additional_info:
+ row_details.append(json.loads(apl.additional_info)[i])
+
+ writer.writerow(row_details)
+ f.close()
+ file_path = LINK_TO_APPLICATIONS_CSV + urllib.parse.quote_plus(filename+".csv")
+ return Response({'action': "Create csv", 'message': "CSV created", 'file': file_path},
+ status=status.HTTP_200_OK)
+ except:
+ logger.warning("Create csv: " + str(sys.exc_info()))
+ print(sys.exc_info())
+ return Response({'action': "Create csv", 'message': "Error Occurred"},
+ status=status.HTTP_400_BAD_REQUEST)
\ No newline at end of file
diff --git a/CDC_Backend/APIs/companyUrls.py b/CDC_Backend/APIs/companyUrls.py
index f175144..5cda889 100644
--- a/CDC_Backend/APIs/companyUrls.py
+++ b/CDC_Backend/APIs/companyUrls.py
@@ -3,5 +3,5 @@ from . import companyViews
urlpatterns = [
- path('addOpening/', companyViews.addOpening, name="Add Opening"),
+ path('addPlacement/', companyViews.addPlacement, name="Add Placement"),
]
diff --git a/CDC_Backend/APIs/companyViews.py b/CDC_Backend/APIs/companyViews.py
index 92c7eac..7d7d50b 100644
--- a/CDC_Backend/APIs/companyViews.py
+++ b/CDC_Backend/APIs/companyViews.py
@@ -1,120 +1,222 @@
import json
from datetime import datetime
-from django.utils.timezone import make_aware
from rest_framework.decorators import api_view
+from .models import *
from .utils import *
logger = logging.getLogger('db')
@api_view(['POST'])
-@precheck([DESIGNATION, DESCRIPTION, OPENING_TYPE, CITY, CITY_TYPE,
- COMPENSATION, COMPENSATION_DETAILS, ALLOWED_BATCH, ALLOWED_BRANCH,
- ROUNDS, CO_OP, START_DATE, ADDITIONAL_INFO,
- DURATION, ROUND_DETAILS])
-def addOpening(request):
+@precheck([COMPANY_NAME, ADDRESS, COMPANY_TYPE, NATURE_OF_BUSINESS, WEBSITE, COMPANY_DETAILS, IS_COMPANY_DETAILS_PDF,
+ CONTACT_PERSON_NAME, PHONE_NUMBER, EMAIL, CITY, STATE, COUNTRY, PINCODE, DESIGNATION, DESCRIPTION,
+ IS_DESCRIPTION_PDF,
+ COMPENSATION_CTC, COMPENSATION_GROSS, COMPENSATION_TAKE_HOME, COMPENSATION_BONUS, COMPENSATION_DETAILS,
+ IS_COMPENSATION_DETAILS_PDF,
+ ALLOWED_BRANCH, SELECTION_PROCEDURE_ROUNDS, SELECTION_PROCEDURE_DETAILS, IS_SELECTION_PROCEDURE_DETAILS_PDF,
+ TENTATIVE_DATE_OF_JOINING,
+ TENTATIVE_NO_OF_OFFERS, OTHER_REQUIREMENTS
+ ])
+def addPlacement(request):
try:
data = request.data
- if data[OPENING_TYPE] == "Placement":
- opening = Placement()
- else:
- raise ValueError("Invalid Opening Type")
+ files = request.FILES
+ opening = Placement()
opening.id = generateRandomString()
- # Create Company object here for every Opening
-
-
- # Some new code above
-
- if data[DESIGNATION] != "":
- opening.designation = data[DESIGNATION]
+ # Add a company details in the opening
+ opening.company_name = data[COMPANY_NAME]
+ opening.address = data[ADDRESS]
+ opening.company_type = data[COMPANY_TYPE]
+ opening.nature_of_business = data[NATURE_OF_BUSINESS]
+ opening.website = data[WEBSITE]
+ opening.company_details = data[COMPANY_DETAILS]
+ if data[IS_COMPANY_DETAILS_PDF] == "true":
+ opening.is_company_details_pdf = True
+ elif data[IS_COMPANY_DETAILS_PDF] == "false":
+ opening.is_company_details_pdf = False
else:
- raise ValueError(DESIGNATION + " Not Found")
+ raise ValueError('Invalid value for is_company_details_pdf')
+ if opening.is_company_details_pdf:
+ company_details_pdf = []
+ for file in files.getlist(COMPANY_DETAILS_PDF):
+ file_location = STORAGE_DESTINATION_COMPANY_ATTACHMENTS + opening.id + '/'
+ company_details_pdf.append(saveFile(file, file_location))
+
+ opening.company_details_pdf_names = company_details_pdf
+
+ # Add a contact person details in the opening
+ opening.contact_person_name = data[CONTACT_PERSON_NAME]
+ # Check if Phone number is Integer
+ if data[PHONE_NUMBER].isdigit():
+ opening.phone_number = int(data[PHONE_NUMBER])
+ else:
+ raise ValueError('Phone number should be integer')
+
+ opening.email = data[EMAIL]
+
+ # Add a company location in the opening
+ opening.city = data[CITY]
+ opening.state = data[STATE]
+ opening.country = data[COUNTRY]
+
+ # Check if Pincode is Integer
+ if data[PINCODE].isdigit():
+ opening.pin_code = int(data[PINCODE])
+ else:
+ raise ValueError('Pincode should be integer')
+
+ # If India then set city_type as Domestic else International
+ if opening.country == 'India':
+ opening.city_type = 'Domestic'
+ else:
+ opening.city_type = 'International'
+
+ # Add a designation details in the opening
+ opening.designation = data[DESIGNATION]
opening.description = data[DESCRIPTION]
- if data[START_DATE] != "":
- opening.description = data[START_DATE]
+ # Check if is_description_pdf is boolean
+ if data[IS_DESCRIPTION_PDF] == "true":
+ opening.is_description_pdf = True
+ elif data[IS_DESCRIPTION_PDF] == "false":
+ opening.is_description_pdf = False
else:
- raise ValueError(START_DATE + " Not Found")
- if data[START_DATE] != "":
- opening.start_date = datetime.strptime(data[START_DATE], '%d-%m-%Y')
+ raise ValueError('Invalid value for is_description_pdf')
+
+ if opening.is_description_pdf:
+ description_pdf = []
+ for file in files.getlist(DESCRIPTION_PDF):
+ file_location = STORAGE_DESTINATION_COMPANY_ATTACHMENTS + opening.id + '/'
+ description_pdf.append(saveFile(file, file_location))
+
+ opening.description_pdf_names = description_pdf
+
+ # Add a compensation details in the opening
+ # Check if compensation_ctc is integer
+ if data[COMPENSATION_CTC].isdigit():
+ opening.compensation_CTC = int(data[COMPENSATION_CTC])
+ elif data[COMPENSATION_CTC] is None:
+ opening.compensation_CTC = None
else:
- raise ValueError(START_DATE + " Not Found")
- if data[CITY] != "":
- opening.city = data[CITY]
+ raise ValueError('Compensation CTC must be an integer')
+
+ # Check if compensation_gross is integer
+ if data[COMPENSATION_GROSS].isdigit():
+ opening.compensation_gross = int(data[COMPENSATION_GROSS])
+ elif data[COMPENSATION_GROSS] is None:
+ opening.compensation_gross = None
else:
- raise ValueError(CITY + " Not Found")
- if data[CITY_TYPE] != "":
- opening.city_type = data[CITY_TYPE]
+ raise ValueError('Compensation Gross must be an integer')
+
+ # Check if compensation_take_home is integer
+ if data[COMPENSATION_TAKE_HOME].isdigit():
+ opening.compensation_take_home = int(data[COMPENSATION_TAKE_HOME])
+ elif data[COMPENSATION_TAKE_HOME] is None:
+ opening.compensation_take_home = None
else:
- raise ValueError(CITY_TYPE + " Not Found")
- if data[COMPENSATION] != "":
- opening.compensation = data[COMPENSATION]
+ raise ValueError('Compensation Take Home must be an integer')
+
+ # Check if compensation_bonus is integer
+ if data[COMPENSATION_BONUS].isdigit():
+ opening.compensation_bonus = int(data[COMPENSATION_BONUS])
+ elif data[COMPENSATION_BONUS] is None:
+ opening.compensation_bonus = None
else:
- raise ValueError(COMPENSATION + " Not Found")
+ raise ValueError('Compensation Bonus must be an integer')
opening.compensation_details = data[COMPENSATION_DETAILS]
-
- if data[ALLOWED_BATCH] != "":
- if set(json.loads(data[ALLOWED_BATCH])).issubset(BATCHES):
- opening.allowed_batch = json.loads(data[ALLOWED_BATCH])
- else:
- raise ValueError(ALLOWED_BATCH + " is Invalid")
+ # Check if is_compensation_details_pdf is boolean
+ if data[IS_COMPENSATION_DETAILS_PDF] == "true":
+ opening.is_compensation_details_pdf = True
+ elif data[IS_COMPENSATION_DETAILS_PDF] == "false":
+ opening.is_compensation_details_pdf = False
else:
- raise ValueError(ALLOWED_BATCH + " Not Found")
- if data[ALLOWED_BRANCH] != "":
- if set(json.loads(data[ALLOWED_BRANCH])).issubset(BRANCHES):
- opening.allowed_branch = json.loads(data[ALLOWED_BRANCH])
- else:
- raise ValueError(ALLOWED_BATCH + " is Invalid")
+ raise ValueError('Invalid value for is_compensation_details_pdf')
+
+ if opening.is_compensation_details_pdf:
+ compensation_details_pdf = []
+ for file in files.getlist(COMPENSATION_DETAILS_PDF):
+ file_location = STORAGE_DESTINATION_COMPANY_ATTACHMENTS + opening.id + '/'
+ compensation_details_pdf.append(saveFile(file, file_location))
+
+ opening.compensation_details_pdf_names = compensation_details_pdf
+
+ opening.bond_details = data[BOND_DETAILS]
+
+ # Check if selection_procedure_rounds is list
+ if data[SELECTION_PROCEDURE_ROUNDS] is None:
+ raise ValueError('Selection Procedure Rounds cannot be empty')
else:
- raise ValueError(ALLOWED_BRANCH + " Not Found")
+ try:
+ opening.selection_procedure_rounds = json.loads(data[SELECTION_PROCEDURE_ROUNDS])
+ except:
+ raise ValueError('Selection Procedure Rounds must be a list')
+ opening.selection_procedure_details = data[SELECTION_PROCEDURE_DETAILS]
+ # Check if is_selection_procedure_details_pdf is boolean
+ if data[IS_SELECTION_PROCEDURE_DETAILS_PDF] == "true":
+ opening.is_selection_procedure_details_pdf = True
+ elif data[IS_SELECTION_PROCEDURE_DETAILS_PDF] == "false":
+ opening.is_selection_procedure_details_pdf = False
+ else:
+ raise ValueError('Invalid value for is_selection_procedure_pdf')
- opening.rounds = json.loads(data[ROUNDS])
+ if opening.is_selection_procedure_details_pdf:
+ selection_procedure_details_pdf = []
+ for file in files.getlist(SELECTION_PROCEDURE_DETAILS_PDF):
+ file_location = STORAGE_DESTINATION_COMPANY_ATTACHMENTS + opening.id + '/'
+ selection_procedure_details_pdf.append(saveFile(file, file_location))
- opening.additional_info = json.loads(data[ADDITIONAL_INFO])
+ opening.selection_procedure_details_pdf_names = selection_procedure_details_pdf
- opening.status = STATUS_ACCEPTING_APPLICATIONS
+ stat, tier = getTier(opening.compensation_gross)
+ if stat:
+ opening.tier = tier
+ else:
+ raise ValueError('Invalid compensation gross')
+ # Convert to date object
+ opening.tentative_date_of_joining = datetime.strptime(data[TENTATIVE_DATE_OF_JOINING], '%d-%m-%Y').date()
- opening.rounds_details = json.loads(data[ROUND_DETAILS])
+ # Only Allowing Fourth Year for Placement
+ opening.allowed_batch = [FOURTH_YEAR, ]
+ # Check if allowed_branch are valid
+ if data[ALLOWED_BRANCH] is None:
+ raise ValueError('Allowed Branch cannot be empty')
+ elif set(json.loads(data[ALLOWED_BRANCH])).issubset(BRANCHES):
+ opening.allowed_branch = json.loads(data[ALLOWED_BRANCH])
+ else:
+ raise ValueError('Allowed Branch must be a subset of ' + str(BRANCHES))
- opening.created_at = make_aware(datetime.now())
- files = request.FILES.getlist(ATTACHMENTS)
- attachments = []
- for file in files:
- attachments.append(saveFile(file, STORAGE_DESTINATION_COMPANY_ATTACHMENTS))
+ # Check if tentative_no_of_offers is integer
+ if data[TENTATIVE_NO_OF_OFFERS].isdigit():
+ opening.tentative_no_of_offers = int(data[TENTATIVE_NO_OF_OFFERS])
+ else:
+ raise ValueError('Tentative No Of Offers must be an integer')
+
+ opening.other_requirements = data[OTHER_REQUIREMENTS]
- opening.attachments = attachments
opening.save()
+
data = {
"designation": opening.designation,
- "opening_type": data[OPENING_TYPE],
- "opening_link": "google.com", # Some Changes here too
- "company_name": opening.company.name
+ "opening_type": PLACEMENT,
+ "opening_link": PLACEMENT_OPENING_URL.format(id=opening.id), # Some Changes here too
+ "company_name": opening.company_name
}
- # Needs some edits here
+ sendEmail(opening.email, COMPANY_OPENING_SUBMITTED_TEMPLATE_SUBJECT.format(id=opening.id), data,
+ COMPANY_OPENING_SUBMITTED_TEMPLATE)
- email = 'This is temporary'
-
- # Delete the above var when done
-
- stat = sendEmail(email, COMPANY_OPENING_SUBMITTED_TEMPLATE_SUBJECT.format(id=opening.id), data,
- COMPANY_OPENING_SUBMITTED_TEMPLATE)
- if stat is not True:
- logger.warning("Add New Opening: Unable to send email - " + stat)
-
- return Response({'action': "Add Opening", 'message': "Opening Added"},
+ return Response({'action': "Add Placement", 'message': "Placement Added Successfully"},
status=status.HTTP_200_OK)
except ValueError as e:
- return Response({'action': "Add Opening", 'message': str(e)},
+ return Response({'action': "Add Placement", 'message': str(e)},
status=status.HTTP_400_BAD_REQUEST)
except:
- logger.warning("Add New Opening: " + str(sys.exc_info()))
- return Response({'action': "Add Opening", 'message': "Error Occurred {0}".format(
- str(sys.exc_info()[1]))},
+ logger.warning("Add New Placement: " + str(sys.exc_info()))
+ return Response({'action': "Add Placement", 'message': "Something went wrong"},
status=status.HTTP_400_BAD_REQUEST)
diff --git a/CDC_Backend/APIs/constants.py b/CDC_Backend/APIs/constants.py
index 7a4b25b..4201ce9 100644
--- a/CDC_Backend/APIs/constants.py
+++ b/CDC_Backend/APIs/constants.py
@@ -1,14 +1,20 @@
BRANCH_CHOICES = [
["CSE", "CSE"],
["EE", "EE"],
- ["ME", "ME"]
+ ["ME", "ME"],
+ ['EP', 'EP'],
+]
+BRANCHES = [
+ "CSE",
+ "EE",
+ "ME",
+ "EP"
]
-
BATCH_CHOICES = [
- ["FIRST", "First"],
- ["SECOND", "Second"],
- ["THIRD", "Third"],
- ["FOURTH", "Fourth"]
+ ["2021", "2021"],
+ ["2020", "2020"],
+ ["2019", "2019"],
+ ["2018", "2018"]
]
OFFER_CITY_TYPE = [
@@ -26,70 +32,105 @@ TIERS = [
['6', 'Tier 6']
]
-
-TOTAL_BRANCHES = 3 # Total No of Branches
+TOTAL_BRANCHES = 4 # Total No of Branches
TOTAL_BATCHES = 4 # Total No of Batches
+# To be Configured Properly
CLIENT_ID = "956830229554-290mirc16pdhd5j7ph7v7ukibo4t1qcp.apps.googleusercontent.com" # Google Login Client ID
+# To be Configured Properly
+PLACEMENT_OPENING_URL = "https://www.googleapis.com/auth/adwords/{id}"
+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/"
+
+
TOKEN = "token_id"
EMAIL = "email"
STUDENT = 'student'
-ADMIN = 'Admin'
+ADMIN = 'admin'
COMPANY = ''
-STORAGE_DESTINATION = "./Storage/Resumes/"
+# To be Configured Properly
+FOURTH_YEAR = '2018'
+MAX_OFFERS_PER_STUDENT = 2
+
+
+STORAGE_DESTINATION_RESUMES = "./Storage/Resumes/"
STORAGE_DESTINATION_COMPANY_ATTACHMENTS = './Storage/Company_Attachments/'
+STORAGE_DESTINATION_APPLICATION_CSV = './Storage/Application_CSV/'
+
RESUME_FILE_NAME = 'resume_file_name'
APPLICATION_ID = "application_id"
OPENING_ID = "opening_id"
-STUDENT_ID = "student_id"
ADDITIONAL_INFO = "additional_info"
STATUS_ACCEPTING_APPLICATIONS = "Accepting Applications"
PLACEMENT = "Placement"
-COMPANY_WEBSITE = 'website'
-COMPANY_ADDRESS = 'address'
+COMPANY_NAME = "company_name"
+ADDRESS = "address"
+COMPANY_TYPE = "company_type"
+NATURE_OF_BUSINESS = "nature_of_business"
+WEBSITE = 'website'
+COMPANY_DETAILS = "company_details"
+COMPANY_DETAILS_PDF = "company_details_pdf"
+IS_COMPANY_DETAILS_PDF = "is_company_details_pdf"
+COMPANY_DETAILS_PDF_NAMES = "company_details_pdf_names"
PHONE_NUMBER = 'phone_number'
CONTACT_PERSON_NAME = 'contact_person_name'
+CITY = 'city'
+STATE = 'state'
+COUNTRY = 'country'
+PINCODE = 'pincode'
+
DESIGNATION = 'designation'
DESCRIPTION = 'description'
+DESCRIPTION_PDF = 'description_pdf'
+DESCRIPTION_PDF_NAMES = 'description_pdf_names'
+IS_DESCRIPTION_PDF = 'is_description_pdf'
OPENING_TYPE = 'opening_type'
-CITY = 'city'
-CITY_TYPE = 'city_type'
-COMPENSATION = 'compensation'
+COMPENSATION_CTC = 'compensation_ctc'
+COMPENSATION_GROSS = 'compensation_gross'
+COMPENSATION_TAKE_HOME = 'compensation_take_home'
+COMPENSATION_BONUS = 'compensation_bonus'
COMPENSATION_DETAILS = 'compensation_details'
+COMPENSATION_DETAILS_PDF = 'compensation_details_pdf'
+COMPENSATION_DETAILS_PDF_NAMES = 'compensation_details_pdf_names'
+IS_COMPENSATION_DETAILS_PDF = 'is_compensation_details_pdf'
ALLOWED_BATCH = 'allowed_batch'
ALLOWED_BRANCH = 'allowed_branch'
-ATTACHMENTS = 'attachments'
-ROUNDS = 'rounds'
-ROUND_DETAILS = 'round_details'
-DURATION = 'duration'
-CO_OP = 'co_op'
-START_DATE = "start_date"
+BOND_DETAILS = 'bond_details'
+SELECTION_PROCEDURE_ROUNDS = 'selection_procedure_rounds'
+SELECTION_PROCEDURE_DETAILS = 'selection_procedure_details'
+SELECTION_PROCEDURE_DETAILS_PDF = 'selection_procedure_details_pdf'
+SELECTION_PROCEDURE_DETAILS_PDF_NAMES = 'selection_procedure_details_pdf_names'
+IS_SELECTION_PROCEDURE_DETAILS_PDF = 'is_selection_procedure_details_pdf'
+TENTATIVE_DATE_OF_JOINING = 'tentative_date_of_joining'
+TENTATIVE_NO_OF_OFFERS = 'tentative_no_of_offers'
+OTHER_REQUIREMENTS = 'other_requirements'
+DEADLINE_DATETIME = 'deadline_datetime'
+OFFER_ACCEPTED = 'offer_accepted'
+EMAIL_VERIFIED = 'email_verified'
STUDENT_LIST = "student_list"
-STUDENT_STATUS = "student_status"
+STUDENT_ID = "student_id"
+STUDENT_SELECTED = "student_selected"
-BRANCHES = [
- "CSE",
- "EE",
- "ME"
-]
-BATCHES = [
- "FIRST",
- "SECOND",
- "THIRD",
- "FOURTH"
-]
COMPANY_OPENING_SUBMITTED_TEMPLATE_SUBJECT = "Notification Submitted - {id} - CDC IIT Dharwad"
+STUDENT_APPLICATION_STATUS_TEMPLATE_SUBJECT = 'Application Status : {company_name} - {id}'
+STUDENT_APPLICATION_SUBMITTED_TEMPLATE_SUBJECT = 'CDC - Application Submitted - {company_name}'
STUDENT_APPLICATION_SUBMITTED_TEMPLATE = 'student_application_submitted.html'
COMPANY_OPENING_SUBMITTED_TEMPLATE = 'company_opening_submitted.html'
+STUDENT_APPLICATION_STATUS_SELECTED_TEMPLATE = 'student_application_status_selected.html'
+STUDENT_APPLICATION_STATUS_NOT_SELECTED_TEMPLATE = 'student_application_status_not_selected.html'
+
+APPLICATION_CSV_COL_NAMES = ['Applied At', 'Roll No.', 'Name', 'Email', 'Phone Number', 'Branch', 'Batch', 'CPI',
+ 'Resume', 'Selected', ]
diff --git a/CDC_Backend/APIs/models.py b/CDC_Backend/APIs/models.py
index 7203738..d8c9080 100644
--- a/CDC_Backend/APIs/models.py
+++ b/CDC_Backend/APIs/models.py
@@ -2,6 +2,8 @@ from django.contrib.postgres.fields import ArrayField
from django.db import models
from django.utils import timezone
from .constants import *
+# from .utils import *
+
class User(models.Model):
@@ -26,58 +28,80 @@ class Admin(models.Model):
name = models.CharField(blank=False, max_length=50)
+def two_day_after_today():
+ return timezone.now() + timezone.timedelta(days=2)
+
+
class Placement(models.Model):
id = models.CharField(blank=False, primary_key=True, max_length=15)
- name = models.CharField(blank=False, max_length=50, default="")
- address = models.CharField(blank=False, max_length=150, default="")
- companyType = models.CharField(blank=False, max_length=50, default="")
- website = models.CharField(blank=True, max_length=50, default="")
- contact_person_name = models.CharField(blank=False, max_length=50, default="")
- phone_number = models.PositiveBigIntegerField(blank=False, default=0)
- designation = models.CharField(blank=False, max_length=25, default=None, null=True)
- description = models.CharField(blank=False, max_length=200)
- start_date = models.DateField(blank=False, verbose_name="Start Date")
+ # Company Details
+ company_name = models.CharField(blank=False, max_length=50)
+ address = models.CharField(blank=False, max_length=150)
+ company_type = models.CharField(blank=False, max_length=50)
+ nature_of_business = models.CharField(blank=False, max_length=50, default="")
+ website = models.CharField(blank=True, max_length=50)
+ company_details = models.CharField(blank=False, max_length=500, default=None, null=True)
+ company_details_pdf_names = ArrayField(models.CharField(null=True, default=None, max_length=100), size=5, default=list, blank=True)
+ is_company_details_pdf = models.BooleanField(blank=False, default=False)
+ contact_person_name = models.CharField(blank=False, max_length=50)
+ phone_number = models.PositiveBigIntegerField(blank=False)
+ email = models.CharField(blank=False, max_length=50, default="")
city = models.CharField(blank=False, max_length=100, default="")
+ state = models.CharField(blank=False, max_length=100, default="")
+ country = models.CharField(blank=False, max_length=100, default="")
+ pin_code = models.IntegerField(blank=False, default=None,null=True)
city_type = models.CharField(blank=False, max_length=15, choices=OFFER_CITY_TYPE)
- compensation = models.IntegerField(blank=False) # Job - Per Year
- compensation_details = models.CharField(blank=True, max_length=200)
+ # Job Details
+ designation = models.CharField(blank=False, max_length=25, default=None, null=True)
+ description = models.CharField(blank=False, max_length=200, default=None, null=True)
+ description_pdf_names = ArrayField(models.CharField(null=True, default=None, max_length=100), size=5, default=list, blank=True)
+ is_description_pdf = models.BooleanField(blank=False, default=False)
+ compensation_CTC = models.IntegerField(blank=False, default=None, null=True ) # Job - Per Year
+ compensation_gross = models.IntegerField(blank=False, default=None, null=True)
+ compensation_take_home = models.IntegerField(blank=False, default=None, null=True)
+ compensation_bonus = models.IntegerField(blank=True, default=None, null=True)
+ compensation_details = models.CharField(blank=True, max_length=200, default=None, null=True)
+ compensation_details_pdf_names = ArrayField(models.CharField(null=True, default=None, max_length=100), size=5, default=list, blank=True)
+ is_compensation_details_pdf = models.BooleanField(blank=False, default=False)
+ bond_details = models.CharField(blank=True, max_length=200)
+ selection_procedure_rounds = ArrayField(models.CharField(null=True, default=None, max_length=100), size=10, default=list, blank=True)
+ selection_procedure_details = models.CharField(blank=True, max_length=200)
+ selection_procedure_details_pdf_names = ArrayField(models.CharField(null=True, default=None, max_length=100), size=5, default=list, blank=True)
+ is_selection_procedure_details_pdf = models.BooleanField(blank=False, default=False)
tier = models.CharField(blank=False, choices=TIERS, max_length=10, default=None, null=True)
+ tentative_date_of_joining = models.DateField(blank=False, verbose_name="Tentative Date", default=timezone.now)
allowed_batch = ArrayField(
models.CharField(max_length=10, choices=BATCH_CHOICES),
size=TOTAL_BATCHES,
default=list
)
+
allowed_branch = ArrayField(
models.CharField(choices=BRANCH_CHOICES, blank=False, max_length=10),
size=TOTAL_BRANCHES,
default=list
)
- attachments = ArrayField(
- models.CharField(max_length=100, blank=True),
- size=10,
- blank=True
- )
- rounds = ArrayField(
- models.CharField(max_length=25, blank=True),
- size=10,
- )
- additional_info = ArrayField(
- models.CharField(max_length=25, blank=True),
- size=10,
- blank=True
- )
- status = models.CharField(max_length=50, blank=False)
- rounds_details = models.JSONField(blank=True, default=dict)
+ tentative_no_of_offers = models.IntegerField(blank=False, default=1)
+ other_requirements = models.CharField(blank=True, max_length=200, default="")
+ additional_info = ArrayField(models.CharField(blank=True, max_length=200), size=15, default=list, blank=True)
+ email_verified = models.BooleanField(blank=False, default=False)
+ offer_accepted = models.BooleanField(blank=False, default=None, null=True)
+ deadline_datetime = models.DateTimeField(blank=False, verbose_name="Deadline Date", default=two_day_after_today)
created_at = models.DateTimeField(blank=False, default=None, null=True)
+ def save(self, *args, **kwargs):
+ ''' On save, add timestamps '''
+ if not self.created_at:
+ self.created_at = timezone.now()
+
+ return super(Placement, self).save(*args, **kwargs)
class PlacementApplication(models.Model):
id = models.CharField(blank=False, primary_key=True, max_length=15)
placement = models.ForeignKey(Placement, blank=False, on_delete=models.RESTRICT, default=None, null=True)
student = models.ForeignKey(Student, blank=False, on_delete=models.CASCADE)
resume = models.CharField(max_length=100, blank=False, null=True, default=None)
- status = models.CharField(max_length=50, null=True, blank=True, default=None)
- additional_info = models.JSONField(blank=True, default=None, null=True)
+ additional_info = models.JSONField(blank=True, null=True, default=None)
selected = models.BooleanField(null=True, default=None, blank=True)
applied_at = models.DateTimeField(blank=False, default=None, null=True)
diff --git a/CDC_Backend/APIs/serializers.py b/CDC_Backend/APIs/serializers.py
index 62f9ef7..a7c1228 100644
--- a/CDC_Backend/APIs/serializers.py
+++ b/CDC_Backend/APIs/serializers.py
@@ -1,56 +1,178 @@
+import urllib
+
from rest_framework import serializers
from .models import *
class StudentSerializer(serializers.ModelSerializer):
+ resume_list = serializers.SerializerMethodField()
+ offers = serializers.SerializerMethodField()
+
+ def get_resume_list(self, obj):
+ links = []
+ for i in obj.resumes:
+ ele = {}
+ ele['link'] = LINK_TO_STORAGE_RESUME + urllib.parse.quote_plus(obj.id + "/" + i)
+ ele['name'] = i
+ links.append(ele)
+ return links
+
+ def get_offers(self, obj):
+ selected_companies = PlacementApplication.objects.filter(student_id=obj.id, selected=True)
+ companies = []
+
+ for i in selected_companies:
+ ele = {}
+ ele['designation'] = i.placement.designation
+ ele['company_name'] = i.placement.company_name
+ ele['application_id'] = i.id
+ companies.append(ele)
+
+ return companies
+
class Meta:
model = Student
- fields = '__all__'
- # exclude = ['id']
+ 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()
-class PlacementSerializer(serializers.ModelSerializer):
- company_details = serializers.SerializerMethodField()
+ def get_company_details_pdf_links(self, obj):
+ 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)
+ ele['link'] = link
+ ele['name'] = pdf_name
+ links.append(ele)
+ return links
+
+ def get_description_pdf_links(self, obj):
+ links =[]
+ for pdf_name in obj.description_pdf_names:
+ ele = {}
+ link = LINK_TO_STORAGE_COMPANY_ATTACHMENT + urllib.parse.quote_plus(obj.id + "/" + pdf_name)
+ ele['link'] = link
+ ele['name'] = pdf_name
+ links.append(ele)
+ return links
+
+ def get_compensation_pdf_links(self, obj):
+ 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)
+ ele['link'] = link
+ ele['name'] = pdf_name
+ links.append(ele)
+ return links
+
+ def get_selection_procedure_details_pdf_links(self, obj):
+ 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)
+ ele['link'] = link
+ ele['name'] = pdf_name
+ links.append(ele)
+ return links
- def get_company_details(self, obj):
- data = {
- "id": obj.company.id,
- "name": obj.company.name,
- "address": obj.company.address,
- "companyType": obj.company.companyType,
- "website": obj.company.website,
- }
- return data
class Meta:
model = Placement
- exclude=[COMPANY]
+ 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]
+ 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 =[]
+ for pdf_name in obj.company_details_pdf_names:
+ ele = {}
+ link = LINK_TO_STORAGE_COMPANY_ATTACHMENT + urllib.parse.quote_plus(obj.id + "/" + pdf_name)
+ ele['link'] = link
+ ele['name'] = pdf_name
+ links.append(ele)
+ return links
+
+ def get_description_pdf_links(self, obj):
+ links =[]
+ for pdf_name in obj.description_pdf_names:
+ ele = {}
+ link = LINK_TO_STORAGE_COMPANY_ATTACHMENT + urllib.parse.quote_plus(obj.id + "/" + pdf_name)
+ ele['link'] = link
+ ele['name'] = pdf_name
+ links.append(ele)
+ return links
+
+ def get_compensation_pdf_links(self, obj):
+ 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)
+ ele['link'] = link
+ ele['name'] = pdf_name
+ links.append(ele)
+ return links
+
+ def get_selection_procedure_details_pdf_links(self, obj):
+ 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)
+ ele['link'] = link
+ ele['name'] = pdf_name
+ 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]
depth = 1
class PlacementApplicationSerializer(serializers.ModelSerializer):
- application_status = serializers.SerializerMethodField()
- company_details = serializers.SerializerMethodField()
+ placement = serializers.SerializerMethodField()
+ resume_link = serializers.SerializerMethodField()
-
- def get_application_status(self, obj):
- if obj.status is None:
- return obj.placement.status
- else:
- return obj.status
-
-
- def get_company_details(self, obj):
- data = {
- "id": obj.placement.company.id,
- "name": obj.placement.company.name,
- "address": obj.placement.company.address,
- "companyType": obj.placement.company.companyType,
- "website": obj.placement.company.website,
- }
+ def get_placement(self, obj):
+ data = PlacementSerializerForStudent(obj.placement).data
return data
+ def get_resume_link(self, obj):
+ link = LINK_TO_STORAGE_RESUME + urllib.parse.quote_plus(obj.id + "/" + obj.resume)
+ return link
+
class Meta:
model = PlacementApplication
- exclude = ['status', 'student']
+ exclude = [STUDENT, 'resume']
+
+class PlacementApplicationSerializerForAdmin(serializers.ModelSerializer):
+ student_details = serializers.SerializerMethodField()
+ resume_link = serializers.SerializerMethodField()
+
+ def get_student_details(self, obj):
+ data = StudentSerializer(obj.student).data
+ return data
+
+ def get_resume_link(self, obj):
+ link = LINK_TO_STORAGE_RESUME + urllib.parse.quote_plus(obj.id + "/" + obj.resume)
+ return link
+
+ class Meta:
+ model = PlacementApplication
+ exclude = ['placement', 'resume']
\ No newline at end of file
diff --git a/CDC_Backend/APIs/studentViews.py b/CDC_Backend/APIs/studentViews.py
index d709576..0ea1824 100644
--- a/CDC_Backend/APIs/studentViews.py
+++ b/CDC_Backend/APIs/studentViews.py
@@ -1,5 +1,5 @@
-import logging
-from os import path, remove
+import json
+from datetime import datetime
from rest_framework.decorators import api_view
@@ -16,8 +16,7 @@ def login(request, id, email, user_type):
return Response({'action': "Login", 'message': "Verified", "user_type": user_type},
status=status.HTTP_200_OK)
except:
- return Response({'action': "Login", 'message': "Error Occurred {0}".format(
- str(sys.exc_info()[1]))},
+ return Response({'action': "Login", 'message': "Something Went Wrong"},
status=status.HTTP_400_BAD_REQUEST)
@@ -31,7 +30,8 @@ def studentProfile(request, id, email, user_type):
return Response({'action': "Student Profile", 'message': "Details Found", "details": data},
status=status.HTTP_200_OK)
except:
- return Response({'action': "Student Profile", 'message': "Error Occurred {0}".format(str(sys.exc_info()[1]))},
+ logger.warning("Student Profile: " + str(sys.exc_info()))
+ return Response({'action': "Student Profile", 'message': "Something Went Wrong"},
status=status.HTTP_400_BAD_REQUEST)
@@ -41,20 +41,12 @@ def addResume(request, id, email, user_type):
destination_path = ""
try:
student = get_object_or_404(Student, id=id)
- prefix = generateRandomString()
files = request.FILES
- file_name = prefix + "_" + files['file'].name
- print(file_name)
- student.resumes.append(file_name)
file = files['file']
- destination_path = STORAGE_DESTINATION + str(file_name)
- if path.exists(destination_path):
- remove(destination_path)
-
- with open(destination_path, 'wb+') as destination:
- for chunk in file.chunks():
- destination.write(chunk)
+ destination_path = STORAGE_DESTINATION_RESUMES + id + "/"
+ file_name = saveFile(file, destination_path)
+ student.resumes.append(file_name)
student.save()
return Response({'action': "Upload Resume", 'message': "Resume Added"},
@@ -68,8 +60,7 @@ def addResume(request, id, email, user_type):
remove(destination_path)
else:
logger.warning("Upload Resume: " + str(sys.exc_info()))
- return Response({'action': "Upload Resume", 'message': "Error Occurred {0}".format(
- str(sys.exc_info()[1]))},
+ return Response({'action': "Upload Resume", 'message': "Something Went Wrong"},
status=status.HTTP_400_BAD_REQUEST)
@@ -81,23 +72,23 @@ def getDashboard(request, id, email, user_type):
placements = Placement.objects.filter(allowed_batch__contains=[studentDetails.batch],
allowed_branch__contains=[studentDetails.branch],
- status=STATUS_ACCEPTING_APPLICATIONS)
- placementsdata = PlacementSerializer(placements, many=True).data
+ deadline_datetime__gte=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': "Placement and Internships", 'message': "Data Found", "placements": placementsdata,
+ {'action': "Get Dashboard - Student", 'message': "Data Found", "placements": placementsdata,
'placementApplication': placementApplications},
status=status.HTTP_200_OK)
except Http404:
- return Response({'action': "Placements and Internships", 'message': 'Student Not Found'},
+ return Response({'action': "Get Dashboard - Student", 'message': 'Student Not Found'},
status=status.HTTP_404_NOT_FOUND)
except:
- logger.warning("Placements and Internships: " + str(sys.exc_info()))
- return Response({'action': "Placements and Internships", 'message': "Error Occurred {0}".format(
- str(sys.exc_info()[1]))},
+ logger.warning("Get Dashboard -Student: " + str(sys.exc_info()))
+ return Response({'action': "Get Dashboard - Student", 'message': "Something Went Wrong"},
status=status.HTTP_400_BAD_REQUEST)
@@ -108,7 +99,7 @@ def deleteResume(request, id, email, user_type):
try:
student = get_object_or_404(Student, id=id)
file_name = request.data[RESUME_FILE_NAME]
- destination_path = STORAGE_DESTINATION + str(file_name)
+ destination_path = STORAGE_DESTINATION_RESUMES + id + "/" + str(file_name)
if path.exists(destination_path):
remove(destination_path)
student.resumes.remove(file_name)
@@ -125,28 +116,32 @@ def deleteResume(request, id, email, user_type):
status=status.HTTP_404_NOT_FOUND)
except:
logger.warning("Delete Resume: " + str(sys.exc_info()))
- return Response({'action': "Delete Resume", 'message': "Error Occurred {0}".format(
- str(sys.exc_info()))},
+ return Response({'action': "Delete Resume", 'message': "Something Went Wrong"},
status=status.HTTP_400_BAD_REQUEST)
@api_view(['POST'])
@isAuthorized(allowed_users=[STUDENT])
@precheck(required_data=[OPENING_TYPE, OPENING_ID, RESUME_FILE_NAME,
- ADDITIONAL_INFO])
+ ])
def submitApplication(request, id, email, user_type):
try:
data = request.data
student = get_object_or_404(Student, id=id)
-
+ # Only Allowing Applications for Placements
if data[OPENING_TYPE] == PLACEMENT:
if not len(PlacementApplication.objects.filter(
student_id=id, placement_id=data[OPENING_ID])):
application = PlacementApplication()
opening = get_object_or_404(Placement, id=data[OPENING_ID],
- status=STATUS_ACCEPTING_APPLICATIONS)
+ allowed_batch__contains=[student.batch],
+ allowed_branch__contains=[student.branch],
+ deadline_datetime__gte=datetime.now().date()
+ )
+ if not opening.offer_accepted or not opening.email_verified:
+ raise PermissionError("Placement Not Approved")
+
cond_stat, cond_msg = PlacementApplicationConditions(student, opening)
- print(cond_stat, cond_msg)
if not cond_stat:
raise PermissionError(cond_msg)
application.placement = opening
@@ -162,21 +157,29 @@ def submitApplication(request, id, email, user_type):
application.student = student
application.id = generateRandomString()
+ additional_info = {}
for i in opening.additional_info:
if i not in data[ADDITIONAL_INFO]:
- print(i)
raise AttributeError(i + " not found in Additional Info")
+ else:
+ additional_info[i] = data[ADDITIONAL_INFO][i]
- application.additional_info = data[ADDITIONAL_INFO]
- if not sendApplicationEmail(email, student.name, opening.company.name, data[OPENING_TYPE],
- data[ADDITIONAL_INFO]):
- logger.error("Submit Application: Unable to Send Email")
- # raise RuntimeError("Unable to Send Email")
+ application.additional_info = json.dumps(additional_info)
+ data = {
+ "name": student.name,
+ "company_name": opening.company_name,
+ "application_type": data[OPENING_TYPE],
+ "additional_info": dict(json.loads(application.additional_info)),
+ }
+ subject = STUDENT_APPLICATION_SUBMITTED_TEMPLATE_SUBJECT.format(company_name=opening.company_name)
+ sendEmail(email, subject, data, STUDENT_APPLICATION_SUBMITTED_TEMPLATE)
application.save()
return Response({'action': "Submit Application", 'message': "Application Submitted"},
status=status.HTTP_200_OK)
-
+ except Http404 as e:
+ return Response({'action': "Submit Application", 'message': str(e)},
+ status=status.HTTP_404_NOT_FOUND)
except PermissionError as e:
return Response({'action': "Submit Application", 'message': str(e)},
status=status.HTTP_403_FORBIDDEN)
@@ -185,6 +188,5 @@ def submitApplication(request, id, email, user_type):
status=status.HTTP_404_NOT_FOUND)
except:
logger.warning("Submit Application: " + str(sys.exc_info()))
- return Response({'action': "Submit Application", 'message': "Error Occurred {0}".format(
- str(sys.exc_info()[1]))},
+ 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 422cec1..496d52c 100644
--- a/CDC_Backend/APIs/utils.py
+++ b/CDC_Backend/APIs/utils.py
@@ -5,6 +5,7 @@ import string
import sys
from os import path, remove
+import background_task
from django.conf import settings
from django.core.mail import EmailMultiAlternatives
from django.http import Http404
@@ -16,7 +17,8 @@ from google.oauth2 import id_token
from rest_framework import status
from rest_framework.response import Response
-from .models import *
+from .constants import *
+from .models import User, PrePlacementOffer, PlacementApplication
logger = logging.getLogger('db')
@@ -78,11 +80,9 @@ def isAuthorized(allowed_users=None):
raise PermissionError("Authorization Header Not Found")
except PermissionError as e:
- print(e)
return Response({'action': "Is Authorized?", 'message': str(e)},
status=status.HTTP_401_UNAUTHORIZED)
except Http404:
- print('http404')
return Response({'action': "Is Authorized?", 'message': "User Not Found. Contact CDC for more details"},
status=status.HTTP_404_NOT_FOUND)
except ValueError as e:
@@ -90,9 +90,10 @@ def isAuthorized(allowed_users=None):
return Response({'action': "Is Authorized?", 'message': str(e)},
status=status.HTTP_401_UNAUTHORIZED)
except:
- return Response({'action': "Is Authorized?", 'message': "Error Occurred {0}".format(
- str(sys.exc_info()[1]))},
- status=status.HTTP_400_BAD_REQUEST)
+ logger.warning("Is Authorized? " + str(sys.exc_info()))
+ return Response(
+ {'action': "Is Authorized?", 'message': "Something went wrong. Contact CDC for more details"},
+ status=status.HTTP_400_BAD_REQUEST)
return wrapper_func
@@ -102,36 +103,12 @@ def isAuthorized(allowed_users=None):
def generateRandomString():
try:
N = 15
- res = ''.join(random.choices(string.ascii_uppercase + string.digits, k=N))
+ res = ''.join(random.choices(string.ascii_uppercase +string.ascii_lowercase+ string.digits, k=N))
return res
except:
return False
-def sendApplicationEmail(email, name, company_name, applicaton_type, additional_info):
- try:
- subject = 'CDC - Application Submitted - ' + str(company_name)
- data = {
- "name": name,
- "company_name": company_name,
- "applicaton_type": applicaton_type,
- "additional_info": additional_info
- }
-
- html_content = render_to_string('student_application_submited.html', data) # render with dynamic value
- text_content = strip_tags(html_content)
-
- email_from = settings.EMAIL_HOST_USER
- recipient_list = [str(email), ]
-
- msg = EmailMultiAlternatives(subject, text_content, email_from, recipient_list)
- msg.attach_alternative(html_content, "text/html")
- msg.send()
- return True
- except:
- return False
-
-
def saveFile(file, location):
prefix = generateRandomString()
file_name = prefix + "_" + file.name
@@ -139,7 +116,7 @@ def saveFile(file, location):
if not path.isdir(location):
os.mkdir(location)
- destination_path = STORAGE_DESTINATION_COMPANY_ATTACHMENTS + str(file_name)
+ destination_path = location + str(file_name)
if path.exists(destination_path):
remove(destination_path)
@@ -150,6 +127,7 @@ def saveFile(file, location):
return file_name
+@background_task.background(schedule=10)
def sendEmail(email_to, subject, data, template):
try:
html_content = render_to_string(template, data) # render with dynamic value
@@ -163,17 +141,18 @@ def sendEmail(email_to, subject, data, template):
msg.send()
return True
except:
+ logger.error("Send Email: " + str(sys.exc_info()))
print(str(sys.exc_info()[1]))
- return str(sys.exc_info()[1])
+ return False
def PlacementApplicationConditions(student, placement):
try:
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(internship_application__student=student, accepted=True)
+ PPO = PrePlacementOffer.objects.filter(student=student, accepted=True)
- if len(selected_companies) + len(PPO) >= 2:
+ if len(selected_companies) + len(PPO) >= MAX_OFFERS_PER_STUDENT:
raise PermissionError("Max Applications Reached for the Season")
if len(selected_companies_PSU) > 0:
@@ -195,3 +174,41 @@ def PlacementApplicationConditions(student, placement):
print(sys.exc_info())
logger.warning("Utils - PlacementApplicationConditions: " + str(sys.exc_info()))
return False, "_"
+
+
+def getTier(compensation_gross, is_psu=False):
+ try:
+ if is_psu:
+ return True, 'psu'
+ if compensation_gross < 0:
+ raise ValueError("Negative Compensation")
+ elif compensation_gross < 600000: # Tier 7 If less than 600,000
+ return True, "7"
+ # Tier 6 If less than 800,000 and greater than or equal to 600,000
+ elif compensation_gross < 800000:
+ return True, "6"
+ # Tier 5 If less than 1,000,000 and greater than or equal to 800,000
+ elif compensation_gross < 1000000:
+ return True, "5"
+ # Tier 4 If less than 1,200,000 and greater than or equal to 1,000,000
+ elif compensation_gross < 1200000:
+ return True, "4"
+ # Tier 3 If less than 1,500,000 and greater than or equal to 1,200,000
+ elif compensation_gross < 1500000:
+ return True, "3"
+ # Tier 2 If less than 1,800,000 and greater than or equal to 1,500,000
+ elif compensation_gross < 1800000:
+ return True, "2"
+ # Tier 1 If greater than or equal to 1,800,000
+ elif compensation_gross >= 1800000:
+ return True, "1"
+ else:
+ raise ValueError("Invalid Compensation")
+
+ except ValueError as e:
+ logger.warning("Utils - getTier: " + str(sys.exc_info()))
+ return False, e
+ except:
+ print(sys.exc_info())
+ logger.warning("Utils - getTier: " + str(sys.exc_info()))
+ return False, "_"
diff --git a/CDC_Backend/CDC_Backend/settings.py b/CDC_Backend/CDC_Backend/settings.py
index e2b812b..8219a0f 100644
--- a/CDC_Backend/CDC_Backend/settings.py
+++ b/CDC_Backend/CDC_Backend/settings.py
@@ -11,7 +11,9 @@ https://docs.djangoproject.com/en/2.2/ref/settings/
"""
import os
+from dotenv import load_dotenv
+load_dotenv("../dev.env")
# import django_heroku
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
@@ -41,6 +43,7 @@ INSTALLED_APPS = [
'rest_framework',
'corsheaders',
'django_db_logger',
+ 'background_task'
]
MIDDLEWARE = [
@@ -80,19 +83,15 @@ WSGI_APPLICATION = 'CDC_Backend.wsgi.application'
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases
DATABASES = {
- # 'default': {
- # 'ENGINE': 'django.db.backends.sqlite3',
- # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
- # }
-
'default': {
- 'ENGINE': 'django.db.backends.postgresql_psycopg2',
- 'NAME': 'cdc',
- 'USER': 'postgres',
- 'PASSWORD': 'root',
- 'HOST': 'localhost',
- 'PORT': '5432',
+ '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',
@@ -159,8 +158,8 @@ EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_USE_TLS = True
EMAIL_PORT = 587
-EMAIL_HOST_USER = 'saisurya3127@gmail.com'#'email here'
-EMAIL_HOST_PASSWORD = 'ehwkqmryyqjiifcz'#'password here'
+EMAIL_HOST_USER = os.environ.get("EMAIL") # 'email here'
+EMAIL_HOST_PASSWORD = os.environ.get("EMAIL_PASSWORD") # 'password here'
LOGGING = {
'version': 1,
@@ -178,6 +177,11 @@ LOGGING = {
'level': 'DEBUG',
'class': 'django_db_logger.db_log_handler.DatabaseLogHandler'
},
+ 'mail_admins': {
+ 'level': 'ERROR',
+ 'class': 'django.utils.log.AdminEmailHandler',
+ 'include_html': True,
+ }
},
'loggers': {
'db': {
@@ -187,5 +191,4 @@ LOGGING = {
}
}
-
# django_heroku.settings(locals())
diff --git a/CDC_Backend/README.md b/CDC_Backend/README.md
index e186f4b..6a041f0 100644
--- a/CDC_Backend/README.md
+++ b/CDC_Backend/README.md
@@ -1,13 +1,23 @@
# API References
+
1. [**Common APIs**](#common-apis)
1. [**api/login/**](#apilogin)
2. [**Student APIs**](#student-portal-apis)
- 1. [**api/student/profile/**](#apistudentprofile)
- 2. [**api/student/getDashboard/**](#apistudentgetdashboard)
- 3. [**api/student/addResume/**](#apistudentaddresume)
- 4. [**api/student/deleteResume/**](#apistudentdeleteresume)
- 5. [**api/student/submitApplication/**](#apistudentsubmitapplication)
-3. [**Common Errors**](#common-errors)
+ 1. [**api/student/profile/**](#apistudentprofile)
+ 2. [**api/student/getDashboard/**](#apistudentgetdashboard)
+ 3. [**api/student/addResume/**](#apistudentaddresume)
+ 4. [**api/student/deleteResume/**](#apistudentdeleteresume)
+ 5. [**api/student/submitApplication/**](#apistudentsubmitapplication)
+3. [**Admin APIs**](#admin-portal-apis)
+ 1. [**api/admin/markStatus/**](#apiadminmarkstatus)
+ 2. [**api/admin/getDashboard/**](#apiadmingetdashboard)
+ 3. [**api/admin/updateDeadline/**](#apiadminupdatedeadline)
+ 4. [**api/admin/updateOfferAccepted**](#apiadminupdateofferaccepted)
+ 5. [**api/admin/updateEmailVerified**](#apiadminupdateemailverified)
+ 6. [**api/admin/updateAdditionalInfo**](#apiadminupdateadditionalinfo)
+4. [**Company APIs**](#company-portal-apis)
+ 1. [**api/company/addPlacement/**](#apicompanyaddplacement)
+5. [**Common Errors**](#common-errors)
---
@@ -35,19 +45,19 @@ Response is a Json with these fields
```json
{
- "action": "Login",
- "message": "Verified",
- "user_type": [
- "student"
- ]
+ "action": "Login",
+ "message": "Verified",
+ "user_type": [
+ "student"
+ ]
}
```
- action: Tells us about the message creator
- message: Tells us what happened with our Request.
- user_type: Tells us about the role the user possess. Can have these values
- - student
- - Admin
+ - student
+ - Admin
### Status Codes
@@ -88,16 +98,26 @@ Response is a Json with these fields
"action": "Student Profile",
"message": "Details Found",
"details": {
- "id": "fdgdb",
+ "id": "190010036",
+ "resume_list": [
+ {
+ "link": "https://storage.googleapis.com/cdc-backend-attachments/resume/190010036%2F8KIOT3PW1JIS718_CSE-V-SEM.pdf",
+ "name": "8KIOT3PW1JIS718_CSE-V-SEM.pdf"
+ }
+ ],
+ "offers": [
+ {
+ "designation": "Software Developer",
+ "company_name": "Make My Trip",
+ "application_id": "LLW4STE76GEJYOR"
+ }
+ ],
"roll_no": 190010036,
"name": "Gowtham Sai",
- "batch": "THIRD",
+ "batch": "2019",
"branch": "CSE",
"phone_number": 9390291911,
- "resumes": [
- "XB85F4RIGBF5VJN_Cv-Gowtham.pdf"
- ],
- "cpi": "9.02"
+ "cpi": "9.15"
}
}
```
@@ -113,7 +133,7 @@ The possible responses for this api request are as follows
| Status Codes | Possible Messages |
| --------------- | ------------------------ |
| 200 OK | `Details Found` |
-| 400 BAD_REQUEST | `Error Occurred {error}` |
+| 400 BAD_REQUEST | `Something Went Wrong` |
You may see some different errors which can be seen [here](#common-errors)
@@ -121,11 +141,11 @@ You may see some different errors which can be seen [here](#common-errors)
## `api/student/getDashboard`
-This Api is used to get all the placements applicable to the student.
+This Api is used to get all the placements applicable to the student and his applications which he has already applied.
### How to Use?
-Send a `GET` request to `api/student/Dashboard`
+Send a `GET` request to `api/student/getDashboard`
Request_Body:
@@ -136,88 +156,215 @@ Request_Body:
> Headers
> Authorization: "Bearer {tokenID}"
+> Only users with `student` role can access this Api.
+
+
### Response
Response is a Json with these fields
```json
{
- "action": "Placement and Internships",
+ "action": "Get Dashboard - Student",
"message": "Data Found",
"placements": [
{
- "id": "fdgdb121",
- "designation": "Software Developer",
- "description": "nice job",
- "start_date": "2021-06-17",
+ "id": "Q54IRZZMC3RP8F6",
+ "company_details_pdf_links": [
+ {
+ "link": "https://storage.googleapis.com/cdc-backend-attachments/company_attachments/Q54IRZZMC3RP8F6%2FI5U4RDTV0OP0EM0_2019+Student+Details+-+Total%28State+Sort%29+-+Copy.pdf",
+ "name": "I5U4RDTV0OP0EM0_2019 Student Details - Total(State Sort) - Copy.pdf"
+ },
+ {
+ "link": "https://storage.googleapis.com/cdc-backend-attachments/company_attachments/Q54IRZZMC3RP8F6%2FW04JWWNNMIBX0JX_2019+Student+Details+-+Total%28State+Sort%29.pdf",
+ "name": "W04JWWNNMIBX0JX_2019 Student Details - Total(State Sort).pdf"
+ },
+ {
+ "link": "https://storage.googleapis.com/cdc-backend-attachments/company_attachments/Q54IRZZMC3RP8F6%2FT1BXP98WBT9BHOR_AP0313017732021LL-Driving+Licence+-+Copy.pdf",
+ "name": "T1BXP98WBT9BHOR_AP0313017732021LL-Driving Licence - Copy.pdf"
+ }
+ ],
+ "description_pdf_links": [
+ {
+ "link": "https://storage.googleapis.com/cdc-backend-attachments/company_attachments/Q54IRZZMC3RP8F6%2FC78TE2Z67BPZ41O_CSE-V-SEM.pdf",
+ "name": "C78TE2Z67BPZ41O_CSE-V-SEM.pdf"
+ }
+ ],
+ "compensation_pdf_links": [
+ {
+ "link": "https://storage.googleapis.com/cdc-backend-attachments/company_attachments/Q54IRZZMC3RP8F6%2F8D5OFQ46H43DD3S_module5And6Attendance.pdf",
+ "name": "8D5OFQ46H43DD3S_module5And6Attendance.pdf"
+ },
+ {
+ "link": "https://storage.googleapis.com/cdc-backend-attachments/company_attachments/Q54IRZZMC3RP8F6%2FG8OU2PE919PFKSR_Print+Application11.pdf",
+ "name": "G8OU2PE919PFKSR_Print Application11.pdf"
+ }
+ ],
+ "selection_procedure_details_pdf_links": [
+ {
+ "link": "https://storage.googleapis.com/cdc-backend-attachments/company_attachments/Q54IRZZMC3RP8F6%2FDZTQQ6YBGBQ47PY_screencapture-onlinesbi-sbi-sbicollect-fsssuccessresponseredirect-htm-2021-07-19-18_",
+ "name": "DZTQQ6YBGBQ47PY_screencapture-onlinesbi-sbi-sbicollect-fsssuccessresponseredirect-htm-2021-07-19-18_"
+ },
+ {
+ "link": "https://storage.googleapis.com/cdc-backend-attachments/company_attachments/Q54IRZZMC3RP8F6%2FN490PUXJEEN4JZ9_screencapture-onlinesbi-sbi-sbicollect-payment-suvidhapayment-htm-2021-07-19-23_12_3",
+ "name": "N490PUXJEEN4JZ9_screencapture-onlinesbi-sbi-sbicollect-payment-suvidhapayment-htm-2021-07-19-23_12_3"
+ }
+ ],
+ "company_name": "Make My Trip",
+ "address": "MakeMyTrip India Pvt. Ltd.5, Awagarh House, MG Road(next to Bachoomal collections)Agra (UP), - 282002India",
+ "company_type": "Private Sector",
+ "nature_of_business": "Technology",
+ "website": "www.makemytrip.com",
+ "company_details": "This s a very nice company",
+ "is_company_details_pdf": true,
"city": "Mumbai",
+ "state": "Maharashtra",
+ "country": "India",
+ "pin_code": 530013,
"city_type": "Domestic",
- "compensation": 1200000,
- "compensation_details": "",
+ "designation": "Software Developer",
+ "description": "very nice job",
+ "is_description_pdf": true,
+ "compensation_CTC": 1200000,
+ "compensation_gross": 1100000,
+ "compensation_take_home": 1000000,
+ "compensation_bonus": 10000,
+ "compensation_details": "very good compensation",
+ "is_compensation_details_pdf": true,
+ "bond_details": "nil",
+ "selection_procedure_rounds": [
+ "Resume Shortlisting",
+ "Technical Interview",
+ "HR Interview"
+ ],
+ "selection_procedure_details": "All rounds are complusory",
+ "is_selection_procedure_details_pdf": true,
+ "tier": "4",
+ "tentative_date_of_joining": "2022-01-15",
"allowed_batch": [
- "THIRD",
- "FOURTH"
+ "2018",
+ "2019"
],
"allowed_branch": [
"CSE",
- "EE",
- "ME"
- ],
- "attachments": [],
- "rounds": [
- "Resume Shortlisting",
- "Technical Test",
- "Interview"
+ "EE"
],
+ "tentative_no_of_offers": 5,
+ "other_requirements": "above 8 cpi",
"additional_info": [
- "school",
- "place of study",
- "language"
+ "School",
+ "Home Town"
],
- "status": "Resume Shortlisting",
- "rounds_details": {
- "Interview": "One -to-One interview",
- "Technical Test": "Online Technical test which will be monitored remotely",
- "Resume Shortlisting": "Resume will be seen"
- },
- "company_details": {
- "id": "fdgdb",
- "name": "Apple",
- "address": "California",
- "companyType": "Technology",
- "website": ""
- }
+ "deadline_date": "2021-12-04",
+ "created_at": "2021-12-02T20:12:21+05:30"
}
],
"placementApplication": [
{
- "id": "dsdads",
- "application_status": "Resume Shortlisting",
- "resume": "XB85F4RIGBF5VJN_Cv-Gowtham.pdf",
- "additional_info": {
- "school": "Delhi Public School",
- "language": "Telugu",
- "place of study": "Visakhapatnam"
+ "id": "LLW4STE76GEJYOR",
+ "placement": {
+ "id": "Q54IRZZMC3RP8F6",
+ "company_details_pdf_links": [
+ {
+ "link": "https://storage.googleapis.com/cdc-backend-attachments/company_attachments/Q54IRZZMC3RP8F6%2FI5U4RDTV0OP0EM0_2019+Student+Details+-+Total%28State+Sort%29+-+Copy.pdf",
+ "name": "I5U4RDTV0OP0EM0_2019 Student Details - Total(State Sort) - Copy.pdf"
+ },
+ {
+ "link": "https://storage.googleapis.com/cdc-backend-attachments/company_attachments/Q54IRZZMC3RP8F6%2FW04JWWNNMIBX0JX_2019+Student+Details+-+Total%28State+Sort%29.pdf",
+ "name": "W04JWWNNMIBX0JX_2019 Student Details - Total(State Sort).pdf"
+ },
+ {
+ "link": "https://storage.googleapis.com/cdc-backend-attachments/company_attachments/Q54IRZZMC3RP8F6%2FT1BXP98WBT9BHOR_AP0313017732021LL-Driving+Licence+-+Copy.pdf",
+ "name": "T1BXP98WBT9BHOR_AP0313017732021LL-Driving Licence - Copy.pdf"
+ }
+ ],
+ "description_pdf_links": [
+ {
+ "link": "https://storage.googleapis.com/cdc-backend-attachments/company_attachments/Q54IRZZMC3RP8F6%2FC78TE2Z67BPZ41O_CSE-V-SEM.pdf",
+ "name": "C78TE2Z67BPZ41O_CSE-V-SEM.pdf"
+ }
+ ],
+ "compensation_pdf_links": [
+ {
+ "link": "https://storage.googleapis.com/cdc-backend-attachments/company_attachments/Q54IRZZMC3RP8F6%2F8D5OFQ46H43DD3S_module5And6Attendance.pdf",
+ "name": "8D5OFQ46H43DD3S_module5And6Attendance.pdf"
+ },
+ {
+ "link": "https://storage.googleapis.com/cdc-backend-attachments/company_attachments/Q54IRZZMC3RP8F6%2FG8OU2PE919PFKSR_Print+Application11.pdf",
+ "name": "G8OU2PE919PFKSR_Print Application11.pdf"
+ }
+ ],
+ "selection_procedure_details_pdf_links": [
+ {
+ "link": "https://storage.googleapis.com/cdc-backend-attachments/company_attachments/Q54IRZZMC3RP8F6%2FDZTQQ6YBGBQ47PY_screencapture-onlinesbi-sbi-sbicollect-fsssuccessresponseredirect-htm-2021-07-19-18_",
+ "name": "DZTQQ6YBGBQ47PY_screencapture-onlinesbi-sbi-sbicollect-fsssuccessresponseredirect-htm-2021-07-19-18_"
+ },
+ {
+ "link": "https://storage.googleapis.com/cdc-backend-attachments/company_attachments/Q54IRZZMC3RP8F6%2FN490PUXJEEN4JZ9_screencapture-onlinesbi-sbi-sbicollect-payment-suvidhapayment-htm-2021-07-19-23_12_3",
+ "name": "N490PUXJEEN4JZ9_screencapture-onlinesbi-sbi-sbicollect-payment-suvidhapayment-htm-2021-07-19-23_12_3"
+ }
+ ],
+ "company_name": "Make My Trip",
+ "address": "MakeMyTrip India Pvt. Ltd.5, Awagarh House, MG Road(next to Bachoomal collections)Agra (UP), - 282002India",
+ "company_type": "Private Sector",
+ "nature_of_business": "Technology",
+ "website": "www.makemytrip.com",
+ "company_details": "This s a very nice company",
+ "is_company_details_pdf": true,
+ "city": "Mumbai",
+ "state": "Maharashtra",
+ "country": "India",
+ "pin_code": 530013,
+ "city_type": "Domestic",
+ "designation": "Software Developer",
+ "description": "very nice job",
+ "is_description_pdf": true,
+ "compensation_CTC": 1200000,
+ "compensation_gross": 1100000,
+ "compensation_take_home": 1000000,
+ "compensation_bonus": 10000,
+ "compensation_details": "very good compensation",
+ "is_compensation_details_pdf": true,
+ "bond_details": "nil",
+ "selection_procedure_rounds": [
+ "Resume Shortlisting",
+ "Technical Interview",
+ "HR Interview"
+ ],
+ "selection_procedure_details": "All rounds are complusory",
+ "is_selection_procedure_details_pdf": true,
+ "tier": "4",
+ "tentative_date_of_joining": "2022-01-15",
+ "allowed_batch": [
+ "2018",
+ "2019"
+ ],
+ "allowed_branch": [
+ "CSE",
+ "EE"
+ ],
+ "tentative_no_of_offers": 5,
+ "other_requirements": "above 8 cpi",
+ "additional_info": [
+ "School",
+ "Home Town"
+ ],
+ "deadline_date": "2021-12-04",
+ "created_at": "2021-12-02T20:12:21+05:30"
},
+ "resume_link": "https://storage.googleapis.com/cdc-backend-attachments/resume/LLW4STE76GEJYOR%2F8KIOT3PW1JIS718_CSE-V-SEM.pdf",
+ "additional_info": "{\"School\": \"Narayana English Medium High School\", \"Home Town\": \"Vizag\"}",
"selected": null,
- "placement": "fdgdb121"
+ "applied_at": "2021-12-02T21:58:18.032466+05:30"
}
- ]
+ ]
}
```
- action: Tells us about the message creator
- message: Tells us what happened with our Request.
-- placements: Has the placements data.
-- internships: Has the internships data.
-- application_status: Can have many names
- - Accepting Applications
- - One of the Round Names
- - Completed
-- selected: Can take three Values
- - null: Student is still in the Selection process
- - true: Student is Selected
- - false: Student is not selected
+- placements: Array of Placement Objects
+- placementApplication: Array of Placement Application Objects
### Status Codes
@@ -225,8 +372,9 @@ The possible responses for this api request are as follows
| Status Codes | Possible Messages |
| --------------- | ------------------------ |
-| 200 OK | `Resume Added` |
-| 400 BAD_REQUEST | `Error Occurred {error}` |
+| 200 OK | `Data Found` |
+| 404 Not Found | `Student Not Found` |
+| 400 BAD_REQUEST | `Something Went Wrong` |
You can see some common errors [here](#common-errors)
@@ -331,7 +479,7 @@ You can see some common errors [here](#common-errors)
## `api/student/submitApplication/`
-This Api is used to submit application to Internships/Placements.
+This Api is used to submit application to Placements.
### How to Use?
@@ -343,24 +491,23 @@ Request_Body:
```json
{
- "opening_type": "Placement",
- "opening_id": "fgervsdgdsf",
- "resume_file_name": "1FYE0PQZZ508HR6_Resume for Google STEP.pdf",
- "additional_info": {
- "school": "Narayana English Medium",
- "place of study": "Vizag",
- "language": "Telugu"
- }
+ "opening_type": "Placement",
+ "opening_id": "Q54IRZZMC3RP8F6",
+ "resume_file_name": "8KIOT3PW1JIS718_CSE-V-SEM.pdf",
+ "additional_info": {
+ "School": "Narayana English Medium High School",
+ "Home Town": "Vizag"
+ }
}
```
> Headers
> Authorization: "Bearer {tokenID}"
-- opening_type: Can be Placement/Internship
+- opening_type: Can be Placement
- opening_id: Opening Id unique to each opening.
-- additional_info: This is the info which the Internship/Placement demands besides the normal user data which has to
- asked and sent. These fields can be found in the Internship Details.
+- additional_info: This is the info which the Placement demands besides the normal user data which has to
+ asked and sent. These fields can be found in the Placement Details.
### Response
@@ -384,12 +531,559 @@ The possible responses for this api request are as follows
| ------------- | ---------------------------------- |
| 200 OK | `Application Submitted` |
| 403 FORBIDDEN | `Application is already Submitted` |
+| 403 FORBIDDEN | `Placement Not Approved` |
| 404 NOT FOUND | `RESUME_FILE_NAME Not Found` |
You can see some common errors [here](#common-errors)
---
+# Admin Portal APIs
+
+## `api/admin/markStatus`
+
+This Api is used to mark the status for application for a specific placement.
+
+### How to Use?
+
+Send a `POST` request to `api/admin/markStatus`
+Request_Body:
+
+```json
+{
+ "opening_id": "Q54IRZZMC3RP8F6",
+ "student_list": [
+ {
+ "student_id":"190010036",
+ "student_selected":"true"
+ },
+ {
+ "student_id":"190050022",
+ "student_selected":"false"
+ }
+ ]
+}
+```
+
+
+
+> Headers
+> Authorization: "Bearer {tokenID}"
+
+### Response
+
+Response is a Json with these fields
+
+```json
+{
+ "action": "Mark Status",
+ "message": "Marked Status"
+}
+```
+
+- action: Tells us about the message creator
+- message: Tells us what happened with our Request.
+
+### Status Codes
+
+The possible responses for this api request are as follows
+
+| Status Codes | Possible Messages |
+| --------------- | ------------------------ |
+| 200 OK | `Marked Status` |
+| 400 BAD_REQUEST | `Something Went Wrong` |
+
+You may see some different errors which can be seen [here](#common-errors)
+
+---
+
+## `api/admin/getDashboard`
+
+This Api is used to get all the placements.
+
+### How to Use?
+
+Send a `GET` request to `api/admin/getdashboard`
+
+Request_Body:
+
+```json
+{}
+```
+
+> Headers
+> Authorization: "Bearer {tokenID}"
+
+### Response
+
+Response is a Json with these fields
+
+```json
+{
+ "action": "Get Dashboard - Admin",
+ "message": "Data Found",
+ "ongoing": [
+ {
+ "id": "Q54IRZZMC3RP8F6",
+ "company_details_pdf_links": [
+ {
+ "link": "https://storage.googleapis.com/cdc-backend-attachments/company_attachments/Q54IRZZMC3RP8F6%2FI5U4RDTV0OP0EM0_2019+Student+Details+-+Total%28State+Sort%29+-+Copy.pdf",
+ "name": "I5U4RDTV0OP0EM0_2019 Student Details - Total(State Sort) - Copy.pdf"
+ },
+ {
+ "link": "https://storage.googleapis.com/cdc-backend-attachments/company_attachments/Q54IRZZMC3RP8F6%2FW04JWWNNMIBX0JX_2019+Student+Details+-+Total%28State+Sort%29.pdf",
+ "name": "W04JWWNNMIBX0JX_2019 Student Details - Total(State Sort).pdf"
+ },
+ {
+ "link": "https://storage.googleapis.com/cdc-backend-attachments/company_attachments/Q54IRZZMC3RP8F6%2FT1BXP98WBT9BHOR_AP0313017732021LL-Driving+Licence+-+Copy.pdf",
+ "name": "T1BXP98WBT9BHOR_AP0313017732021LL-Driving Licence - Copy.pdf"
+ }
+ ],
+ "description_pdf_links": [
+ {
+ "link": "https://storage.googleapis.com/cdc-backend-attachments/company_attachments/Q54IRZZMC3RP8F6%2FC78TE2Z67BPZ41O_CSE-V-SEM.pdf",
+ "name": "C78TE2Z67BPZ41O_CSE-V-SEM.pdf"
+ }
+ ],
+ "compensation_pdf_links": [
+ {
+ "link": "https://storage.googleapis.com/cdc-backend-attachments/company_attachments/Q54IRZZMC3RP8F6%2F8D5OFQ46H43DD3S_module5And6Attendance.pdf",
+ "name": "8D5OFQ46H43DD3S_module5And6Attendance.pdf"
+ },
+ {
+ "link": "https://storage.googleapis.com/cdc-backend-attachments/company_attachments/Q54IRZZMC3RP8F6%2FG8OU2PE919PFKSR_Print+Application11.pdf",
+ "name": "G8OU2PE919PFKSR_Print Application11.pdf"
+ }
+ ],
+ "selection_procedure_details_pdf_links": [
+ {
+ "link": "https://storage.googleapis.com/cdc-backend-attachments/company_attachments/Q54IRZZMC3RP8F6%2FDZTQQ6YBGBQ47PY_screencapture-onlinesbi-sbi-sbicollect-fsssuccessresponseredirect-htm-2021-07-19-18_",
+ "name": "DZTQQ6YBGBQ47PY_screencapture-onlinesbi-sbi-sbicollect-fsssuccessresponseredirect-htm-2021-07-19-18_"
+ },
+ {
+ "link": "https://storage.googleapis.com/cdc-backend-attachments/company_attachments/Q54IRZZMC3RP8F6%2FN490PUXJEEN4JZ9_screencapture-onlinesbi-sbi-sbicollect-payment-suvidhapayment-htm-2021-07-19-23_12_3",
+ "name": "N490PUXJEEN4JZ9_screencapture-onlinesbi-sbi-sbicollect-payment-suvidhapayment-htm-2021-07-19-23_12_3"
+ }
+ ],
+ "company_name": "Make My Trip",
+ "address": "MakeMyTrip India Pvt. Ltd.5, Awagarh House, MG Road(next to Bachoomal collections)Agra (UP), - 282002India",
+ "company_type": "Private Sector",
+ "nature_of_business": "Technology",
+ "website": "www.makemytrip.com",
+ "company_details": "This s a very nice company",
+ "is_company_details_pdf": true,
+ "contact_person_name": "Gowtham",
+ "phone_number": 9390291911,
+ "email": "saisurya3127@gmail.com",
+ "city": "Mumbai",
+ "state": "Maharashtra",
+ "country": "India",
+ "pin_code": 530013,
+ "city_type": "Domestic",
+ "designation": "Software Developer",
+ "description": "very nice job",
+ "is_description_pdf": true,
+ "compensation_CTC": 1200000,
+ "compensation_gross": 1100000,
+ "compensation_take_home": 1000000,
+ "compensation_bonus": 10000,
+ "compensation_details": "very good compensation",
+ "is_compensation_details_pdf": true,
+ "bond_details": "nil",
+ "selection_procedure_rounds": [
+ "Resume Shortlisting",
+ "Technical Interview",
+ "HR Interview"
+ ],
+ "selection_procedure_details": "All rounds are complusory",
+ "is_selection_procedure_details_pdf": true,
+ "tier": "4",
+ "tentative_date_of_joining": "2022-01-15",
+ "allowed_batch": [
+ "2018",
+ "2019"
+ ],
+ "allowed_branch": [
+ "CSE",
+ "EE"
+ ],
+ "tentative_no_of_offers": 5,
+ "other_requirements": "above 8 cpi",
+ "additional_info": [
+ "School",
+ "Home Town"
+ ],
+ "email_verified": false,
+ "offer_accepted": null,
+ "deadline_date": "2021-12-04",
+ "created_at": "2021-12-02T20:12:21+05:30"
+ }
+ ],
+ "previous": []
+}
+```
+
+- action: Tells us about the message creator
+- message: Tells us what happened with our Request.
+- ongoing: Gives us the list of placements that are accepting applications.
+- previous: Gives us the list of placements that stopped accepting applications.
+
+
+### Status Codes
+
+The possible responses for this api request are as follows
+
+| Status Codes | Possible Messages |
+| --------------- | ------------------------ |
+| 200 OK | `Data Found` |
+| 400 BAD_REQUEST | `Something Went Wrong` |
+
+You can see some common errors [here](#common-errors)
+
+---
+
+## `api/admin/updateDeadline`
+
+This Api is used to update deadline for a specific placement.
+
+### How to Use?
+
+Send a `POST` request to `api/admin/updateDeadline`
+Request_Body:
+
+```json
+{
+ "opening_id": "Q54IRZZMC3RP8F6",
+ "deadline_datetime": "2021-12-06 16:28:18 +0530"
+}
+```
+
+> Headers
+> Authorization: "Bearer {tokenID}"
+
+### Response
+
+Response is a Json with these fields
+
+```json
+{
+ "action": "Update Deadline",
+ "message": "Deadline Updated"
+}
+```
+
+- action: Tells us about the message creator
+- message: Tells us what happened with our Request.
+
+### Status Codes
+
+The possible responses for this api request are as follows
+
+| Status Codes | Possible Messages |
+| --------------- | ------------------------ |
+| 200 OK | `Deadline Updated` |
+| 400 BAD_REQUEST | `Something Went Wrong` |
+
+You may see some different errors which can be seen [here](#common-errors)
+
+---
+
+## `api/admin/updateOfferAccepted`
+
+This Api is used to update offer verification state for a specific placement.
+
+### How to Use?
+
+Send a `POST` request to `api/admin/updateOfferAccepted`
+Request_Body:
+
+```json
+{
+ "opening_id": "Q54IRZZMC3RP8F6",
+ "offer_accepted": "true"
+}
+```
+
+> Headers
+> Authorization: "Bearer {tokenID}"
+
+### Response
+
+Response is a Json with these fields
+
+```json
+{
+ "action": "Update Offer Accepted",
+ "message": "Offer Accepted Updated"
+}
+```
+
+- action: Tells us about the message creator
+- message: Tells us what happened with our Request.
+
+### Status Codes
+
+The possible responses for this api request are as follows
+
+| Status Codes | Possible Messages |
+| --------------- | ------------------------ |
+| 200 OK | `Update Offer Accepted` |
+| 400 BAD_REQUEST | `Something Went Wrong` |
+
+You may see some different errors which can be seen [here](#common-errors)
+
+---
+
+## `api/admin/updateEmailVerified`
+
+This Api is used to update email verification state for a specific placement.
+
+### How to Use?
+
+Send a `POST` request to `api/admin/updateEmailVerified`
+Request_Body:
+
+```json
+{
+ "opening_id": "Q54IRZZMC3RP8F6",
+ "email_verified": "false"
+}
+```
+
+> Headers
+> Authorization: "Bearer {tokenID}"
+
+### Response
+
+Response is a Json with these fields
+
+```json
+{
+ "action": "Update Email Verified",
+ "message": "Email Verified Updated"
+}
+```
+
+- action: Tells us about the message creator
+- message: Tells us what happened with our Request.
+
+### Status Codes
+
+The possible responses for this api request are as follows
+
+| Status Codes | Possible Messages |
+| --------------- | ------------------------ |
+| 200 OK | `Email Verified Updated` |
+| 400 BAD_REQUEST | `Something Went Wrong` |
+
+You may see some different errors which can be seen [here](#common-errors)
+
+---
+
+## `api/admin/updateAdditionalInfo`
+
+This Api is used to update additional_info for a specific placement.
+
+### How to Use?
+
+Send a `POST` request to `api/admin/updateAdditionalInfo`
+Request_Body:
+
+```json
+{
+ "opening_id": "Q54IRZZMC3RP8F6",
+ "additional_info": [
+ "School",
+ "Place of Living",
+ "Research Interests"
+ ]
+}
+```
+
+> Headers
+> Authorization: "Bearer {tokenID}"
+
+### Response
+
+Response is a Json with these fields
+
+```json
+{
+ "action": "Update Additional Info",
+ "message": "Additional Info Updated"
+}
+```
+
+- action: Tells us about the message creator
+- message: Tells us what happened with our Request.
+
+### Status Codes
+
+The possible responses for this api request are as follows
+
+| Status Codes | Possible Messages |
+| --------------- | ------------------------ |
+| 200 OK | `Additional Info Updated` |
+| 400 BAD_REQUEST | `Something Went Wrong` |
+
+You may see some different errors which can be seen [here](#common-errors)
+
+---
+
+# Company Portal APIs
+
+## `api/company/addPlacement/`
+
+This Api is used to add placements.
+
+### How to Use?
+
+Send a `POST` request to `api/company/addPlacement`
+
+Request_Body:
+
+```json
+{
+ "company_name": [
+ "Make My Trip"
+ ],
+ "address": [
+ "MakeMyTrip India Pvt. Ltd.\n5, Awagarh House, MG Road\n(next to Bachoomal collections)\nAgra (UP), - 282002\nIndia"
+ ],
+ "company_type": [
+ "Private Sector"
+ ],
+ "nature_of_business": [
+ "Technology"
+ ],
+ "website": [
+ "www.makemytrip.com"
+ ],
+ "company_details": [
+ "This s a very nice company"
+ ],
+ "is_company_details_pdf": [
+ "true"
+ ],
+ "contact_person_name": [
+ "Gowtham"
+ ],
+ "phone_number": [
+ "9390291911"
+ ],
+ "email": [
+ "saisurya3127@gmail.com"
+ ],
+ "city": [
+ "Mumbai"
+ ],
+ "state": [
+ "Maharashtra"
+ ],
+ "country": [
+ "India"
+ ],
+ "pincode": [
+ "530013"
+ ],
+ "designation": [
+ "Software Developer"
+ ],
+ "description": [
+ "very nice job"
+ ],
+ "is_description_pdf": [
+ "true"
+ ],
+ "compensation_ctc": [
+ "1200000"
+ ],
+ "compensation_gross": [
+ "1100000"
+ ],
+ "compensation_take_home": [
+ "1000000"
+ ],
+ "compensation_bonus": [
+ "10000"
+ ],
+ "compensation_details": [
+ "very good compensation"
+ ],
+ "is_compensation_details_pdf": [
+ "true"
+ ],
+ "bond_details": [
+ "nil"
+ ],
+ "selection_procedure_rounds": [
+ "['Resume Shortlisting', 'Technical Interview', 'HR Interview']"
+ ],
+ "selection_procedure_details": [
+ "All rounds are complusory"
+ ],
+ "is_selection_procedure_details_pdf": [
+ "true"
+ ],
+ "tentative_date_of_joining": [
+ "15-01-2022"
+ ],
+ "allowed_branch": [
+ "['CSE', 'EE']"
+ ],
+ "tentative_no_of_offers": [
+ "5"
+ ],
+ "other_requirements": [
+ "above 8 cpi"
+ ],
+ "company_details_pdf": [
+ "__FILE_OBJECT__",
+ "__FILE_OBJECT__"
+ ],
+ "description_pdf": [
+ "__FILE_OBJECT__"
+ ],
+ "compensation_details_pdf": [
+ "__FILE_OBJECT__"
+ ],
+ "selection_procedure_details_pdf": [
+ "__FILE_OBJECT__",
+ "__FILE_OBJECT__"
+ ]
+}
+```
+
+### Response
+
+Response is a Json with these fields
+
+```json
+{
+ "action": "Add Placement",
+ "message": "Placement Added Successfully"
+}
+```
+
+> Headers
+> Authorization: "Bearer {tokenID}"
+
+- action: Tells us about the message creator
+- message: Tells us what happened with our Request.
+
+### Status Codes
+
+The possible responses for this api request are as follows
+
+| Status Codes | Possible Messages |
+| ------------- | ----------------- |
+| 200 OK | `Placement Added Successfully` |
+| 404 NOT FOUND | `Something went wrong` |
+
+You can see some common errors [here](#common-errors)
+
+---
+
## `Common Errors`
Some common errors that you may see while accessing the Apis
@@ -400,4 +1094,9 @@ Some common errors that you may see while accessing the Apis
| 401 UNAUTHORIZED | `Access Denied. You are not allowed to use this service` | Your may not have required access to those access those Apis. |
| 401 UNAUTHORIZED | `Token has wrong audience` | You may be using wrong credentials for Google OAuth2.0. |
| 404 NOT FOUND | `User Not Found. Contact CDC for more details` | You may not be a user at CDC, IIT Dharwad. Please contact us to get your user account |
-| 400 BAD_REQUEST | `Error Occurred {error}` | Any random Error which can be seen in the {error} string. |
+| 400 BAD_REQUEST | `Error Occurred` | Any random Error which can be seen in the {error} string. |
+| 400 BAD_REQUEST | `Something went wrong` | Any random Error which can be seen in the {error} string. |
+
+
+
+
diff --git a/CDC_Backend/templates/company_opening_submitted.html b/CDC_Backend/templates/company_opening_submitted.html
new file mode 100644
index 0000000..88147e0
--- /dev/null
+++ b/CDC_Backend/templates/company_opening_submitted.html
@@ -0,0 +1,85 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Thank You for filling the form
+
+ 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
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ® CDC,IIT Dharwad,2021
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CDC_Backend/templates/student_application_status_not_selected.html b/CDC_Backend/templates/student_application_status_not_selected.html
new file mode 100644
index 0000000..ee01642
--- /dev/null
+++ b/CDC_Backend/templates/student_application_status_not_selected.html
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Hey, {{ student_name }}
+
+ We regret to inform you that you have not been selected for {{ designation }} role at {{ company_name }}.
+ CDC will keep bringing more such opportunities for you in the future.
+
- We have received your application for a {{ applicaton_type }} offer at
+ We have received your application for a {{ application_type }} offer at
{{ company_name }}
. We received these additional details