Commit - 21-06-24

This commit is contained in:
CDC 2024-06-21 00:45:45 +05:30
commit 52abf6e967
113 changed files with 125621 additions and 0 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

142
.gitignore vendored Normal file
View File

@ -0,0 +1,142 @@
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
.python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
/venv/
/.github/
./CDC_Backend/static
./CDC_Backend/Storage
/CDC_Backend/CDC_Backend/__pycache__/
/CDC_Backend/APIs/__pycache__/
/CDC_Backend/APIs/migrations/
/CDC_Backend/static/
/CDC_Backend/Storage/
.idea
*.pyc
dev.env

BIN
CDC_Backend.zip Normal file

Binary file not shown.

BIN
CDC_Backend/.DS_Store vendored Normal file

Binary file not shown.

BIN
CDC_Backend/APIs/.DS_Store vendored Normal file

Binary file not shown.

View File

228
CDC_Backend/APIs/admin.py Normal file
View File

@ -0,0 +1,228 @@
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 simple_history.admin import SimpleHistoryAdmin
from import_export.admin import ImportExportMixin, ExportMixin
from import_export import resources
from .models import *
from .utils import send_email_for_opening
class ArrayFieldListFilter(admin.SimpleListFilter):
"""This is a list filter based on the values
from a model's `keywords` ArrayField. """
title = 'Roles'
parameter_name = 'user_type'
def lookups(self, request, model_admin):
# Very similar to our code above, but this method must return a
# list of tuples: (lookup_value, human-readable value). These
# appear in the admin's right sidebar
keywords = User.objects.values_list("user_type", flat=True)
keywords = [(kw, kw) for sublist in keywords for kw in sublist if kw]
keywords = sorted(set(keywords))
return keywords
def queryset(self, request, queryset):
# when a user clicks on a filter, this method gets called. The
# provided queryset with be a queryset of Items, so we need to
# filter that based on the clicked keyword.
lookup_value = self.value() # The clicked keyword. It can be None!
if lookup_value:
# the __contains lookup expects a list, so...
queryset = queryset.filter(user_type__contains=[lookup_value])
return queryset
class UserAdmin(ImportExportMixin, SimpleHistoryAdmin):
list_display = ('email', 'user_type', 'last_login_time')
list_filter = (ArrayFieldListFilter, 'last_login_time')
search_fields = ('email', 'user_type')
ordering = ('email', 'user_type')
admin.site.register(User, UserAdmin)
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('<a href="{}">{}</a>', url, name or str(obj))
class StudentAdmin(ImportExportMixin, SimpleHistoryAdmin):
pass
@admin.register(Student)
class Student(StudentAdmin):
list_display = ("roll_no", "name", "batch", "branch", "phone_number", 'can_apply')
search_fields = ("roll_no", "name", "phone_number")
ordering = ("roll_no", "name", "batch", "branch", "phone_number")
list_filter = ("batch", "branch")
actions = ['mark_can_apply_as_no', 'mark_can_apply_as_yes']
@admin.action(description="Deregister students")
def mark_can_apply_as_no(self, request, queryset):
queryset.update(can_apply=False)
self.message_user(request, "Deregistered the users")
@admin.action(description="Register students")
def mark_can_apply_as_yes(self, request, queryset):
queryset.update(can_apply=True)
self.message_user(request, "Registered the users")
class PlacementResources(resources.ModelResource):
class Meta:
model = Placement
exclude = ('changed_by', 'is_company_details_pdf', 'is_description_pdf',
'is_compensation_details_pdf', 'is_selection_procedure_details_pdf')
class AdminAdmin(ExportMixin, SimpleHistoryAdmin):
resource_class = PlacementResources
class PlacementResources(resources.ModelResource):
class Meta:
model = Placement
exclude = ('changed_by', 'is_company_details_pdf', 'is_description_pdf',
'is_compensation_details_pdf', 'is_selection_procedure_details_pdf')
class AdminAdmin(ExportMixin, SimpleHistoryAdmin):
resource_class = PlacementResources
class PlacementResources(resources.ModelResource):
class Meta:
model = Placement
exclude = ('changed_by', 'is_company_details_pdf', 'is_description_pdf',
'is_compensation_details_pdf', 'is_selection_procedure_details_pdf')
class AdminAdmin(ExportMixin, SimpleHistoryAdmin):
resource_class = PlacementResources
def save_model(self, request, obj, form, change):
# Check if email_verified field is being changed from False to True
if change and not obj._state.adding and obj.email_verified and form.initial.get('email_verified', False) != obj.email_verified:
# Run the send_email_for_opening function
send_email_for_opening(obj)
# Save the model as usual
super().save_model(request, obj, form, change)
@admin.register(Placement)
class Placement(AdminAdmin):
list_display = (COMPANY_NAME, DESIGNATION , CONTACT_PERSON_NAME, PHONE_NUMBER, 'tier', 'compensation_CTC', 'email_verified', 'updated_at')
search_fields = (COMPANY_NAME, CONTACT_PERSON_NAME)
ordering = ('updated_at', COMPANY_NAME, CONTACT_PERSON_NAME, 'tier', 'compensation_CTC')
list_filter = ('tier',)
class PlacementApplicationResources(resources.ModelResource):
class Meta:
model = PlacementApplication
exclude = ('id', 'changed_by')
class PlacementAdmin(ExportMixin, SimpleHistoryAdmin):
resource_class = PlacementApplicationResources
class InternshipApplicationResources(resources.ModelResource):
class Meta:
model = InternshipApplication
exclude = ('id', 'changed_by')
class InternshipApplicationAdmin(ExportMixin, SimpleHistoryAdmin):
resource_class = InternshipApplicationResources
@admin.register(PlacementApplication)
class PlacementApplication(PlacementAdmin):
list_display = ('id', 'Placement', 'Student', 'selected')
search_fields = ('id',)
ordering = ('id',)
list_filter = ('selected',)
def Placement(self, obj):
return model_admin_url(obj.placement)
def Student(self, obj):
return model_admin_url(obj.student)
@admin.register(InternshipApplication)
class InternshipApplication(InternshipApplicationAdmin):
list_display = ('id', 'Internship', 'Student', 'selected')
search_fields = ('id',)
ordering = ('id',)
list_filter = ('selected',)
def Internship(self, obj):
return model_admin_url(obj.internship)
def Student(self, obj):
return model_admin_url(obj.student)
class PrePlacementResources(resources.ModelResource):
class Meta:
model = PrePlacementOffer
exclude = ('id', 'changed_by')
class PrePlacementOfferAdmin(ExportMixin, SimpleHistoryAdmin):
resource_class = PrePlacementResources
@admin.register(PrePlacementOffer)
class PrePlacementOffer(PrePlacementOfferAdmin):
list_display = ('company', 'Student', 'accepted')
search_fields = ('company',)
ordering = ('company',)
list_filter = ('accepted',)
def Student(self, obj):
return model_admin_url(obj.student)
class InternshipResources(resources.ModelResource):
class Meta:
model = Internship
exclude = ('id', 'changed_by', 'is_company_details_pdf', 'is_description_pdf',
'is_stipend_details_pdf', 'is_selection_procedure_details_pdf')
class InternAdmin(ExportMixin, SimpleHistoryAdmin):
resource_class = InternshipResources
def save_model(self, request, obj, form, change):
# Check if email_verified field is being changed from False to True
if change and not obj._state.adding and obj.email_verified and form.initial.get('email_verified', False) != obj.email_verified:
# Run the send_email_for_opening function
send_email_for_opening(obj)
super().save_model(request, obj, form, change)
@admin.register(Internship)
class Placement(InternAdmin):
list_display = (COMPANY_NAME, DESIGNATION, CONTACT_PERSON_NAME, PHONE_NUMBER, 'stipend', 'email_verified', 'updated_at')
search_fields = (COMPANY_NAME, CONTACT_PERSON_NAME)
ordering = ('updated_at', COMPANY_NAME, CONTACT_PERSON_NAME, 'stipend')
@admin.register(Issues)
class Issues(admin.ModelAdmin):
list_display = ('id', 'title', 'description')
search_fields = ('id', 'title', 'description')
ordering = ('id', 'title', 'description')
# list_filter = ('status',)
def Student(self, obj):
return model_admin_url(obj.student)

View File

@ -0,0 +1,20 @@
from django.urls import path
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('deleteAdditionalInfo/', adminViews.deleteAdditionalInfo, name="Delete Additional Info"),
path('addAdditionalInfo/', adminViews.addAdditionalInfo, name="Add Additional Info"),
path('getApplications/', adminViews.getApplications, name="Get Applications"),
path("submitApplication/", adminViews.submitApplication, name="Submit Application"),
path('generateCSV/', adminViews.generateCSV, name="Generate CSV"),
path('addPPO/', adminViews.addPPO, name="Add PPO"),
path('getStudentApplication/', adminViews.getStudentApplication, name="Get student application"),
path('getStats/', adminViews.getStats, name="Get Stats"),
path('getEligibleStudents/', adminViews.get_eligible_students, name="Get Eligible Students"),
]

View File

@ -0,0 +1,784 @@
import csv
from rest_framework.decorators import api_view
from .serializers import *
from .utils import *
@api_view(['POST'])
@isAuthorized([ADMIN])
@precheck([OPENING_ID, STUDENT_LIST])
def markStatus(request, id, email, user_type):
try:
data = request.data
if OPENING_TYPE in data:
opening_type= data[OPENING_TYPE] #not to break the code
else:
opening_type= "Placement"
if opening_type == "Internship":
applications = InternshipApplication.objects.filter(internship_id=data[OPENING_ID])
else:
applications = PlacementApplication.objects.filter(placement_id=data[OPENING_ID])
for i in data[STUDENT_LIST]:
application = applications.filter(student__roll_no=i[STUDENT_ID]) # Filtering student's application
if len(application) > 0:
application = application[0]
if not application.selected:
if i[STUDENT_SELECTED] == True:
application.selected = True
else:
application.selected = False
else:
raise ValueError("Student already selected")
email = str(application.student.roll_no) + "@iitdh.ac.in" # Only allowing for IITDh emails
if opening_type == "Internship":
subject = STUDENT_APPLICATION_STATUS_TEMPLATE_SUBJECT.format(
company_name=application.internship.company_name,id=application.id)
data = {
"company_name": application.internship.company_name,
"designation": application.internship.designation,
"student_name": application.student.name
}
else:
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.chaged_by = get_object_or_404(User, id=id)
application.save()
else:
raise ValueError("Student - " + str(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=timezone.now(), offer_accepted=True, email_verified=True)
previous = placements.exclude(deadline_datetime__gt=timezone.now()).filter(
offer_accepted=True, email_verified=True)
new = placements.filter(offer_accepted__isnull=True, email_verified=True)
internships=Internship.objects.all().order_by('-created_at')
ongoing_internships = internships.filter(deadline_datetime__gt=timezone.now(), offer_accepted=True, email_verified=True)
previous_internships = internships.exclude(deadline_datetime__gt=timezone.now()).filter(
offer_accepted=True, email_verified=True)
new_internships = internships.filter(offer_accepted__isnull=True, email_verified=True)
ongoing = PlacementSerializerForAdmin(ongoing, many=True).data
previous = PlacementSerializerForAdmin(previous, many=True).data
new = PlacementSerializerForAdmin(new, many=True).data
ongoing_internships = InternshipSerializerForAdmin(ongoing_internships, many=True).data
previous_internships = InternshipSerializerForAdmin(previous_internships, many=True).data
new_internships = InternshipSerializerForAdmin(new_internships, many=True).data
return Response(
{'action': "Get Dashboard - Admin", 'message': "Data Found", "ongoing": ongoing, "previous": previous,
"new": new, "ongoing_internships": ongoing_internships, "previous_internships": previous_internships,
"new_internships": new_internships},
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
if OPENING_TYPE in data:
opening_type= data[OPENING_TYPE]
else:
opening_type= "Placement"
if opening_type == "Internship":
opening = get_object_or_404(Internship, pk=data[OPENING_ID])
else:
opening = get_object_or_404(Placement, pk=data[OPENING_ID])
# Updating deadline date with correct format in datetime field
opening.deadline_datetime = datetime.datetime.strptime(data[DEADLINE_DATETIME], '%Y-%m-%d %H:%M:%S %z')
opening.changed_by = get_object_or_404(User, id=id)
opening.save()
send_opening_to_notifications_service(id=opening.id,name=opening.company_name,deadline=data[DEADLINE_DATETIME],role=opening.designation,opening_type=opening_type)
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([SUPER_ADMIN])
@precheck([OPENING_ID, OFFER_ACCEPTED])
def updateOfferAccepted(request, id, email, user_type):
try:
data = request.data
offer_accepted = data[OFFER_ACCEPTED]
if OPENING_TYPE in data:
opening_type= data[OPENING_TYPE]
else:
opening_type= "Placement"
if DEADLINE_DATETIME in data:
deadline_datetime = datetime.datetime.strptime(data[DEADLINE_DATETIME], '%Y-%m-%d %H:%M:%S %z')
#else:
# deadline_datetime = timezone.localtime(timezone.now()).replace(hour=0, minute=0, second=0, microsecond=0) + datetime.timedelta(days=2)
if opening_type == "Internship":
opening = get_object_or_404(Internship, pk=data[OPENING_ID])
else:
opening = get_object_or_404(Placement, pk=data[OPENING_ID])
if opening.offer_accepted is None:
opening.offer_accepted = offer_accepted == "true"
#opening.deadline_datetime = deadline_datetime
opening.changed_by = get_object_or_404(User, id=id)
opening.save()
if opening.offer_accepted:
deadline=opening.deadline_datetime.strftime('%Y-%m-%d %H:%M:%S %z')
send_opening_to_notifications_service(id=opening.id,name=opening.company_name,deadline=deadline,role=opening.designation,opening_type=opening_type)
send_opening_notifications(opening.id,opening_type)
else:
raise ValueError("Offer Status already updated")
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 ValueError as e:
return Response({'action': "Update Offer Accepted", 'message': str(e)},
status=status.HTTP_400_BAD_REQUEST)
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
if OPENING_TYPE in data:
opening_type= data[OPENING_TYPE]
else:
opening_type= "Placement"
if opening_type == "Internship":
opening = get_object_or_404(Internship, pk=data[OPENING_ID])
else:
opening = get_object_or_404(Placement, pk=data[OPENING_ID])
opening.email_verified = True if data[EMAIL_VERIFIED] == "true" else False
opening.changed_by = get_object_or_404(User, id=id)
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, FIELD])
def deleteAdditionalInfo(request, id, email, user_type):
try:
data = request.data
if OPENING_TYPE in data:
opening_type= data[OPENING_TYPE]
else:
opening_type= "Placement"
if opening_type == "Internship":
opening = get_object_or_404(Internship, pk=data[OPENING_ID])
else:
opening = get_object_or_404(Placement, pk=data[OPENING_ID])
if data[FIELD] in opening.additional_info:
opening.additional_info.remove(data[FIELD])
opening.changed_by = get_object_or_404(User, id=id)
opening.save()
return Response({'action': "Delete Additional Info", 'message': "Additional Info Deleted"},
status=status.HTTP_200_OK)
else:
raise ValueError("Additional Info Not Found")
except Http404:
return Response({'action': "Delete Additional Info", 'message': 'Opening Not Found'},
status=status.HTTP_404_NOT_FOUND)
except ValueError:
return Response({'action': "Delete Additional Info", 'message': "Additional Info not found"},
status=status.HTTP_404_NOT_FOUND)
except Exception as e:
logger.warning("Delete Additional Info: " + str(e))
return Response({'action': "Delete Additional Info", 'message': "Something went wrong"},
status=status.HTTP_400_BAD_REQUEST)
@api_view(['POST'])
@isAuthorized([ADMIN])
@precheck([OPENING_ID, FIELD])
def addAdditionalInfo(request, id, email, user_type):
try:
data = request.data
if OPENING_TYPE in data:
opening_type= data[OPENING_TYPE]
else:
opening_type= "Placement"
if opening_type == "Internship":
opening = get_object_or_404(Internship, pk=data[OPENING_ID])
else:
opening = get_object_or_404(Placement, pk=data[OPENING_ID])
if data[FIELD] not in opening.additional_info:
opening.additional_info.append(data[FIELD])
opening.save()
return Response({'action': "Add Additional Info", 'message': "Additional Info Added"},
status=status.HTTP_200_OK)
else:
raise ValueError("Additional Info Found")
except Http404:
return Response({'action': "Add Additional Info", 'message': 'Opening Not Found'},
status=status.HTTP_404_NOT_FOUND)
except ValueError:
return Response({'action': "Add Additional Info", 'message': "Additional Info already found"},
status=status.HTTP_400_BAD_REQUEST)
except Exception as e:
logger.warning("Add Additional Info: " + str(e))
return Response({'action': "Add 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
if OPENING_TYPE in data:
opening_type= data[OPENING_TYPE]
else:
opening_type= "Placement"
if opening_type == "Internship":
opening = get_object_or_404(Internship, pk=data[OPENING_ID])
applications = InternshipApplication.objects.filter(internship=opening)
serializer = InternshipApplicationSerializerForAdmin(applications, many=True)
else:
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=[APPLICATION_ID, STUDENT_ID, OPENING_ID, ADDITIONAL_INFO, RESUME_FILE_NAME])
def submitApplication(request, id, email, user_type):
try:
data = request.data
if OPENING_TYPE in data:
opening_type= data[OPENING_TYPE]
else:
opening_type= "Placement"
if opening_type == "Internship":
opening = get_object_or_404(Internship, pk=data[OPENING_ID])
else:
opening = get_object_or_404(Placement, pk=data[OPENING_ID])
student = get_object_or_404(Student, pk=data[STUDENT_ID])
# opening = get_object_or_404(Placement, pk=data[OPENING_ID])
student_user = get_object_or_404(User, id=student.id)
if data[APPLICATION_ID] == "":
application = PlacementApplication() if opening_type == "Placement" else InternshipApplication()
application.id = generateRandomString()
if(opening_type == "Placement"):
application.placement = opening
else:
application.internship = opening
application.student = student
if data[RESUME_FILE_NAME] in student.resumes:
application.resume = data[RESUME_FILE_NAME]
else:
raise FileNotFoundError(RESUME_FILE_NAME + " Not Found")
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": "Placement" if opening_type == "Placement" else "Internship",
"additional_info": dict(json.loads(application.additional_info)),
}
subject = STUDENT_APPLICATION_SUBMITTED_TEMPLATE_SUBJECT.format(company_name=opening.company_name)
application.changed_by = get_object_or_404(User, id=id)
application.save()
sendEmail(student_user.email, subject, data, STUDENT_APPLICATION_SUBMITTED_TEMPLATE)
return Response({'action': "Add Student Application", 'message': "Application added"},
status=status.HTTP_200_OK)
else:
if opening_type == "Internship":
application = get_object_or_404(InternshipApplication, id=data[APPLICATION_ID])
else:
application = get_object_or_404(PlacementApplication, id=data[APPLICATION_ID])
if application:
if data[RESUME_FILE_NAME] in student.resumes:
application.resume = data[RESUME_FILE_NAME]
else:
raise FileNotFoundError(RESUME_FILE_NAME + " Not Found")
application.resume = data[RESUME_FILE_NAME]
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": "Placement" if opening_type == "Placement" else "Internship",
"resume": application.resume[16:],
"additional_info_items": dict(json.loads(application.additional_info)),
}
subject = STUDENT_APPLICATION_UPDATED_TEMPLATE_SUBJECT.format(company_name=opening.company_name)
application.changed_by = get_object_or_404(User, id=id)
application.save()
sendEmail(student_user.email, subject, data, STUDENT_APPLICATION_UPDATED_TEMPLATE)
return Response({'action': "Add Student Application", 'message': "Application updated"},
status=status.HTTP_200_OK)
else:
return Response({'action': "Edit Student Application", 'message': "No Application Found"},
status=status.HTTP_400_BAD_REQUEST)
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 AttributeError as e:
return Response({'action': "Submit Application", 'message': str(e)},
status=status.HTTP_400_BAD_REQUEST)
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
if OPENING_TYPE in data:
opening_type= data[OPENING_TYPE]
else:
opening_type= "Placement"
if opening_type == "Internship":
opening = get_object_or_404(Internship, id=data[OPENING_ID])
applications = InternshipApplication.objects.filter(internship=opening)
else:
opening = get_object_or_404(Placement, id=data[OPENING_ID])
applications = PlacementApplication.objects.filter(placement=opening)
filename = generateRandomString()
if not os.path.isdir(STORAGE_DESTINATION_APPLICATION_CSV):
os.makedirs(STORAGE_DESTINATION_APPLICATION_CSV, exist_ok=True)
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(opening.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(str(apl.student.id)) + "/" + urllib.parse.quote(str(apl.resume))
row_details.append(link)
row_details.append(apl.selected)
for i in opening.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()))
return Response({'action': "Create csv", 'message': "Something Went Wrong"},
status=status.HTTP_400_BAD_REQUEST)
@api_view(['POST'])
@isAuthorized(allowed_users=[ADMIN])
@precheck(required_data=[COMPANY_NAME, COMPENSATION_GROSS, OFFER_ACCEPTED, STUDENT_ID, DESIGNATION, TIER])
def addPPO(request, id, email, user_type):
try:
data = request.data
PPO = PrePlacementOffer()
PPO.company = data[COMPANY_NAME]
PPO.compensation = int(data[COMPENSATION_GROSS])
if data[OFFER_ACCEPTED] == "true":
PPO.accepted = True
elif data[OFFER_ACCEPTED] == "false":
PPO.accepted = False
else:
PPO.accepted = None
PPO.student = get_object_or_404(Student, id=data[STUDENT_ID])
PPO.designation = data[DESIGNATION]
PPO.tier = int(data[TIER])
if COMPENSATION_DETAILS in data:
PPO.compensation_details = data[COMPENSATION_DETAILS]
PPO.changed_by = get_object_or_404(User, id=id)
PPO.save()
return Response({'action': "Add PPO", 'message': "PPO added"},
status=status.HTTP_200_OK)
except:
logger.warning("Add PPO: " + str(sys.exc_info()))
return Response({'action': "Add PPO", 'message': "Something Went Wrong"},
status=status.HTTP_400_BAD_REQUEST)
@api_view(['POST'])
@isAuthorized(allowed_users=[ADMIN])
@precheck(required_data=[STUDENT_ID, OPENING_ID])
def getStudentApplication(request, id, email, user_type):
try:
data = request.data
if OPENING_TYPE in data:
opening_type= data[OPENING_TYPE]
else:
opening_type= "Placement"
student = get_object_or_404(Student, id=data[STUDENT_ID])
student_serializer = StudentSerializer(student)
student_details = {
"name": student_serializer.data['name'],
"batch": student.batch,
"branch": student.branch,
"resume_list": student_serializer.data['resume_list'],
}
# search for the application if there or not
if opening_type == "Internship":
application = InternshipApplication.objects.filter(student=student,
internship=get_object_or_404(Internship,
id=data[OPENING_ID]))
else:
application = PlacementApplication.objects.filter(student=student,
placement=get_object_or_404(Placement, id=data[OPENING_ID]))
if application:
if opening_type == "Internship":
serializer = InternshipApplicationSerializer(application[0])
application_info = {
"id": serializer.data['id'],
"additional_info": serializer.data['additional_info'],
"resume": serializer.data['resume_link'],
}
else:
serializer = PlacementApplicationSerializer(application[0])
application_info = {
"id": serializer.data['id'],
"additional_info": serializer.data['additional_info'],
"resume": serializer.data['resume_link'],
}
return Response(
{'action': "Get Student Application", 'application_found': "true", "application_info": application_info,
"student_details": student_details}, status=status.HTTP_200_OK)
else:
return Response(
{'action': "Get Student Application", 'application_found': "false", "student_details": student_details},
status=status.HTTP_404_NOT_FOUND)
except Http404:
return Response({'action': "Get Student Application", 'message': "Student not found."},
status.HTTP_404_NOT_FOUND)
except:
logger.warning("Get Student Application: " + str(sys.exc_info()))
return Response({'action': "Get Student Application", 'message': "Something Went Wrong"},
status.HTTP_400_BAD_REQUEST)
@api_view(['GET'])
# @isAuthorized(allowed_users=[ADMIN])
def getStats(request, id, email, user_type):
try:
stats = []
placement_ids = {}
tier_count = {
"CSE": {
"1":0,
"2":0,
"3":0,
"4":0,
"5":0,
"6":0,
"7":0,
"8":0,
"psu":0,
},
"EE": {
"1":0,
"2":0,
"3":0,
"4":0,
"5":0,
"6":0,
"7":0,
"psu":0,
},
"MMAE": {
"1":0,
"2":0,
"3":0,
"4":0,
"5":0,
"6":0,
"7":0,
"8":0,
"psu":0,
},
"Total": {
"1":0,
"2":0,
"3":0,
"4":0,
"5":0,
"6":0,
"7":0,
"8":0,
"psu":0,
},
}
number_of_students_placed = {
"CSE": 0,
"EE": 0,
"MMAE": 0,
"Total": 0,
}
number_of_students_with_multiple_offers = 0
number_of_students_with_no_offers = {
"CSE": 0,
"EE": 0,
"MMAE": 0,
"Total": 0,
}
max_CTC = {
"CSE": 0,
"EE": 0,
"MMAE": 0
}
average_CTC = {
"CSE": 0,
"EE": 0,
"MMAE": 0
}
count = {
"CSE": 0,
"EE": 0,
"MMAE": 0
}
students = Student.objects.all().order_by("roll_no")
for student in students.iterator():
applications = PlacementApplication.objects.filter(student=student, selected=True)
ppos = PrePlacementOffer.objects.filter(student=student, accepted=True)
first_offer_data = None
second_offer_data = None
# get the first and second offer
offers = []
offers.extend(applications)
offers.extend(ppos)
if len(offers) == 0:
number_of_students_with_no_offers[student.branch] += 1
number_of_students_with_no_offers["Total"] += 1
else:
number_of_students_placed[student.branch] += 1
number_of_students_placed["Total"] += 1
if len(offers) > 1:
number_of_students_with_multiple_offers += 1
for offer in offers:
if type(offer) == PrePlacementOffer:
if first_offer_data is None:
first_offer_data = {
"id": offer.id,
"company": offer.company,
"compensation": offer.compensation,
"tier": offer.tier,
"type": "PPO",
}
elif second_offer_data is None:
second_offer_data = {
"id": offer.id,
"company": offer.company,
"compensation": offer.compensation,
"tier": offer.tier,
"type": "PPO",
}
elif type(offer) == PlacementApplication:
if first_offer_data is None:
first_offer_data = {
"id": offer.placement.id,
"company": offer.placement.company_name,
"compensation": offer.placement.compensation_CTC,
"tier": offer.placement.tier,
"type": "Placement",
}
elif second_offer_data is None:
second_offer_data = {
"id": offer.placement.id,
"company": offer.placement.company_name,
"compensation": offer.placement.compensation_CTC,
"tier": offer.placement.tier,
"type": "Placement",
}
data = {
"id": student.id,
"name": student.name,
"roll_no": student.roll_no,
"batch": student.batch,
"branch": student.branch,
"cpi": student.cpi,
"first_offer": first_offer_data['company'] if first_offer_data is not None else None,
"first_offer_tier": first_offer_data['tier'] if first_offer_data is not None else None,
"first_offer_compensation": first_offer_data['compensation'] if first_offer_data is not None else None,
"second_offer": second_offer_data['company'] if second_offer_data is not None else None,
"second_offer_tier": second_offer_data['tier'] if second_offer_data is not None else None,
"second_offer_compensation": second_offer_data['compensation'] if second_offer_data is not None else None,
}
if first_offer_data is not None:
tier_count[student.branch][first_offer_data['tier']] += 1
tier_count['Total'][first_offer_data['tier']] += 1
max_CTC[student.branch] = max(max_CTC[student.branch], first_offer_data['compensation'])
average_CTC[student.branch] += first_offer_data['compensation']
count[student.branch] += 1
if first_offer_data['type'] == "Placement":
placement_ids[first_offer_data['company']] = first_offer_data['id']
if second_offer_data is not None:
tier_count[student.branch][second_offer_data['tier']] += 1
tier_count['Total'][second_offer_data['tier']] += 1
max_CTC[student.branch] = max(max_CTC[student.branch], second_offer_data['compensation'])
average_CTC[student.branch] += second_offer_data['compensation']
count[student.branch] += 1
if second_offer_data['type'] == "Placement":
placement_ids[second_offer_data['company']] = second_offer_data['id']
stats.append(data)
for branch in average_CTC:
if count[branch] > 0:
average_CTC[branch] /= count[branch]
# round off to 2 decimal places
average_CTC[branch] = round(average_CTC[branch], 2)
else:
average_CTC[branch] = 0
return Response({'action': "Get Stats", 'message': "Stats fetched", 'stats': stats, 'placement_ids': placement_ids,
"tier_count": {br: tier_count[br].values() for br in tier_count},
"number_of_students_placed": number_of_students_placed,
"number_of_students_with_multiple_offers": number_of_students_with_multiple_offers,
"number_of_students_with_no_offers": number_of_students_with_no_offers,
"max_CTC": max_CTC,
"average_CTC": average_CTC,
},
status=status.HTTP_200_OK)
except:
logger.warning("Get Stats: " + str(sys.exc_info()))
print(sys.exc_info())
return Response({'action': "Get Stats", 'message': "Something Went Wrong"},
status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET'])
@isAuthorizedService()
@precheck(required_data=[OPENING_ID])
def get_eligible_students(request):
try:
data = request.GET
opening_id = data[OPENING_ID]
if OPENING_TYPE in data:
opening_type= data[OPENING_TYPE]
else:
opening_type= "Placement"
if "send_all" in data:
send_all = "True"==data["send_all"]
else:
send_all = False
eligible_students=get_eligible_emails(opening_id=opening_id, opening_type=opening_type, send_all=send_all)
return Response({'action': "Get Eligible Students", 'message': "Eligible Students Fetched",
'eligible_students': eligible_students},
status=status.HTTP_200_OK)
except Http404:
return Response({'action': "Get Eligible Students", 'message': "Opening Not Found"},
status=status.HTTP_404_NOT_FOUND)
except:
logger.warning("Get Eligible Students: " + str(sys.exc_info()))
return Response({'action': "Get Eligible Students", 'message': "Something Went Wrong"},
status=status.HTTP_400_BAD_REQUEST)

View File

@ -0,0 +1,636 @@
import csv
from rest_framework.decorators import api_view
from .serializers import *
from .utils 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__roll_no=i[STUDENT_ID]) # Filtering student's application
if len(application) > 0:
application = application[0]
if not application.selected:
if i[STUDENT_SELECTED] == True:
application.selected = True
else:
application.selected = False
else:
raise ValueError("Student already selected")
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.chaged_by = get_object_or_404(User, id=id)
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=timezone.now(), offer_accepted=True, email_verified=True)
previous = placements.exclude(deadline_datetime__gt=timezone.now()).filter(
offer_accepted=True, email_verified=True)
new = placements.filter(offer_accepted__isnull=True, email_verified=True)
ongoing = PlacementSerializerForAdmin(ongoing, many=True).data
previous = PlacementSerializerForAdmin(previous, many=True).data
new = PlacementSerializerForAdmin(new, many=True).data
return Response(
{'action': "Get Dashboard - Admin", 'message': "Data Found", "ongoing": ongoing, "previous": previous,
"new": new},
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.datetime.strptime(data[DEADLINE_DATETIME], '%Y-%m-%d %H:%M:%S %z')
opening.changed_by = get_object_or_404(User, id=id)
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([SUPER_ADMIN])
@precheck([OPENING_ID, OFFER_ACCEPTED])
def updateOfferAccepted(request, id, email, user_type):
try:
data = request.data
offer_accepted = data[OFFER_ACCEPTED]
opening = get_object_or_404(Placement, pk=data[OPENING_ID])
if opening.offer_accepted is None:
opening.offer_accepted = offer_accepted == "true"
opening.changed_by = get_object_or_404(User, id=id)
opening.save()
if opening.offer_accepted:
send_opening_notifications(opening.id)
else:
raise ValueError("Offer Status already updated")
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 ValueError as e:
return Response({'action': "Update Offer Accepted", 'message': str(e)},
status=status.HTTP_400_BAD_REQUEST)
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.changed_by = get_object_or_404(User, id=id)
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, FIELD])
def deleteAdditionalInfo(request, id, email, user_type):
try:
data = request.data
opening = get_object_or_404(Placement, pk=data[OPENING_ID])
if data[FIELD] in opening.additional_info:
opening.additional_info.remove(data[FIELD])
opening.changed_by = get_object_or_404(User, id=id)
opening.save()
return Response({'action': "Delete Additional Info", 'message': "Additional Info Deleted"},
status=status.HTTP_200_OK)
else:
raise ValueError("Additional Info Not Found")
except Http404:
return Response({'action': "Delete Additional Info", 'message': 'Opening Not Found'},
status=status.HTTP_404_NOT_FOUND)
except ValueError:
return Response({'action': "Delete Additional Info", 'message': "Additional Info not found"},
status=status.HTTP_404_NOT_FOUND)
except Exception as e:
logger.warning("Delete Additional Info: " + str(e))
return Response({'action': "Delete Additional Info", 'message': "Something went wrong"},
status=status.HTTP_400_BAD_REQUEST)
@api_view(['POST'])
@isAuthorized([ADMIN])
@precheck([OPENING_ID, FIELD])
def addAdditionalInfo(request, id, email, user_type):
try:
data = request.data
opening = get_object_or_404(Placement, pk=data[OPENING_ID])
if data[FIELD] not in opening.additional_info:
opening.additional_info.append(data[FIELD])
opening.save()
return Response({'action': "Add Additional Info", 'message': "Additional Info Added"},
status=status.HTTP_200_OK)
else:
raise ValueError("Additional Info Found")
except Http404:
return Response({'action': "Add Additional Info", 'message': 'Opening Not Found'},
status=status.HTTP_404_NOT_FOUND)
except ValueError:
return Response({'action': "Add Additional Info", 'message': "Additional Info already found"},
status=status.HTTP_400_BAD_REQUEST)
except Exception as e:
logger.warning("Add Additional Info: " + str(e))
return Response({'action': "Add 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=[APPLICATION_ID, STUDENT_ID, OPENING_ID, ADDITIONAL_INFO, RESUME_FILE_NAME])
def submitApplication(request, id, email, user_type):
try:
data = request.data
student = get_object_or_404(Student, pk=data[STUDENT_ID])
opening = get_object_or_404(Placement, pk=data[OPENING_ID])
student_user = get_object_or_404(User, id=student.id)
if data[APPLICATION_ID] == "":
application = PlacementApplication()
application.id = generateRandomString()
application.placement = opening
application.student = student
if data[RESUME_FILE_NAME] in student.resumes:
application.resume = data[RESUME_FILE_NAME]
else:
raise FileNotFoundError(RESUME_FILE_NAME + " Not Found")
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": "Placement",
"additional_info": dict(json.loads(application.additional_info)),
}
subject = STUDENT_APPLICATION_SUBMITTED_TEMPLATE_SUBJECT.format(company_name=opening.company_name)
application.changed_by = get_object_or_404(User, id=id)
application.save()
sendEmail(student_user.email, subject, data, STUDENT_APPLICATION_SUBMITTED_TEMPLATE)
return Response({'action': "Add Student Application", 'message': "Application added"},
status=status.HTTP_200_OK)
else:
application = get_object_or_404(PlacementApplication, id=data[APPLICATION_ID])
if application:
if data[RESUME_FILE_NAME] in student.resumes:
application.resume = data[RESUME_FILE_NAME]
else:
raise FileNotFoundError(RESUME_FILE_NAME + " Not Found")
application.resume = data[RESUME_FILE_NAME]
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": "Placement",
"resume": application.resume[16:],
"additional_info_items": dict(json.loads(application.additional_info)),
}
subject = STUDENT_APPLICATION_UPDATED_TEMPLATE_SUBJECT.format(company_name=opening.company_name)
application.changed_by = get_object_or_404(User, id=id)
application.save()
sendEmail(student_user.email, subject, data, STUDENT_APPLICATION_UPDATED_TEMPLATE)
return Response({'action': "Add Student Application", 'message': "Application updated"},
status=status.HTTP_200_OK)
else:
return Response({'action': "Edit Student Application", 'message': "No Application Found"},
status=status.HTTP_400_BAD_REQUEST)
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(apl.student.id) + "/" + urllib.parse.quote(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()))
return Response({'action': "Create csv", 'message': "Something Went Wrong"},
status=status.HTTP_400_BAD_REQUEST)
@api_view(['POST'])
@isAuthorized(allowed_users=[ADMIN])
@precheck(required_data=[COMPANY_NAME, COMPENSATION_GROSS, OFFER_ACCEPTED, STUDENT_ID, DESIGNATION, TIER])
def addPPO(request, id, email, user_type):
try:
data = request.data
PPO = PrePlacementOffer()
PPO.company = data[COMPANY_NAME]
PPO.compensation = int(data[COMPENSATION_GROSS])
if data[OFFER_ACCEPTED] == "true":
PPO.accepted = True
elif data[OFFER_ACCEPTED] == "false":
PPO.accepted = False
else:
PPO.accepted = None
PPO.student = get_object_or_404(Student, id=data[STUDENT_ID])
PPO.designation = data[DESIGNATION]
PPO.tier = int(data[TIER])
if COMPENSATION_DETAILS in data:
PPO.compensation_details = data[COMPENSATION_DETAILS]
PPO.changed_by = get_object_or_404(User, id=id)
PPO.save()
return Response({'action': "Add PPO", 'message': "PPO added"},
status=status.HTTP_200_OK)
except:
logger.warning("Add PPO: " + str(sys.exc_info()))
return Response({'action': "Add PPO", 'message': "Something Went Wrong"},
status=status.HTTP_400_BAD_REQUEST)
@api_view(['POST'])
@isAuthorized(allowed_users=[ADMIN])
@precheck(required_data=[STUDENT_ID, OPENING_ID])
def getStudentApplication(request, id, email, user_type):
try:
data = request.data
student = get_object_or_404(Student, id=data[STUDENT_ID])
student_serializer = StudentSerializer(student)
student_details = {
"name": student_serializer.data['name'],
"batch": student.batch,
"branch": student.branch,
"resume_list": student_serializer.data['resume_list'],
}
# search for the application if there or not
application = PlacementApplication.objects.filter(student=student,
placement=get_object_or_404(Placement, id=data[OPENING_ID]))
if application:
serializer = PlacementApplicationSerializer(application[0])
application_info = {
"id": serializer.data['id'],
"additional_info": serializer.data['additional_info'],
"resume": serializer.data['resume_link'],
}
return Response(
{'action': "Get Student Application", 'application_found': "true", "application_info": application_info,
"student_details": student_details}, status=status.HTTP_200_OK)
else:
return Response(
{'action': "Get Student Application", 'application_found': "false", "student_details": student_details},
status=status.HTTP_404_NOT_FOUND)
except Http404:
return Response({'action': "Get Student Application", 'message': "Student not found."},
status.HTTP_404_NOT_FOUND)
except:
logger.warning("Get Student Application: " + str(sys.exc_info()))
return Response({'action': "Get Student Application", 'message': "Something Went Wrong"},
status.HTTP_400_BAD_REQUEST)
@api_view(['GET'])
@isAuthorized(allowed_users=[ADMIN])
def getStats(request, id, email, user_type):
try:
stats = []
placement_ids = {}
tier_count = {
"CSE": {
"1":0,
"2":0,
"3":0,
"4":0,
"5":0,
"6":0,
"7":0,
"8":0,
"psu":0,
},
"EE": {
"1":0,
"2":0,
"3":0,
"4":0,
"5":0,
"6":0,
"7":0,
"8":0,
"psu":0,
},
"MMAE": {
"1":0,
"2":0,
"3":0,
"4":0,
"5":0,
"6":0,
"7":0,
"8":0,
"psu":0,
},
"Total": {
"1":0,
"2":0,
"3":0,
"4":0,
"5":0,
"6":0,
"7":0,
"psu":0,
},
}
number_of_students_placed = {
"CSE": 0,
"EE": 0,
"MMAE": 0,
"Total": 0,
}
number_of_students_with_multiple_offers = 0
number_of_students_with_no_offers = {
"CSE": 0,
"EE": 0,
"MMAE": 0,
"Total": 0,
}
max_CTC = {
"CSE": 0,
"EE": 0,
"MMAE": 0
}
average_CTC = {
"CSE": 0,
"EE": 0,
"MMAE": 0
}
count = {
"CSE": 0,
"EE": 0,
"MMAE": 0
}
students = Student.objects.all().order_by("roll_no")
for student in students.iterator():
applications = PlacementApplication.objects.filter(student=student, selected=True)
ppos = PrePlacementOffer.objects.filter(student=student, accepted=True)
first_offer_data = None
second_offer_data = None
# get the first and second offer
offers = []
offers.extend(applications)
offers.extend(ppos)
if len(offers) == 0:
number_of_students_with_no_offers[student.branch] += 1
number_of_students_with_no_offers["Total"] += 1
else:
number_of_students_placed[student.branch] += 1
number_of_students_placed["Total"] += 1
if len(offers) > 1:
number_of_students_with_multiple_offers += 1
for offer in offers:
if type(offer) == PrePlacementOffer:
if first_offer_data is None:
first_offer_data = {
"id": offer.id,
"company": offer.company,
"compensation": offer.compensation,
"tier": offer.tier,
"type": "PPO",
}
elif second_offer_data is None:
second_offer_data = {
"id": offer.id,
"company": offer.company,
"compensation": offer.compensation,
"tier": offer.tier,
"type": "PPO",
}
elif type(offer) == PlacementApplication:
if first_offer_data is None:
first_offer_data = {
"id": offer.placement.id,
"company": offer.placement.company_name,
"compensation": offer.placement.compensation_CTC,
"tier": offer.placement.tier,
"type": "Placement",
}
elif second_offer_data is None:
second_offer_data = {
"id": offer.placement.id,
"company": offer.placement.company_name,
"compensation": offer.placement.compensation_CTC,
"tier": offer.placement.tier,
"type": "Placement",
}
data = {
"id": student.id,
"name": student.name,
"roll_no": student.roll_no,
"batch": student.batch,
"branch": student.branch,
"cpi": student.cpi,
"first_offer": first_offer_data['company'] if first_offer_data is not None else None,
"first_offer_tier": first_offer_data['tier'] if first_offer_data is not None else None,
"first_offer_compensation": first_offer_data['compensation'] if first_offer_data is not None else None,
"second_offer": second_offer_data['company'] if second_offer_data is not None else None,
"second_offer_tier": second_offer_data['tier'] if second_offer_data is not None else None,
"second_offer_compensation": second_offer_data['compensation'] if second_offer_data is not None else None,
}
if first_offer_data is not None:
tier_count[student.branch][first_offer_data['tier']] += 1
tier_count['Total'][first_offer_data['tier']] += 1
max_CTC[student.branch] = max(max_CTC[student.branch], first_offer_data['compensation'])
average_CTC[student.branch] += first_offer_data['compensation']
count[student.branch] += 1
if first_offer_data['type'] == "Placement":
placement_ids[first_offer_data['company']] = first_offer_data['id']
if second_offer_data is not None:
tier_count[student.branch][second_offer_data['tier']] += 1
tier_count['Total'][second_offer_data['tier']] += 1
max_CTC[student.branch] = max(max_CTC[student.branch], second_offer_data['compensation'])
average_CTC[student.branch] += second_offer_data['compensation']
count[student.branch] += 1
if second_offer_data['type'] == "Placement":
placement_ids[second_offer_data['company']] = second_offer_data['id']
stats.append(data)
for branch in average_CTC:
if count[branch] > 0:
average_CTC[branch] /= count[branch]
# round off to 2 decimal places
average_CTC[branch] = round(average_CTC[branch], 2)
else:
average_CTC[branch] = 0
return Response({'action': "Get Stats", 'message': "Stats fetched", 'stats': stats, 'placement_ids': placement_ids,
"tier_count": {br: tier_count[br].values() for br in tier_count},
"number_of_students_placed": number_of_students_placed,
"number_of_students_with_multiple_offers": number_of_students_with_multiple_offers,
"number_of_students_with_no_offers": number_of_students_with_no_offers,
"max_CTC": max_CTC,
"average_CTC": average_CTC,
},
status=status.HTTP_200_OK)
except:
logger.warning("Get Stats: " + str(sys.exc_info()))
print(sys.exc_info())
return Response({'action': "Get Stats", 'message': "Something Went Wrong"},
status=status.HTTP_400_BAD_REQUEST)

6
CDC_Backend/APIs/apps.py Normal file
View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class ApisConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'APIs'

View File

@ -0,0 +1,11 @@
from django.urls import path
from . import companyViews
urlpatterns = [
path('addPlacement/', companyViews.addPlacement, name="Add Placement"),
path('verifyEmail/', companyViews.verifyEmail, name="Verify Email"),
path('getAutoFillJnf/', companyViews.autoFillJnf, name="Auto FIll JNF"),
path('addInternship/',companyViews.addInternship,name="Add Internship"),
path('getAutoFillInf/', companyViews.autoFillInf, name="Auto FIll INF"),
]

View File

@ -0,0 +1,541 @@
from rest_framework.decorators import api_view
from .utils import *
from .serializers import *
logger = logging.getLogger('db')
@api_view(['POST'])
@precheck([COMPANY_NAME, ADDRESS, COMPANY_TYPE, NATURE_OF_BUSINESS, TYPE_OF_ORGANISATION, 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,
IS_COMPENSATION_DETAILS_PDF, ALLOWED_BRANCH, RS_ELIGIBLE, SELECTION_PROCEDURE_ROUNDS,
SELECTION_PROCEDURE_DETAILS,
IS_SELECTION_PROCEDURE_DETAILS_PDF, TENTATIVE_DATE_OF_JOINING, TENTATIVE_NO_OF_OFFERS, OTHER_REQUIREMENTS,
RECAPTCHA_VALUE, JOB_LOCATION
])
def addPlacement(request):
logger.info("JNF filled by " + str(request.data['email']))
logger.info(request.data)
try:
data = request.data
files = request.FILES
opening = Placement()
if not verify_recaptcha(data[RECAPTCHA_VALUE]):
raise Exception("Recaptcha Failed")
opening.id = generateRandomString()
# 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.type_of_organisation = data[TYPE_OF_ORGANISATION]
opening.website = data[WEBSITE]
opening.company_details = data[COMPANY_DETAILS]
opening.is_company_details_pdf = data[IS_COMPANY_DETAILS_PDF]
if data[RS_ELIGIBLE] == 'Yes':
opening.rs_eligible = True
else:
opening.rs_eligible = False
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
if data[IS_COMPANY_DETAILS_PDF] == "true" and len(opening.company_details_pdf_names) > 0:
opening.is_company_details_pdf = True
elif data[IS_COMPANY_DETAILS_PDF] == "false" and len(opening.company_details_pdf_names) == 0:
opening.is_company_details_pdf = False
else:
raise ValueError('Invalid value for is_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.upper() == '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]
opening.job_location = data[JOB_LOCATION]
opening.is_description_pdf = data[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
# Check if is_description_pdf is boolean
if data[IS_DESCRIPTION_PDF] == "true" and len(opening.description_pdf_names) > 0:
opening.is_description_pdf = True
elif data[IS_DESCRIPTION_PDF] == "false" and len(opening.description_pdf_names) == 0:
opening.is_description_pdf = False
else:
raise ValueError('Invalid value for is_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('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('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('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 Bonus must be an integer')
opening.is_compensation_details_pdf = data[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
# Check if is_compensation_details_pdf is boolean
if data[IS_COMPENSATION_DETAILS_PDF] == "true" and len(opening.compensation_details_pdf_names) > 0:
opening.is_compensation_details_pdf = True
elif data[IS_COMPENSATION_DETAILS_PDF] == "false" and len(opening.compensation_details_pdf_names) == 0:
opening.is_compensation_details_pdf = False
else:
raise ValueError('Invalid value for is_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:
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]
opening.is_selection_procedure_details_pdf = data[IS_SELECTION_PROCEDURE_DETAILS_PDF]
if opening.is_selection_procedure_details_pdf == "true":
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.selection_procedure_details_pdf_names = selection_procedure_details_pdf
# Check if is_selection_procedure_details_pdf is boolean
if data[IS_SELECTION_PROCEDURE_DETAILS_PDF] == "true" and len(
opening.selection_procedure_details_pdf_names) > 0:
opening.is_selection_procedure_details_pdf = True
elif data[IS_SELECTION_PROCEDURE_DETAILS_PDF] == "false" and len(
opening.selection_procedure_details_pdf_names) == 0:
opening.is_selection_procedure_details_pdf = False
else:
raise ValueError('Invalid value for is_selection_procedure_pdf')
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.datetime.strptime(data[TENTATIVE_DATE_OF_JOINING],
'%d-%m-%Y').date()
# 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))
# 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])
elif data[TENTATIVE_NO_OF_OFFERS] == 'null':
opening.tentative_no_of_offers = None
else:
raise ValueError('Tentative No Of Offers must be an integer')
opening.other_requirements = data[OTHER_REQUIREMENTS]
opening.save()
stat, link = generateOneTimeVerificationLink(opening.email, opening.id, "Placement")
if not stat:
raise RuntimeError("Error in generating one time verification link for placement")
data = {
"designation": opening.designation,
"one_time_link": link,
"opening_type": "Job"
}
sendEmail(opening.email, COMPANY_EMAIl_VERIFICATION_TEMPLATE_SUBJECT, data,
COMPANY_EMAIL_VERIFICATION_TEMPLATE)
return Response({'action': "Add Placement", 'message': "Placement Added Successfully"},
status=status.HTTP_200_OK)
except ValueError as e:
store_all_files(request)
#exception_email(data)
logger.warning("ValueError in addPlacement: " + str(e))
logger.warning(traceback.format_exc())
return Response({'action': "Add Placement", 'message': str(e)},
status=status.HTTP_400_BAD_REQUEST)
except:
store_all_files(request)
#exception_email(data)
logger.warning("Add New Placement: " + str(sys.exc_info()))
logger.warning(traceback.format_exc())
return Response({'action': "Add Placement", 'message': "Something went wrong"},
status=status.HTTP_400_BAD_REQUEST)
@api_view(['POST'])
@precheck([TOKEN])
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'])
# get email, opening_id, opening_type from token
email = decoded_token['email']
opening_id = decoded_token['opening_id']
opening_type = decoded_token['opening_type']
# get opening based on opening_type and opening_id
if opening_type == PLACEMENT:
opening = get_object_or_404(Placement, id=opening_id)
if email != opening.email:
raise ValueError("Invalid Email")
if not opening.email_verified:
opening.email_verified = True
send_email_to_company = True
else:
send_email_to_company = False
opening.save()
elif opening_type == INTERNSHIP:
opening = get_object_or_404(Internship, id=opening_id)
if email != opening.email:
raise ValueError("Invalid Email")
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.
send_email_for_opening(opening)
return Response({'action': "Verify Email", 'message': "Email Verified Successfully"},
status=status.HTTP_200_OK)
except Http404:
return Response({'action': "Verify Email", 'message': "Opening Not Found"},
status=status.HTTP_404_NOT_FOUND)
except ValueError as e:
return Response({'action': "Verify Email", 'message': str(e)},
status=status.HTTP_400_BAD_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)
@api_view(['GET'])
@precheck([PLACEMENT_ID])
def autoFillJnf(request):
try:
data = request.GET
placement_id = data.get(PLACEMENT_ID)
opening = get_object_or_404(Placement, id=placement_id)
serializer = AutofillSerializers(opening)
return Response({'action': "Get AutoFill", 'message': 'Data Found', 'placement_data': serializer.data},
status=status.HTTP_200_OK)
except Http404:
return Response({'action': "Get AutoFill", 'message': 'Placement Not Found'},
status=status.HTTP_404_NOT_FOUND)
except Exception as e:
traceback_str = traceback.format_exc()
logger.warning("Get AutoFill: " + traceback_str)
return Response({'action': "Get AutoFill", 'message': "Something went wrong"},
status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET'])
@precheck([INTERNSHIP_ID])
def autoFillInf(request):
try:
data = request.GET
internship_id = data.get(INTERNSHIP_ID)
opening = get_object_or_404(Internship, id=internship_id)
serializer = AutofillSerializersInternship(opening)
return Response({'action': "Get AutoFill ", 'message': 'Data Found', 'internship_data': serializer.data},
status=status.HTTP_200_OK)
except Http404:
return Response({'action': "Get AutoFill", 'message': 'Internship Not Found'},
status=status.HTTP_404_NOT_FOUND)
except Exception as e:
traceback_str = traceback.format_exc()
logger.warning("Get AutoFill: " + traceback_str)
return Response({'action': "Get AutoFill", 'message': "Something went wrong"},
status=status.HTTP_400_BAD_REQUEST)
## Internships ##
@api_view(['POST'])
@precheck([COMPANY_NAME, WEBSITE, IS_COMPANY_DETAILS_PDF, COMPANY_DETAILS, ADDRESS,
CITY, STATE, COUNTRY, PINCODE, COMPANY_TYPE, NATURE_OF_BUSINESS, IS_DESCRIPTION_PDF,
DESIGNATION, INTERNSHIP_LOCATION, DESCRIPTION, SEASON, START_DATE, END_DATE, WORK_TYPE,
ALLOWED_BRANCH, SOPHOMORES_ELIIGIBLE, RS_ELIGIBLE, NUM_OFFERS, IS_STIPEND_DETAILS_PDF, STIPEND,
FACILITIES, OTHER_FACILITIES, SELECTION_PROCEDURE_ROUNDS, SELECTION_PROCEDURE_DETAILS, IS_SELECTION_PROCEDURE_DETAILS_PDF,
SELECTION_PROCEDURE_DETAILS, OTHER_REQUIREMENTS,
CONTACT_PERSON_NAME, PHONE_NUMBER, EMAIL, RECAPTCHA_VALUE])
def addInternship(request):
logger.info("INF filled by " + str(request.data['email']))
logger.info(request.data)
try:
data = request.data
files = request.FILES
internship = Internship()
if not verify_recaptcha(data[RECAPTCHA_VALUE]):
raise Exception("Recaptcha Failed")
internship.id = generateRandomString()
# Add a company details in the internship
internship.company_name = data[COMPANY_NAME]
internship.website = data[WEBSITE]
if data[IS_COMPANY_DETAILS_PDF] == "true":
internship.is_company_details_pdf = True
else:
internship.is_company_details_pdf = False
if internship.is_company_details_pdf:
company_details_pdf = []
for file in files.getlist(COMPANY_DETAILS_PDF):
file_location = STORAGE_DESTINATION_COMPANY_ATTACHMENTS + internship.id + '/'
company_details_pdf.append(saveFile(file, file_location))
internship.company_details_pdf_names = company_details_pdf
internship.company_details = data[COMPANY_DETAILS]
internship.address = data[ADDRESS]
internship.city = data[CITY]
internship.state = data[STATE]
internship.country = data[COUNTRY]
if internship.country.upper() == 'INDIA':
internship.city_type = 'Domestic'
else:
internship.city_type = 'International'
internship.pin_code = data[PINCODE]
internship.company_type = data[COMPANY_TYPE]
internship.nature_of_business = data[NATURE_OF_BUSINESS]
if data[IS_DESCRIPTION_PDF] == "true":
internship.is_description_pdf = True
else:
internship.is_description_pdf = False
if internship.is_description_pdf:
description_pdf = []
for file in files.getlist(DESCRIPTION_PDF):
file_location = STORAGE_DESTINATION_COMPANY_ATTACHMENTS + internship.id + '/'
description_pdf.append(saveFile(file, file_location))
internship.description_pdf_names = description_pdf
internship.designation = data[DESIGNATION]
internship.location = data[INTERNSHIP_LOCATION]
internship.description = data[DESCRIPTION]
if data[SEASON] == "":
raise ValueError('Season cannot be empty')
elif set(json.loads(data[SEASON])).issubset(SEASONS):
internship.season = json.loads(data[SEASON])
else:
raise ValueError('Season must be a subset of ' + str(SEASONS))
internship.interning_period_from = datetime.datetime.strptime(data[START_DATE], '%d-%m-%Y').date()
internship.interning_period_to = datetime.datetime.strptime(data[END_DATE], '%d-%m-%Y').date()
if data[WORK_TYPE] == 'Work from home':
internship.is_work_from_home = True
else:
internship.is_work_from_home = False
if ALLOWED_BATCH in data and (data[ALLOWED_BATCH] is None or json.loads(data[ALLOWED_BATCH]) == ""):
raise ValueError('Allowed Batches cannot be empty')
elif ALLOWED_BATCH in data and set(json.loads(data[ALLOWED_BATCH])).issubset(BATCHES):
internship.allowed_batch = json.loads(data[ALLOWED_BATCH])
else:
internship.allowed_batch = ['2021']
if data[ALLOWED_BRANCH] is None or json.loads(data[ALLOWED_BRANCH]) == "":
raise ValueError('Allowed Branch cannot be empty')
elif set(json.loads(data[ALLOWED_BRANCH])).issubset(BRANCHES):
internship.allowed_branch = json.loads(data[ALLOWED_BRANCH])
else:
raise ValueError('Allowed Branch must be a subset of ' + str(BRANCHES))
if data[SOPHOMORES_ELIIGIBLE] == 'Yes':
internship.sophomore_eligible = True
else:
internship.sophomore_eligible = False
if data[RS_ELIGIBLE] == 'Yes':
internship.rs_eligible = True
else:
internship.rs_eligible = False
if data[NUM_OFFERS].isdigit():
internship.tentative_no_of_offers = int(data[NUM_OFFERS])
else:
raise ValueError('Number of offers must be an integer')
if data[IS_STIPEND_DETAILS_PDF] == "true":
internship.is_stipend_description_pdf = True
else:
internship.is_stipend_description_pdf = False
if internship.is_stipend_description_pdf:
stipend_details_pdf = []
for file in files.getlist(STIPEND_DETAILS_PDF):
file_location = STORAGE_DESTINATION_COMPANY_ATTACHMENTS + internship.id + '/'
stipend_details_pdf.append(saveFile(file, file_location))
internship.stipend_description_pdf_names = stipend_details_pdf
if data[STIPEND].isdigit():
internship.stipend = int(data[STIPEND])
else:
raise ValueError('Stipend must be an integer')
if data[FACILITIES] != "" :
if json.loads(data[FACILITIES]) == "":
internship.facilities_provided = []
elif set(json.loads(data[FACILITIES])).issubset(FACILITIES_CHOICES):
internship.facilities_provided = json.loads(data[FACILITIES])
else:
raise ValueError('Facilities must be a subset of ' + str(FACILITIES_CHOICES))
else:
internship.facilities_provided = []
internship.other_facilities = data[OTHER_FACILITIES]
if data[SELECTION_PROCEDURE_ROUNDS] is None:
raise ValueError('Selection Procedure Rounds cannot be empty')
else:
try:
internship.selection_procedure_rounds = json.loads(data[SELECTION_PROCEDURE_ROUNDS])
except:
raise ValueError('Selection Procedure Rounds must be a list')
internship.selection_procedure_details = data[SELECTION_PROCEDURE_DETAILS]
if data[IS_SELECTION_PROCEDURE_DETAILS_PDF] == "true":
internship.is_selection_procedure_details_pdf = True
else:
internship.is_selection_procedure_details_pdf = False
if internship.is_selection_procedure_details_pdf:
selection_procedure_details_pdf = []
for file in files.getlist(SELECTION_PROCEDURE_DETAILS_PDF):
file_location = STORAGE_DESTINATION_COMPANY_ATTACHMENTS + internship.id + '/'
selection_procedure_details_pdf.append(saveFile(file, file_location))
internship.selection_procedure_details_pdf_names = selection_procedure_details_pdf
internship.additional_facilities = data[OTHER_FACILITIES]
#add additional info
# Only Allowing Fourth Year for Placement
internship.academic_requirements = data[OTHER_REQUIREMENTS]
internship.contact_person_name = data[CONTACT_PERSON_NAME]
internship.phone_number = data[PHONE_NUMBER]
internship.email = data[EMAIL]
internship.save()
stat, link = generateOneTimeVerificationLink(internship.email, internship.id, "Internship")
if not stat:
raise RuntimeError("Error in generating one time verification link for internship")
data = {
"designation": internship.designation,
"one_time_link": link,
"opening_type": "Internship"
}
sendEmail(internship.email, COMPANY_EMAIl_VERIFICATION_TEMPLATE_SUBJECT, data,
COMPANY_EMAIL_VERIFICATION_TEMPLATE)
return Response({'action': "Add Internship", 'message': "Internship Added Successfully"},
status=status.HTTP_200_OK)
except ValueError as e:
store_all_files(request)
# exception_email(data)
logger.warning("ValueError in addInternship: " + str(e))
logger.warning(traceback.format_exc())
return Response({'action': "Add Internship", 'message': str(e)},
status=status.HTTP_400_BAD_REQUEST)
except:
store_all_files(request)
# exception_email(data)
logger.warning("Add New Internship: " + str(sys.exc_info()))
logger.warning(traceback.format_exc())
return Response({'action': "Add Internship", 'message': "Something went wrong"},
status=status.HTTP_400_BAD_REQUEST)

View File

@ -0,0 +1,269 @@
import os
DEBUG = os.environ.get('DEBUG') == "True"
BRANCH_CHOICES = [
["CSE", "CSE"],
["EE", "EE"],
["ME", "ME"],
['MMAE', 'MMAE'],
['EP', 'EP'],
['CIVIL', 'CIVIL'],
['CHEMICAL', 'CHEMICAL'],
['BSMS', 'BSMS'],
]
BRANCHES = [
"CSE",
"EE",
"MMAE",
"EP",
"CIVIL",
"CHEMICAL",
"BSMS",
]
BATCHES = [ #change it accordingly
"2023",
"2022",
"2021",
"2020",
]
BATCH_CHOICES = [
["2022", "2022"],
["2021", "2021"],
["2020", "2020"],
["2019", "2019"],
["2018", "2018"],
["2017", "2017"],
]
OFFER_CITY_TYPE = [
['Domestic', 'Domestic'],
['International', 'International']
]
TIERS = [
['psu', 'PSU'],
['1', 'Tier 1'],
['2', 'Tier 2'],
['3', 'Tier 3'],
['4', 'Tier 4'],
['5', 'Tier 5'],
['6', 'Tier 6'],
['7', 'Tier 7'],
['8', 'Open Tier'],
]
DEGREE_CHOICES = [
['bTech', 'B.Tech'],
['ms/phd', 'MS/ PhD'],
['mTech', 'M.Tech'],
]
TOTAL_BRANCHES = 7 # Total No of Branches
TOTAL_BATCHES = 6 # Total No of Batches
CDC_REPS_EMAILS = [
"cdc@iitdh.ac.in",
"cdcfic@iitdh.ac.in",
"vandana@iitdh.ac.in",
"sameerjoshi@iitdh.ac.in",
"sairam@iitdh.ac.in",
"satyapriya.gupta@iitdh.ac.in",
"dhriti.ghosh@iitdh.ac.in",
"suvamay.jana@iitdh.ac.in",
"ramesh.nayaka@iitdh.ac.in",
"210030035@iitdh.ac.in",
"210010046@iitdh.ac.in"
]
CDC_REPS_EMAILS_FOR_ISSUE=[ #add reps emails
"cdc.support@iitdh.ac.in",
"cdc@iitdh.ac.in"
]
# To be Configured Properly
CLIENT_ID = os.environ.get('GOOGLE_OAUTH_CLIENT_ID') # Google Login Client ID
CLIENT_SECRET = os.environ.get('GOOGLE_OAUTH_CLIENT_SECRET') # Google Login Client Secret
REDIRECT_URI = 'postmessage' # Google Login Redirect URI
OAUTH2_API_ENDPOINT = 'https://oauth2.googleapis.com/token' # Google Login OAUTH2 URL
# To be Configured Properly
PLACEMENT_OPENING_URL = "https://cdc.iitdh.ac.in/portal/student/dashboard/placements/{id}" # On frontend, this is the URL to be opened
LINK_TO_STORAGE_COMPANY_ATTACHMENT = "https://cdc.iitdh.ac.in/storage/Company_Attachments/"
LINK_TO_STORAGE_RESUME = "https://cdc.iitdh.ac.in/storage/Resumes/"
LINK_TO_APPLICATIONS_CSV = "https://cdc.iitdh.ac.in/storage/Application_CSV/"
LINK_TO_EMAIl_VERIFICATION_API = "https://cdc.iitdh.ac.in/portal/company/verifyEmail?token={token}"
PDF_FILES_SERVING_ENDPOINT = 'https://cdc.iitdh.ac.in/storage/Company_Attachments/' # TODO: Change this to actual URL
AUTH_CODE = "code"
ID_TOKEN = "id_token"
REFRESH_TOKEN = "refresh_token"
EMAIL = "email"
STUDENT = 'student'
ADMIN = 'admin'
SUPER_ADMIN = 's_admin'
SERVICE= 'service'
COMPANY = 'company'
TIER = 'tier'
# To be Configured Properly
FOURTH_YEAR = '2021'
MAX_OFFERS_PER_STUDENT = 2
MAX_RESUMES_PER_STUDENT = 3
EMAIL_VERIFICATION_TOKEN_TTL = 48 # in hours
JNF_TEXT_MAX_CHARACTER_COUNT = 100
JNF_TEXTMEDIUM_MAX_CHARACTER_COUNT = 200
JNF_TEXTAREA_MAX_CHARACTER_COUNT = 1000
JNF_SMALLTEXT_MAX_CHARACTER_COUNT = 50
STORAGE_DESTINATION_RESUMES = "./Storage/Resumes/"
STORAGE_DESTINATION_COMPANY_ATTACHMENTS = './Storage/Company_Attachments/'
STORAGE_DESTINATION_APPLICATION_CSV = './Storage/Application_CSV/'
TOKEN = 'token'
RESUME_FILE_NAME = 'resume_file_name'
APPLICATION_ID = "application_id"
OPENING_ID = "opening_id"
ADDITIONAL_INFO = "additional_info"
FIELD = "field"
STATUS_ACCEPTING_APPLICATIONS = "Accepting Applications"
PLACEMENT = "Placement"
PLACEMENT_ID = "placement_id"
COMPANY_NAME = "company_name"
COMPANY_TYPE = "company_type"
NATURE_OF_BUSINESS = "nature_of_business"
TYPE_OF_ORGANISATION = "type_of_organisation"
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'
ADDRESS = "address"
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'
JOB_LOCATION = 'job_location'
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'
RS_ELIGIBLE = 'rs_eligible'
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'
RECAPTCHA_VALUE = 'recaptchakey'
STUDENT_LIST = "student_list"
STUDENT_ID = "student_id"
STUDENT_SELECTED = "student_selected"
EXCLUDE_IN_PDF = ['id', 'is_company_details_pdf', 'offer_accepted', 'is_description_pdf',
'is_compensation_details_pdf', 'is_selection_procedure_details_pdf',
'email_verified', 'created_at', 'changed_by', 'is_stipend_description_pdf']
SPECIAL_FORMAT_IN_PDF = ['website', 'company_details_pdf_names', 'description_pdf_names',
'compensation_details_pdf_names',
'selection_procedure_details_pdf_names',
'stipend_description_pdf_names']
COMPANY_OPENING_ERROR_TEMPLATE = "Alert! Error submitting opening for {company_name}."
COMPANY_OPENING_SUBMITTED_TEMPLATE_SUBJECT = "Notification Submitted - {id}, {company} - Career Development Cell, IIT Dharwad"
STUDENT_APPLICATION_STATUS_TEMPLATE_SUBJECT = 'Application Status - {company_name} - {id}'
STUDENT_APPLICATION_SUBMITTED_TEMPLATE_SUBJECT = 'CDC - Application Submitted - {company_name}'
STUDENT_APPLICATION_UPDATED_TEMPLATE_SUBJECT = 'CDC - Application Updated - {company_name}'
COMPANY_EMAIl_VERIFICATION_TEMPLATE_SUBJECT = 'Email Verification - Career Development Cell, IIT Dharwad'
NOTIFY_STUDENTS_OPENING_TEMPLATE_SUBJECT = 'Placement Opportunity at {company_name}'
REMINDER_STUDENTS_OPENING_TEMPLATE_SUBJECT = 'Reminder - Placement Opportunity at {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'
STUDENT_APPLICATION_UPDATED_TEMPLATE = 'student_application_updated.html'
COMPANY_EMAIL_VERIFICATION_TEMPLATE = 'company_email_verification.html'
COMPANY_JNF_RESPONSE_TEMPLATE = 'company_jnf_response.html'
NOTIFY_STUDENTS_OPENING_TEMPLATE = 'notify_students_new_opening.html'
REMINDER_STUDENTS_OPENING_TEMPLATE = 'students_opening_reminder.html'
APPLICATION_CSV_COL_NAMES = ['Applied At', 'Roll No.', 'Name', 'Email', 'Phone Number', 'Branch', 'Batch', 'CPI',
'Resume', 'Selected', ]
ISSUE_SUBMITTED_TEMPLATE_SUBJECT = 'CDC - Issue Submitted'
STUDENT_ISSUE_SUBMITTED_TEMPLATE = 'student_issue_submitted.html'
REPS_ISSUE_SUBMITTED_TEMPLATE = 'reps_issue_submitted.html'
# Internships
INTERNSHIP = 'Internship'
INTERNSHIP_ID = 'internship_id'
INF_COMPANY_NAME = 'companyname'
INTERNSHIP_LOCATION = 'internship_location'
SEASON = 'season'
START_DATE = 'start_date'
END_DATE = 'end_date'
WORK_TYPE = 'work_type'
SOPHOMORES_ELIIGIBLE = 'sophomores_allowed'
NUM_OFFERS = 'num_offers'
IS_STIPEND_DETAILS_PDF = 'is_stipend_details_pdf'
STIPEND = 'stipend'
FACILITIES = 'facilities'
OTHER_FACILITIES = 'other_facilities'
STIPEND_DETAILS_PDF = 'compensation_details_pdf'
STIPEND_DETAILS_PDF_NAMES = 'stipend_description_pdf_names'
INTERNSHIP_OPENING_URL = "https://cdc.iitdh.ac.in/portal/student/dashboard/internships/{id}" # On frontend, this is the URL to be opened
SEASONS = (
'Summer',
'Winter',
'Autumn',
'Spring',
)
SEASON_CHOICES = (
['Summer', 'Summer'],
['Winter', 'Winter'],
['Autumn', 'Autumn'],
['Spring', 'Spring'],
)
FACILITIES_CHOICES = [
'Accommodation',
'Food',
'Transport',
'Medical',
]
INF_FACILITIES_PROVIDED = [
['Accommodation', 'Accommodation'],
['Food', 'Food'],
['Transport', 'Transport'],
['Medical', 'Medical'],
]
INF_TOTAL_SEASONS = len(SEASONS)
INF_TOTAL_FACILITIES = len(FACILITIES_CHOICES)

63
CDC_Backend/APIs/cron.py Normal file
View File

@ -0,0 +1,63 @@
from .models import *
from .utils import *
import shutil
import logging
import traceback
logger=logging.getLogger('db')
def clean_up_tests():
# Delete all the test internships and placements created
try:
internships= Internship.objects.filter(company_name="test company",email="notifications@cdc-iitdh.tech")
hits_internship=len(internships)
for internship in internships:
#count number of file
files = os.listdir(STORAGE_DESTINATION_COMPANY_ATTACHMENTS+internship.id)
if len(files) == 4:
print("working fine")
else:
print("not working fine")
logger.error("files submitted in inf are not getting stored for test case"+internship.description)
#remove folder from the server
print("removing folder ",STORAGE_DESTINATION_COMPANY_ATTACHMENTS+internship.id)
shutil.rmtree(STORAGE_DESTINATION_COMPANY_ATTACHMENTS+internship.id)
internship.delete()
placements= Placement.objects.filter(company_name="test company",email="notifications@cdc-iitdh.tech")
hits_placement=len(placements)
for placement in placements:
#count number of file
files = os.listdir(STORAGE_DESTINATION_COMPANY_ATTACHMENTS+placement.id)
if len(files) == 4:
print("working fine")
else:
print("not working fine")
logger.error("files submitted in inf are not getting stored for test case"+placement.description)
#remove folder from the server
print("removing folder ",STORAGE_DESTINATION_COMPANY_ATTACHMENTS+internship.id)
shutil.rmtree(STORAGE_DESTINATION_COMPANY_ATTACHMENTS+placement.id)
placement.delete()
if hits_internship >= 6:
print("all hits are working fine")
else:
print("some hits are not working fine")
logger.error("some test hits are not working fine for internship")
if hits_placement >= 6:
print("all hits are working fine")
else:
print("some hits are not working fine")
logger.error("some test hits are not working fine for placement")
except :
logger.error("error in clean up function")
logger.error(traceback.format_exc())

511
CDC_Backend/APIs/models.py Normal file
View File

@ -0,0 +1,511 @@
from django.contrib.postgres.fields import ArrayField
from django.db import models
from django.utils import timezone
from simple_history.models import HistoricalRecords
from .constants import *
# from .utils import *
class User(models.Model):
email = models.EmailField(primary_key=True, blank=False, max_length=JNF_TEXT_MAX_CHARACTER_COUNT)
id = models.CharField(blank=False, max_length=25, db_index=True)
user_type = ArrayField(models.CharField(blank=False, max_length=10), size=4, default=list, blank=False)
last_login_time = models.DateTimeField(default=timezone.now)
history = HistoricalRecords()
class Meta:
verbose_name_plural = "User"
unique_together = ('email', 'id')
class Student(models.Model):
id = models.CharField(blank=False, max_length=15, primary_key=True)
roll_no = models.CharField(blank=False, max_length=15, unique=True)
name = models.CharField(blank=False, max_length=JNF_TEXT_MAX_CHARACTER_COUNT)
batch = models.CharField(max_length=10, choices=BATCH_CHOICES, blank=False)
branch = models.CharField(choices=BRANCH_CHOICES, blank=False, max_length=10)
phone_number = models.PositiveBigIntegerField(blank=True, default=None, null=True)
resumes = ArrayField(models.CharField(null=True, default=None, max_length=JNF_TEXT_MAX_CHARACTER_COUNT), size=10,
default=list, blank=True)
cpi = models.DecimalField(decimal_places=2, max_digits=4)
can_apply = models.BooleanField(default=True, verbose_name='Registered')
can_apply_internship = models.BooleanField(default=True, verbose_name='Internship Registered') #added for internship
changed_by = models.ForeignKey(User, blank=True, on_delete=models.RESTRICT, default=None, null=True)
degree = models.CharField(choices=DEGREE_CHOICES, blank=False, max_length=10, default=DEGREE_CHOICES[0][0])
history = HistoricalRecords(user_model=User)
def __str__(self):
return str(self.roll_no)
@property
def _history_user(self):
return self.changed_by
@_history_user.setter
def _history_user(self, value):
if isinstance(value, User):
self.changed_by = value
else:
self.changed_by = None
class Admin(models.Model):
id = models.CharField(blank=False, max_length=15, primary_key=True)
name = models.CharField(blank=False, max_length=JNF_TEXT_MAX_CHARACTER_COUNT)
changed_by = models.ForeignKey(User, blank=True, on_delete=models.RESTRICT, default=None, null=True)
history = HistoricalRecords(user_model=User)
@property
def _history_user(self):
return self.changed_by
@_history_user.setter
def _history_user(self, value):
if isinstance(value, User):
self.changed_by = value
else:
self.changed_by = None
def two_day_after_today():
# round off to nearest day
return timezone.now().replace(hour=0, minute=0, second=0, microsecond=0) + timezone.timedelta(days=2)
class Placement(models.Model):
id = models.CharField(blank=False, primary_key=True, max_length=15)
# Company Details
company_name = models.CharField(blank=False, max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT)
address = models.CharField(blank=False, max_length=JNF_TEXTAREA_MAX_CHARACTER_COUNT)
company_type = models.CharField(blank=False, max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT)
nature_of_business = models.CharField(blank=False, max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, default="")
type_of_organisation = models.CharField(max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, default="", blank=False)
website = models.CharField(blank=True, max_length=JNF_TEXT_MAX_CHARACTER_COUNT)
company_details = models.CharField(max_length=JNF_TEXTAREA_MAX_CHARACTER_COUNT, default=None, null=True, blank=True)
company_details_pdf_names = ArrayField(
models.CharField(null=True, default=None, max_length=JNF_TEXT_MAX_CHARACTER_COUNT), 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=JNF_TEXT_MAX_CHARACTER_COUNT)
phone_number = models.PositiveBigIntegerField(blank=False)
email = models.CharField(blank=False, max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, default="")
city = models.CharField(blank=False, max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, default="")
state = models.CharField(blank=False, max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, default="")
country = models.CharField(blank=False, max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, default="")
pin_code = models.IntegerField(blank=False, default=None, null=True)
city_type = models.CharField(blank=False, max_length=15, choices=OFFER_CITY_TYPE)
# Job Details
designation = models.CharField(blank=False, max_length=JNF_TEXT_MAX_CHARACTER_COUNT, default=None, null=True)
description = models.CharField(blank=False, max_length=JNF_TEXTAREA_MAX_CHARACTER_COUNT, default=None, null=True)
job_location = models.CharField(blank=False, max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, default="")
description_pdf_names = ArrayField(
models.CharField(null=True, default=None, max_length=JNF_TEXT_MAX_CHARACTER_COUNT), 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_pdf_names = ArrayField(
models.CharField(null=True, default=None, max_length=JNF_TEXT_MAX_CHARACTER_COUNT), size=5,
default=list, blank=True)
is_compensation_details_pdf = models.BooleanField(blank=False, default=False)
bond_details = models.CharField(blank=True, max_length=JNF_TEXTAREA_MAX_CHARACTER_COUNT)
selection_procedure_rounds = ArrayField(
models.CharField(null=True, default=None, max_length=JNF_TEXT_MAX_CHARACTER_COUNT), size=10,
default=list, blank=True)
selection_procedure_details = models.CharField(blank=True, max_length=JNF_TEXTAREA_MAX_CHARACTER_COUNT)
selection_procedure_details_pdf_names = ArrayField(
models.CharField(null=True, default=None, max_length=JNF_TEXT_MAX_CHARACTER_COUNT),
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
)
tentative_no_of_offers = models.IntegerField(blank=False, default=None, null=True)
rs_eligible = models.BooleanField(blank=False, default=False)
other_requirements = models.CharField(blank=True, max_length=JNF_TEXTAREA_MAX_CHARACTER_COUNT, default="")
additional_info = ArrayField(models.CharField(blank=True, max_length=JNF_TEXTMEDIUM_MAX_CHARACTER_COUNT), 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)
updated_at = models.DateTimeField(blank=False, default=None, null=True)
changed_by = models.ForeignKey(User, on_delete=models.RESTRICT, blank=True, null=True)
history = HistoricalRecords(user_model=User)
def format(self):
if self.company_name is not None:
self.company_name = self.company_name.strip()[:JNF_SMALLTEXT_MAX_CHARACTER_COUNT]
if self.company_type is not None:
self.company_type = self.company_type.strip()[:JNF_SMALLTEXT_MAX_CHARACTER_COUNT]
if self.company_details is not None:
self.company_details = self.company_details.strip()[:JNF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.address is not None:
self.address = self.address.strip()[:JNF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.nature_of_business is not None:
self.nature_of_business = self.nature_of_business.strip()[:JNF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.type_of_organisation is not None:
self.type_of_organisation = self.type_of_organisation.strip()[:JNF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.website is not None:
self.website = self.website.strip()[:JNF_TEXT_MAX_CHARACTER_COUNT]
if self.contact_person_name is not None:
self.contact_person_name = self.contact_person_name.strip()[:JNF_TEXT_MAX_CHARACTER_COUNT]
if self.email is not None:
self.email = self.email.strip()[:JNF_SMALLTEXT_MAX_CHARACTER_COUNT]
if self.city is not None:
self.city = self.city.strip()[:JNF_SMALLTEXT_MAX_CHARACTER_COUNT]
if self.state is not None:
self.state = self.state.strip()[:JNF_SMALLTEXT_MAX_CHARACTER_COUNT]
if self.country is not None:
self.country = self.country.strip()[:JNF_SMALLTEXT_MAX_CHARACTER_COUNT]
if self.city_type is not None:
self.city_type = self.city_type.strip()[:JNF_SMALLTEXT_MAX_CHARACTER_COUNT]
if self.designation is not None:
self.designation = self.designation.strip()[:JNF_TEXT_MAX_CHARACTER_COUNT]
if self.description is not None:
self.description = self.description.strip()[:JNF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.job_location is not None:
self.job_location = self.job_location.strip()[:JNF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.selection_procedure_details is not None:
self.selection_procedure_details = self.selection_procedure_details.strip()[
:JNF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.bond_details is not None:
self.bond_details = self.bond_details.strip()[:JNF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.other_requirements is not None:
self.other_requirements = self.other_requirements.strip()[:JNF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.additional_info is not None:
self.additional_info = [info.strip()[:JNF_TEXTMEDIUM_MAX_CHARACTER_COUNT] for info in
list(self.additional_info)]
@property
def _history_user(self):
return self.changed_by
@_history_user.setter
def _history_user(self, value):
if isinstance(value, User):
self.changed_by = value
else:
self.changed_by = None
def save(self, *args, **kwargs):
''' On save, add timestamps '''
if not self.created_at:
self.created_at = timezone.now()
self.format()
self.updated_at = timezone.now()
return super(Placement, self).save(*args, **kwargs)
def __str__(self):
return self.company_name + " - " + self.designation
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=JNF_TEXT_MAX_CHARACTER_COUNT, blank=False, null=True, default=None)
additional_info = models.JSONField(blank=True, null=True, default=None)
selected = models.BooleanField(null=True, default=None, blank=True)
offer_accepted = models.BooleanField(null=True, default=None, blank=True) # True if offer accepted, False if rejected, None if not yet decided
applied_at = models.DateTimeField(blank=False, default=None, null=True)
updated_at = models.DateTimeField(blank=False, default=None, null=True)
changed_by = models.ForeignKey(User, blank=False, on_delete=models.RESTRICT, default=None, null=True)
history = HistoricalRecords(user_model=User)
def save(self, *args, **kwargs):
''' On save, add timestamps '''
if not self.applied_at:
self.applied_at = timezone.now()
self.updated_at = timezone.now()
return super(PlacementApplication, self).save(*args, **kwargs)
@property
def _history_user(self):
return self.changed_by
@_history_user.setter
def _history_user(self, value):
if isinstance(value, User):
self.changed_by = value
else:
self.changed_by = None
class Meta:
verbose_name_plural = "Placement Applications"
unique_together = ('placement_id', 'student_id')
def __str__(self):
return self.placement.company_name + " - " + self.student.name
class PrePlacementOffer(models.Model):
id = models.AutoField(primary_key=True)
student = models.ForeignKey(Student, on_delete=models.CASCADE, blank=False)
company = models.CharField(max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, blank=False, default="",
verbose_name="Company Name")
compensation = models.IntegerField(blank=False) # Job - Per Year
compensation_details = models.CharField(blank=True, max_length=200)
tier = models.CharField(blank=False, choices=TIERS, max_length=10)
designation = models.CharField(blank=False, max_length=100, default=None, null=True)
accepted = models.BooleanField(default=None, null=True)
changed_by = models.ForeignKey(User, blank=False, on_delete=models.RESTRICT, default=None, null=True)
history = HistoricalRecords(user_model=User)
@property
def _history_user(self):
return self.changed_by
@_history_user.setter
def _history_user(self, value):
if isinstance(value, User):
self.changed_by = value
else:
self.changed_by = None
class Internship(models.Model):
id = models.CharField(blank=False, primary_key=True, max_length=15) #unique id for each internship
# Company Details
company_name = models.CharField(blank=False, max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT)
website = models.CharField(blank=True, max_length=JNF_TEXT_MAX_CHARACTER_COUNT)
is_company_details_pdf = models.BooleanField(blank=False, default=False)
company_details_pdf_names = ArrayField(
models.CharField(null=True, default=None, max_length=JNF_TEXT_MAX_CHARACTER_COUNT), size=5,
default=list, blank=True)
company_details = models.CharField(max_length=JNF_TEXTAREA_MAX_CHARACTER_COUNT, default=None, null=True, blank=True)
#Company Address
address = models.CharField(blank=False, max_length=JNF_TEXTAREA_MAX_CHARACTER_COUNT)
city = models.CharField(blank=False, max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, default="")
city_type = models.CharField(blank=True, max_length=15, choices=OFFER_CITY_TYPE)
state = models.CharField(blank=False, max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, default="")
country = models.CharField(blank=False, max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, default="")
pin_code = models.IntegerField(blank=False, default=None, null=True)
company_type = models.CharField(blank=False, max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT)
nature_of_business = models.CharField(blank=False, max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, default="")
#Internship Details
is_description_pdf = models.BooleanField(blank=False, default=False)
description_pdf_names = ArrayField(
models.CharField(null=True, default=None, max_length=JNF_TEXT_MAX_CHARACTER_COUNT), size=5, default=list,
blank=True)
designation = models.CharField(blank=False, max_length=JNF_TEXT_MAX_CHARACTER_COUNT, default="")
description = models.CharField(blank=False, max_length=JNF_TEXTAREA_MAX_CHARACTER_COUNT, default=None, null=True)
location = models.CharField(blank=False, max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, default="")
season = ArrayField(
models.CharField(choices=SEASON_CHOICES, max_length=10, blank=False),
size=INF_TOTAL_SEASONS,
default=list
)
interning_period_from = models.DateField(blank=False, default=None, null=True)
interning_period_to = models.DateField(blank=False, default=None, null=True)
is_work_from_home = models.BooleanField(blank=False, default=False)
allowed_branch = ArrayField(
models.CharField(choices=BRANCH_CHOICES, blank=False, max_length=10),
size=TOTAL_BRANCHES,
default=list
)
allowed_batch = ArrayField(
models.CharField(max_length=10, choices=BATCH_CHOICES),
size=TOTAL_BATCHES,
default=list
)
sophomore_eligible = models.BooleanField(blank=False, default=False)
rs_eligible = models.BooleanField(blank=False, default=False)
tentative_no_of_offers = models.IntegerField(blank=False, default=None, null=True)
is_stipend_description_pdf = models.BooleanField(blank=False, default=False)
stipend_description_pdf_names=ArrayField(
models.CharField(null=True, default=None, max_length=JNF_TEXT_MAX_CHARACTER_COUNT), size=5, default=list,
blank=True)
stipend=models.IntegerField(blank=False, default=None, null=True)
facilities_provided=ArrayField(
models.CharField(null=True, choices=INF_FACILITIES_PROVIDED, max_length=20),
size=INF_TOTAL_FACILITIES,
default=list,
blank=True
)
additional_info = ArrayField(models.CharField(blank=True, max_length=JNF_TEXTMEDIUM_MAX_CHARACTER_COUNT), size=15,
default=list, blank=True)
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)
additional_facilities = models.CharField(blank=True, max_length=JNF_TEXTAREA_MAX_CHARACTER_COUNT, default=None, null=True)
academic_requirements = models.CharField(blank=True, max_length=JNF_TEXTAREA_MAX_CHARACTER_COUNT, default=None, null=True)
# selection process
selection_procedure_rounds = ArrayField(
models.CharField(null=True, default=None, max_length=JNF_TEXT_MAX_CHARACTER_COUNT), size=10,
default=list, blank=True)
selection_procedure_details = models.CharField(blank=True, max_length=JNF_TEXTAREA_MAX_CHARACTER_COUNT)
selection_procedure_details_pdf_names = ArrayField(
models.CharField(null=True, default=None, max_length=JNF_TEXT_MAX_CHARACTER_COUNT),
size=5, default=list, blank=True)
is_selection_procedure_details_pdf = models.BooleanField(blank=False, default=False)
#contact details of company person
contact_person_name = models.CharField(blank=False, max_length=JNF_TEXT_MAX_CHARACTER_COUNT)
phone_number = models.PositiveBigIntegerField(blank=False)
email = models.EmailField(blank=False)
# contact_person_designation = models.CharField(blank=False, max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, default="")
# telephone_number = models.PositiveBigIntegerField(blank=True, default=None, null=True)
email_verified = models.BooleanField(blank=False, default=False)
#history
created_at = models.DateTimeField(blank=False, default=None, null=True)
updated_at = models.DateTimeField(blank=False, default=None, null=True)
changed_by = models.ForeignKey(User, on_delete=models.RESTRICT, blank=True, null=True)
history = HistoricalRecords(user_model=User)
def format(self):
if self.company_name is not None:
self.company_name = self.company_name.strip()[:JNF_SMALLTEXT_MAX_CHARACTER_COUNT]
if self.company_type is not None:
self.company_type = self.company_type.strip()[:JNF_SMALLTEXT_MAX_CHARACTER_COUNT]
if self.company_details is not None:
self.company_details = self.company_details.strip()[:JNF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.address is not None:
self.address = self.address.strip()[:JNF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.nature_of_business is not None:
self.nature_of_business = self.nature_of_business.strip()[:JNF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.website is not None:
self.website = self.website.strip()[:JNF_TEXT_MAX_CHARACTER_COUNT]
if self.contact_person_name is not None:
self.contact_person_name = self.contact_person_name.strip()[:JNF_TEXT_MAX_CHARACTER_COUNT]
if self.city is not None:
self.city = self.city.strip()[:JNF_SMALLTEXT_MAX_CHARACTER_COUNT]
if self.state is not None:
self.state = self.state.strip()[:JNF_SMALLTEXT_MAX_CHARACTER_COUNT]
if self.country is not None:
self.country = self.country.strip()[:JNF_SMALLTEXT_MAX_CHARACTER_COUNT]
if self.city_type is not None:
self.city_type = self.city_type.strip()[:JNF_SMALLTEXT_MAX_CHARACTER_COUNT]
if self.selection_procedure_details is not None:
self.selection_procedure_details = self.selection_procedure_details.strip()[:JNF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.description is not None:
self.description = self.description.strip()[:JNF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.additional_facilities is not None:
self.additional_facilities = self.additional_facilities.strip()[:JNF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.academic_requirements is not None:
self.academic_requirements = self.academic_requirements.strip()[:JNF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.additional_info is not None:
self.additional_info = [info.strip()[:JNF_TEXTMEDIUM_MAX_CHARACTER_COUNT] for info in
list(self.additional_info)]
# if self.contact_person_designation is not None:
# self.contact_person_designation = self.contact_person_designation.strip()[:JNF_SMALLTEXT_MAX_CHARACTER_COUNT]
@property
def _history_user(self):
return self.changed_by
@_history_user.setter
def _history_user(self, value):
if isinstance(value, User):
self.changed_by = value
else:
self.changed_by = None
def save(self, *args, **kwargs):
''' On save, add timestamps '''
if not self.created_at:
self.created_at = timezone.now()
self.format()
self.updated_at = timezone.now()
return super(Internship, self).save(*args, **kwargs)
def __str__(self):
return self.company_name + " - " + self.designation
class InternshipApplication(models.Model):
id = models.CharField(blank=False, primary_key=True, max_length=15)
internship = models.ForeignKey(Internship, 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=JNF_TEXT_MAX_CHARACTER_COUNT, blank=False, null=True, default=None)
additional_info = models.JSONField(blank=True, null=True, default=None)
selected = models.BooleanField(null=True, default=None, blank=True)
offer_accepted = models.BooleanField(null=True, default=None, blank=True) # True if offer accepted, False if rejected, None if not yet decided
stipend = models.IntegerField(blank=True, default=None, null=True)
applied_at = models.DateTimeField(blank=False, default=None, null=True)
updated_at = models.DateTimeField(blank=False, default=None, null=True)
changed_by = models.ForeignKey(User, blank=False, on_delete=models.RESTRICT, default=None, null=True)
history = HistoricalRecords(user_model=User)
def save(self, *args, **kwargs):
''' On save, add timestamps '''
if not self.applied_at:
self.applied_at = timezone.now()
self.updated_at = timezone.now()
return super(InternshipApplication, self).save(*args, **kwargs)
@property
def _history_user(self):
return self.changed_by
@_history_user.setter
def _history_user(self, value):
if isinstance(value, User):
self.changed_by = value
else:
self.changed_by = None
class Meta:
verbose_name_plural = "Internship Applications"
unique_together = ('internship_id', 'student_id')
def __str__(self):
return self.internship.company_name + " - " + self.student.name
class Contributor(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, blank=False, default="")
email = models.EmailField(max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, blank=False, default="", unique=True)
github_id = models.CharField(max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, blank=False, default="", unique=True)
linkedin = models.CharField(max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, unique=True, null=True)
commits = models.IntegerField(blank=False, default=0)
image = models.CharField(max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, blank=False, default="", null=True)
def __str__(self):
return self.name
class Issues(models.Model):
id = models.AutoField(primary_key=True)
title = models.CharField(max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, blank=False, default="")
description = models.CharField(max_length=200, blank=False, default="")
#opening=(models.ForeignKey(Placement, on_delete=models.CASCADE, blank=False) or models.ForeignKey(Internship, on_delete=models.CASCADE, blank=False))
opening_id=models.CharField(blank=False, max_length=15, default=None, null=True)
opening_type=models.CharField(choices=[('Placement','Placement'),('Internship','Internship')], blank=False, max_length=15, default=PLACEMENT)
#status = models.CharField(max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, blank=False, default="")
student=models.ForeignKey(Student, on_delete=models.CASCADE, blank=False)
created_at = models.DateTimeField(blank=False, default=None, null=True)
updated_at = models.DateTimeField(blank=False, default=None, null=True)
changed_by = models.ForeignKey(User, on_delete=models.RESTRICT, blank=True, null=True)
history = HistoricalRecords(user_model=User)
def save(self, *args, **kwargs):
''' On save, add timestamps '''
if not self.created_at:
self.created_at = timezone.now()
self.updated_at = timezone.now()
return super(Issues, self).save(*args, **kwargs)
def __str__(self):
return self.title + " - " + self.student.name
class Meta:
verbose_name_plural = "Issues"

View File

@ -0,0 +1,339 @@
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(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)
pre_placement_offers = PrePlacementOffer.objects.filter(student_id=obj.id)
companies = []
for i in selected_companies:
ele = {}
ele['designation'] = i.placement.designation
ele['company_name'] = i.placement.company_name
ele['application_id'] = i.id
ele['placement_offer_type'] = 'Normal'
companies.append(ele)
for i in pre_placement_offers:
ele = {}
ele['designation'] = i.designation
ele['company_name'] = i.company
ele['application_id'] = i.id
ele['placement_offer_type'] = 'PPO'
companies.append(ele)
return companies
class Meta:
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 = []
for pdf_name in obj.company_details_pdf_names:
ele = {}
link = LINK_TO_STORAGE_COMPANY_ATTACHMENT + urllib.parse.quote(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(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(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(obj.id + "/" + pdf_name)
ele['link'] = link
ele['name'] = pdf_name
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,
]
depth = 1
class InternshipSerializerForStudent(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(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(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.stipend_description_pdf_names:
ele = {}
link = LINK_TO_STORAGE_COMPANY_ATTACHMENT + urllib.parse.quote(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(obj.id + "/" + pdf_name)
ele['link'] = link
ele['name'] = pdf_name
links.append(ele)
return links
class Meta:
model = Internship
exclude = [CONTACT_PERSON_NAME, PHONE_NUMBER, EMAIL, COMPANY_DETAILS_PDF_NAMES, DESCRIPTION_PDF_NAMES,
STIPEND_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(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(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(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(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 InternshipSerializerForAdmin(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(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(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.stipend_description_pdf_names:
ele = {}
link = LINK_TO_STORAGE_COMPANY_ATTACHMENT + urllib.parse.quote(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(obj.id + "/" + pdf_name)
ele['link'] = link
ele['name'] = pdf_name
links.append(ele)
return links
class Meta:
model = Internship
exclude = [COMPANY_DETAILS_PDF_NAMES, DESCRIPTION_PDF_NAMES, SELECTION_PROCEDURE_DETAILS_PDF_NAMES,
STIPEND_DETAILS_PDF_NAMES]
depth = 1
class PlacementApplicationSerializer(serializers.ModelSerializer):
placement = serializers.SerializerMethodField()
resume_link = serializers.SerializerMethodField()
def get_placement(self, obj):
data = PlacementSerializerForStudent(obj.placement).data
return data
def get_resume_link(self, obj):
ele = {'link': LINK_TO_STORAGE_RESUME + urllib.parse.quote(str(obj.student.roll_no) + "/" + obj.resume), 'name': obj.resume}
return ele
class Meta:
model = PlacementApplication
exclude = [STUDENT, 'resume']
class InternshipApplicationSerializer(serializers.ModelSerializer):
internship = serializers.SerializerMethodField()
resume_link = serializers.SerializerMethodField()
def get_internship(self, obj):
data = InternshipSerializerForStudent(obj.internship).data
return data
def get_resume_link(self, obj):
ele = {'link': LINK_TO_STORAGE_RESUME + urllib.parse.quote(str(obj.student.roll_no) + "/" + obj.resume), 'name': obj.resume}
return ele
class Meta:
model = InternshipApplication
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):
ele = {'link': LINK_TO_STORAGE_RESUME + urllib.parse.quote(obj.id + "/" + obj.resume), 'name': obj.resume}
return ele
class Meta:
model = PlacementApplication
exclude = ['placement', 'resume']
class InternshipApplicationSerializerForAdmin(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):
ele = {'link': LINK_TO_STORAGE_RESUME + urllib.parse.quote(obj.id + "/" + obj.resume), 'name': obj.resume}
return ele
class Meta:
model = InternshipApplication
exclude = ['internship', 'resume']
class ContributorSerializer(serializers.ModelSerializer):
class Meta:
model = Contributor
class AutofillSerializers(serializers.ModelSerializer):
class Meta:
model = Placement
fields = '__all__'
class AutofillSerializersInternship(serializers.ModelSerializer):
class Meta:
model = Internship
fields = '__all__'

View File

@ -0,0 +1,16 @@
from django.urls import path
from . import studentViews
urlpatterns = [
path('login/', studentViews.login, name="Login"),
path('profile/', studentViews.studentProfile, name="Student Profile"),
path('getDashboard/', studentViews.getDashboard, name="Dashboard"),
path("addResume/", studentViews.addResume, name="Upload Resume"),
path("deleteResume/", studentViews.deleteResume, name="Delete Resume"),
path("submitApplication/", studentViews.submitApplication, name="Add Application"),
path("deleteApplication/", studentViews.deleteApplication, name="Delete Application"),
path("getContributorStats/", studentViews.getContributorStats, name="Get Contributor Stats"),
path("studentAcceptOffer/", studentViews.studentAcceptOffer, name="Student Accept Offer"),
path("addIssue/",studentViews.addIssue,name= "Add Issue")
]

View File

@ -0,0 +1,407 @@
from rest_framework.decorators import api_view
from .serializers import *
from .utils import *
logger = logging.getLogger('db')
@api_view(['POST'])
@precheck(required_data=[AUTH_CODE])
@get_token()
@isAuthorized(allowed_users='*')
def login(request, id, email, user_type, token, refresh_token):
try:
return Response({'action': "Login", 'message': "Verified", "user_type": user_type, "id_token": token, "refresh_token": refresh_token},
status=status.HTTP_200_OK)
except:
return Response({'action': "Login", 'message': "Something Went Wrong"},
status=status.HTTP_400_BAD_REQUEST)
@api_view(['POST'])
@precheck(required_data=[REFRESH_TOKEN])
def refresh(request):
refresh_token = request.data[REFRESH_TOKEN]
data = {
'refresh_token': refresh_token,
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET,
'redirect_uri': REDIRECT_URI,
'grant_type': 'refresh_token'
}
response = rq.post(OAUTH2_API_ENDPOINT, data=data)
if response.status_code == 200:
id_info = id_token.verify_oauth2_token(response.json()['id_token'], requests.Request(), CLIENT_ID)
if id_info['iss'] not in ['accounts.google.com', 'https://accounts.google.com']:
raise ValueError('Wrong issuer.')
user_types = User.objects.filter(email=id_info['email']).values_list('user_type', flat=True)
return Response({'action': "Refresh Token", 'message': "Token Refreshed", "id_token": response.json()['id_token'], "user_type": user_types[0]},
status=status.HTTP_200_OK)
else:
logger.error("refresh_token"+str(response))
return Response({'action': "Refresh Token", 'message': "Something Went Wrong"},
status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET'])
@isAuthorized(allowed_users=[STUDENT])
def studentProfile(request, id, email, user_type):
try:
#print(id)
studentDetails = get_object_or_404(Student, id=id)
data = StudentSerializer(studentDetails).data
return Response({'action': "Student Profile", 'message': "Details Found", "details": data},
status=status.HTTP_200_OK)
except:
logger.warning("Student Profile: " + str(sys.exc_info()))
return Response({'action': "Student Profile", 'message': "Something Went Wrong"},
status=status.HTTP_400_BAD_REQUEST)
@api_view(['POST'])
@isAuthorized(allowed_users=[STUDENT])
def addResume(request, id, email, user_type):
destination_path = ""
try:
student = get_object_or_404(Student, id=id)
files = request.FILES
if len(student.resumes) >= MAX_RESUMES_PER_STUDENT:
raise PermissionError('Max Number of Resumes limit reached')
file = files['file']
destination_path = STORAGE_DESTINATION_RESUMES + str(student.roll_no) + "/"
file_name = saveFile(file, destination_path)
student.resumes.append(file_name)
student.changed_by = get_object_or_404(User, id=id)
student.save()
return Response({'action': "Upload Resume", 'message': "Resume Added"},
status=status.HTTP_200_OK)
except Http404:
return Response({'action': "Upload Resume", 'message': 'Student Not Found'},
status=status.HTTP_404_NOT_FOUND)
except PermissionError:
return Response({'action': "Upload Resume", 'message': 'Max Number of Resumes limit reached'},
status=status.HTTP_400_BAD_REQUEST)
except:
if path.exists(destination_path):
logger.error("Upload Resume: Error in Saving Resume")
remove(destination_path)
else:
logger.warning("Upload Resume: " + str(sys.exc_info()))
return Response({'action': "Upload Resume", 'message': "Something Went Wrong"},
status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET'])
@isAuthorized(allowed_users=[STUDENT])
def getDashboard(request, id, email, user_type):
try:
studentDetails = get_object_or_404(Student, id=id)
placements = Placement.objects.filter(allowed_batch__contains=[studentDetails.batch],
allowed_branch__contains=[studentDetails.branch],
deadline_datetime__gte=datetime.datetime.now(),
offer_accepted=True, email_verified=True).order_by('deadline_datetime')
filtered_placements = placement_eligibility_filters(studentDetails, placements)
placementsdata = PlacementSerializerForStudent(filtered_placements, many=True).data
placementApplications = PlacementApplication.objects.filter(student_id=id).order_by('-updated_at')
placementApplications = PlacementApplicationSerializer(placementApplications, many=True).data
internships = Internship.objects.filter(allowed_batch__contains=[studentDetails.batch],
allowed_branch__contains=[studentDetails.branch],
deadline_datetime__gte=datetime.datetime.now(),
offer_accepted=True, email_verified=True).order_by('deadline_datetime')
filtered_internships = internship_eligibility_filters(studentDetails, internships)
internshipsdata = InternshipSerializerForStudent(filtered_internships, many=True).data
internshipApplications = InternshipApplication.objects.filter(student_id=id).order_by('-updated_at')
internshipApplications = InternshipApplicationSerializer(internshipApplications, many=True).data
return Response(
{'action': "Get Dashboard - Student", 'message': "Data Found", "placements": placementsdata,
'placementApplication': placementApplications, 'internships':internshipsdata,'internshipApplication':internshipApplications},
status=status.HTTP_200_OK)
except Http404:
return Response({'action': "Get Dashboard - Student", 'message': 'Student Not Found'},
status=status.HTTP_404_NOT_FOUND)
except:
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)
@api_view(['POST'])
@isAuthorized(allowed_users=[STUDENT])
@precheck(required_data=[RESUME_FILE_NAME])
def deleteResume(request, id, email, user_type):
try:
student = get_object_or_404(Student, id=id)
file_name = request.data[RESUME_FILE_NAME]
if file_name not in student.resumes:
return Response({'action': "Delete Resume", 'message': "Resume Not Found"},
status=status.HTTP_404_NOT_FOUND)
destination_path = STORAGE_DESTINATION_RESUMES + id + "/" + str(file_name)
if path.exists(destination_path):
# remove(destination_path)
student.resumes.remove(file_name)
student.changed_by = get_object_or_404(User, id=id)
student.save()
return Response({'action': "Delete Resume", 'message': "Resume Deleted"},
status=status.HTTP_200_OK)
else:
raise FileNotFoundError("File Not Found")
except Http404:
return Response({'action': "Delete Resume", 'message': 'Student Not Found'},
status=status.HTTP_404_NOT_FOUND)
except FileNotFoundError as e:
return Response({'action': "Delete Resume", 'message': 'File Not Found'},
status=status.HTTP_404_NOT_FOUND)
except:
logger.warning("Delete Resume: " + 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 student.can_apply:
return Response({'action': "Submit Application", 'message': "Student Can't Apply"},
status=status.HTTP_400_BAD_REQUEST)
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],
allowed_batch__contains=[student.batch],
allowed_branch__contains=[student.branch],
deadline_datetime__gte=timezone.now()
)
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")
elif data[OPENING_TYPE] == INTERNSHIP:
if not student.can_apply_internship:
return Response({'action': "Submit Application", 'message': "Student Can't Apply"},
status=status.HTTP_400_BAD_REQUEST)
if not len(InternshipApplication.objects.filter(
student_id=id, internship_id=data[OPENING_ID])):
application = InternshipApplication()
opening = get_object_or_404(Internship, id=data[OPENING_ID],
allowed_batch__contains=[student.batch],
allowed_branch__contains=[student.branch],
deadline_datetime__gte=timezone.now()
)
if not opening.offer_accepted or not opening.email_verified:
raise PermissionError("Internship Not Approved")
cond_stat, cond_msg = InternshipApplicationConditions(student, opening)
if not cond_stat:
raise PermissionError(cond_msg)
application.internship = 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)
sendEmail(email, subject, data, STUDENT_APPLICATION_SUBMITTED_TEMPLATE)
application.changed_by = get_object_or_404(User, id=id)
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=[STUDENT])
@precheck(required_data=[APPLICATION_ID])
def deleteApplication(request, id, email, user_type):
try:
data = request.data
if OPENING_TYPE in request.data:
opening_type = request.data[OPENING_TYPE]
else:
opening_type = PLACEMENT
if opening_type==INTERNSHIP: #check whether it has header or not
application = get_object_or_404(InternshipApplication, id=data[APPLICATION_ID],
student_id=id)
if application.internship.deadline_datetime < timezone.now():
raise PermissionError("Deadline Passed")
else:
application = get_object_or_404(PlacementApplication, id=data[APPLICATION_ID],
student_id=id)
if application.placement.deadline_datetime < timezone.now():
raise PermissionError("Deadline Passed")
application.delete()
return Response({'action': "Delete Application", 'message': "Application Deleted"},
status=status.HTTP_200_OK)
except Http404 as e:
return Response({'action': "Delete Application", 'message': str(e)},
status=status.HTTP_404_NOT_FOUND)
except PermissionError as e:
return Response({'action': "Delete Application", 'message': str(e)},
status=status.HTTP_403_FORBIDDEN)
except:
logger.warning("Delete Application: " + str(sys.exc_info()))
return Response({'action': "Delete Application", 'message': "Something Went Wrong"},
status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET'])
@isAuthorized(allowed_users='*')
def getContributorStats(request, id, email, user_type):
try:
contributors = Contributor.objects.all()
serialized_data = ContributorSerializer(contributors, many=True).data
return Response({'action': "Get Contributor Stats", 'message': "Contributor Stats Fetched",
'data': serialized_data},
status=status.HTTP_200_OK)
except:
logger.warning("Get Contributor Stats: " + str(sys.exc_info()))
return Response({'action': "Get Contributor Stats", 'message': "Something Went Wrong"},
status=status.HTTP_400_BAD_REQUEST)
#view for sudentAcceptOffer
@api_view(['POST'])
@precheck(required_data=[OPENING_ID,"offer_accepted"])
@isAuthorized(allowed_users=[STUDENT])
def studentAcceptOffer(request, id, email, user_type):
try:
company_id = request.data[OPENING_ID]
#student_id=request.data['profileInfo']['id'] //check this once
student_id=id
offer_accepted = request.data['offer_accepted']
if OPENING_TYPE in request.data:
opening_type = request.data[OPENING_TYPE]
else:
opening_type = PLACEMENT
if opening_type==INTERNSHIP:
application=InternshipApplication.objects.filter(internship=company_id,student=student_id,selected=True)
else:
application=PlacementApplication.objects.filter(placement=company_id,student=student_id,selected=True)
if len(application):
application[0].offer_accepted=offer_accepted
application[0].save()
return Response({'action': "Accept Offer", 'message': "Updated Offer Status"},
status=status.HTTP_200_OK)
else:
return Response({'action': "Accept Offer", 'message': "Offer Not Found"},
status=status.HTTP_404_NOT_FOUND)
except:
logger.warning("Accept Offer: " + str(sys.exc_info()))
return Response({'action': "Accept Offer", 'message': "Something Went Wrong"},
status=status.HTTP_400_BAD_REQUEST)
#view for addIssue
@api_view(['POST'])
@isAuthorized(allowed_users=[STUDENT])
@precheck(required_data=["Title","Description","opening_id","opening_type"])
def addIssue(request, id, email, user_type):
try:
data = request.data
student = get_object_or_404(Student, id=id)
issue = Issues()
issue.student = student
issue.title = data["Title"]
issue.description = data["Description"]
issue.opening_id = data["opening_id"]
issue.opening_type = data["opening_type"]
try:
if data["opening_type"]==PLACEMENT:
opening=get_object_or_404(Placement, id=data["opening_id"])
else:
opening=get_object_or_404(Internship, id=data["opening_id"])
except:
return Response({'action': "Add Issue", 'message': "Opening Not Found"},
status=status.HTTP_400_BAD_REQUEST)
issue.save()
subject=ISSUE_SUBMITTED_TEMPLATE_SUBJECT
data={
"name":student.name,
"application_type":issue.opening_type,
"company_name":opening.company_name,
"additional_info":{
"Abstract":issue.title,
"Description":issue.description
},
"email":email
}
sendEmail(email, subject, data, STUDENT_ISSUE_SUBMITTED_TEMPLATE)
#send_mail_to reps
sendEmail(CDC_REPS_EMAILS_FOR_ISSUE,"Issue Raised",data,REPS_ISSUE_SUBMITTED_TEMPLATE)
return Response({'action': "Add Issue", 'message': "Issue Added"},
status=status.HTTP_200_OK)
except Http404:
return Response({'action': "Add Issue", 'message': 'Student Not Found'},
status=status.HTTP_404_NOT_FOUND)
except:
logger.warning("Add Issue: " + str(sys.exc_info()))
return Response({'action': "Add Issue", 'message': "Something Went Wrong"},
status=status.HTTP_400_BAD_REQUEST)

View File

@ -0,0 +1 @@
# Create your tests here.

View File

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,195 @@
from django.test import TestCase, Client
from rest_framework import status
from rest_framework.test import APITestCase, APIClient
from django.urls import reverse
from ..models import *
import json
from ..utils import generateRandomString
import jwt
# initialize the APIClient app
client = APIClient()
class AddNewPlacementTest(APITestCase):
""" Test module for adding a new placement """
def setUp(self):
self.valid_payload = {
'company_name': 'Test Company 3', 'address': 'Test Address 3', 'company_type': 'Test Company Type 3',
'nature_of_business': 'Test Nature of Business 3', 'type_of_organisation': 'Test Type of Organisation 3',
'website': 'Test Website 3', 'company_details': 'Test Company Details 3', 'is_company_details_pdf': True,
'contact_person_name': 'Test Contact Person Name 3', 'phone_number': 1234567890, 'email': 'test3@test.com',
'city': 'Test City 3', 'state': 'Test State 3', 'country': 'Test Country 3', 'pin_code': 123456,
'designation': 'Test Designation 3', 'description': 'Test Description 3', 'job_location': 'Test Job Location 3',
'is_description_pdf': True, 'compensation_CTC': 300000, 'compensation_gross': 240000,
'compensation_take_home': 180000, 'compensation_bonus': 60000, 'is_compensation_details_pdf': True,
'allowed_branch': 'Test Allowed Branch 3', 'rs_eligible': True,
'selection_procedure_rounds': 'Test Selection Procedure Rounds 3',
'selection_procedure_details': 'Test Selection Procedure Details 3',
'is_selection_procedure_details_pdf': True, 'tentative_date_of_joining': '2022-03-01',
'tentative_no_of_offers': 30, 'other_requirements': 'Test Other Requirements 3'
}
self.invalid_payload = {
'company_name': '', 'address': 'Test Address 4', 'company_type': 'Test Company Type 4',
'nature_of_business': 'Test Nature of Business 4', 'type_of_organisation': 'Test Type of Organisation 4',
'website': 'Test Website 4', 'company_details': 'Test Company Details 4', 'is_company_details_pdf': True,
'contact_person_name': 'Test Contact Person Name 4', 'phone_number': 1234567890, 'email': 'test4@test.com',
'city': 'Test City 4', 'state': 'Test State 4', 'country': 'Test Country 4', 'pin_code': 123456,
'designation': 'Test Designation 4', 'description': 'Test Description 4', 'job_location': 'Test Job Location 4',
'is_description_pdf': True, 'compensation_CTC': 400000, 'compensation_gross': 320000,
'compensation_take_home': 240000, 'compensation_bonus': 80000, 'is_compensation_details_pdf': True,
'allowed_branch': 'Test Allowed Branch 4', 'rs_eligible': True,
'selection_procedure_rounds': 'Test Selection Procedure Rounds 4',
'selection_procedure_details': 'Test Selection Procedure Details 4',
'is_selection_procedure_details_pdf': True, 'tentative_date_of_joining': '2022-04-01',
'tentative_no_of_offers': 40, 'other_requirements': 'Test Other Requirements 4'
}
self.placement1 = Placement.objects.create(
company_name='ABC Corp', compensation_CTC=1000000, tier='1', id=generateRandomString(), allowed_branch=["CSE", "EE"], allowed_batch=["2020"], contact_person_name="test", phone_number=1234567890, email="test1@test.com", offer_accepted=True)
self.internship1 = Internship.objects.create(
company_name='ABC Corp', stipend=100000, id=generateRandomString(), allowed_branch=["CSE", "EE"], allowed_batch=["2020"], contact_person_name="test", phone_number=1234567890, email="test@gmail.com", offer_accepted=True)
self.token_placement1=jwt.encode({'opening_id': self.placement1.id,'opening_type':PLACEMENT,'email':"test1@test.com"}, os.environ.get("EMAIL_VERIFICATION_SECRET_KEY"), algorithm='HS256')
# def test_create_valid_placement(self):
# response = client.post(
# reverse('addPlacement'),
# data=json.dumps(self.valid_payload),
# content_type='application/json'
# )
# self.assertEqual(response.status_code, status.HTTP_201_CREATED)
# def test_create_invalid_placement(self):
# response = client.post(
# reverse('addPlacement'),
# data=json.dumps(self.invalid_payload),
# content_type='application/json'
# )
# self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
def test_autofill_jnf_success(self):
response = client.get(
reverse('Auto FIll JNF'),{"placement_id": self.placement1.id}
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data["message"], "Data Found")
self.assertEqual(response.data["placement_data"]["company_name"], "ABC Corp")
self.assertEqual(response.data["placement_data"]["compensation_CTC"], 1000000)
self.assertEqual(response.data["placement_data"]["tier"], "1")
self.assertEqual(response.data["placement_data"]["allowed_branch"], ["CSE", "EE"])
self.assertEqual(response.data["placement_data"]["allowed_batch"], ["2020"])
self.assertEqual(response.data["placement_data"]["contact_person_name"], "test")
self.assertEqual(response.data["placement_data"]["phone_number"], 1234567890)
self.assertEqual(response.data["placement_data"]["email"], "test1@test.com")
def test_autofill_jnf_WithInvalidId(self):
response = client.get(
reverse('Auto FIll JNF'),{"placement_id": generateRandomString()}
)
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertEqual(response.data["message"], "Placement Not Found")
def test_autofill_inf_success(self):
response = client.get(
reverse('Auto FIll INF'),{"internship_id": self.internship1.id}
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data["message"], "Data Found")
self.assertEqual(response.data["internship_data"]["company_name"], "ABC Corp")
self.assertEqual(response.data["internship_data"]["stipend"], 100000)
self.assertEqual(response.data["internship_data"]["allowed_branch"], ["CSE", "EE"])
self.assertEqual(response.data["internship_data"]["allowed_batch"], ["2020"])
self.assertEqual(response.data["internship_data"]["contact_person_name"], "test")
self.assertEqual(response.data["internship_data"]["phone_number"], 1234567890)
self.assertEqual(response.data["internship_data"]["email"], "test@gmail.com")
def test_autofill_inf_WithInvalidId(self):
response = client.get(
reverse('Auto FIll INF'),{"internship_id": generateRandomString()}
)
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertEqual(response.data["message"], "Internship Not Found")
def test_verify_email_success_placement(self):
response = client.post(
reverse('Verify Email'),{"token": self.token_placement1}
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data["message"], "Email Verified Successfully")
def test_verify_email_WithInvalidEmail_placement(self):
token_placement1=jwt.encode({'opening_id': self.placement1.id,'opening_type':PLACEMENT,'email':"hai@hai.com"}, os.environ.get("EMAIL_VERIFICATION_SECRET_KEY"), algorithm='HS256')
response = client.post(
reverse('Verify Email'),{"token": token_placement1}
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(response.data["message"], "Invalid Email")
def test_verify_email_WithInvalidOpeningId_Placement(self):
token_placement1=jwt.encode({'opening_id': generateRandomString(),'opening_type':PLACEMENT,'email':"hai@hai.com"}, os.environ.get("EMAIL_VERIFICATION_SECRET_KEY"), algorithm='HS256')
response = client.post(
reverse('Verify Email'),{"token": token_placement1}
)
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertEqual(response.data["message"], "Opening Not Found")
def test_verify_email_WithInvalidOpeningType(self):
token_placement1=jwt.encode({'opening_id': self.placement1.id,'opening_type':"hai",'email':"hai@hai.com"}, os.environ.get("EMAIL_VERIFICATION_SECRET_KEY"), algorithm='HS256')
response = client.post(
reverse('Verify Email'),{"token": token_placement1}
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(response.data["message"], "Invalid opening type")
def test_verify_email_WithInvalidToken(self):
response = client.post(
reverse('Verify Email'),{"token": generateRandomString()}
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(response.data["message"], "Something went wrong")
def test_verify_email_success_Internship(self):
token_placement1=jwt.encode({'opening_id': self.internship1.id,'opening_type':INTERNSHIP,'email':"test@gmail.com"}, os.environ.get("EMAIL_VERIFICATION_SECRET_KEY"), algorithm='HS256')
response = client.post(
reverse('Verify Email'),{"token": token_placement1}
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data["message"], "Email Verified Successfully")
def test_verify_email_WithInvalidEmail_Internship(self):
token_placement1=jwt.encode({'opening_id': self.internship1.id,'opening_type':INTERNSHIP,'email':"hai@hai.com"}, os.environ.get("EMAIL_VERIFICATION_SECRET_KEY"), algorithm='HS256')
response = client.post(
reverse('Verify Email'),{"token": token_placement1}
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(response.data["message"], "Invalid Email")
def test_verify_email_WithInvalidOpeningId_Internship(self):
token_placement1=jwt.encode({'opening_id': generateRandomString(),'opening_type':INTERNSHIP,'email':"hai@hai.com"}, os.environ.get("EMAIL_VERIFICATION_SECRET_KEY"), algorithm='HS256')
response = client.post(
reverse('Verify Email'),{"token": token_placement1}
)
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertEqual(response.data["message"], "Opening Not Found")
################################################################
# 1.Write Tests For AddPlacement Functions All cases #
# #
# 2.Write Tests For AddInternship Function All cases #
# #
################################################################
def test_addPlacement_sucess(self):
self.assertTrue(True)
def test_addPlacement_failure(self):
self.assertTrue(True)

View File

@ -0,0 +1,835 @@
# Create your tests here.
from ..models import *
from ..serializers import *
from django.test import TestCase, Client
from rest_framework import status
from rest_framework.test import APITestCase, APIClient
from django.urls import reverse
from ..utils import *
import json
from django.utils import timezone
from django.core.files.uploadedfile import SimpleUploadedFile
class StudentViewsTestCase(APITestCase):
def setUp(self):
self.client = APIClient()
self.user = User.objects.create(
email=str(os.environ.get("EMAIL_ID")),
id=str(os.environ.get("ROLL_NO")),
user_type=[STUDENT])
self.assertEqual(
self.user.email, User.objects.get(id=self.user.id).email)
self.student = Student.objects.create(
name="Test Student", id=self.user.id, resumes=["8BSLybntULgrPPm_beehyv.pdf"], roll_no=str(os.environ.get("ROLL_NO")), branch="CSE", batch="2020", phone_number=1234567890, changed_by=self.user, can_apply=True,
can_apply_internship=True, degree="bTech", cpi=7.95,
)
self.assertEqual(self.student.name,
Student.objects.get(id=self.student.id).name)
self.internship = Internship.objects.create(
company_name="Test Company", id=generateRandomString(), website="https://testwebsite.com", address="Test Address", company_type="Test Company Type", offer_accepted=True, season=["Summer"], allowed_branch=["CSE"],
allowed_batch=["2020"], contact_person_name="Test Contact Person", phone_number="1234567890", email="test@test.com", email_verified=True, stipend=10000,
)
self.placement = Placement.objects.create(
company_name="Test Company", id=generateRandomString(), website="https://testwebsite.com", address="Test Address", company_type="Test Company Type", offer_accepted=True, tier="6", allowed_branch=["CSE"], allowed_batch=["2020"],
contact_person_name="Test Contact Person", phone_number="1234567890", email="test@test.com", email_verified=True,
)
self.assertEqual(self.placement.company_name, Placement.objects.get(
id=self.placement.id).company_name)
self.internship_application = InternshipApplication.objects.create(
id=generateRandomString(), internship=self.internship, student=self.student, resume="8BSLybntULgrPPm_beehyv.pdf", selected=True
)
self.assertEqual(self.internship_application.internship.company_name, InternshipApplication.objects.get(
id=self.internship_application.id).internship.company_name)
self.placement_application = PlacementApplication.objects.create(
id=generateRandomString(), placement=self.placement, student=self.student, resume="8BSLybntULgrPPm_beehyv.pdf", selected=True
)
self.assertEqual(self.placement_application.placement.company_name, PlacementApplication.objects.get(
id=self.placement_application.id).placement.company_name)
self.issue = Issues.objects.create(
student=self.student, title="Test Issue", description="Test Issue Description", opening_id=self.internship.id,
opening_type=INTERNSHIP
)
# get token from google OAuth API
response = self.client.post(reverse('Refresh Token'), {
'refresh_token': os.environ.get("REFRESH_TOKEN")}, format='json')
self.student_token = response.data['id_token']
def test_student_accept_offer_internship(self):
url = reverse('Student Accept Offer')
data = {
'opening_id': self.internship.id,
'offer_accepted': True,
'opening_type': INTERNSHIP
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['message'], 'Updated Offer Status')
self.assertEqual(InternshipApplication.objects.get(
id=self.internship_application.id).offer_accepted, True)
def test_student_accept_offer_internship_notFound(self):
url = reverse('Student Accept Offer')
data = {
'opening_id': self.internship.id,
'offer_accepted': True,
'opening_type': INTERNSHIP
}
self.internship_application.selected = False
self.internship_application.offer_accepted = False
self.internship_application.save()
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertEqual(response.data['message'], 'Offer Not Found')
self.assertEqual(InternshipApplication.objects.get(
id=self.internship_application.id).offer_accepted, False)
def test_delete_application_internship(self):
url = reverse('Delete Application')
data = {
'application_id': self.internship_application.id,
'opening_type': INTERNSHIP
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['message'], 'Application Deleted')
self.assertEqual(InternshipApplication.objects.filter(
id=self.internship_application.id).count(), 0)
def test_delete_application_internship_deadlinePassed(self):
url = reverse('Delete Application')
data = {
'application_id': self.internship_application.id,
'opening_type': INTERNSHIP
}
self.internship.deadline_datetime = timezone.now().replace(
hour=0, minute=0, second=0, microsecond=0)
self.internship.save()
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
self.assertEqual(response.data['message'], 'Deadline Passed')
self.assertEqual(InternshipApplication.objects.filter(
id=self.internship_application.id).count(), 1)
def test_delete_application_internship_notFound(self):
url = reverse('Delete Application')
data = {
'application_id': self.internship_application.id,
'opening_type': INTERNSHIP
}
self.internship_application.delete()
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code,
status.HTTP_404_NOT_FOUND)
self.assertEqual(
response.data['message'], 'No InternshipApplication matches the given query.')
self.assertEqual(InternshipApplication.objects.filter(
id=self.internship_application.id).count(), 0)
# def test_add_application_internship(self):
# url = reverse('Delete Application')
# data = {
# 'application_id': self.internship_application.id,
# 'opening_type': INTERNSHIP
# }
# self.client.credentials(
# HTTP_AUTHORIZATION='Bearer ' + self.student_token)
# response = self.client.post(url, data, format='json')
# self.assertEqual(response.status_code, status.HTTP_200_OK)
# self.assertEqual(response.data['message'], 'Application Deleted')
# self.assertEqual(InternshipApplication.objects.filter(
# id=self.internship_application.id).count(), 0)
# # deleted existing application
# url = reverse('Add Application')
# data = {
# OPENING_ID: self.internship.id,
# OPENING_TYPE: INTERNSHIP,
# RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
# ADDITIONAL_INFO: []
# }
# self.client.credentials(
# HTTP_AUTHORIZATION='Bearer ' + self.student_token)
# response = self.client.post(url, data, format='json')
# self.assertEqual(response.status_code, status.HTTP_200_OK)
# self.assertEqual(response.data['message'], 'Application Submitted')
# self.assertEqual(InternshipApplication.objects.filter(
# student=self.student).count(), 1)
# self.internship_application = InternshipApplication.objects.filter(
# student=self.student)
# # self.internship.deadline_datetime = timezone.now().replace(
# # hour=0, minute=0, second=0, microsecond=0)
# # self.internship.save()
# response = self.client.post(url, data, format='json')
# self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
# self.assertEqual(response.data['message'],
# 'Application is already Submitted')
# self.assertEqual(InternshipApplication.objects.filter(
# student=self.student).count(), 1)
# self.internship_application.delete()
# data[OPENING_ID] = generateRandomString()
# response = self.client.post(url, data, format='json')
# self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
# self.assertEqual(response.data['message'],
# 'No Internship matches the given query.')
# self.assertEqual(InternshipApplication.objects.filter(
# student=self.student).count(), 0)
def test_student_accept_offer_placement(self):
url = reverse('Student Accept Offer')
data = {
'opening_id': self.placement.id,
'offer_accepted': True,
'opening_type': PLACEMENT
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['message'], 'Updated Offer Status')
self.assertEqual(PlacementApplication.objects.get(
id=self.placement_application.id).offer_accepted, True)
def test_student_accept_offer_placement_offerNotFound(self):
url = reverse('Student Accept Offer')
data = {
'opening_id': self.placement.id,
'offer_accepted': True,
'opening_type': PLACEMENT
}
self.placement_application.selected = False
self.placement_application.offer_accepted = False
self.placement_application.save()
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code,
status.HTTP_404_NOT_FOUND)
self.assertEqual(response.data['message'], 'Offer Not Found')
self.assertEqual(PlacementApplication.objects.filter(
id=self.placement_application.id, selected=True).count(), 0)
self.assertEqual(PlacementApplication.objects.get(
id=self.placement_application.id).offer_accepted, False)
def test_delete_application_placement(self):
url = reverse('Delete Application')
data = {
'application_id': self.placement_application.id,
'opening_type': PLACEMENT
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['message'], 'Application Deleted')
self.assertEqual(PlacementApplication.objects.filter(
id=self.placement_application.id).count(), 0)
def test_delete_application_placement_notFound(self):
url = reverse('Delete Application')
data = {
'application_id': self.placement_application.id,
'opening_type': PLACEMENT
}
self.placement_application.delete()
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code,
status.HTTP_404_NOT_FOUND)
self.assertEqual(
response.data['message'], 'No PlacementApplication matches the given query.')
self.assertEqual(PlacementApplication.objects.filter(
id=self.placement_application.id).count(), 0)
def test_delete_application_placement_deadlinePassed(self):
url = reverse('Delete Application')
data = {
'application_id': self.placement_application.id,
'opening_type': PLACEMENT
}
self.placement.deadline_datetime = timezone.now().replace(
hour=0, minute=0, second=0, microsecond=0)
self.placement.save()
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code,
status.HTTP_403_FORBIDDEN)
self.assertEqual(response.data['message'], 'Deadline Passed')
self.assertEqual(PlacementApplication.objects.filter(
id=self.placement_application.id).count(), 1)
def test_add_application_placement(self):
self.placement.additional_info = ["Test"]
self.placement_application.delete()
# deleted existing application
url = reverse('Add Application')
data = {
OPENING_ID: self.placement.id,
OPENING_TYPE: PLACEMENT,
RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
ADDITIONAL_INFO: [{"Test": "Test"}]
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['message'], 'Application Submitted')
self.assertEqual(PlacementApplication.objects.filter(
student=self.student).count(), 1)
def test_add_application_placement_deadlinePassed(self):
self.placement.deadline_datetime = timezone.now().replace(
hour=0, minute=0, second=0, microsecond=0)
self.placement.save()
# deleted existing application
self.placement_application.delete()
url = reverse('Add Application')
data = {
OPENING_ID: self.placement.id,
OPENING_TYPE: PLACEMENT,
RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
ADDITIONAL_INFO: []
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertEqual(response.data['message'],
'No Placement matches the given query.')
self.assertEqual(PlacementApplication.objects.filter(
student=self.student, placement=self.placement).count(), 0)
def test_add_application_placement_alreadyApplied(self):
url = reverse('Add Application')
data = {
OPENING_ID: self.placement.id,
OPENING_TYPE: PLACEMENT,
RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
ADDITIONAL_INFO: []
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
self.assertEqual(response.data['message'],
'Application is already Submitted')
self.assertEqual(PlacementApplication.objects.filter(
student=self.student, placement=self.placement).count(), 1)
def test_add_application_placement_notFound(self):
self.placement_application.delete()
url = reverse('Add Application')
data = {
OPENING_ID: self.placement.id,
OPENING_TYPE: PLACEMENT,
RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
ADDITIONAL_INFO: []
}
data[OPENING_ID] = generateRandomString()
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertEqual(response.data['message'],
'No Placement matches the given query.')
self.assertEqual(PlacementApplication.objects.filter(
student=self.student).count(), 0)
def test_add_application_placement_notApproved(self):
self.placement_application.delete()
url = reverse('Add Application')
data = {
OPENING_ID: self.placement.id,
OPENING_TYPE: PLACEMENT,
RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
ADDITIONAL_INFO: []
}
self.placement.offer_accepted = False
self.placement.save()
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
self.assertEqual(response.data['message'],
'Placement Not Approved')
self.assertEqual(PlacementApplication.objects.filter(
student=self.student, placement=self.placement).count(), 0)
def test_add_application_placement_notEmailVerified(self):
self.placement_application.delete()
url = reverse('Add Application')
data = {
OPENING_ID: self.placement.id,
OPENING_TYPE: PLACEMENT,
RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
ADDITIONAL_INFO: []
}
self.placement.email_verified = False
self.placement.save()
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
self.assertEqual(response.data['message'],
'Placement Not Approved')
self.assertEqual(PlacementApplication.objects.filter(
student=self.student, placement=self.placement).count(), 0)
def test_add_application_placement_notRegistered(self):
self.placement_application.delete()
url = reverse('Add Application')
data = {
OPENING_ID: self.placement.id,
OPENING_TYPE: PLACEMENT,
RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
ADDITIONAL_INFO: []
}
self.student.can_apply = False
self.student.save()
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(response.data['message'],
"Student Can't Apply")
self.assertEqual(PlacementApplication.objects.filter(
student=self.student, placement=self.placement).count(), 0)
def test_add_application_placement_InvalidOpeningtype(self):
self.placement_application.delete()
url = reverse('Add Application')
data = {
OPENING_ID: self.placement.id,
OPENING_TYPE: "Invalid",
RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
ADDITIONAL_INFO: []
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(response.data['message'],
"Something Went Wrong")
self.assertEqual(PlacementApplication.objects.filter(
student=self.student, placement=self.placement).count(), 0)
def test_add_application_placement_InvalidResume(self):
self.placement_application.delete()
url = reverse('Add Application')
data = {
OPENING_ID: self.placement.id,
OPENING_TYPE: PLACEMENT,
RESUME_FILE_NAME: 'Invalid',
ADDITIONAL_INFO: []
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertEqual(response.data['message'],
"resume_file_name Not Found")
self.assertEqual(PlacementApplication.objects.filter(
student=self.student, placement=self.placement).count(), 0)
def test_add_application_placement_MissingAdditionalInfo(self):
self.placement_application.delete()
url = reverse('Add Application')
self.placement.additional_info = ["Test"]
self.placement.save()
data = {
OPENING_ID: self.placement.id,
OPENING_TYPE: PLACEMENT,
RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
ADDITIONAL_INFO: []
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(response.data['message'],
"Something Went Wrong")
self.assertEqual(PlacementApplication.objects.filter(
student=self.student, placement=self.placement).count(), 0)
def test_getdashboard(self):
url = reverse('Dashboard')
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.get(url, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['message'], 'Data Found')
internships = Internship.objects.filter(allowed_batch__contains=[self.student.batch],
allowed_branch__contains=[
self.student.branch],
deadline_datetime__gte=datetime.datetime.now(),
offer_accepted=True, email_verified=True)
placements = Placement.objects.filter(allowed_batch__contains=[self.student.batch],
allowed_branch__contains=[
self.student.branch],
deadline_datetime__gte=datetime.datetime.now(),
offer_accepted=True, email_verified=True)
filtered_internships = internship_eligibility_filters(
self.student, internships)
filtered_placements = placement_eligibility_filters(
self.student, placements)
self.assertEqual(
len(response.data['internships']), len(filtered_internships))
self.assertEqual(
len(response.data['placements']), len(filtered_placements))
self.assertEqual(len(response.data['placementApplication']), 1)
self.assertEqual(len(response.data['internshipApplication']), 1)
self.assertEqual(response.data['placementApplication'][0]
['placement']['company_name'], self.placement.company_name)
self.assertEqual(response.data['internshipApplication'][0]
['internship']['company_name'], self.internship.company_name)
# def test_get_contributor_stats(self):
# url = reverse('get_contributor_stats', kwargs={'id': self.student.id})
# self.client.credentials(HTTP_AUTHORIZATION='Bearer ' + self.contributor_token)
# response = self.client.get(url, format='json')
# self.assertEqual(response.status_code, status.HTTP_200_OK)
# self.assertEqual(response.data['message'], 'Contributor Stats Fetched')
# self.assertEqual(len(response.data['data']), 1)
# self.assertEqual(response.data['data'][0]['name'], self.contributor.name)
# self.assertEqual(response.data['data'][0]['email'], self.contributor.email)
# self.assertEqual(response.data['data'][0]['contribution_count'], self.contributor.contribution_count)
def test_add_issue(self):
url = reverse('Add Issue')
data = {
'Title': 'Test Issue 2',
'Description': 'Test Issue Description 2',
'opening_id': self.placement.id,
'opening_type': PLACEMENT
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['message'], 'Issue Added')
self.assertEqual(Issues.objects.filter(
student=self.student).count(), 2)
self.assertEqual(Issues.objects.filter(
opening_id=self.placement.id).count(), 1)
self.assertEqual(Issues.objects.filter(
opening_type=PLACEMENT).count(), 1)
def test_add_application_internship(self):
self.internship.additional_info = ["Test"]
self.internship_application.delete()
# deleted existing application
url = reverse('Add Application')
data = {
OPENING_ID: self.internship.id,
OPENING_TYPE: INTERNSHIP,
RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
ADDITIONAL_INFO: [{"Test": "Test"}]
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['message'], 'Application Submitted')
self.assertEqual(InternshipApplication.objects.filter(
student=self.student).count(), 1)
def test_add_application_internship_deadlinePassed(self):
self.internship.deadline_datetime = timezone.now().replace(hour=0, minute=0, second=0, microsecond=0)
self.internship.save()
# deleted existing application
self.internship_application.delete()
url = reverse('Add Application')
data = {
OPENING_ID: self.internship.id,
OPENING_TYPE: INTERNSHIP,
RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
ADDITIONAL_INFO: []
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertEqual(response.data['message'],
'No Internship matches the given query.')
self.assertEqual(InternshipApplication.objects.filter(
student=self.student, internship=self.internship).count(), 0)
def test_add_application_internship_alreadyApplied(self):
url = reverse('Add Application')
data = {
OPENING_ID: self.internship.id,
OPENING_TYPE: INTERNSHIP,
RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
ADDITIONAL_INFO: []
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
self.assertEqual(response.data['message'],
'Application is already Submitted')
self.assertEqual(InternshipApplication.objects.filter(
student=self.student, internship=self.internship).count(), 1)
def test_add_application_internship_notFound(self):
self.internship_application.delete()
url = reverse('Add Application')
data = {
OPENING_ID: self.internship.id,
OPENING_TYPE: INTERNSHIP,
RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
ADDITIONAL_INFO: []
}
data[OPENING_ID] = generateRandomString()
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertEqual(response.data['message'],
'No Internship matches the given query.')
self.assertEqual(InternshipApplication.objects.filter(
student=self.student).count(), 0)
def test_add_application_internship_notApproved(self):
self.internship_application.delete()
url = reverse('Add Application')
data = {
OPENING_ID: self.internship.id,
OPENING_TYPE: INTERNSHIP,
RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
ADDITIONAL_INFO: []
}
self.internship.offer_accepted = False
self.internship.save()
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
self.assertEqual(response.data['message'],
'Internship Not Approved')
self.assertEqual(InternshipApplication.objects.filter(
student=self.student, internship=self.internship).count(), 0)
def test_add_application_internship_notEmailVerified(self):
self.internship_application.delete()
url = reverse('Add Application')
data = {
OPENING_ID: self.internship.id,
OPENING_TYPE: INTERNSHIP,
RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
ADDITIONAL_INFO: []
}
self.internship.email_verified = False
self.internship.save()
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
self.assertEqual(response.data['message'],
'Internship Not Approved')
self.assertEqual(InternshipApplication.objects.filter(
student=self.student, internship=self.internship).count(), 0)
def test_add_application_internship_notRegistered(self):
self.internship_application.delete()
url = reverse('Add Application')
data = {
OPENING_ID: self.internship.id,
OPENING_TYPE: INTERNSHIP,
RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
ADDITIONAL_INFO: []
}
self.student.can_apply_internship = False
self.student.save()
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(response.data['message'],
"Student Can't Apply")
self.assertEqual(InternshipApplication.objects.filter(
student=self.student, internship=self.internship).count(), 0)
def test_add_application_internship_InvalidOpeningtype(self):
self.internship_application.delete()
url = reverse('Add Application')
data = {
OPENING_ID: self.internship.id,
OPENING_TYPE: "Invalid",
RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
ADDITIONAL_INFO: []
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(response.data['message'],
"Something Went Wrong")
self.assertEqual(InternshipApplication.objects.filter(
student=self.student, internship=self.internship).count(), 0)
def test_add_application_internship_InvalidResume(self):
self.internship_application.delete()
url = reverse('Add Application')
data = {
OPENING_ID: self.internship.id,
OPENING_TYPE: INTERNSHIP,
RESUME_FILE_NAME: 'Invalid',
ADDITIONAL_INFO: []
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertEqual(response.data['message'],
"resume_file_name Not Found")
self.assertEqual(InternshipApplication.objects.filter(
student=self.student, internship=self.internship).count(), 0)
def test_add_application_internship_MissingAdditionalInfo(self):
self.internship_application.delete()
url = reverse('Add Application')
self.internship.additional_info = ["Test"]
self.internship.save()
data = {
OPENING_ID: self.internship.id,
OPENING_TYPE: INTERNSHIP,
RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
ADDITIONAL_INFO: []
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(response.data['message'],
"Something Went Wrong")
self.assertEqual(InternshipApplication.objects.filter(
student=self.student, internship=self.internship).count(), 0)
def test_getStudentProfile(self):
url = reverse('Student Profile')
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.get(url, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['message'], 'Details Found')
self.assertEqual(response.data['details']['id'], self.student.id)
self.assertEqual(response.data['details']['roll_no'],
self.student.roll_no)
self.assertEqual(response.data['details']['name'], self.student.name)
self.assertEqual(response.data['details']['batch'], self.student.batch)
self.assertEqual(response.data['details']['branch'],
self.student.branch)
self.assertEqual(response.data['details']['phone_number'],
self.student.phone_number)
self.assertEqual(response.data['details']
['cpi'], str(self.student.cpi))
for i in range(len(response.data['details']['resume_list'])):
self.assertIn(
response.data['details']['resume_list'][i]['name'], self.student.resumes)
for i in range(len(response.data['details']['offers'])):
self.assertIn(response.data['details']['offers'][i]
['application_id'], self.placement_application.id)
def test_addResume_success(self):
pdf = SimpleUploadedFile(
'kalera.pdf', b'content', content_type='application/pdf')
url = reverse('Upload Resume')
files = {'file': pdf}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, files, format='multipart')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['message'], 'Resume Added')
def test_add_resume_max_limit_reached(self):
pdf = SimpleUploadedFile(
'kalera.pdf', b'content', content_type='application/pdf')
url = reverse('Upload Resume')
files = {'file': pdf}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
self.student.resumes = ['resume1.pdf', 'resume2.pdf', 'resume3.pdf']
self.student.save()
response = self.client.post(url, files, format='multipart')
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(response.data, {
'action': 'Upload Resume', 'message': 'Max Number of Resumes limit reached'})
self.student.refresh_from_db()
self.assertEqual(len(self.student.resumes), 3)
def test_deleteResume_success(self):
destination_path = STORAGE_DESTINATION_RESUMES + \
self.student.id+'/'+"8BSLybntULgrPPm_beehyv.pdf"
# check it whats this above without this test giving error
with open(destination_path, 'w') as f:
f.write('test')
f.close()
# create a file here
url = reverse('Delete Resume')
data = {
'resume_file_name': '8BSLybntULgrPPm_beehyv.pdf'
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['message'], 'Resume Deleted')
self.student.refresh_from_db()
self.assertEqual(self.student.resumes, [])
remove(destination_path)
def test_deleteResume_invalidResume(self):
url = reverse('Delete Resume')
data = {
'resume_file_name': 'Invalid'
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertEqual(response.data['message'],
'Resume Not Found')
self.student.refresh_from_db()
self.assertEqual(self.student.resumes, ['8BSLybntULgrPPm_beehyv.pdf'])
def test_deleteResume_missingResumeinStorage(self):
url = reverse('Delete Resume')
data = {
'resume_file_name': '8BSLybntULgrPPm_beehyv.pdf'
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertEqual(response.data['message'], 'File Not Found')

11
CDC_Backend/APIs/urls.py Normal file
View File

@ -0,0 +1,11 @@
from django.urls import path, include
from . import studentViews, studentUrls, companyUrls, adminUrls
urlpatterns = [
path('login/', studentViews.login, name="Login"),
path('refresh_token/', studentViews.refresh, name="Refresh Token"),
path('student/', include(studentUrls)),
path('company/', include(companyUrls)),
path('admin/', include(adminUrls)),
]

594
CDC_Backend/APIs/utils.py Normal file
View File

@ -0,0 +1,594 @@
import datetime
import json
import logging
import os
import random
import re
import string
import sys
import traceback
from os import path, remove
import background_task
import jwt
import pdfkit
import pytz
import requests as rq
from django.conf import settings
from django.core.mail import EmailMultiAlternatives
from django.forms.models import model_to_dict
from django.http import Http404
from django.shortcuts import get_object_or_404
from django.template.loader import render_to_string
from django.utils.html import strip_tags
from django.utils import timezone
from google.auth.transport import requests
from google.oauth2 import id_token
from rest_framework import status
from rest_framework.response import Response
from .constants import *
from .models import User, PrePlacementOffer, PlacementApplication, Placement, Student, Internship,InternshipApplication
logger = logging.getLogger('db')
def get_token():
def decorator(view_func):
def wrapper_func(request, *args, **kwargs):
try:
authcode = request.data[AUTH_CODE]
data = {
'code': authcode,
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET,
'redirect_uri': REDIRECT_URI,
'grant_type': 'authorization_code'
}
r = rq.post(OAUTH2_API_ENDPOINT, data=data)
if r.status_code == 200:
response = r.json()
token = response[ID_TOKEN]
refresh_token = response[REFRESH_TOKEN]
request.META["HTTP_AUTHORIZATION"] = "Bearer " + token
request.META["MODIFIED"] = "True"
kwargs['refresh_token'] = refresh_token
return view_func(request, *args, **kwargs)
else:
return Response({'action': "Get Token", 'message': "Invalid Auth Code"},
status=status.HTTP_400_BAD_REQUEST)
except Exception as e:
logger.warning("Get Token: " + str(sys.exc_info()))
return Response({'action': "Get Token", 'message': str(e)},
status=status.HTTP_400_BAD_REQUEST)
return wrapper_func
return decorator
def precheck(required_data=None):
if required_data is None:
required_data = []
def decorator(view_func):
def wrapper_func(request, *args, **kwargs):
try:
request_data = None
if request.method == 'GET':
request_data = request.GET
elif request.method == 'POST':
request_data = request.data
if not len(request_data):
request_data = request.POST
if len(request_data):
for i in required_data:
# print(i)
if i not in request_data:
return Response({'action': "Pre check", 'message': str(i) + " Not Found"},
status=status.HTTP_400_BAD_REQUEST)
else:
return Response({'action': "Pre check", 'message': "Message Data not Found"},
status=status.HTTP_400_BAD_REQUEST)
# print("Pre check: " + str(request_data))
return view_func(request, *args, **kwargs)
except:
# print what exception is
print(traceback.format_exc())
logger.warning("Pre check: " + str(sys.exc_info()))
return Response({'action': "Pre check", 'message': "Something went wrong"},
status=status.HTTP_400_BAD_REQUEST)
return wrapper_func
return decorator
def isAuthorized(allowed_users=None):
if allowed_users is None:
allowed_users = []
def decorator(view_func):
def wrapper_func(request, *args, **kwargs):
try:
headers = request.META
if 'HTTP_AUTHORIZATION' in headers:
token_id = headers['HTTP_AUTHORIZATION'][7:]
idinfo = id_token.verify_oauth2_token(token_id, requests.Request(), CLIENT_ID)
email = idinfo[EMAIL]
user = get_object_or_404(User, email=email)
if user:
user.last_login_time = timezone.now()
user.save()
if len(set(user.user_type).intersection(set(allowed_users))) or allowed_users == '*':
if "MODIFIED" in headers:
return view_func(request, user.id, user.email, user.user_type, token_id, *args,
**kwargs)
else:
return view_func(request, user.id, user.email, user.user_type, *args, **kwargs)
else:
raise PermissionError("Access Denied. You are not allowed to use this service")
else:
raise PermissionError("Authorization Header Not Found")
except PermissionError:
return Response({'action': "Is Authorized?", 'message': 'Access Denied'},
status=status.HTTP_401_UNAUTHORIZED)
except 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:
logger.error("Problem with Google Oauth2.0 " + str(e))
return Response({'action': "Is Authorized?", 'message': 'Problem with Google Sign In'},
status=status.HTTP_401_UNAUTHORIZED)
except:
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
return decorator
def isAuthorizedService():
def decorator(view_func):
def wrapper_func(request, *args, **kwargs):
try:
headers = request.META
if 'HTTP_AUTHORIZATION' in headers:
token_id = headers['HTTP_AUTHORIZATION'][7:]
jwt.decode(token_id, os.environ.get("JWT_SECRET_KEY"), algorithms="HS256")
return view_func(request, *args, **kwargs)
else:
raise PermissionError("Authorization Header Not Found")
except:
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
return decorator
def generateRandomString():
try:
N = 15
res = ''.join(random.choices(string.ascii_uppercase + string.ascii_lowercase + string.digits, k=N))
return res
except:
return False
def saveFile(file, location):
prefix = generateRandomString()
file_name = prefix + "_" + file.name.strip()
file_name = re.sub(r'[\\/:*?"<>|]', '_', file_name)
if not path.isdir(location):
os.makedirs(location)
destination_path = location + 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)
return file_name
@background_task.background(schedule=2)
def sendEmail(email_to, subject, data, template, attachment_jnf_response=None):
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)
email_from = settings.EMAIL_HOST_USER
if type(email_to) is list:
recipient_list = [str(email) for email in email_to]
else:
recipient_list = [str(email_to), ]
#batch 100 ppl to send as bcc
for i in range(0,len(recipient_list),100):
msg = EmailMultiAlternatives(subject, text_content, email_from,None,bcc=recipient_list[i:i+100])
msg.attach_alternative(html_content, "text/html")
if attachment_jnf_response:
# logger.info(attachment_jnf_response)
pdf = pdfkit.from_string(attachment_jnf_response['html'], False,
options={"--enable-local-file-access": "", '--dpi': '96'})
msg.attach(attachment_jnf_response['name'], pdf, 'application/pdf')
msg.send()
return True
except:
logger.error("Send Email: " + str(sys.exc_info()))
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(student=student, accepted=True)
PPO_PSU = [i for i in PPO if i.tier == 'psu']
# find length of PPO
if len(selected_companies) + len(PPO) >= MAX_OFFERS_PER_STUDENT:
raise PermissionError("Max Applications Reached for the Season")
if len(selected_companies_PSU) > 0:
raise PermissionError('Selected for PSU Can\'t apply anymore')
if len(PPO_PSU) > 0:
raise PermissionError('Selected for PSU Can\'t apply anymore')
if placement.tier == 'psu':
return True, "Conditions Satisfied"
for i in selected_companies:
if int(i.placement.tier) != 1 and int(i.placement.tier) <= int(placement.tier):
return False, "Can't apply for this tier"
elif int(i.placement.tier) == 1 and int(placement.tier) != 1:
return False, "Can't apply for this tier"
for i in PPO:
if int(i.tier) != 1 and int(i.tier) <= int(placement.tier):
return False, "Can't apply for this tier"
elif int(i.tier) == 1 and int(placement.tier) != 1:
return False, "Can't apply for this tier"
if student.degree != 'bTech' and not placement.rs_eligible:
raise PermissionError("Can't apply for this placement")
return True, "Conditions Satisfied"
except PermissionError as e:
return False, e
except:
logger.warning("Utils - PlacementApplicationConditions: " + str(sys.exc_info()))
return False, "_"
def InternshipApplicationConditions(student, internship):
try:
selected_companies = InternshipApplication.objects.filter(student=student, selected=True)
if len(selected_companies)>=1:
# print("selected companies > 1")
return False, "You have already secured a Internship"
return True, "Conditions Satisfied"
except PermissionError as e:
return False, e
except:
logger.warning("Utils - InternshipApplicationConditions: " + 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 < 450000: # Open Tier If less than 450,000
return True, "8"
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:
logger.warning("Utils - getTier: " + str(sys.exc_info()))
return False, "_"
def generateOneTimeVerificationLink(email, opening_id, opening_type):
try:
token_payload = {
"email": email,
"opening_id": opening_id,
"opening_type": opening_type,
'exp': datetime.datetime.utcnow() + datetime.timedelta(hours=EMAIL_VERIFICATION_TOKEN_TTL)
}
token = jwt.encode(token_payload, os.environ.get("EMAIL_VERIFICATION_SECRET_KEY"), algorithm="HS256")
link = LINK_TO_EMAIl_VERIFICATION_API.format(token=token)
return True, link
except:
logger.warning("Utils - generateOneTimeVerificationLink: " + str(sys.exc_info()))
return False, "_"
def verify_recaptcha(request):
try:
data = {
'secret': settings.RECAPTCHA_SECRET_KEY,
'response': request
}
r = rq.post('https://www.google.com/recaptcha/api/siteverify', data=data)
result = r.json()
if not result['success']:
logger.warning("Utils - verify_recaptcha: " + str(result))
return result['success']
except:
# get exception line number
logger.warning("Utils - verify_recaptcha: " + str(sys.exc_info()))
return False, "_"
def opening_description_table_html(opening):
# check typing of opening
type = ""
if isinstance(opening, Placement):
type = "Job"
details = model_to_dict(opening, fields=[field.name for field in Placement._meta.fields],
exclude=EXCLUDE_IN_PDF)
elif isinstance(opening, Internship):
type = "Internship"
details = model_to_dict(opening, fields=[field.name for field in Internship._meta.fields],
exclude=EXCLUDE_IN_PDF)
# check typing of opening is query dict
else: # if isinstance(opening, QueryDict):
details = opening
keys = list(details.keys())
newdetails = {"ID": opening.id}
for key in keys:
if isinstance(details[key], list):
details[key] = {"details": details[key], "type": ["list"]}
if key in SPECIAL_FORMAT_IN_PDF:
if key == 'website':
details[key] = {"details": details[key], "type": ["link"]}
else:
details[key] = {"details": [item for item in details[key]["details"]], "type": ["list", "link"],
"link": PDF_FILES_SERVING_ENDPOINT + opening.id + "/"}
new_key = key.replace('_', ' ')
if new_key.endswith(' names'):
new_key = new_key[:-6]
new_key = new_key.capitalize()
newdetails[new_key] = details[key]
imagepath = os.path.abspath('./templates/image.png')
data = {
"data": newdetails,
"imgpath": imagepath,
"type": type
}
return render_to_string(COMPANY_JNF_RESPONSE_TEMPLATE, data)
def placement_eligibility_filters(student, placements):
try:
filtered_placements = []
for placement in placements.iterator():
if PlacementApplicationConditions(student, placement)[0]:
filtered_placements.append(placement)
return filtered_placements
except:
logger.warning("Utils - placement_eligibility_filters: " + str(sys.exc_info()))
return placements
def internship_eligibility_filters(student, internships):
try:
filtered_internships = []
for internship in internships.iterator():
if InternshipApplicationConditions(student, internship)[0]:
filtered_internships.append(internship)
return filtered_internships
except:
logger.warning("Utils - internship_eligibility_filters: " + str(sys.exc_info()))
return internships
@background_task.background(schedule=2)
def send_opening_notifications(opening_id, opening_type=PLACEMENT):
try:
# print(opening_id, opening_type)
if opening_type == PLACEMENT:
opening = get_object_or_404(Placement, id=opening_id)
else:
opening = get_object_or_404(Internship, id=opening_id)
emails=[]
students = Student.objects.all()
for student in students.iterator():
if student.branch in opening.allowed_branch:
if student.degree == 'bTech' or opening.rs_eligible is True:
if (isinstance(opening,Placement) and PlacementApplicationConditions(student, opening)[0]) or (isinstance(opening,Internship) and InternshipApplicationConditions(student, opening)[0]):
try:
student_user = get_object_or_404(User, id=student.id)
emails.append(student_user.email)
#sendEmail(student_user.email, subject, data, NOTIFY_STUDENTS_OPENING_TEMPLATE)
except Http404:
logger.warning('Utils - send_opening_notifications: user not found : ' + student.id)
except Exception as e:
logger.warning('Utils - send_opening_notifications: For Loop' + str(e))
subject = NOTIFY_STUDENTS_OPENING_TEMPLATE_SUBJECT.format(
company_name=opening.company_name)
deadline_datetime = opening.deadline_datetime.astimezone(pytz.timezone('Asia/Kolkata'))
data = {
"company_name": opening.company_name,
"opening_type": "INTERNSHIP" if isinstance(opening, Internship) else "PLACEMENT",
"designation": opening.designation,
"deadline": deadline_datetime.strftime("%A, %-d %B %Y, %-I:%M %p"),
"link": PLACEMENT_OPENING_URL.format(id=opening.designation) if opening_type == PLACEMENT else INTERNSHIP_OPENING_URL.format(id=opening.designation),
}
sendEmail(emails, subject, data, NOTIFY_STUDENTS_OPENING_TEMPLATE) #handled multiple mailings
except:
logger.warning('Utils - send_opening_notifications: ' + str(sys.exc_info()))
return False
def get_eligible_emails(opening_id, opening_type=PLACEMENT,send_all=False):
try:
# print(opening_id, opening_type)
if opening_type == PLACEMENT:
opening = get_object_or_404(Placement, id=opening_id)
else:
opening = get_object_or_404(Internship, id=opening_id)
emails=[]
students = Student.objects.all()
for student in students.iterator():
if student.branch in opening.allowed_branch:
if student.degree == 'bTech' or opening.rs_eligible is True:
if (isinstance(opening,Placement) and PlacementApplicationConditions(student, opening)[0]) or (
isinstance(opening,Internship) and InternshipApplicationConditions(student, opening)[0]):
try:
student_user = get_object_or_404(User, id=student.id)
#if send_all True send all students eligible for the opening
if send_all:
emails.append(student_user.email)
continue
# check if he applied
if opening_type == PLACEMENT:
if PlacementApplication.objects.filter(student=student, placement=opening).exists():
continue
else:
if InternshipApplication.objects.filter(student=student, internship=opening).exists():
continue
emails.append(student_user.email)
except Exception as e:
logger.warning('Utils - send_opening_notifications: For Loop' + str(e))
return False, []
return True, emails
except:
logger.warning('Utils - send_opening_notifications: ' + str(sys.exc_info()))
return False, []
def exception_email(opening):
opening = opening.dict()
data = {
"designation": opening["designation"],
"opening_type": "INTERNSHIP" if opening["opening_type"] == "INF" else "PLACEMENT",
"company_name": opening["company_name"],
}
pdfhtml = opening_description_table_html(opening)
name = opening["company_name"] + '_jnf_response.pdf' if opening[OPENING_TYPE]!="INF" else opening["company_name"] + '_inf_response.pdf'
attachment_jnf_respone = {
"name": name,
"html": pdfhtml,
}
sendEmail("cdc@iitdh.ac.in", COMPANY_OPENING_ERROR_TEMPLATE.format(company_name=opening["company_name"]), data,
COMPANY_OPENING_SUBMITTED_TEMPLATE, attachment_jnf_respone)
def store_all_files(request):
files = request.FILES
data = request.data
# save all the files
if files:
# company details pdf
for file in files.getlist(COMPANY_DETAILS_PDF):
file_location = STORAGE_DESTINATION_COMPANY_ATTACHMENTS + "temp" + '/'
saveFile(file, file_location)
# compensation details pdf
for file in files.getlist(COMPENSATION_DETAILS_PDF):
file_location = STORAGE_DESTINATION_COMPANY_ATTACHMENTS + "temp" + '/'
saveFile(file, file_location)
#stipend details pdf for internships
for file in files.getlist(STIPEND_DETAILS_PDF):
file_location = STORAGE_DESTINATION_COMPANY_ATTACHMENTS + "temp" + '/'
saveFile(file, file_location)
# selection procedure details pdf
for file in files.getlist(SELECTION_PROCEDURE_DETAILS_PDF):
file_location = STORAGE_DESTINATION_COMPANY_ATTACHMENTS + "temp" + '/'
saveFile(file, file_location)
# description pdf
for file in files.getlist(DESCRIPTION_PDF):
file_location = STORAGE_DESTINATION_COMPANY_ATTACHMENTS + "temp" + '/'
saveFile(file, file_location)
def send_email_for_opening(opening):
try:
# Prepare email data and attachment
pdfhtml = opening_description_table_html(opening)
if isinstance(opening, Placement):
name = opening.company_name + '_jnf_response.pdf'
elif isinstance(opening, Internship):
name = opening.company_name + '_inf_response.pdf'
attachment_jnf_respone = {
"name": name,
"html": pdfhtml,
}
data = {
"designation": opening.designation,
"opening_type": "INTERNSHIP" if isinstance(opening, Internship) else "PLACEMENT",
"company_name": opening.company_name,
}
emails = [opening.email] + CDC_REPS_EMAILS
# Send the email
sendEmail(emails,
COMPANY_OPENING_SUBMITTED_TEMPLATE_SUBJECT.format(id=opening.designation, company=opening.company_name), data,
COMPANY_OPENING_SUBMITTED_TEMPLATE, attachment_jnf_respone)
except Exception as e:
# Handle the exception here (e.g., log the error, send an error email, etc.)
print("An error occurred while sending the email:", e)
@background_task.background(schedule=2)
def send_opening_to_notifications_service(id,name,deadline,role,opening_type=PLACEMENT):
data={
"id":id,
"company":name,
"deadline":deadline,
"role":role,
"opening_type":opening_type
}
encoded=jwt.encode(data,os.environ.get("JWT_SECRET_KEY"),algorithm="HS256")
data_={
"token":encoded,
}
resp=rq.post(url=os.environ.get("PUSH_API_URL")+"addopening/",data=data_)
if resp.status_code==200:
print("Notification Sent")
else:
print("Notification Failed")
logger.warning("Utils - send_opening_to_notifications_service: " + str(resp) + "data sent:"+str(data))

BIN
CDC_Backend/CDC_Backend/.DS_Store vendored Normal file

Binary file not shown.

View File

View File

@ -0,0 +1,228 @@
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 simple_history.admin import SimpleHistoryAdmin
from import_export.admin import ImportExportMixin, ExportMixin
from import_export import resources
from .models import *
from .utils import send_email_for_opening
class ArrayFieldListFilter(admin.SimpleListFilter):
"""This is a list filter based on the values
from a model's `keywords` ArrayField. """
title = 'Roles'
parameter_name = 'user_type'
def lookups(self, request, model_admin):
# Very similar to our code above, but this method must return a
# list of tuples: (lookup_value, human-readable value). These
# appear in the admin's right sidebar
keywords = User.objects.values_list("user_type", flat=True)
keywords = [(kw, kw) for sublist in keywords for kw in sublist if kw]
keywords = sorted(set(keywords))
return keywords
def queryset(self, request, queryset):
# when a user clicks on a filter, this method gets called. The
# provided queryset with be a queryset of Items, so we need to
# filter that based on the clicked keyword.
lookup_value = self.value() # The clicked keyword. It can be None!
if lookup_value:
# the __contains lookup expects a list, so...
queryset = queryset.filter(user_type__contains=[lookup_value])
return queryset
class UserAdmin(ImportExportMixin, SimpleHistoryAdmin):
list_display = ('email', 'user_type', 'last_login_time')
list_filter = (ArrayFieldListFilter, 'last_login_time')
search_fields = ('email', 'user_type')
ordering = ('email', 'user_type')
admin.site.register(User, UserAdmin)
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('<a href="{}">{}</a>', url, name or str(obj))
class StudentAdmin(ImportExportMixin, SimpleHistoryAdmin):
pass
@admin.register(Student)
class Student(StudentAdmin):
list_display = ("roll_no", "name", "batch", "branch", "phone_number", 'can_apply')
search_fields = ("roll_no", "name", "phone_number")
ordering = ("roll_no", "name", "batch", "branch", "phone_number")
list_filter = ("batch", "branch")
actions = ['mark_can_apply_as_no', 'mark_can_apply_as_yes']
@admin.action(description="Deregister students")
def mark_can_apply_as_no(self, request, queryset):
queryset.update(can_apply=False)
self.message_user(request, "Deregistered the users")
@admin.action(description="Register students")
def mark_can_apply_as_yes(self, request, queryset):
queryset.update(can_apply=True)
self.message_user(request, "Registered the users")
class PlacementResources(resources.ModelResource):
class Meta:
model = Placement
exclude = ('id','changed_by', 'is_company_details_pdf', 'is_description_pdf',
'is_compensation_details_pdf', 'is_selection_procedure_details_pdf')
class AdminAdmin(ExportMixin, SimpleHistoryAdmin):
resource_class = PlacementResources
class PlacementResources(resources.ModelResource):
class Meta:
model = Placement
exclude = ('id', 'changed_by', 'is_company_details_pdf', 'is_description_pdf',
'is_compensation_details_pdf', 'is_selection_procedure_details_pdf')
class AdminAdmin(ExportMixin, SimpleHistoryAdmin):
resource_class = PlacementResources
class PlacementResources(resources.ModelResource):
class Meta:
model = Placement
exclude = ('id', 'changed_by', 'is_company_details_pdf', 'is_description_pdf',
'is_compensation_details_pdf', 'is_selection_procedure_details_pdf')
class AdminAdmin(ExportMixin, SimpleHistoryAdmin):
resource_class = PlacementResources
def save_model(self, request, obj, form, change):
# Check if email_verified field is being changed from False to True
if change and not obj._state.adding and obj.email_verified and form.initial.get('email_verified', False) != obj.email_verified:
# Run the send_email_for_opening function
send_email_for_opening(obj)
# Save the model as usual
super().save_model(request, obj, form, change)
@admin.register(Placement)
class Placement(AdminAdmin):
list_display = (COMPANY_NAME, DESIGNATION , CONTACT_PERSON_NAME, PHONE_NUMBER, 'tier', 'compensation_CTC', 'email_verified', 'updated_at')
search_fields = (COMPANY_NAME, CONTACT_PERSON_NAME)
ordering = ('updated_at', COMPANY_NAME, CONTACT_PERSON_NAME, 'tier', 'compensation_CTC')
list_filter = ('tier',)
class PlacementApplicationResources(resources.ModelResource):
class Meta:
model = PlacementApplication
exclude = ('id', 'changed_by')
class PlacementAdmin(ExportMixin, SimpleHistoryAdmin):
resource_class = PlacementApplicationResources
class InternshipApplicationResources(resources.ModelResource):
class Meta:
model = InternshipApplication
exclude = ('id', 'changed_by')
class InternshipApplicationAdmin(ExportMixin, SimpleHistoryAdmin):
resource_class = InternshipApplicationResources
@admin.register(PlacementApplication)
class PlacementApplication(PlacementAdmin):
list_display = ('id', 'Placement', 'Student', 'selected')
search_fields = ('id',)
ordering = ('id',)
list_filter = ('selected',)
def Placement(self, obj):
return model_admin_url(obj.placement)
def Student(self, obj):
return model_admin_url(obj.student)
@admin.register(InternshipApplication)
class InternshipApplication(InternshipApplicationAdmin):
list_display = ('id', 'Internship', 'Student', 'selected')
search_fields = ('id',)
ordering = ('id',)
list_filter = ('selected',)
def Internship(self, obj):
return model_admin_url(obj.internship)
def Student(self, obj):
return model_admin_url(obj.student)
class PrePlacementResources(resources.ModelResource):
class Meta:
model = PrePlacementOffer
exclude = ('id', 'changed_by')
class PrePlacementOfferAdmin(ExportMixin, SimpleHistoryAdmin):
resource_class = PrePlacementResources
@admin.register(PrePlacementOffer)
class PrePlacementOffer(PrePlacementOfferAdmin):
list_display = ('company', 'Student', 'accepted')
search_fields = ('company',)
ordering = ('company',)
list_filter = ('accepted',)
def Student(self, obj):
return model_admin_url(obj.student)
class InternshipResources(resources.ModelResource):
class Meta:
model = Internship
exclude = ('id', 'changed_by', 'is_company_details_pdf', 'is_description_pdf',
'is_stipend_details_pdf', 'is_selection_procedure_details_pdf')
class InternAdmin(ExportMixin, SimpleHistoryAdmin):
resource_class = InternshipResources
def save_model(self, request, obj, form, change):
# Check if email_verified field is being changed from False to True
if change and not obj._state.adding and obj.email_verified and form.initial.get('email_verified', False) != obj.email_verified:
# Run the send_email_for_opening function
send_email_for_opening(obj)
super().save_model(request, obj, form, change)
@admin.register(Internship)
class Placement(InternAdmin):
list_display = (COMPANY_NAME, DESIGNATION, CONTACT_PERSON_NAME, PHONE_NUMBER, 'stipend', 'email_verified', 'updated_at')
search_fields = (COMPANY_NAME, CONTACT_PERSON_NAME)
ordering = ('updated_at', COMPANY_NAME, CONTACT_PERSON_NAME, 'stipend')
@admin.register(Issues)
class Issues(admin.ModelAdmin):
list_display = ('id', 'title', 'description')
search_fields = ('id', 'title', 'description')
ordering = ('id', 'title', 'description')
# list_filter = ('status',)
def Student(self, obj):
return model_admin_url(obj.student)

View File

@ -0,0 +1,20 @@
from django.urls import path
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('deleteAdditionalInfo/', adminViews.deleteAdditionalInfo, name="Delete Additional Info"),
path('addAdditionalInfo/', adminViews.addAdditionalInfo, name="Add Additional Info"),
path('getApplications/', adminViews.getApplications, name="Get Applications"),
path("submitApplication/", adminViews.submitApplication, name="Submit Application"),
path('generateCSV/', adminViews.generateCSV, name="Generate CSV"),
path('addPPO/', adminViews.addPPO, name="Add PPO"),
path('getStudentApplication/', adminViews.getStudentApplication, name="Get student application"),
path('getStats/', adminViews.getStats, name="Get Stats"),
path('getEligibleStudents/', adminViews.get_eligible_students, name="Get Eligible Students"),
]

View File

@ -0,0 +1,784 @@
import csv
from rest_framework.decorators import api_view
from .serializers import *
from .utils import *
@api_view(['POST'])
@isAuthorized([ADMIN])
@precheck([OPENING_ID, STUDENT_LIST])
def markStatus(request, id, email, user_type):
try:
data = request.data
if OPENING_TYPE in data:
opening_type= data[OPENING_TYPE] #not to break the code
else:
opening_type= "Placement"
if opening_type == "Internship":
applications = InternshipApplication.objects.filter(internship_id=data[OPENING_ID])
else:
applications = PlacementApplication.objects.filter(placement_id=data[OPENING_ID])
for i in data[STUDENT_LIST]:
application = applications.filter(student__roll_no=i[STUDENT_ID]) # Filtering student's application
if len(application) > 0:
application = application[0]
if not application.selected:
if i[STUDENT_SELECTED] == True:
application.selected = True
else:
application.selected = False
else:
raise ValueError("Student already selected")
email = str(application.student.roll_no) + "@iitdh.ac.in" # Only allowing for IITDh emails
if opening_type == "Internship":
subject = STUDENT_APPLICATION_STATUS_TEMPLATE_SUBJECT.format(
company_name=application.internship.company_name,id=application.id)
data = {
"company_name": application.internship.company_name,
"designation": application.internship.designation,
"student_name": application.student.name
}
else:
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.chaged_by = get_object_or_404(User, id=id)
application.save()
else:
raise ValueError("Student - " + str(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=timezone.now(), offer_accepted=True, email_verified=True)
previous = placements.exclude(deadline_datetime__gt=timezone.now()).filter(
offer_accepted=True, email_verified=True)
new = placements.filter(offer_accepted__isnull=True, email_verified=True)
internships=Internship.objects.all().order_by('-created_at')
ongoing_internships = internships.filter(deadline_datetime__gt=timezone.now(), offer_accepted=True, email_verified=True)
previous_internships = internships.exclude(deadline_datetime__gt=timezone.now()).filter(
offer_accepted=True, email_verified=True)
new_internships = internships.filter(offer_accepted__isnull=True, email_verified=True)
ongoing = PlacementSerializerForAdmin(ongoing, many=True).data
previous = PlacementSerializerForAdmin(previous, many=True).data
new = PlacementSerializerForAdmin(new, many=True).data
ongoing_internships = InternshipSerializerForAdmin(ongoing_internships, many=True).data
previous_internships = InternshipSerializerForAdmin(previous_internships, many=True).data
new_internships = InternshipSerializerForAdmin(new_internships, many=True).data
return Response(
{'action': "Get Dashboard - Admin", 'message': "Data Found", "ongoing": ongoing, "previous": previous,
"new": new, "ongoing_internships": ongoing_internships, "previous_internships": previous_internships,
"new_internships": new_internships},
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
if OPENING_TYPE in data:
opening_type= data[OPENING_TYPE]
else:
opening_type= "Placement"
if opening_type == "Internship":
opening = get_object_or_404(Internship, pk=data[OPENING_ID])
else:
opening = get_object_or_404(Placement, pk=data[OPENING_ID])
# Updating deadline date with correct format in datetime field
opening.deadline_datetime = datetime.datetime.strptime(data[DEADLINE_DATETIME], '%Y-%m-%d %H:%M:%S %z')
opening.changed_by = get_object_or_404(User, id=id)
opening.save()
send_opening_to_notifications_service(id=opening.id,name=opening.company_name,deadline=data[DEADLINE_DATETIME],role=opening.designation,opening_type=opening_type)
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([SUPER_ADMIN])
@precheck([OPENING_ID, OFFER_ACCEPTED])
def updateOfferAccepted(request, id, email, user_type):
try:
data = request.data
offer_accepted = data[OFFER_ACCEPTED]
if OPENING_TYPE in data:
opening_type= data[OPENING_TYPE]
else:
opening_type= "Placement"
if DEADLINE_DATETIME in data:
deadline_datetime = datetime.datetime.strptime(data[DEADLINE_DATETIME], '%Y-%m-%d %H:%M:%S %z')
else:
deadline_datetime = timezone.localtime(timezone.now()).replace(hour=0, minute=0, second=0, microsecond=0) + datetime.timedelta(days=2)
if opening_type == "Internship":
opening = get_object_or_404(Internship, pk=data[OPENING_ID])
else:
opening = get_object_or_404(Placement, pk=data[OPENING_ID])
if opening.offer_accepted is None:
opening.offer_accepted = offer_accepted == "true"
opening.deadline_datetime = deadline_datetime
opening.changed_by = get_object_or_404(User, id=id)
opening.save()
if opening.offer_accepted:
deadline=deadline_datetime.strftime('%Y-%m-%d %H:%M:%S %z')
send_opening_to_notifications_service(id=opening.id,name=opening.company_name,deadline=deadline,role=opening.designation,opening_type=opening_type)
send_opening_notifications(opening.id,opening_type)
else:
raise ValueError("Offer Status already updated")
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 ValueError as e:
return Response({'action': "Update Offer Accepted", 'message': str(e)},
status=status.HTTP_400_BAD_REQUEST)
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
if OPENING_TYPE in data:
opening_type= data[OPENING_TYPE]
else:
opening_type= "Placement"
if opening_type == "Internship":
opening = get_object_or_404(Internship, pk=data[OPENING_ID])
else:
opening = get_object_or_404(Placement, pk=data[OPENING_ID])
opening.email_verified = True if data[EMAIL_VERIFIED] == "true" else False
opening.changed_by = get_object_or_404(User, id=id)
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, FIELD])
def deleteAdditionalInfo(request, id, email, user_type):
try:
data = request.data
if OPENING_TYPE in data:
opening_type= data[OPENING_TYPE]
else:
opening_type= "Placement"
if opening_type == "Internship":
opening = get_object_or_404(Internship, pk=data[OPENING_ID])
else:
opening = get_object_or_404(Placement, pk=data[OPENING_ID])
if data[FIELD] in opening.additional_info:
opening.additional_info.remove(data[FIELD])
opening.changed_by = get_object_or_404(User, id=id)
opening.save()
return Response({'action': "Delete Additional Info", 'message': "Additional Info Deleted"},
status=status.HTTP_200_OK)
else:
raise ValueError("Additional Info Not Found")
except Http404:
return Response({'action': "Delete Additional Info", 'message': 'Opening Not Found'},
status=status.HTTP_404_NOT_FOUND)
except ValueError:
return Response({'action': "Delete Additional Info", 'message': "Additional Info not found"},
status=status.HTTP_404_NOT_FOUND)
except Exception as e:
logger.warning("Delete Additional Info: " + str(e))
return Response({'action': "Delete Additional Info", 'message': "Something went wrong"},
status=status.HTTP_400_BAD_REQUEST)
@api_view(['POST'])
@isAuthorized([ADMIN])
@precheck([OPENING_ID, FIELD])
def addAdditionalInfo(request, id, email, user_type):
try:
data = request.data
if OPENING_TYPE in data:
opening_type= data[OPENING_TYPE]
else:
opening_type= "Placement"
if opening_type == "Internship":
opening = get_object_or_404(Internship, pk=data[OPENING_ID])
else:
opening = get_object_or_404(Placement, pk=data[OPENING_ID])
if data[FIELD] not in opening.additional_info:
opening.additional_info.append(data[FIELD])
opening.save()
return Response({'action': "Add Additional Info", 'message': "Additional Info Added"},
status=status.HTTP_200_OK)
else:
raise ValueError("Additional Info Found")
except Http404:
return Response({'action': "Add Additional Info", 'message': 'Opening Not Found'},
status=status.HTTP_404_NOT_FOUND)
except ValueError:
return Response({'action': "Add Additional Info", 'message': "Additional Info already found"},
status=status.HTTP_400_BAD_REQUEST)
except Exception as e:
logger.warning("Add Additional Info: " + str(e))
return Response({'action': "Add 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
if OPENING_TYPE in data:
opening_type= data[OPENING_TYPE]
else:
opening_type= "Placement"
if opening_type == "Internship":
opening = get_object_or_404(Internship, pk=data[OPENING_ID])
applications = InternshipApplication.objects.filter(internship=opening)
serializer = InternshipApplicationSerializerForAdmin(applications, many=True)
else:
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=[APPLICATION_ID, STUDENT_ID, OPENING_ID, ADDITIONAL_INFO, RESUME_FILE_NAME])
def submitApplication(request, id, email, user_type):
try:
data = request.data
if OPENING_TYPE in data:
opening_type= data[OPENING_TYPE]
else:
opening_type= "Placement"
if opening_type == "Internship":
opening = get_object_or_404(Internship, pk=data[OPENING_ID])
else:
opening = get_object_or_404(Placement, pk=data[OPENING_ID])
student = get_object_or_404(Student, pk=data[STUDENT_ID])
# opening = get_object_or_404(Placement, pk=data[OPENING_ID])
student_user = get_object_or_404(User, id=student.id)
if data[APPLICATION_ID] == "":
application = PlacementApplication() if opening_type == "Placement" else InternshipApplication()
application.id = generateRandomString()
if(opening_type == "Placement"):
application.placement = opening
else:
application.internship = opening
application.student = student
if data[RESUME_FILE_NAME] in student.resumes:
application.resume = data[RESUME_FILE_NAME]
else:
raise FileNotFoundError(RESUME_FILE_NAME + " Not Found")
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": "Placement" if opening_type == "Placement" else "Internship",
"additional_info": dict(json.loads(application.additional_info)),
}
subject = STUDENT_APPLICATION_SUBMITTED_TEMPLATE_SUBJECT.format(company_name=opening.company_name)
application.changed_by = get_object_or_404(User, id=id)
application.save()
sendEmail(student_user.email, subject, data, STUDENT_APPLICATION_SUBMITTED_TEMPLATE)
return Response({'action': "Add Student Application", 'message': "Application added"},
status=status.HTTP_200_OK)
else:
if opening_type == "Internship":
application = get_object_or_404(InternshipApplication, id=data[APPLICATION_ID])
else:
application = get_object_or_404(PlacementApplication, id=data[APPLICATION_ID])
if application:
if data[RESUME_FILE_NAME] in student.resumes:
application.resume = data[RESUME_FILE_NAME]
else:
raise FileNotFoundError(RESUME_FILE_NAME + " Not Found")
application.resume = data[RESUME_FILE_NAME]
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": "Placement" if opening_type == "Placement" else "Internship",
"resume": application.resume[16:],
"additional_info_items": dict(json.loads(application.additional_info)),
}
subject = STUDENT_APPLICATION_UPDATED_TEMPLATE_SUBJECT.format(company_name=opening.company_name)
application.changed_by = get_object_or_404(User, id=id)
application.save()
sendEmail(student_user.email, subject, data, STUDENT_APPLICATION_UPDATED_TEMPLATE)
return Response({'action': "Add Student Application", 'message': "Application updated"},
status=status.HTTP_200_OK)
else:
return Response({'action': "Edit Student Application", 'message': "No Application Found"},
status=status.HTTP_400_BAD_REQUEST)
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 AttributeError as e:
return Response({'action': "Submit Application", 'message': str(e)},
status=status.HTTP_400_BAD_REQUEST)
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
if OPENING_TYPE in data:
opening_type= data[OPENING_TYPE]
else:
opening_type= "Placement"
if opening_type == "Internship":
opening = get_object_or_404(Internship, id=data[OPENING_ID])
applications = InternshipApplication.objects.filter(internship=opening)
else:
opening = get_object_or_404(Placement, id=data[OPENING_ID])
applications = PlacementApplication.objects.filter(placement=opening)
filename = generateRandomString()
if not os.path.isdir(STORAGE_DESTINATION_APPLICATION_CSV):
os.makedirs(STORAGE_DESTINATION_APPLICATION_CSV, exist_ok=True)
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(opening.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(str(apl.student.id)) + "/" + urllib.parse.quote(str(apl.resume))
row_details.append(link)
row_details.append(apl.selected)
for i in opening.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()))
return Response({'action': "Create csv", 'message': "Something Went Wrong"},
status=status.HTTP_400_BAD_REQUEST)
@api_view(['POST'])
@isAuthorized(allowed_users=[ADMIN])
@precheck(required_data=[COMPANY_NAME, COMPENSATION_GROSS, OFFER_ACCEPTED, STUDENT_ID, DESIGNATION, TIER])
def addPPO(request, id, email, user_type):
try:
data = request.data
PPO = PrePlacementOffer()
PPO.company = data[COMPANY_NAME]
PPO.compensation = int(data[COMPENSATION_GROSS])
if data[OFFER_ACCEPTED] == "true":
PPO.accepted = True
elif data[OFFER_ACCEPTED] == "false":
PPO.accepted = False
else:
PPO.accepted = None
PPO.student = get_object_or_404(Student, id=data[STUDENT_ID])
PPO.designation = data[DESIGNATION]
PPO.tier = int(data[TIER])
if COMPENSATION_DETAILS in data:
PPO.compensation_details = data[COMPENSATION_DETAILS]
PPO.changed_by = get_object_or_404(User, id=id)
PPO.save()
return Response({'action': "Add PPO", 'message': "PPO added"},
status=status.HTTP_200_OK)
except:
logger.warning("Add PPO: " + str(sys.exc_info()))
return Response({'action': "Add PPO", 'message': "Something Went Wrong"},
status=status.HTTP_400_BAD_REQUEST)
@api_view(['POST'])
@isAuthorized(allowed_users=[ADMIN])
@precheck(required_data=[STUDENT_ID, OPENING_ID])
def getStudentApplication(request, id, email, user_type):
try:
data = request.data
if OPENING_TYPE in data:
opening_type= data[OPENING_TYPE]
else:
opening_type= "Placement"
student = get_object_or_404(Student, id=data[STUDENT_ID])
student_serializer = StudentSerializer(student)
student_details = {
"name": student_serializer.data['name'],
"batch": student.batch,
"branch": student.branch,
"resume_list": student_serializer.data['resume_list'],
}
# search for the application if there or not
if opening_type == "Internship":
application = InternshipApplication.objects.filter(student=student,
internship=get_object_or_404(Internship,
id=data[OPENING_ID]))
else:
application = PlacementApplication.objects.filter(student=student,
placement=get_object_or_404(Placement, id=data[OPENING_ID]))
if application:
if opening_type == "Internship":
serializer = InternshipApplicationSerializer(application[0])
application_info = {
"id": serializer.data['id'],
"additional_info": serializer.data['additional_info'],
"resume": serializer.data['resume_link'],
}
else:
serializer = PlacementApplicationSerializer(application[0])
application_info = {
"id": serializer.data['id'],
"additional_info": serializer.data['additional_info'],
"resume": serializer.data['resume_link'],
}
return Response(
{'action': "Get Student Application", 'application_found': "true", "application_info": application_info,
"student_details": student_details}, status=status.HTTP_200_OK)
else:
return Response(
{'action': "Get Student Application", 'application_found': "false", "student_details": student_details},
status=status.HTTP_404_NOT_FOUND)
except Http404:
return Response({'action': "Get Student Application", 'message': "Student not found."},
status.HTTP_404_NOT_FOUND)
except:
logger.warning("Get Student Application: " + str(sys.exc_info()))
return Response({'action': "Get Student Application", 'message': "Something Went Wrong"},
status.HTTP_400_BAD_REQUEST)
@api_view(['GET'])
@isAuthorized(allowed_users=[ADMIN])
def getStats(request, id, email, user_type):
try:
stats = []
placement_ids = {}
tier_count = {
"CSE": {
"1":0,
"2":0,
"3":0,
"4":0,
"5":0,
"6":0,
"7":0,
"8":0,
"psu":0,
},
"EE": {
"1":0,
"2":0,
"3":0,
"4":0,
"5":0,
"6":0,
"7":0,
"psu":0,
},
"MMAE": {
"1":0,
"2":0,
"3":0,
"4":0,
"5":0,
"6":0,
"7":0,
"8":0,
"psu":0,
},
"Total": {
"1":0,
"2":0,
"3":0,
"4":0,
"5":0,
"6":0,
"7":0,
"8":0,
"psu":0,
},
}
number_of_students_placed = {
"CSE": 0,
"EE": 0,
"MMAE": 0,
"Total": 0,
}
number_of_students_with_multiple_offers = 0
number_of_students_with_no_offers = {
"CSE": 0,
"EE": 0,
"MMAE": 0,
"Total": 0,
}
max_CTC = {
"CSE": 0,
"EE": 0,
"MMAE": 0
}
average_CTC = {
"CSE": 0,
"EE": 0,
"MMAE": 0
}
count = {
"CSE": 0,
"EE": 0,
"MMAE": 0
}
students = Student.objects.all().order_by("roll_no")
for student in students.iterator():
applications = PlacementApplication.objects.filter(student=student, selected=True)
ppos = PrePlacementOffer.objects.filter(student=student, accepted=True)
first_offer_data = None
second_offer_data = None
# get the first and second offer
offers = []
offers.extend(applications)
offers.extend(ppos)
if len(offers) == 0:
number_of_students_with_no_offers[student.branch] += 1
number_of_students_with_no_offers["Total"] += 1
else:
number_of_students_placed[student.branch] += 1
number_of_students_placed["Total"] += 1
if len(offers) > 1:
number_of_students_with_multiple_offers += 1
for offer in offers:
if type(offer) == PrePlacementOffer:
if first_offer_data is None:
first_offer_data = {
"id": offer.id,
"company": offer.company,
"compensation": offer.compensation,
"tier": offer.tier,
"type": "PPO",
}
elif second_offer_data is None:
second_offer_data = {
"id": offer.id,
"company": offer.company,
"compensation": offer.compensation,
"tier": offer.tier,
"type": "PPO",
}
elif type(offer) == PlacementApplication:
if first_offer_data is None:
first_offer_data = {
"id": offer.placement.id,
"company": offer.placement.company_name,
"compensation": offer.placement.compensation_CTC,
"tier": offer.placement.tier,
"type": "Placement",
}
elif second_offer_data is None:
second_offer_data = {
"id": offer.placement.id,
"company": offer.placement.company_name,
"compensation": offer.placement.compensation_CTC,
"tier": offer.placement.tier,
"type": "Placement",
}
data = {
"id": student.id,
"name": student.name,
"roll_no": student.roll_no,
"batch": student.batch,
"branch": student.branch,
"cpi": student.cpi,
"first_offer": first_offer_data['company'] if first_offer_data is not None else None,
"first_offer_tier": first_offer_data['tier'] if first_offer_data is not None else None,
"first_offer_compensation": first_offer_data['compensation'] if first_offer_data is not None else None,
"second_offer": second_offer_data['company'] if second_offer_data is not None else None,
"second_offer_tier": second_offer_data['tier'] if second_offer_data is not None else None,
"second_offer_compensation": second_offer_data['compensation'] if second_offer_data is not None else None,
}
if first_offer_data is not None:
tier_count[student.branch][first_offer_data['tier']] += 1
tier_count['Total'][first_offer_data['tier']] += 1
max_CTC[student.branch] = max(max_CTC[student.branch], first_offer_data['compensation'])
average_CTC[student.branch] += first_offer_data['compensation']
count[student.branch] += 1
if first_offer_data['type'] == "Placement":
placement_ids[first_offer_data['company']] = first_offer_data['id']
if second_offer_data is not None:
tier_count[student.branch][second_offer_data['tier']] += 1
tier_count['Total'][second_offer_data['tier']] += 1
max_CTC[student.branch] = max(max_CTC[student.branch], second_offer_data['compensation'])
average_CTC[student.branch] += second_offer_data['compensation']
count[student.branch] += 1
if second_offer_data['type'] == "Placement":
placement_ids[second_offer_data['company']] = second_offer_data['id']
stats.append(data)
for branch in average_CTC:
if count[branch] > 0:
average_CTC[branch] /= count[branch]
# round off to 2 decimal places
average_CTC[branch] = round(average_CTC[branch], 2)
else:
average_CTC[branch] = 0
return Response({'action': "Get Stats", 'message': "Stats fetched", 'stats': stats, 'placement_ids': placement_ids,
"tier_count": {br: tier_count[br].values() for br in tier_count},
"number_of_students_placed": number_of_students_placed,
"number_of_students_with_multiple_offers": number_of_students_with_multiple_offers,
"number_of_students_with_no_offers": number_of_students_with_no_offers,
"max_CTC": max_CTC,
"average_CTC": average_CTC,
},
status=status.HTTP_200_OK)
except:
logger.warning("Get Stats: " + str(sys.exc_info()))
print(sys.exc_info())
return Response({'action': "Get Stats", 'message': "Something Went Wrong"},
status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET'])
@isAuthorizedService()
@precheck(required_data=[OPENING_ID])
def get_eligible_students(request):
try:
data = request.GET
opening_id = data[OPENING_ID]
if OPENING_TYPE in data:
opening_type= data[OPENING_TYPE]
else:
opening_type= "Placement"
if "send_all" in data:
send_all = "True"==data["send_all"]
else:
send_all = False
eligible_students=get_eligible_emails(opening_id=opening_id, opening_type=opening_type, send_all=send_all)
return Response({'action': "Get Eligible Students", 'message': "Eligible Students Fetched",
'eligible_students': eligible_students},
status=status.HTTP_200_OK)
except Http404:
return Response({'action': "Get Eligible Students", 'message': "Opening Not Found"},
status=status.HTTP_404_NOT_FOUND)
except:
logger.warning("Get Eligible Students: " + str(sys.exc_info()))
return Response({'action': "Get Eligible Students", 'message': "Something Went Wrong"},
status=status.HTTP_400_BAD_REQUEST)

View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class ApisConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'APIs'

View File

@ -0,0 +1,11 @@
from django.urls import path
from . import companyViews
urlpatterns = [
path('addPlacement/', companyViews.addPlacement, name="Add Placement"),
path('verifyEmail/', companyViews.verifyEmail, name="Verify Email"),
path('getAutoFillJnf/', companyViews.autoFillJnf, name="Auto FIll JNF"),
path('addInternship/',companyViews.addInternship,name="Add Internship"),
path('getAutoFillInf/', companyViews.autoFillInf, name="Auto FIll INF"),
]

View File

@ -0,0 +1,537 @@
from rest_framework.decorators import api_view
from .utils import *
from .serializers import *
logger = logging.getLogger('db')
@api_view(['POST'])
@precheck([COMPANY_NAME, ADDRESS, COMPANY_TYPE, NATURE_OF_BUSINESS, TYPE_OF_ORGANISATION, 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,
IS_COMPENSATION_DETAILS_PDF, ALLOWED_BRANCH, RS_ELIGIBLE, SELECTION_PROCEDURE_ROUNDS,
SELECTION_PROCEDURE_DETAILS,
IS_SELECTION_PROCEDURE_DETAILS_PDF, TENTATIVE_DATE_OF_JOINING, TENTATIVE_NO_OF_OFFERS, OTHER_REQUIREMENTS,
RECAPTCHA_VALUE, JOB_LOCATION
])
def addPlacement(request):
try:
data = request.data
files = request.FILES
opening = Placement()
if not verify_recaptcha(data[RECAPTCHA_VALUE]):
raise Exception("Recaptcha Failed")
opening.id = generateRandomString()
# 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.type_of_organisation = data[TYPE_OF_ORGANISATION]
opening.website = data[WEBSITE]
opening.company_details = data[COMPANY_DETAILS]
opening.is_company_details_pdf = data[IS_COMPANY_DETAILS_PDF]
if data[RS_ELIGIBLE] == 'Yes':
opening.rs_eligible = True
else:
opening.rs_eligible = False
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
if data[IS_COMPANY_DETAILS_PDF] == "true" and len(opening.company_details_pdf_names) > 0:
opening.is_company_details_pdf = True
elif data[IS_COMPANY_DETAILS_PDF] == "false" and len(opening.company_details_pdf_names) == 0:
opening.is_company_details_pdf = False
else:
raise ValueError('Invalid value for is_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.upper() == '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]
opening.job_location = data[JOB_LOCATION]
opening.is_description_pdf = data[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
# Check if is_description_pdf is boolean
if data[IS_DESCRIPTION_PDF] == "true" and len(opening.description_pdf_names) > 0:
opening.is_description_pdf = True
elif data[IS_DESCRIPTION_PDF] == "false" and len(opening.description_pdf_names) == 0:
opening.is_description_pdf = False
else:
raise ValueError('Invalid value for is_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('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('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('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 Bonus must be an integer')
opening.is_compensation_details_pdf = data[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
# Check if is_compensation_details_pdf is boolean
if data[IS_COMPENSATION_DETAILS_PDF] == "true" and len(opening.compensation_details_pdf_names) > 0:
opening.is_compensation_details_pdf = True
elif data[IS_COMPENSATION_DETAILS_PDF] == "false" and len(opening.compensation_details_pdf_names) == 0:
opening.is_compensation_details_pdf = False
else:
raise ValueError('Invalid value for is_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:
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]
opening.is_selection_procedure_details_pdf = data[IS_SELECTION_PROCEDURE_DETAILS_PDF]
if opening.is_selection_procedure_details_pdf == "true":
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.selection_procedure_details_pdf_names = selection_procedure_details_pdf
# Check if is_selection_procedure_details_pdf is boolean
if data[IS_SELECTION_PROCEDURE_DETAILS_PDF] == "true" and len(
opening.selection_procedure_details_pdf_names) > 0:
opening.is_selection_procedure_details_pdf = True
elif data[IS_SELECTION_PROCEDURE_DETAILS_PDF] == "false" and len(
opening.selection_procedure_details_pdf_names) == 0:
opening.is_selection_procedure_details_pdf = False
else:
raise ValueError('Invalid value for is_selection_procedure_pdf')
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.datetime.strptime(data[TENTATIVE_DATE_OF_JOINING],
'%d-%m-%Y').date()
# 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))
# 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])
elif data[TENTATIVE_NO_OF_OFFERS] == 'null':
opening.tentative_no_of_offers = None
else:
raise ValueError('Tentative No Of Offers must be an integer')
opening.other_requirements = data[OTHER_REQUIREMENTS]
opening.save()
stat, link = generateOneTimeVerificationLink(opening.email, opening.id, "Placement")
if not stat:
raise RuntimeError("Error in generating one time verification link for placement")
data = {
"designation": opening.designation,
"one_time_link": link,
"opening_type": "Job"
}
sendEmail(opening.email, COMPANY_EMAIl_VERIFICATION_TEMPLATE_SUBJECT, data,
COMPANY_EMAIL_VERIFICATION_TEMPLATE)
return Response({'action': "Add Placement", 'message': "Placement Added Successfully"},
status=status.HTTP_200_OK)
except ValueError as e:
store_all_files(request)
exception_email(data)
logger.warning("ValueError in addPlacement: " + str(e))
logger.warning(traceback.format_exc())
return Response({'action': "Add Placement", 'message': str(e)},
status=status.HTTP_400_BAD_REQUEST)
except:
store_all_files(request)
exception_email(data)
logger.warning("Add New Placement: " + str(sys.exc_info()))
logger.warning(traceback.format_exc())
return Response({'action': "Add Placement", 'message': "Something went wrong"},
status=status.HTTP_400_BAD_REQUEST)
@api_view(['POST'])
@precheck([TOKEN])
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'])
# get email, opening_id, opening_type from token
email = decoded_token['email']
opening_id = decoded_token['opening_id']
opening_type = decoded_token['opening_type']
# get opening based on opening_type and opening_id
if opening_type == PLACEMENT:
opening = get_object_or_404(Placement, id=opening_id)
if email != opening.email:
raise ValueError("Invalid Email")
if not opening.email_verified:
opening.email_verified = True
send_email_to_company = True
else:
send_email_to_company = False
opening.save()
elif opening_type == INTERNSHIP:
opening = get_object_or_404(Internship, id=opening_id)
if email != opening.email:
raise ValueError("Invalid Email")
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.
send_email_for_opening(opening)
return Response({'action': "Verify Email", 'message': "Email Verified Successfully"},
status=status.HTTP_200_OK)
except Http404:
return Response({'action': "Verify Email", 'message': "Opening Not Found"},
status=status.HTTP_404_NOT_FOUND)
except ValueError as e:
return Response({'action': "Verify Email", 'message': str(e)},
status=status.HTTP_400_BAD_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)
@api_view(['GET'])
@precheck([PLACEMENT_ID])
def autoFillJnf(request):
try:
data = request.GET
placement_id = data.get(PLACEMENT_ID)
opening = get_object_or_404(Placement, id=placement_id)
serializer = AutofillSerializers(opening)
return Response({'action': "Get AutoFill", 'message': 'Data Found', 'placement_data': serializer.data},
status=status.HTTP_200_OK)
except Http404:
return Response({'action': "Get AutoFill", 'message': 'Placement Not Found'},
status=status.HTTP_404_NOT_FOUND)
except Exception as e:
traceback_str = traceback.format_exc()
logger.warning("Get AutoFill: " + traceback_str)
return Response({'action': "Get AutoFill", 'message': "Something went wrong"},
status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET'])
@precheck([INTERNSHIP_ID])
def autoFillInf(request):
try:
data = request.GET
internship_id = data.get(INTERNSHIP_ID)
opening = get_object_or_404(Internship, id=internship_id)
serializer = AutofillSerializersInternship(opening)
return Response({'action': "Get AutoFill ", 'message': 'Data Found', 'internship_data': serializer.data},
status=status.HTTP_200_OK)
except Http404:
return Response({'action': "Get AutoFill", 'message': 'Internship Not Found'},
status=status.HTTP_404_NOT_FOUND)
except Exception as e:
traceback_str = traceback.format_exc()
logger.warning("Get AutoFill: " + traceback_str)
return Response({'action': "Get AutoFill", 'message': "Something went wrong"},
status=status.HTTP_400_BAD_REQUEST)
## Internships ##
@api_view(['POST'])
@precheck([COMPANY_NAME, WEBSITE, IS_COMPANY_DETAILS_PDF, COMPANY_DETAILS, ADDRESS,
CITY, STATE, COUNTRY, PINCODE, COMPANY_TYPE, NATURE_OF_BUSINESS, IS_DESCRIPTION_PDF,
DESIGNATION, INTERNSHIP_LOCATION, DESCRIPTION, SEASON, START_DATE, END_DATE, WORK_TYPE,
ALLOWED_BRANCH, SOPHOMORES_ELIIGIBLE, RS_ELIGIBLE, NUM_OFFERS, IS_STIPEND_DETAILS_PDF, STIPEND,
FACILITIES, OTHER_FACILITIES, SELECTION_PROCEDURE_ROUNDS, SELECTION_PROCEDURE_DETAILS, IS_SELECTION_PROCEDURE_DETAILS_PDF,
SELECTION_PROCEDURE_DETAILS, OTHER_REQUIREMENTS,
CONTACT_PERSON_NAME, PHONE_NUMBER, EMAIL, RECAPTCHA_VALUE])
def addInternship(request):
logger.info("INF filled by " + str(request.data['email']))
try:
data = request.data
files = request.FILES
internship = Internship()
if not verify_recaptcha(data[RECAPTCHA_VALUE]):
raise Exception("Recaptcha Failed")
internship.id = generateRandomString()
# Add a company details in the internship
internship.company_name = data[COMPANY_NAME]
internship.website = data[WEBSITE]
if data[IS_COMPANY_DETAILS_PDF] == "true":
internship.is_company_details_pdf = True
else:
internship.is_company_details_pdf = False
if internship.is_company_details_pdf:
company_details_pdf = []
for file in files.getlist(COMPANY_DETAILS_PDF):
file_location = STORAGE_DESTINATION_COMPANY_ATTACHMENTS + internship.id + '/'
company_details_pdf.append(saveFile(file, file_location))
internship.company_details_pdf_names = company_details_pdf
internship.company_details = data[COMPANY_DETAILS]
internship.address = data[ADDRESS]
internship.city = data[CITY]
internship.state = data[STATE]
internship.country = data[COUNTRY]
if internship.country.upper() == 'INDIA':
internship.city_type = 'Domestic'
else:
internship.city_type = 'International'
internship.pin_code = data[PINCODE]
internship.company_type = data[COMPANY_TYPE]
internship.nature_of_business = data[NATURE_OF_BUSINESS]
if data[IS_DESCRIPTION_PDF] == "true":
internship.is_description_pdf = True
else:
internship.is_description_pdf = False
if internship.is_description_pdf:
description_pdf = []
for file in files.getlist(DESCRIPTION_PDF):
file_location = STORAGE_DESTINATION_COMPANY_ATTACHMENTS + internship.id + '/'
description_pdf.append(saveFile(file, file_location))
internship.description_pdf_names = description_pdf
internship.designation = data[DESIGNATION]
internship.location = data[INTERNSHIP_LOCATION]
internship.description = data[DESCRIPTION]
if data[SEASON] == "":
raise ValueError('Season cannot be empty')
elif set(json.loads(data[SEASON])).issubset(SEASONS):
internship.season = json.loads(data[SEASON])
else:
raise ValueError('Season must be a subset of ' + str(SEASONS))
internship.interning_period_from = datetime.datetime.strptime(data[START_DATE], '%d-%m-%Y').date()
internship.interning_period_to = datetime.datetime.strptime(data[END_DATE], '%d-%m-%Y').date()
if data[WORK_TYPE] == 'Work from home':
internship.is_work_from_home = True
else:
internship.is_work_from_home = False
if data[ALLOWED_BATCH] is None or json.loads(data[ALLOWED_BATCH]) == "":
raise ValueError('Allowed Branch cannot be empty')
elif set(json.loads(data[ALLOWED_BATCH])).issubset(BATCHES):
internship.allowed_batch = json.loads(data[ALLOWED_BATCH])
else:
raise ValueError('Allowed Batch must be a subset of ' + str(BATCHES))
if data[ALLOWED_BRANCH] is None or json.loads(data[ALLOWED_BRANCH]) == "":
raise ValueError('Allowed Branch cannot be empty')
elif set(json.loads(data[ALLOWED_BRANCH])).issubset(BRANCHES):
internship.allowed_branch = json.loads(data[ALLOWED_BRANCH])
else:
raise ValueError('Allowed Branch must be a subset of ' + str(BRANCHES))
if data[SOPHOMORES_ELIIGIBLE] == 'Yes':
internship.sophomore_eligible = True
else:
internship.sophomore_eligible = False
if data[RS_ELIGIBLE] == 'Yes':
internship.rs_eligible = True
else:
internship.rs_eligible = False
if data[NUM_OFFERS].isdigit():
internship.tentative_no_of_offers = int(data[NUM_OFFERS])
else:
raise ValueError('Number of offers must be an integer')
if data[IS_STIPEND_DETAILS_PDF] == "true":
internship.is_stipend_description_pdf = True
else:
internship.is_stipend_description_pdf = False
if internship.is_stipend_description_pdf:
stipend_details_pdf = []
for file in files.getlist(STIPEND_DETAILS_PDF):
file_location = STORAGE_DESTINATION_COMPANY_ATTACHMENTS + internship.id + '/'
stipend_details_pdf.append(saveFile(file, file_location))
internship.stipend_description_pdf_names = stipend_details_pdf
if data[STIPEND].isdigit():
internship.stipend = int(data[STIPEND])
else:
raise ValueError('Stipend must be an integer')
if data[FACILITIES] != "" :
if json.loads(data[FACILITIES]) == "":
internship.facilities_provided = []
elif set(json.loads(data[FACILITIES])).issubset(FACILITIES_CHOICES):
internship.facilities_provided = json.loads(data[FACILITIES])
else:
raise ValueError('Facilities must be a subset of ' + str(FACILITIES_CHOICES))
else:
internship.facilities_provided = []
internship.other_facilities = data[OTHER_FACILITIES]
if data[SELECTION_PROCEDURE_ROUNDS] is None:
raise ValueError('Selection Procedure Rounds cannot be empty')
else:
try:
internship.selection_procedure_rounds = json.loads(data[SELECTION_PROCEDURE_ROUNDS])
except:
raise ValueError('Selection Procedure Rounds must be a list')
internship.selection_procedure_details = data[SELECTION_PROCEDURE_DETAILS]
if data[IS_SELECTION_PROCEDURE_DETAILS_PDF] == "true":
internship.is_selection_procedure_details_pdf = True
else:
internship.is_selection_procedure_details_pdf = False
if internship.is_selection_procedure_details_pdf:
selection_procedure_details_pdf = []
for file in files.getlist(SELECTION_PROCEDURE_DETAILS_PDF):
file_location = STORAGE_DESTINATION_COMPANY_ATTACHMENTS + internship.id + '/'
selection_procedure_details_pdf.append(saveFile(file, file_location))
internship.selection_procedure_details_pdf_names = selection_procedure_details_pdf
internship.additional_facilities = data[OTHER_FACILITIES]
#add additional info
# Only Allowing Fourth Year for Placement
internship.academic_requirements = data[OTHER_REQUIREMENTS]
internship.contact_person_name = data[CONTACT_PERSON_NAME]
internship.phone_number = data[PHONE_NUMBER]
internship.email = data[EMAIL]
internship.save()
stat, link = generateOneTimeVerificationLink(internship.email, internship.id, "Internship")
if not stat:
raise RuntimeError("Error in generating one time verification link for internship")
data = {
"designation": internship.designation,
"one_time_link": link,
"opening_type": "Internship"
}
sendEmail(internship.email, COMPANY_EMAIl_VERIFICATION_TEMPLATE_SUBJECT, data,
COMPANY_EMAIL_VERIFICATION_TEMPLATE)
return Response({'action': "Add Internship", 'message': "Internship Added Successfully"},
status=status.HTTP_200_OK)
except ValueError as e:
store_all_files(request)
# exception_email(data)
logger.warning("ValueError in addInternship: " + str(e))
logger.warning(traceback.format_exc())
return Response({'action': "Add Internship", 'message': str(e)},
status=status.HTTP_400_BAD_REQUEST)
except:
store_all_files(request)
# exception_email(data)
logger.warning("Add New Internship: " + str(sys.exc_info()))
logger.warning(traceback.format_exc())
return Response({'action': "Add Internship", 'message': "Something went wrong"},
status=status.HTTP_400_BAD_REQUEST)

View File

@ -0,0 +1,266 @@
import os
DEBUG = os.environ.get('DEBUG') == "True"
BRANCH_CHOICES = [
["CSE", "CSE"],
["EE", "EE"],
["ME", "ME"],
['MMAE', 'MMAE'],
['EP', 'EP'],
['CIVIL', 'CIVIL'],
['CHEMICAL', 'CHEMICAL'],
['BSMS', 'BSMS'],
]
BRANCHES = [
"CSE",
"EE",
"MMAE",
"EP",
"CIVIL",
"CHEMICAL",
"BSMS",
]
BATCHES = [ #change it accordingly
"2023",
"2022",
"2021",
"2020",
]
BATCH_CHOICES = [
["2022", "2022"],
["2021", "2021"],
["2020", "2020"],
["2019", "2019"],
["2018", "2018"],
["2017", "2017"],
]
OFFER_CITY_TYPE = [
['Domestic', 'Domestic'],
['International', 'International']
]
TIERS = [
['psu', 'PSU'],
['1', 'Tier 1'],
['2', 'Tier 2'],
['3', 'Tier 3'],
['4', 'Tier 4'],
['5', 'Tier 5'],
['6', 'Tier 6'],
['7', 'Tier 7'],
['8', 'Open Tier'],
]
DEGREE_CHOICES = [
['bTech', 'B.Tech'],
['ms/phd', 'MS/ PhD'],
['mTech', 'M.Tech'],
]
TOTAL_BRANCHES = 7 # Total No of Branches
TOTAL_BATCHES = 6 # Total No of Batches
CDC_REPS_EMAILS = [
"cdc@iitdh.ac.in",
"cdcfic@iitdh.ac.in",
"vandana@iitdh.ac.in",
"sairam@iitdh.ac.in",
"satyapriya.gupta@iitdh.ac.in",
"dhriti.ghosh@iitdh.ac.in",
"suvamay.jana@iitdh.ac.in",
"ramesh.nayaka@iitdh.ac.in"
]
CDC_REPS_EMAILS_FOR_ISSUE=[ #add reps emails
"cdc.support@iitdh.ac.in",
"cdc@iitdh.ac.in"
]
# To be Configured Properly
CLIENT_ID = os.environ.get('GOOGLE_OAUTH_CLIENT_ID') # Google Login Client ID
CLIENT_SECRET = os.environ.get('GOOGLE_OAUTH_CLIENT_SECRET') # Google Login Client Secret
REDIRECT_URI = 'postmessage' # Google Login Redirect URI
OAUTH2_API_ENDPOINT = 'https://oauth2.googleapis.com/token' # Google Login OAUTH2 URL
# To be Configured Properly
PLACEMENT_OPENING_URL = "https://cdc.iitdh.ac.in/portal/student/dashboard/placements/{id}" # On frontend, this is the URL to be opened
LINK_TO_STORAGE_COMPANY_ATTACHMENT = "https://cdc.iitdh.ac.in/storage/Company_Attachments/"
LINK_TO_STORAGE_RESUME = "https://cdc.iitdh.ac.in/storage/Resumes/"
LINK_TO_APPLICATIONS_CSV = "https://cdc.iitdh.ac.in/storage/Application_CSV/"
LINK_TO_EMAIl_VERIFICATION_API = "https://cdc.iitdh.ac.in/portal/company/verifyEmail?token={token}"
PDF_FILES_SERVING_ENDPOINT = 'https://cdc.iitdh.ac.in/storage/Company_Attachments/' # TODO: Change this to actual URL
AUTH_CODE = "code"
ID_TOKEN = "id_token"
REFRESH_TOKEN = "refresh_token"
EMAIL = "email"
STUDENT = 'student'
ADMIN = 'admin'
SUPER_ADMIN = 's_admin'
SERVICE= 'service'
COMPANY = 'company'
TIER = 'tier'
# To be Configured Properly
FOURTH_YEAR = '2021'
MAX_OFFERS_PER_STUDENT = 2
MAX_RESUMES_PER_STUDENT = 3
EMAIL_VERIFICATION_TOKEN_TTL = 48 # in hours
JNF_TEXT_MAX_CHARACTER_COUNT = 100
JNF_TEXTMEDIUM_MAX_CHARACTER_COUNT = 200
JNF_TEXTAREA_MAX_CHARACTER_COUNT = 1000
JNF_SMALLTEXT_MAX_CHARACTER_COUNT = 50
STORAGE_DESTINATION_RESUMES = "./Storage/Resumes/"
STORAGE_DESTINATION_COMPANY_ATTACHMENTS = './Storage/Company_Attachments/'
STORAGE_DESTINATION_APPLICATION_CSV = './Storage/Application_CSV/'
TOKEN = 'token'
RESUME_FILE_NAME = 'resume_file_name'
APPLICATION_ID = "application_id"
OPENING_ID = "opening_id"
ADDITIONAL_INFO = "additional_info"
FIELD = "field"
STATUS_ACCEPTING_APPLICATIONS = "Accepting Applications"
PLACEMENT = "Placement"
PLACEMENT_ID = "placement_id"
COMPANY_NAME = "company_name"
COMPANY_TYPE = "company_type"
NATURE_OF_BUSINESS = "nature_of_business"
TYPE_OF_ORGANISATION = "type_of_organisation"
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'
ADDRESS = "address"
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'
JOB_LOCATION = 'job_location'
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'
RS_ELIGIBLE = 'rs_eligible'
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'
RECAPTCHA_VALUE = 'recaptchakey'
STUDENT_LIST = "student_list"
STUDENT_ID = "student_id"
STUDENT_SELECTED = "student_selected"
EXCLUDE_IN_PDF = ['id', 'is_company_details_pdf', 'offer_accepted', 'is_description_pdf',
'is_compensation_details_pdf', 'is_selection_procedure_details_pdf',
'email_verified', 'created_at', 'changed_by', 'is_stipend_description_pdf']
SPECIAL_FORMAT_IN_PDF = ['website', 'company_details_pdf_names', 'description_pdf_names',
'compensation_details_pdf_names',
'selection_procedure_details_pdf_names',
'stipend_description_pdf_names']
COMPANY_OPENING_ERROR_TEMPLATE = "Alert! Error submitting opening for {company_name}."
COMPANY_OPENING_SUBMITTED_TEMPLATE_SUBJECT = "Notification Submitted - {id}, {company} - Career Development Cell, IIT Dharwad"
STUDENT_APPLICATION_STATUS_TEMPLATE_SUBJECT = 'Application Status - {company_name} - {id}'
STUDENT_APPLICATION_SUBMITTED_TEMPLATE_SUBJECT = 'CDC - Application Submitted - {company_name}'
STUDENT_APPLICATION_UPDATED_TEMPLATE_SUBJECT = 'CDC - Application Updated - {company_name}'
COMPANY_EMAIl_VERIFICATION_TEMPLATE_SUBJECT = 'Email Verification - Career Development Cell, IIT Dharwad'
NOTIFY_STUDENTS_OPENING_TEMPLATE_SUBJECT = 'Placement Opportunity at {company_name}'
REMINDER_STUDENTS_OPENING_TEMPLATE_SUBJECT = 'Reminder - Placement Opportunity at {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'
STUDENT_APPLICATION_UPDATED_TEMPLATE = 'student_application_updated.html'
COMPANY_EMAIL_VERIFICATION_TEMPLATE = 'company_email_verification.html'
COMPANY_JNF_RESPONSE_TEMPLATE = 'company_jnf_response.html'
NOTIFY_STUDENTS_OPENING_TEMPLATE = 'notify_students_new_opening.html'
REMINDER_STUDENTS_OPENING_TEMPLATE = 'students_opening_reminder.html'
APPLICATION_CSV_COL_NAMES = ['Applied At', 'Roll No.', 'Name', 'Email', 'Phone Number', 'Branch', 'Batch', 'CPI',
'Resume', 'Selected', ]
ISSUE_SUBMITTED_TEMPLATE_SUBJECT = 'CDC - Issue Submitted'
STUDENT_ISSUE_SUBMITTED_TEMPLATE = 'student_issue_submitted.html'
REPS_ISSUE_SUBMITTED_TEMPLATE = 'reps_issue_submitted.html'
# Internships
INTERNSHIP = 'Internship'
INTERNSHIP_ID = 'internship_id'
INF_COMPANY_NAME = 'companyname'
INTERNSHIP_LOCATION = 'internship_location'
SEASON = 'season'
START_DATE = 'start_date'
END_DATE = 'end_date'
WORK_TYPE = 'work_type'
SOPHOMORES_ELIIGIBLE = 'sophomores_allowed'
NUM_OFFERS = 'num_offers'
IS_STIPEND_DETAILS_PDF = 'is_stipend_details_pdf'
STIPEND = 'stipend'
FACILITIES = 'facilities'
OTHER_FACILITIES = 'other_facilities'
STIPEND_DETAILS_PDF = 'compensation_details_pdf'
STIPEND_DETAILS_PDF_NAMES = 'stipend_description_pdf_names'
INTERNSHIP_OPENING_URL = "https://cdc.iitdh.ac.in/portal/student/dashboard/internships/{id}" # On frontend, this is the URL to be opened
SEASONS = (
'Summer',
'Winter',
'Autumn',
'Spring',
)
SEASON_CHOICES = (
['Summer', 'Summer'],
['Winter', 'Winter'],
['Autumn', 'Autumn'],
['Spring', 'Spring'],
)
FACILITIES_CHOICES = [
'Accommodation',
'Food',
'Transport',
'Medical',
]
INF_FACILITIES_PROVIDED = [
['Accommodation', 'Accommodation'],
['Food', 'Food'],
['Transport', 'Transport'],
['Medical', 'Medical'],
]
INF_TOTAL_SEASONS = len(SEASONS)
INF_TOTAL_FACILITIES = len(FACILITIES_CHOICES)

View File

@ -0,0 +1,511 @@
from django.contrib.postgres.fields import ArrayField
from django.db import models
from django.utils import timezone
from simple_history.models import HistoricalRecords
from .constants import *
# from .utils import *
class User(models.Model):
email = models.EmailField(primary_key=True, blank=False, max_length=JNF_TEXT_MAX_CHARACTER_COUNT)
id = models.CharField(blank=False, max_length=25, db_index=True)
user_type = ArrayField(models.CharField(blank=False, max_length=10), size=4, default=list, blank=False)
last_login_time = models.DateTimeField(default=timezone.now)
history = HistoricalRecords()
class Meta:
verbose_name_plural = "User"
unique_together = ('email', 'id')
class Student(models.Model):
id = models.CharField(blank=False, max_length=15, primary_key=True)
roll_no = models.CharField(blank=False, max_length=15, unique=True)
name = models.CharField(blank=False, max_length=JNF_TEXT_MAX_CHARACTER_COUNT)
batch = models.CharField(max_length=10, choices=BATCH_CHOICES, blank=False)
branch = models.CharField(choices=BRANCH_CHOICES, blank=False, max_length=10)
phone_number = models.PositiveBigIntegerField(blank=True, default=None, null=True)
resumes = ArrayField(models.CharField(null=True, default=None, max_length=JNF_TEXT_MAX_CHARACTER_COUNT), size=10,
default=list, blank=True)
cpi = models.DecimalField(decimal_places=2, max_digits=4)
can_apply = models.BooleanField(default=True, verbose_name='Registered')
can_apply_internship = models.BooleanField(default=True, verbose_name='Internship Registered') #added for internship
changed_by = models.ForeignKey(User, blank=True, on_delete=models.RESTRICT, default=None, null=True)
degree = models.CharField(choices=DEGREE_CHOICES, blank=False, max_length=10, default=DEGREE_CHOICES[0][0])
history = HistoricalRecords(user_model=User)
def __str__(self):
return str(self.roll_no)
@property
def _history_user(self):
return self.changed_by
@_history_user.setter
def _history_user(self, value):
if isinstance(value, User):
self.changed_by = value
else:
self.changed_by = None
class Admin(models.Model):
id = models.CharField(blank=False, max_length=15, primary_key=True)
name = models.CharField(blank=False, max_length=JNF_TEXT_MAX_CHARACTER_COUNT)
changed_by = models.ForeignKey(User, blank=True, on_delete=models.RESTRICT, default=None, null=True)
history = HistoricalRecords(user_model=User)
@property
def _history_user(self):
return self.changed_by
@_history_user.setter
def _history_user(self, value):
if isinstance(value, User):
self.changed_by = value
else:
self.changed_by = None
def two_day_after_today():
# round off to nearest day
return timezone.now().replace(hour=0, minute=0, second=0, microsecond=0) + timezone.timedelta(days=2)
class Placement(models.Model):
id = models.CharField(blank=False, primary_key=True, max_length=15)
# Company Details
company_name = models.CharField(blank=False, max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT)
address = models.CharField(blank=False, max_length=JNF_TEXTAREA_MAX_CHARACTER_COUNT)
company_type = models.CharField(blank=False, max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT)
nature_of_business = models.CharField(blank=False, max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, default="")
type_of_organisation = models.CharField(max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, default="", blank=False)
website = models.CharField(blank=True, max_length=JNF_TEXT_MAX_CHARACTER_COUNT)
company_details = models.CharField(max_length=JNF_TEXTAREA_MAX_CHARACTER_COUNT, default=None, null=True, blank=True)
company_details_pdf_names = ArrayField(
models.CharField(null=True, default=None, max_length=JNF_TEXT_MAX_CHARACTER_COUNT), 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=JNF_TEXT_MAX_CHARACTER_COUNT)
phone_number = models.PositiveBigIntegerField(blank=False)
email = models.CharField(blank=False, max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, default="")
city = models.CharField(blank=False, max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, default="")
state = models.CharField(blank=False, max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, default="")
country = models.CharField(blank=False, max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, default="")
pin_code = models.IntegerField(blank=False, default=None, null=True)
city_type = models.CharField(blank=False, max_length=15, choices=OFFER_CITY_TYPE)
# Job Details
designation = models.CharField(blank=False, max_length=JNF_TEXT_MAX_CHARACTER_COUNT, default=None, null=True)
description = models.CharField(blank=False, max_length=JNF_TEXTAREA_MAX_CHARACTER_COUNT, default=None, null=True)
job_location = models.CharField(blank=False, max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, default="")
description_pdf_names = ArrayField(
models.CharField(null=True, default=None, max_length=JNF_TEXT_MAX_CHARACTER_COUNT), 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_pdf_names = ArrayField(
models.CharField(null=True, default=None, max_length=JNF_TEXT_MAX_CHARACTER_COUNT), size=5,
default=list, blank=True)
is_compensation_details_pdf = models.BooleanField(blank=False, default=False)
bond_details = models.CharField(blank=True, max_length=JNF_TEXTAREA_MAX_CHARACTER_COUNT)
selection_procedure_rounds = ArrayField(
models.CharField(null=True, default=None, max_length=JNF_TEXT_MAX_CHARACTER_COUNT), size=10,
default=list, blank=True)
selection_procedure_details = models.CharField(blank=True, max_length=JNF_TEXTAREA_MAX_CHARACTER_COUNT)
selection_procedure_details_pdf_names = ArrayField(
models.CharField(null=True, default=None, max_length=JNF_TEXT_MAX_CHARACTER_COUNT),
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
)
tentative_no_of_offers = models.IntegerField(blank=False, default=None, null=True)
rs_eligible = models.BooleanField(blank=False, default=False)
other_requirements = models.CharField(blank=True, max_length=JNF_TEXTAREA_MAX_CHARACTER_COUNT, default="")
additional_info = ArrayField(models.CharField(blank=True, max_length=JNF_TEXTMEDIUM_MAX_CHARACTER_COUNT), 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)
updated_at = models.DateTimeField(blank=False, default=None, null=True)
changed_by = models.ForeignKey(User, on_delete=models.RESTRICT, blank=True, null=True)
history = HistoricalRecords(user_model=User)
def format(self):
if self.company_name is not None:
self.company_name = self.company_name.strip()[:JNF_SMALLTEXT_MAX_CHARACTER_COUNT]
if self.company_type is not None:
self.company_type = self.company_type.strip()[:JNF_SMALLTEXT_MAX_CHARACTER_COUNT]
if self.company_details is not None:
self.company_details = self.company_details.strip()[:JNF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.address is not None:
self.address = self.address.strip()[:JNF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.nature_of_business is not None:
self.nature_of_business = self.nature_of_business.strip()[:JNF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.type_of_organisation is not None:
self.type_of_organisation = self.type_of_organisation.strip()[:JNF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.website is not None:
self.website = self.website.strip()[:JNF_TEXT_MAX_CHARACTER_COUNT]
if self.contact_person_name is not None:
self.contact_person_name = self.contact_person_name.strip()[:JNF_TEXT_MAX_CHARACTER_COUNT]
if self.email is not None:
self.email = self.email.strip()[:JNF_SMALLTEXT_MAX_CHARACTER_COUNT]
if self.city is not None:
self.city = self.city.strip()[:JNF_SMALLTEXT_MAX_CHARACTER_COUNT]
if self.state is not None:
self.state = self.state.strip()[:JNF_SMALLTEXT_MAX_CHARACTER_COUNT]
if self.country is not None:
self.country = self.country.strip()[:JNF_SMALLTEXT_MAX_CHARACTER_COUNT]
if self.city_type is not None:
self.city_type = self.city_type.strip()[:JNF_SMALLTEXT_MAX_CHARACTER_COUNT]
if self.designation is not None:
self.designation = self.designation.strip()[:JNF_TEXT_MAX_CHARACTER_COUNT]
if self.description is not None:
self.description = self.description.strip()[:JNF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.job_location is not None:
self.job_location = self.job_location.strip()[:JNF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.selection_procedure_details is not None:
self.selection_procedure_details = self.selection_procedure_details.strip()[
:JNF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.bond_details is not None:
self.bond_details = self.bond_details.strip()[:JNF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.other_requirements is not None:
self.other_requirements = self.other_requirements.strip()[:JNF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.additional_info is not None:
self.additional_info = [info.strip()[:JNF_TEXTMEDIUM_MAX_CHARACTER_COUNT] for info in
list(self.additional_info)]
@property
def _history_user(self):
return self.changed_by
@_history_user.setter
def _history_user(self, value):
if isinstance(value, User):
self.changed_by = value
else:
self.changed_by = None
def save(self, *args, **kwargs):
''' On save, add timestamps '''
if not self.created_at:
self.created_at = timezone.now()
self.format()
self.updated_at = timezone.now()
return super(Placement, self).save(*args, **kwargs)
def __str__(self):
return self.company_name + " - " + self.designation
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=JNF_TEXT_MAX_CHARACTER_COUNT, blank=False, null=True, default=None)
additional_info = models.JSONField(blank=True, null=True, default=None)
selected = models.BooleanField(null=True, default=None, blank=True)
offer_accepted = models.BooleanField(null=True, default=None, blank=True) # True if offer accepted, False if rejected, None if not yet decided
applied_at = models.DateTimeField(blank=False, default=None, null=True)
updated_at = models.DateTimeField(blank=False, default=None, null=True)
changed_by = models.ForeignKey(User, blank=False, on_delete=models.RESTRICT, default=None, null=True)
history = HistoricalRecords(user_model=User)
def save(self, *args, **kwargs):
''' On save, add timestamps '''
if not self.applied_at:
self.applied_at = timezone.now()
self.updated_at = timezone.now()
return super(PlacementApplication, self).save(*args, **kwargs)
@property
def _history_user(self):
return self.changed_by
@_history_user.setter
def _history_user(self, value):
if isinstance(value, User):
self.changed_by = value
else:
self.changed_by = None
class Meta:
verbose_name_plural = "Placement Applications"
unique_together = ('placement_id', 'student_id')
def __str__(self):
return self.placement.company_name + " - " + self.student.name
class PrePlacementOffer(models.Model):
id = models.AutoField(primary_key=True)
student = models.ForeignKey(Student, on_delete=models.CASCADE, blank=False)
company = models.CharField(max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, blank=False, default="",
verbose_name="Company Name")
compensation = models.IntegerField(blank=False) # Job - Per Year
compensation_details = models.CharField(blank=True, max_length=200)
tier = models.CharField(blank=False, choices=TIERS, max_length=10)
designation = models.CharField(blank=False, max_length=100, default=None, null=True)
accepted = models.BooleanField(default=None, null=True)
changed_by = models.ForeignKey(User, blank=False, on_delete=models.RESTRICT, default=None, null=True)
history = HistoricalRecords(user_model=User)
@property
def _history_user(self):
return self.changed_by
@_history_user.setter
def _history_user(self, value):
if isinstance(value, User):
self.changed_by = value
else:
self.changed_by = None
class Internship(models.Model):
id = models.CharField(blank=False, primary_key=True, max_length=15) #unique id for each internship
# Company Details
company_name = models.CharField(blank=False, max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT)
website = models.CharField(blank=True, max_length=JNF_TEXT_MAX_CHARACTER_COUNT)
is_company_details_pdf = models.BooleanField(blank=False, default=False)
company_details_pdf_names = ArrayField(
models.CharField(null=True, default=None, max_length=JNF_TEXT_MAX_CHARACTER_COUNT), size=5,
default=list, blank=True)
company_details = models.CharField(max_length=JNF_TEXTAREA_MAX_CHARACTER_COUNT, default=None, null=True, blank=True)
#Company Address
address = models.CharField(blank=False, max_length=JNF_TEXTAREA_MAX_CHARACTER_COUNT)
city = models.CharField(blank=False, max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, default="")
city_type = models.CharField(blank=True, max_length=15, choices=OFFER_CITY_TYPE)
state = models.CharField(blank=False, max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, default="")
country = models.CharField(blank=False, max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, default="")
pin_code = models.IntegerField(blank=False, default=None, null=True)
company_type = models.CharField(blank=False, max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT)
nature_of_business = models.CharField(blank=False, max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, default="")
#Internship Details
is_description_pdf = models.BooleanField(blank=False, default=False)
description_pdf_names = ArrayField(
models.CharField(null=True, default=None, max_length=JNF_TEXT_MAX_CHARACTER_COUNT), size=5, default=list,
blank=True)
designation = models.CharField(blank=False, max_length=JNF_TEXT_MAX_CHARACTER_COUNT, default="")
description = models.CharField(blank=False, max_length=JNF_TEXTAREA_MAX_CHARACTER_COUNT, default=None, null=True)
location = models.CharField(blank=False, max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, default="")
season = ArrayField(
models.CharField(choices=SEASON_CHOICES, max_length=10, blank=False),
size=INF_TOTAL_SEASONS,
default=list
)
interning_period_from = models.DateField(blank=False, default=None, null=True)
interning_period_to = models.DateField(blank=False, default=None, null=True)
is_work_from_home = models.BooleanField(blank=False, default=False)
allowed_branch = ArrayField(
models.CharField(choices=BRANCH_CHOICES, blank=False, max_length=10),
size=TOTAL_BRANCHES,
default=list
)
allowed_batch = ArrayField(
models.CharField(max_length=10, choices=BATCH_CHOICES),
size=TOTAL_BATCHES,
default=list
)
sophomore_eligible = models.BooleanField(blank=False, default=False)
rs_eligible = models.BooleanField(blank=False, default=False)
tentative_no_of_offers = models.IntegerField(blank=False, default=None, null=True)
is_stipend_description_pdf = models.BooleanField(blank=False, default=False)
stipend_description_pdf_names=ArrayField(
models.CharField(null=True, default=None, max_length=JNF_TEXT_MAX_CHARACTER_COUNT), size=5, default=list,
blank=True)
stipend=models.IntegerField(blank=False, default=None, null=True)
facilities_provided=ArrayField(
models.CharField(null=True, choices=INF_FACILITIES_PROVIDED, max_length=20),
size=INF_TOTAL_FACILITIES,
default=list,
blank=True
)
additional_info = ArrayField(models.CharField(blank=True, max_length=JNF_TEXTMEDIUM_MAX_CHARACTER_COUNT), size=15,
default=list, blank=True)
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)
additional_facilities = models.CharField(blank=True, max_length=JNF_TEXTAREA_MAX_CHARACTER_COUNT, default=None, null=True)
academic_requirements = models.CharField(blank=True, max_length=JNF_TEXTAREA_MAX_CHARACTER_COUNT, default=None, null=True)
# selection process
selection_procedure_rounds = ArrayField(
models.CharField(null=True, default=None, max_length=JNF_TEXT_MAX_CHARACTER_COUNT), size=10,
default=list, blank=True)
selection_procedure_details = models.CharField(blank=True, max_length=JNF_TEXTAREA_MAX_CHARACTER_COUNT)
selection_procedure_details_pdf_names = ArrayField(
models.CharField(null=True, default=None, max_length=JNF_TEXT_MAX_CHARACTER_COUNT),
size=5, default=list, blank=True)
is_selection_procedure_details_pdf = models.BooleanField(blank=False, default=False)
#contact details of company person
contact_person_name = models.CharField(blank=False, max_length=JNF_TEXT_MAX_CHARACTER_COUNT)
phone_number = models.PositiveBigIntegerField(blank=False)
email = models.EmailField(blank=False)
# contact_person_designation = models.CharField(blank=False, max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, default="")
# telephone_number = models.PositiveBigIntegerField(blank=True, default=None, null=True)
email_verified = models.BooleanField(blank=False, default=False)
#history
created_at = models.DateTimeField(blank=False, default=None, null=True)
updated_at = models.DateTimeField(blank=False, default=None, null=True)
changed_by = models.ForeignKey(User, on_delete=models.RESTRICT, blank=True, null=True)
history = HistoricalRecords(user_model=User)
def format(self):
if self.company_name is not None:
self.company_name = self.company_name.strip()[:JNF_SMALLTEXT_MAX_CHARACTER_COUNT]
if self.company_type is not None:
self.company_type = self.company_type.strip()[:JNF_SMALLTEXT_MAX_CHARACTER_COUNT]
if self.company_details is not None:
self.company_details = self.company_details.strip()[:JNF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.address is not None:
self.address = self.address.strip()[:JNF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.nature_of_business is not None:
self.nature_of_business = self.nature_of_business.strip()[:JNF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.website is not None:
self.website = self.website.strip()[:JNF_TEXT_MAX_CHARACTER_COUNT]
if self.contact_person_name is not None:
self.contact_person_name = self.contact_person_name.strip()[:JNF_TEXT_MAX_CHARACTER_COUNT]
if self.city is not None:
self.city = self.city.strip()[:JNF_SMALLTEXT_MAX_CHARACTER_COUNT]
if self.state is not None:
self.state = self.state.strip()[:JNF_SMALLTEXT_MAX_CHARACTER_COUNT]
if self.country is not None:
self.country = self.country.strip()[:JNF_SMALLTEXT_MAX_CHARACTER_COUNT]
if self.city_type is not None:
self.city_type = self.city_type.strip()[:JNF_SMALLTEXT_MAX_CHARACTER_COUNT]
if self.selection_procedure_details is not None:
self.selection_procedure_details = self.selection_procedure_details.strip()[:JNF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.description is not None:
self.description = self.description.strip()[:JNF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.additional_facilities is not None:
self.additional_facilities = self.additional_facilities.strip()[:JNF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.academic_requirements is not None:
self.academic_requirements = self.academic_requirements.strip()[:JNF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.additional_info is not None:
self.additional_info = [info.strip()[:JNF_TEXTMEDIUM_MAX_CHARACTER_COUNT] for info in
list(self.additional_info)]
# if self.contact_person_designation is not None:
# self.contact_person_designation = self.contact_person_designation.strip()[:JNF_SMALLTEXT_MAX_CHARACTER_COUNT]
@property
def _history_user(self):
return self.changed_by
@_history_user.setter
def _history_user(self, value):
if isinstance(value, User):
self.changed_by = value
else:
self.changed_by = None
def save(self, *args, **kwargs):
''' On save, add timestamps '''
if not self.created_at:
self.created_at = timezone.now()
self.format()
self.updated_at = timezone.now()
return super(Internship, self).save(*args, **kwargs)
def __str__(self):
return self.company_name + " - " + self.designation
class InternshipApplication(models.Model):
id = models.CharField(blank=False, primary_key=True, max_length=15)
internship = models.ForeignKey(Internship, 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=JNF_TEXT_MAX_CHARACTER_COUNT, blank=False, null=True, default=None)
additional_info = models.JSONField(blank=True, null=True, default=None)
selected = models.BooleanField(null=True, default=None, blank=True)
offer_accepted = models.BooleanField(null=True, default=None, blank=True) # True if offer accepted, False if rejected, None if not yet decided
stipend = models.IntegerField(blank=True, default=None, null=True)
applied_at = models.DateTimeField(blank=False, default=None, null=True)
updated_at = models.DateTimeField(blank=False, default=None, null=True)
changed_by = models.ForeignKey(User, blank=False, on_delete=models.RESTRICT, default=None, null=True)
history = HistoricalRecords(user_model=User)
def save(self, *args, **kwargs):
''' On save, add timestamps '''
if not self.applied_at:
self.applied_at = timezone.now()
self.updated_at = timezone.now()
return super(InternshipApplication, self).save(*args, **kwargs)
@property
def _history_user(self):
return self.changed_by
@_history_user.setter
def _history_user(self, value):
if isinstance(value, User):
self.changed_by = value
else:
self.changed_by = None
class Meta:
verbose_name_plural = "Internship Applications"
unique_together = ('internship_id', 'student_id')
def __str__(self):
return self.internship.company_name + " - " + self.student.name
class Contributor(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, blank=False, default="")
email = models.EmailField(max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, blank=False, default="", unique=True)
github_id = models.CharField(max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, blank=False, default="", unique=True)
linkedin = models.CharField(max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, unique=True, null=True)
commits = models.IntegerField(blank=False, default=0)
image = models.CharField(max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, blank=False, default="", null=True)
def __str__(self):
return self.name
class Issues(models.Model):
id = models.AutoField(primary_key=True)
title = models.CharField(max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, blank=False, default="")
description = models.CharField(max_length=200, blank=False, default="")
#opening=(models.ForeignKey(Placement, on_delete=models.CASCADE, blank=False) or models.ForeignKey(Internship, on_delete=models.CASCADE, blank=False))
opening_id=models.CharField(blank=False, max_length=15, default=None, null=True)
opening_type=models.CharField(choices=[('Placement','Placement'),('Internship','Internship')], blank=False, max_length=15, default=PLACEMENT)
#status = models.CharField(max_length=JNF_SMALLTEXT_MAX_CHARACTER_COUNT, blank=False, default="")
student=models.ForeignKey(Student, on_delete=models.CASCADE, blank=False)
created_at = models.DateTimeField(blank=False, default=None, null=True)
updated_at = models.DateTimeField(blank=False, default=None, null=True)
changed_by = models.ForeignKey(User, on_delete=models.RESTRICT, blank=True, null=True)
history = HistoricalRecords(user_model=User)
def save(self, *args, **kwargs):
''' On save, add timestamps '''
if not self.created_at:
self.created_at = timezone.now()
self.updated_at = timezone.now()
return super(Issues, self).save(*args, **kwargs)
def __str__(self):
return self.title + " - " + self.student.name
class Meta:
verbose_name_plural = "Issues"

View File

@ -0,0 +1,339 @@
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(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)
pre_placement_offers = PrePlacementOffer.objects.filter(student_id=obj.id)
companies = []
for i in selected_companies:
ele = {}
ele['designation'] = i.placement.designation
ele['company_name'] = i.placement.company_name
ele['application_id'] = i.id
ele['placement_offer_type'] = 'Normal'
companies.append(ele)
for i in pre_placement_offers:
ele = {}
ele['designation'] = i.designation
ele['company_name'] = i.company
ele['application_id'] = i.id
ele['placement_offer_type'] = 'PPO'
companies.append(ele)
return companies
class Meta:
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 = []
for pdf_name in obj.company_details_pdf_names:
ele = {}
link = LINK_TO_STORAGE_COMPANY_ATTACHMENT + urllib.parse.quote(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(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(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(obj.id + "/" + pdf_name)
ele['link'] = link
ele['name'] = pdf_name
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,
]
depth = 1
class InternshipSerializerForStudent(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(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(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.stipend_description_pdf_names:
ele = {}
link = LINK_TO_STORAGE_COMPANY_ATTACHMENT + urllib.parse.quote(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(obj.id + "/" + pdf_name)
ele['link'] = link
ele['name'] = pdf_name
links.append(ele)
return links
class Meta:
model = Internship
exclude = [CONTACT_PERSON_NAME, PHONE_NUMBER, EMAIL, COMPANY_DETAILS_PDF_NAMES, DESCRIPTION_PDF_NAMES,
STIPEND_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(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(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(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(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 InternshipSerializerForAdmin(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(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(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.stipend_description_pdf_names:
ele = {}
link = LINK_TO_STORAGE_COMPANY_ATTACHMENT + urllib.parse.quote(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(obj.id + "/" + pdf_name)
ele['link'] = link
ele['name'] = pdf_name
links.append(ele)
return links
class Meta:
model = Internship
exclude = [COMPANY_DETAILS_PDF_NAMES, DESCRIPTION_PDF_NAMES, SELECTION_PROCEDURE_DETAILS_PDF_NAMES,
STIPEND_DETAILS_PDF_NAMES]
depth = 1
class PlacementApplicationSerializer(serializers.ModelSerializer):
placement = serializers.SerializerMethodField()
resume_link = serializers.SerializerMethodField()
def get_placement(self, obj):
data = PlacementSerializerForStudent(obj.placement).data
return data
def get_resume_link(self, obj):
ele = {'link': LINK_TO_STORAGE_RESUME + urllib.parse.quote(str(obj.student.roll_no) + "/" + obj.resume), 'name': obj.resume}
return ele
class Meta:
model = PlacementApplication
exclude = [STUDENT, 'resume']
class InternshipApplicationSerializer(serializers.ModelSerializer):
internship = serializers.SerializerMethodField()
resume_link = serializers.SerializerMethodField()
def get_internship(self, obj):
data = InternshipSerializerForStudent(obj.internship).data
return data
def get_resume_link(self, obj):
ele = {'link': LINK_TO_STORAGE_RESUME + urllib.parse.quote(str(obj.student.roll_no) + "/" + obj.resume), 'name': obj.resume}
return ele
class Meta:
model = InternshipApplication
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):
ele = {'link': LINK_TO_STORAGE_RESUME + urllib.parse.quote(obj.id + "/" + obj.resume), 'name': obj.resume}
return ele
class Meta:
model = PlacementApplication
exclude = ['placement', 'resume']
class InternshipApplicationSerializerForAdmin(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):
ele = {'link': LINK_TO_STORAGE_RESUME + urllib.parse.quote(obj.id + "/" + obj.resume), 'name': obj.resume}
return ele
class Meta:
model = InternshipApplication
exclude = ['internship', 'resume']
class ContributorSerializer(serializers.ModelSerializer):
class Meta:
model = Contributor
class AutofillSerializers(serializers.ModelSerializer):
class Meta:
model = Placement
fields = '__all__'
class AutofillSerializersInternship(serializers.ModelSerializer):
class Meta:
model = Internship
fields = '__all__'

View File

@ -0,0 +1,16 @@
from django.urls import path
from . import studentViews
urlpatterns = [
path('login/', studentViews.login, name="Login"),
path('profile/', studentViews.studentProfile, name="Student Profile"),
path('getDashboard/', studentViews.getDashboard, name="Dashboard"),
path("addResume/", studentViews.addResume, name="Upload Resume"),
path("deleteResume/", studentViews.deleteResume, name="Delete Resume"),
path("submitApplication/", studentViews.submitApplication, name="Add Application"),
path("deleteApplication/", studentViews.deleteApplication, name="Delete Application"),
path("getContributorStats/", studentViews.getContributorStats, name="Get Contributor Stats"),
path("studentAcceptOffer/", studentViews.studentAcceptOffer, name="Student Accept Offer"),
path("addIssue/",studentViews.addIssue,name= "Add Issue")
]

View File

@ -0,0 +1,407 @@
from rest_framework.decorators import api_view
from .serializers import *
from .utils import *
logger = logging.getLogger('db')
@api_view(['POST'])
@precheck(required_data=[AUTH_CODE])
@get_token()
@isAuthorized(allowed_users='*')
def login(request, id, email, user_type, token, refresh_token):
try:
return Response({'action': "Login", 'message': "Verified", "user_type": user_type, "id_token": token, "refresh_token": refresh_token},
status=status.HTTP_200_OK)
except:
return Response({'action': "Login", 'message': "Something Went Wrong"},
status=status.HTTP_400_BAD_REQUEST)
@api_view(['POST'])
@precheck(required_data=[REFRESH_TOKEN])
def refresh(request):
refresh_token = request.data[REFRESH_TOKEN]
data = {
'refresh_token': refresh_token,
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET,
'redirect_uri': REDIRECT_URI,
'grant_type': 'refresh_token'
}
response = rq.post(OAUTH2_API_ENDPOINT, data=data)
if response.status_code == 200:
id_info = id_token.verify_oauth2_token(response.json()['id_token'], requests.Request(), CLIENT_ID)
if id_info['iss'] not in ['accounts.google.com', 'https://accounts.google.com']:
raise ValueError('Wrong issuer.')
user_types = User.objects.filter(email=id_info['email']).values_list('user_type', flat=True)
return Response({'action': "Refresh Token", 'message': "Token Refreshed", "id_token": response.json()['id_token'], "user_type": user_types[0]},
status=status.HTTP_200_OK)
else:
logger.error("refresh_token"+str(response))
return Response({'action': "Refresh Token", 'message': "Something Went Wrong"},
status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET'])
@isAuthorized(allowed_users=[STUDENT])
def studentProfile(request, id, email, user_type):
try:
#print(id)
studentDetails = get_object_or_404(Student, id=id)
data = StudentSerializer(studentDetails).data
return Response({'action': "Student Profile", 'message': "Details Found", "details": data},
status=status.HTTP_200_OK)
except:
logger.warning("Student Profile: " + str(sys.exc_info()))
return Response({'action': "Student Profile", 'message': "Something Went Wrong"},
status=status.HTTP_400_BAD_REQUEST)
@api_view(['POST'])
@isAuthorized(allowed_users=[STUDENT])
def addResume(request, id, email, user_type):
destination_path = ""
try:
student = get_object_or_404(Student, id=id)
files = request.FILES
if len(student.resumes) >= MAX_RESUMES_PER_STUDENT:
raise PermissionError('Max Number of Resumes limit reached')
file = files['file']
destination_path = STORAGE_DESTINATION_RESUMES + str(student.roll_no) + "/"
file_name = saveFile(file, destination_path)
student.resumes.append(file_name)
student.changed_by = get_object_or_404(User, id=id)
student.save()
return Response({'action': "Upload Resume", 'message': "Resume Added"},
status=status.HTTP_200_OK)
except Http404:
return Response({'action': "Upload Resume", 'message': 'Student Not Found'},
status=status.HTTP_404_NOT_FOUND)
except PermissionError:
return Response({'action': "Upload Resume", 'message': 'Max Number of Resumes limit reached'},
status=status.HTTP_400_BAD_REQUEST)
except:
if path.exists(destination_path):
logger.error("Upload Resume: Error in Saving Resume")
remove(destination_path)
else:
logger.warning("Upload Resume: " + str(sys.exc_info()))
return Response({'action': "Upload Resume", 'message': "Something Went Wrong"},
status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET'])
@isAuthorized(allowed_users=[STUDENT])
def getDashboard(request, id, email, user_type):
try:
studentDetails = get_object_or_404(Student, id=id)
placements = Placement.objects.filter(allowed_batch__contains=[studentDetails.batch],
allowed_branch__contains=[studentDetails.branch],
deadline_datetime__gte=datetime.datetime.now(),
offer_accepted=True, email_verified=True).order_by('deadline_datetime')
filtered_placements = placement_eligibility_filters(studentDetails, placements)
placementsdata = PlacementSerializerForStudent(filtered_placements, many=True).data
placementApplications = PlacementApplication.objects.filter(student_id=id).order_by('-updated_at')
placementApplications = PlacementApplicationSerializer(placementApplications, many=True).data
internships = Internship.objects.filter(allowed_batch__contains=[studentDetails.batch],
allowed_branch__contains=[studentDetails.branch],
deadline_datetime__gte=datetime.datetime.now(),
offer_accepted=True, email_verified=True).order_by('deadline_datetime')
filtered_internships = internship_eligibility_filters(studentDetails, internships)
internshipsdata = InternshipSerializerForStudent(filtered_internships, many=True).data
internshipApplications = InternshipApplication.objects.filter(student_id=id).order_by('-updated_at')
internshipApplications = InternshipApplicationSerializer(internshipApplications, many=True).data
return Response(
{'action': "Get Dashboard - Student", 'message': "Data Found", "placements": placementsdata,
'placementApplication': placementApplications, 'internships':internshipsdata,'internshipApplication':internshipApplications},
status=status.HTTP_200_OK)
except Http404:
return Response({'action': "Get Dashboard - Student", 'message': 'Student Not Found'},
status=status.HTTP_404_NOT_FOUND)
except:
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)
@api_view(['POST'])
@isAuthorized(allowed_users=[STUDENT])
@precheck(required_data=[RESUME_FILE_NAME])
def deleteResume(request, id, email, user_type):
try:
student = get_object_or_404(Student, id=id)
file_name = request.data[RESUME_FILE_NAME]
if file_name not in student.resumes:
return Response({'action': "Delete Resume", 'message': "Resume Not Found"},
status=status.HTTP_404_NOT_FOUND)
destination_path = STORAGE_DESTINATION_RESUMES + id + "/" + str(file_name)
if path.exists(destination_path):
# remove(destination_path)
student.resumes.remove(file_name)
student.changed_by = get_object_or_404(User, id=id)
student.save()
return Response({'action': "Delete Resume", 'message': "Resume Deleted"},
status=status.HTTP_200_OK)
else:
raise FileNotFoundError("File Not Found")
except Http404:
return Response({'action': "Delete Resume", 'message': 'Student Not Found'},
status=status.HTTP_404_NOT_FOUND)
except FileNotFoundError as e:
return Response({'action': "Delete Resume", 'message': 'File Not Found'},
status=status.HTTP_404_NOT_FOUND)
except:
logger.warning("Delete Resume: " + 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 student.can_apply:
return Response({'action': "Submit Application", 'message': "Student Can't Apply"},
status=status.HTTP_400_BAD_REQUEST)
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],
allowed_batch__contains=[student.batch],
allowed_branch__contains=[student.branch],
deadline_datetime__gte=timezone.now()
)
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")
elif data[OPENING_TYPE] == INTERNSHIP:
if not student.can_apply_internship:
return Response({'action': "Submit Application", 'message': "Student Can't Apply"},
status=status.HTTP_400_BAD_REQUEST)
if not len(InternshipApplication.objects.filter(
student_id=id, internship_id=data[OPENING_ID])):
application = InternshipApplication()
opening = get_object_or_404(Internship, id=data[OPENING_ID],
allowed_batch__contains=[student.batch],
allowed_branch__contains=[student.branch],
deadline_datetime__gte=timezone.now()
)
if not opening.offer_accepted or not opening.email_verified:
raise PermissionError("Internship Not Approved")
cond_stat, cond_msg = InternshipApplicationConditions(student, opening)
if not cond_stat:
raise PermissionError(cond_msg)
application.internship = 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)
sendEmail(email, subject, data, STUDENT_APPLICATION_SUBMITTED_TEMPLATE)
application.changed_by = get_object_or_404(User, id=id)
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=[STUDENT])
@precheck(required_data=[APPLICATION_ID])
def deleteApplication(request, id, email, user_type):
try:
data = request.data
if OPENING_TYPE in request.data:
opening_type = request.data[OPENING_TYPE]
else:
opening_type = PLACEMENT
if opening_type==INTERNSHIP: #check whether it has header or not
application = get_object_or_404(InternshipApplication, id=data[APPLICATION_ID],
student_id=id)
if application.internship.deadline_datetime < timezone.now():
raise PermissionError("Deadline Passed")
else:
application = get_object_or_404(PlacementApplication, id=data[APPLICATION_ID],
student_id=id)
if application.placement.deadline_datetime < timezone.now():
raise PermissionError("Deadline Passed")
application.delete()
return Response({'action': "Delete Application", 'message': "Application Deleted"},
status=status.HTTP_200_OK)
except Http404 as e:
return Response({'action': "Delete Application", 'message': str(e)},
status=status.HTTP_404_NOT_FOUND)
except PermissionError as e:
return Response({'action': "Delete Application", 'message': str(e)},
status=status.HTTP_403_FORBIDDEN)
except:
logger.warning("Delete Application: " + str(sys.exc_info()))
return Response({'action': "Delete Application", 'message': "Something Went Wrong"},
status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET'])
@isAuthorized(allowed_users='*')
def getContributorStats(request, id, email, user_type):
try:
contributors = Contributor.objects.all()
serialized_data = ContributorSerializer(contributors, many=True).data
return Response({'action': "Get Contributor Stats", 'message': "Contributor Stats Fetched",
'data': serialized_data},
status=status.HTTP_200_OK)
except:
logger.warning("Get Contributor Stats: " + str(sys.exc_info()))
return Response({'action': "Get Contributor Stats", 'message': "Something Went Wrong"},
status=status.HTTP_400_BAD_REQUEST)
#view for sudentAcceptOffer
@api_view(['POST'])
@precheck(required_data=[OPENING_ID,"offer_accepted"])
@isAuthorized(allowed_users=[STUDENT])
def studentAcceptOffer(request, id, email, user_type):
try:
company_id = request.data[OPENING_ID]
#student_id=request.data['profileInfo']['id'] //check this once
student_id=id
offer_accepted = request.data['offer_accepted']
if OPENING_TYPE in request.data:
opening_type = request.data[OPENING_TYPE]
else:
opening_type = PLACEMENT
if opening_type==INTERNSHIP:
application=InternshipApplication.objects.filter(internship=company_id,student=student_id,selected=True)
else:
application=PlacementApplication.objects.filter(placement=company_id,student=student_id,selected=True)
if len(application):
application[0].offer_accepted=offer_accepted
application[0].save()
return Response({'action': "Accept Offer", 'message': "Updated Offer Status"},
status=status.HTTP_200_OK)
else:
return Response({'action': "Accept Offer", 'message': "Offer Not Found"},
status=status.HTTP_404_NOT_FOUND)
except:
logger.warning("Accept Offer: " + str(sys.exc_info()))
return Response({'action': "Accept Offer", 'message': "Something Went Wrong"},
status=status.HTTP_400_BAD_REQUEST)
#view for addIssue
@api_view(['POST'])
@isAuthorized(allowed_users=[STUDENT])
@precheck(required_data=["Title","Description","opening_id","opening_type"])
def addIssue(request, id, email, user_type):
try:
data = request.data
student = get_object_or_404(Student, id=id)
issue = Issues()
issue.student = student
issue.title = data["Title"]
issue.description = data["Description"]
issue.opening_id = data["opening_id"]
issue.opening_type = data["opening_type"]
try:
if data["opening_type"]==PLACEMENT:
opening=get_object_or_404(Placement, id=data["opening_id"])
else:
opening=get_object_or_404(Internship, id=data["opening_id"])
except:
return Response({'action': "Add Issue", 'message': "Opening Not Found"},
status=status.HTTP_400_BAD_REQUEST)
issue.save()
subject=ISSUE_SUBMITTED_TEMPLATE_SUBJECT
data={
"name":student.name,
"application_type":issue.opening_type,
"company_name":opening.company_name,
"additional_info":{
"Abstract":issue.title,
"Description":issue.description
},
"email":email
}
sendEmail(email, subject, data, STUDENT_ISSUE_SUBMITTED_TEMPLATE)
#send_mail_to reps
sendEmail(CDC_REPS_EMAILS_FOR_ISSUE,"Issue Raised",data,REPS_ISSUE_SUBMITTED_TEMPLATE)
return Response({'action': "Add Issue", 'message': "Issue Added"},
status=status.HTTP_200_OK)
except Http404:
return Response({'action': "Add Issue", 'message': 'Student Not Found'},
status=status.HTTP_404_NOT_FOUND)
except:
logger.warning("Add Issue: " + str(sys.exc_info()))
return Response({'action': "Add Issue", 'message': "Something Went Wrong"},
status=status.HTTP_400_BAD_REQUEST)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,195 @@
from django.test import TestCase, Client
from rest_framework import status
from rest_framework.test import APITestCase, APIClient
from django.urls import reverse
from ..models import *
import json
from ..utils import generateRandomString
import jwt
# initialize the APIClient app
client = APIClient()
class AddNewPlacementTest(APITestCase):
""" Test module for adding a new placement """
def setUp(self):
self.valid_payload = {
'company_name': 'Test Company 3', 'address': 'Test Address 3', 'company_type': 'Test Company Type 3',
'nature_of_business': 'Test Nature of Business 3', 'type_of_organisation': 'Test Type of Organisation 3',
'website': 'Test Website 3', 'company_details': 'Test Company Details 3', 'is_company_details_pdf': True,
'contact_person_name': 'Test Contact Person Name 3', 'phone_number': 1234567890, 'email': 'test3@test.com',
'city': 'Test City 3', 'state': 'Test State 3', 'country': 'Test Country 3', 'pin_code': 123456,
'designation': 'Test Designation 3', 'description': 'Test Description 3', 'job_location': 'Test Job Location 3',
'is_description_pdf': True, 'compensation_CTC': 300000, 'compensation_gross': 240000,
'compensation_take_home': 180000, 'compensation_bonus': 60000, 'is_compensation_details_pdf': True,
'allowed_branch': 'Test Allowed Branch 3', 'rs_eligible': True,
'selection_procedure_rounds': 'Test Selection Procedure Rounds 3',
'selection_procedure_details': 'Test Selection Procedure Details 3',
'is_selection_procedure_details_pdf': True, 'tentative_date_of_joining': '2022-03-01',
'tentative_no_of_offers': 30, 'other_requirements': 'Test Other Requirements 3'
}
self.invalid_payload = {
'company_name': '', 'address': 'Test Address 4', 'company_type': 'Test Company Type 4',
'nature_of_business': 'Test Nature of Business 4', 'type_of_organisation': 'Test Type of Organisation 4',
'website': 'Test Website 4', 'company_details': 'Test Company Details 4', 'is_company_details_pdf': True,
'contact_person_name': 'Test Contact Person Name 4', 'phone_number': 1234567890, 'email': 'test4@test.com',
'city': 'Test City 4', 'state': 'Test State 4', 'country': 'Test Country 4', 'pin_code': 123456,
'designation': 'Test Designation 4', 'description': 'Test Description 4', 'job_location': 'Test Job Location 4',
'is_description_pdf': True, 'compensation_CTC': 400000, 'compensation_gross': 320000,
'compensation_take_home': 240000, 'compensation_bonus': 80000, 'is_compensation_details_pdf': True,
'allowed_branch': 'Test Allowed Branch 4', 'rs_eligible': True,
'selection_procedure_rounds': 'Test Selection Procedure Rounds 4',
'selection_procedure_details': 'Test Selection Procedure Details 4',
'is_selection_procedure_details_pdf': True, 'tentative_date_of_joining': '2022-04-01',
'tentative_no_of_offers': 40, 'other_requirements': 'Test Other Requirements 4'
}
self.placement1 = Placement.objects.create(
company_name='ABC Corp', compensation_CTC=1000000, tier='1', id=generateRandomString(), allowed_branch=["CSE", "EE"], allowed_batch=["2020"], contact_person_name="test", phone_number=1234567890, email="test1@test.com", offer_accepted=True)
self.internship1 = Internship.objects.create(
company_name='ABC Corp', stipend=100000, id=generateRandomString(), allowed_branch=["CSE", "EE"], allowed_batch=["2020"], contact_person_name="test", phone_number=1234567890, email="test@gmail.com", offer_accepted=True)
self.token_placement1=jwt.encode({'opening_id': self.placement1.id,'opening_type':PLACEMENT,'email':"test1@test.com"}, os.environ.get("EMAIL_VERIFICATION_SECRET_KEY"), algorithm='HS256')
# def test_create_valid_placement(self):
# response = client.post(
# reverse('addPlacement'),
# data=json.dumps(self.valid_payload),
# content_type='application/json'
# )
# self.assertEqual(response.status_code, status.HTTP_201_CREATED)
# def test_create_invalid_placement(self):
# response = client.post(
# reverse('addPlacement'),
# data=json.dumps(self.invalid_payload),
# content_type='application/json'
# )
# self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
def test_autofill_jnf_success(self):
response = client.get(
reverse('Auto FIll JNF'),{"placement_id": self.placement1.id}
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data["message"], "Data Found")
self.assertEqual(response.data["placement_data"]["company_name"], "ABC Corp")
self.assertEqual(response.data["placement_data"]["compensation_CTC"], 1000000)
self.assertEqual(response.data["placement_data"]["tier"], "1")
self.assertEqual(response.data["placement_data"]["allowed_branch"], ["CSE", "EE"])
self.assertEqual(response.data["placement_data"]["allowed_batch"], ["2020"])
self.assertEqual(response.data["placement_data"]["contact_person_name"], "test")
self.assertEqual(response.data["placement_data"]["phone_number"], 1234567890)
self.assertEqual(response.data["placement_data"]["email"], "test1@test.com")
def test_autofill_jnf_WithInvalidId(self):
response = client.get(
reverse('Auto FIll JNF'),{"placement_id": generateRandomString()}
)
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertEqual(response.data["message"], "Placement Not Found")
def test_autofill_inf_success(self):
response = client.get(
reverse('Auto FIll INF'),{"internship_id": self.internship1.id}
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data["message"], "Data Found")
self.assertEqual(response.data["internship_data"]["company_name"], "ABC Corp")
self.assertEqual(response.data["internship_data"]["stipend"], 100000)
self.assertEqual(response.data["internship_data"]["allowed_branch"], ["CSE", "EE"])
self.assertEqual(response.data["internship_data"]["allowed_batch"], ["2020"])
self.assertEqual(response.data["internship_data"]["contact_person_name"], "test")
self.assertEqual(response.data["internship_data"]["phone_number"], 1234567890)
self.assertEqual(response.data["internship_data"]["email"], "test@gmail.com")
def test_autofill_inf_WithInvalidId(self):
response = client.get(
reverse('Auto FIll INF'),{"internship_id": generateRandomString()}
)
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertEqual(response.data["message"], "Internship Not Found")
def test_verify_email_success_placement(self):
response = client.post(
reverse('Verify Email'),{"token": self.token_placement1}
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data["message"], "Email Verified Successfully")
def test_verify_email_WithInvalidEmail_placement(self):
token_placement1=jwt.encode({'opening_id': self.placement1.id,'opening_type':PLACEMENT,'email':"hai@hai.com"}, os.environ.get("EMAIL_VERIFICATION_SECRET_KEY"), algorithm='HS256')
response = client.post(
reverse('Verify Email'),{"token": token_placement1}
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(response.data["message"], "Invalid Email")
def test_verify_email_WithInvalidOpeningId_Placement(self):
token_placement1=jwt.encode({'opening_id': generateRandomString(),'opening_type':PLACEMENT,'email':"hai@hai.com"}, os.environ.get("EMAIL_VERIFICATION_SECRET_KEY"), algorithm='HS256')
response = client.post(
reverse('Verify Email'),{"token": token_placement1}
)
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertEqual(response.data["message"], "Opening Not Found")
def test_verify_email_WithInvalidOpeningType(self):
token_placement1=jwt.encode({'opening_id': self.placement1.id,'opening_type':"hai",'email':"hai@hai.com"}, os.environ.get("EMAIL_VERIFICATION_SECRET_KEY"), algorithm='HS256')
response = client.post(
reverse('Verify Email'),{"token": token_placement1}
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(response.data["message"], "Invalid opening type")
def test_verify_email_WithInvalidToken(self):
response = client.post(
reverse('Verify Email'),{"token": generateRandomString()}
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(response.data["message"], "Something went wrong")
def test_verify_email_success_Internship(self):
token_placement1=jwt.encode({'opening_id': self.internship1.id,'opening_type':INTERNSHIP,'email':"test@gmail.com"}, os.environ.get("EMAIL_VERIFICATION_SECRET_KEY"), algorithm='HS256')
response = client.post(
reverse('Verify Email'),{"token": token_placement1}
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data["message"], "Email Verified Successfully")
def test_verify_email_WithInvalidEmail_Internship(self):
token_placement1=jwt.encode({'opening_id': self.internship1.id,'opening_type':INTERNSHIP,'email':"hai@hai.com"}, os.environ.get("EMAIL_VERIFICATION_SECRET_KEY"), algorithm='HS256')
response = client.post(
reverse('Verify Email'),{"token": token_placement1}
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(response.data["message"], "Invalid Email")
def test_verify_email_WithInvalidOpeningId_Internship(self):
token_placement1=jwt.encode({'opening_id': generateRandomString(),'opening_type':INTERNSHIP,'email':"hai@hai.com"}, os.environ.get("EMAIL_VERIFICATION_SECRET_KEY"), algorithm='HS256')
response = client.post(
reverse('Verify Email'),{"token": token_placement1}
)
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertEqual(response.data["message"], "Opening Not Found")
################################################################
# 1.Write Tests For AddPlacement Functions All cases #
# #
# 2.Write Tests For AddInternship Function All cases #
# #
################################################################
def test_addPlacement_sucess(self):
self.assertTrue(True)
def test_addPlacement_failure(self):
self.assertTrue(True)

View File

@ -0,0 +1,835 @@
# Create your tests here.
from ..models import *
from ..serializers import *
from django.test import TestCase, Client
from rest_framework import status
from rest_framework.test import APITestCase, APIClient
from django.urls import reverse
from ..utils import *
import json
from django.utils import timezone
from django.core.files.uploadedfile import SimpleUploadedFile
class StudentViewsTestCase(APITestCase):
def setUp(self):
self.client = APIClient()
self.user = User.objects.create(
email=str(os.environ.get("EMAIL_ID")),
id=str(os.environ.get("ROLL_NO")),
user_type=[STUDENT])
self.assertEqual(
self.user.email, User.objects.get(id=self.user.id).email)
self.student = Student.objects.create(
name="Test Student", id=self.user.id, resumes=["8BSLybntULgrPPm_beehyv.pdf"], roll_no=str(os.environ.get("ROLL_NO")), branch="CSE", batch="2020", phone_number=1234567890, changed_by=self.user, can_apply=True,
can_apply_internship=True, degree="bTech", cpi=7.95,
)
self.assertEqual(self.student.name,
Student.objects.get(id=self.student.id).name)
self.internship = Internship.objects.create(
company_name="Test Company", id=generateRandomString(), website="https://testwebsite.com", address="Test Address", company_type="Test Company Type", offer_accepted=True, season=["Summer"], allowed_branch=["CSE"],
allowed_batch=["2020"], contact_person_name="Test Contact Person", phone_number="1234567890", email="test@test.com", email_verified=True, stipend=10000,
)
self.placement = Placement.objects.create(
company_name="Test Company", id=generateRandomString(), website="https://testwebsite.com", address="Test Address", company_type="Test Company Type", offer_accepted=True, tier="6", allowed_branch=["CSE"], allowed_batch=["2020"],
contact_person_name="Test Contact Person", phone_number="1234567890", email="test@test.com", email_verified=True,
)
self.assertEqual(self.placement.company_name, Placement.objects.get(
id=self.placement.id).company_name)
self.internship_application = InternshipApplication.objects.create(
id=generateRandomString(), internship=self.internship, student=self.student, resume="8BSLybntULgrPPm_beehyv.pdf", selected=True
)
self.assertEqual(self.internship_application.internship.company_name, InternshipApplication.objects.get(
id=self.internship_application.id).internship.company_name)
self.placement_application = PlacementApplication.objects.create(
id=generateRandomString(), placement=self.placement, student=self.student, resume="8BSLybntULgrPPm_beehyv.pdf", selected=True
)
self.assertEqual(self.placement_application.placement.company_name, PlacementApplication.objects.get(
id=self.placement_application.id).placement.company_name)
self.issue = Issues.objects.create(
student=self.student, title="Test Issue", description="Test Issue Description", opening_id=self.internship.id,
opening_type=INTERNSHIP
)
# get token from google OAuth API
response = self.client.post(reverse('Refresh Token'), {
'refresh_token': os.environ.get("REFRESH_TOKEN")}, format='json')
self.student_token = response.data['id_token']
def test_student_accept_offer_internship(self):
url = reverse('Student Accept Offer')
data = {
'opening_id': self.internship.id,
'offer_accepted': True,
'opening_type': INTERNSHIP
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['message'], 'Updated Offer Status')
self.assertEqual(InternshipApplication.objects.get(
id=self.internship_application.id).offer_accepted, True)
def test_student_accept_offer_internship_notFound(self):
url = reverse('Student Accept Offer')
data = {
'opening_id': self.internship.id,
'offer_accepted': True,
'opening_type': INTERNSHIP
}
self.internship_application.selected = False
self.internship_application.offer_accepted = False
self.internship_application.save()
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertEqual(response.data['message'], 'Offer Not Found')
self.assertEqual(InternshipApplication.objects.get(
id=self.internship_application.id).offer_accepted, False)
def test_delete_application_internship(self):
url = reverse('Delete Application')
data = {
'application_id': self.internship_application.id,
'opening_type': INTERNSHIP
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['message'], 'Application Deleted')
self.assertEqual(InternshipApplication.objects.filter(
id=self.internship_application.id).count(), 0)
def test_delete_application_internship_deadlinePassed(self):
url = reverse('Delete Application')
data = {
'application_id': self.internship_application.id,
'opening_type': INTERNSHIP
}
self.internship.deadline_datetime = timezone.now().replace(
hour=0, minute=0, second=0, microsecond=0)
self.internship.save()
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
self.assertEqual(response.data['message'], 'Deadline Passed')
self.assertEqual(InternshipApplication.objects.filter(
id=self.internship_application.id).count(), 1)
def test_delete_application_internship_notFound(self):
url = reverse('Delete Application')
data = {
'application_id': self.internship_application.id,
'opening_type': INTERNSHIP
}
self.internship_application.delete()
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code,
status.HTTP_404_NOT_FOUND)
self.assertEqual(
response.data['message'], 'No InternshipApplication matches the given query.')
self.assertEqual(InternshipApplication.objects.filter(
id=self.internship_application.id).count(), 0)
# def test_add_application_internship(self):
# url = reverse('Delete Application')
# data = {
# 'application_id': self.internship_application.id,
# 'opening_type': INTERNSHIP
# }
# self.client.credentials(
# HTTP_AUTHORIZATION='Bearer ' + self.student_token)
# response = self.client.post(url, data, format='json')
# self.assertEqual(response.status_code, status.HTTP_200_OK)
# self.assertEqual(response.data['message'], 'Application Deleted')
# self.assertEqual(InternshipApplication.objects.filter(
# id=self.internship_application.id).count(), 0)
# # deleted existing application
# url = reverse('Add Application')
# data = {
# OPENING_ID: self.internship.id,
# OPENING_TYPE: INTERNSHIP,
# RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
# ADDITIONAL_INFO: []
# }
# self.client.credentials(
# HTTP_AUTHORIZATION='Bearer ' + self.student_token)
# response = self.client.post(url, data, format='json')
# self.assertEqual(response.status_code, status.HTTP_200_OK)
# self.assertEqual(response.data['message'], 'Application Submitted')
# self.assertEqual(InternshipApplication.objects.filter(
# student=self.student).count(), 1)
# self.internship_application = InternshipApplication.objects.filter(
# student=self.student)
# # self.internship.deadline_datetime = timezone.now().replace(
# # hour=0, minute=0, second=0, microsecond=0)
# # self.internship.save()
# response = self.client.post(url, data, format='json')
# self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
# self.assertEqual(response.data['message'],
# 'Application is already Submitted')
# self.assertEqual(InternshipApplication.objects.filter(
# student=self.student).count(), 1)
# self.internship_application.delete()
# data[OPENING_ID] = generateRandomString()
# response = self.client.post(url, data, format='json')
# self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
# self.assertEqual(response.data['message'],
# 'No Internship matches the given query.')
# self.assertEqual(InternshipApplication.objects.filter(
# student=self.student).count(), 0)
def test_student_accept_offer_placement(self):
url = reverse('Student Accept Offer')
data = {
'opening_id': self.placement.id,
'offer_accepted': True,
'opening_type': PLACEMENT
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['message'], 'Updated Offer Status')
self.assertEqual(PlacementApplication.objects.get(
id=self.placement_application.id).offer_accepted, True)
def test_student_accept_offer_placement_offerNotFound(self):
url = reverse('Student Accept Offer')
data = {
'opening_id': self.placement.id,
'offer_accepted': True,
'opening_type': PLACEMENT
}
self.placement_application.selected = False
self.placement_application.offer_accepted = False
self.placement_application.save()
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code,
status.HTTP_404_NOT_FOUND)
self.assertEqual(response.data['message'], 'Offer Not Found')
self.assertEqual(PlacementApplication.objects.filter(
id=self.placement_application.id, selected=True).count(), 0)
self.assertEqual(PlacementApplication.objects.get(
id=self.placement_application.id).offer_accepted, False)
def test_delete_application_placement(self):
url = reverse('Delete Application')
data = {
'application_id': self.placement_application.id,
'opening_type': PLACEMENT
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['message'], 'Application Deleted')
self.assertEqual(PlacementApplication.objects.filter(
id=self.placement_application.id).count(), 0)
def test_delete_application_placement_notFound(self):
url = reverse('Delete Application')
data = {
'application_id': self.placement_application.id,
'opening_type': PLACEMENT
}
self.placement_application.delete()
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code,
status.HTTP_404_NOT_FOUND)
self.assertEqual(
response.data['message'], 'No PlacementApplication matches the given query.')
self.assertEqual(PlacementApplication.objects.filter(
id=self.placement_application.id).count(), 0)
def test_delete_application_placement_deadlinePassed(self):
url = reverse('Delete Application')
data = {
'application_id': self.placement_application.id,
'opening_type': PLACEMENT
}
self.placement.deadline_datetime = timezone.now().replace(
hour=0, minute=0, second=0, microsecond=0)
self.placement.save()
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code,
status.HTTP_403_FORBIDDEN)
self.assertEqual(response.data['message'], 'Deadline Passed')
self.assertEqual(PlacementApplication.objects.filter(
id=self.placement_application.id).count(), 1)
def test_add_application_placement(self):
self.placement.additional_info = ["Test"]
self.placement_application.delete()
# deleted existing application
url = reverse('Add Application')
data = {
OPENING_ID: self.placement.id,
OPENING_TYPE: PLACEMENT,
RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
ADDITIONAL_INFO: [{"Test": "Test"}]
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['message'], 'Application Submitted')
self.assertEqual(PlacementApplication.objects.filter(
student=self.student).count(), 1)
def test_add_application_placement_deadlinePassed(self):
self.placement.deadline_datetime = timezone.now().replace(
hour=0, minute=0, second=0, microsecond=0)
self.placement.save()
# deleted existing application
self.placement_application.delete()
url = reverse('Add Application')
data = {
OPENING_ID: self.placement.id,
OPENING_TYPE: PLACEMENT,
RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
ADDITIONAL_INFO: []
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertEqual(response.data['message'],
'No Placement matches the given query.')
self.assertEqual(PlacementApplication.objects.filter(
student=self.student, placement=self.placement).count(), 0)
def test_add_application_placement_alreadyApplied(self):
url = reverse('Add Application')
data = {
OPENING_ID: self.placement.id,
OPENING_TYPE: PLACEMENT,
RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
ADDITIONAL_INFO: []
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
self.assertEqual(response.data['message'],
'Application is already Submitted')
self.assertEqual(PlacementApplication.objects.filter(
student=self.student, placement=self.placement).count(), 1)
def test_add_application_placement_notFound(self):
self.placement_application.delete()
url = reverse('Add Application')
data = {
OPENING_ID: self.placement.id,
OPENING_TYPE: PLACEMENT,
RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
ADDITIONAL_INFO: []
}
data[OPENING_ID] = generateRandomString()
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertEqual(response.data['message'],
'No Placement matches the given query.')
self.assertEqual(PlacementApplication.objects.filter(
student=self.student).count(), 0)
def test_add_application_placement_notApproved(self):
self.placement_application.delete()
url = reverse('Add Application')
data = {
OPENING_ID: self.placement.id,
OPENING_TYPE: PLACEMENT,
RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
ADDITIONAL_INFO: []
}
self.placement.offer_accepted = False
self.placement.save()
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
self.assertEqual(response.data['message'],
'Placement Not Approved')
self.assertEqual(PlacementApplication.objects.filter(
student=self.student, placement=self.placement).count(), 0)
def test_add_application_placement_notEmailVerified(self):
self.placement_application.delete()
url = reverse('Add Application')
data = {
OPENING_ID: self.placement.id,
OPENING_TYPE: PLACEMENT,
RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
ADDITIONAL_INFO: []
}
self.placement.email_verified = False
self.placement.save()
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
self.assertEqual(response.data['message'],
'Placement Not Approved')
self.assertEqual(PlacementApplication.objects.filter(
student=self.student, placement=self.placement).count(), 0)
def test_add_application_placement_notRegistered(self):
self.placement_application.delete()
url = reverse('Add Application')
data = {
OPENING_ID: self.placement.id,
OPENING_TYPE: PLACEMENT,
RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
ADDITIONAL_INFO: []
}
self.student.can_apply = False
self.student.save()
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(response.data['message'],
"Student Can't Apply")
self.assertEqual(PlacementApplication.objects.filter(
student=self.student, placement=self.placement).count(), 0)
def test_add_application_placement_InvalidOpeningtype(self):
self.placement_application.delete()
url = reverse('Add Application')
data = {
OPENING_ID: self.placement.id,
OPENING_TYPE: "Invalid",
RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
ADDITIONAL_INFO: []
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(response.data['message'],
"Something Went Wrong")
self.assertEqual(PlacementApplication.objects.filter(
student=self.student, placement=self.placement).count(), 0)
def test_add_application_placement_InvalidResume(self):
self.placement_application.delete()
url = reverse('Add Application')
data = {
OPENING_ID: self.placement.id,
OPENING_TYPE: PLACEMENT,
RESUME_FILE_NAME: 'Invalid',
ADDITIONAL_INFO: []
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertEqual(response.data['message'],
"resume_file_name Not Found")
self.assertEqual(PlacementApplication.objects.filter(
student=self.student, placement=self.placement).count(), 0)
def test_add_application_placement_MissingAdditionalInfo(self):
self.placement_application.delete()
url = reverse('Add Application')
self.placement.additional_info = ["Test"]
self.placement.save()
data = {
OPENING_ID: self.placement.id,
OPENING_TYPE: PLACEMENT,
RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
ADDITIONAL_INFO: []
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(response.data['message'],
"Something Went Wrong")
self.assertEqual(PlacementApplication.objects.filter(
student=self.student, placement=self.placement).count(), 0)
def test_getdashboard(self):
url = reverse('Dashboard')
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.get(url, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['message'], 'Data Found')
internships = Internship.objects.filter(allowed_batch__contains=[self.student.batch],
allowed_branch__contains=[
self.student.branch],
deadline_datetime__gte=datetime.datetime.now(),
offer_accepted=True, email_verified=True)
placements = Placement.objects.filter(allowed_batch__contains=[self.student.batch],
allowed_branch__contains=[
self.student.branch],
deadline_datetime__gte=datetime.datetime.now(),
offer_accepted=True, email_verified=True)
filtered_internships = internship_eligibility_filters(
self.student, internships)
filtered_placements = placement_eligibility_filters(
self.student, placements)
self.assertEqual(
len(response.data['internships']), len(filtered_internships))
self.assertEqual(
len(response.data['placements']), len(filtered_placements))
self.assertEqual(len(response.data['placementApplication']), 1)
self.assertEqual(len(response.data['internshipApplication']), 1)
self.assertEqual(response.data['placementApplication'][0]
['placement']['company_name'], self.placement.company_name)
self.assertEqual(response.data['internshipApplication'][0]
['internship']['company_name'], self.internship.company_name)
# def test_get_contributor_stats(self):
# url = reverse('get_contributor_stats', kwargs={'id': self.student.id})
# self.client.credentials(HTTP_AUTHORIZATION='Bearer ' + self.contributor_token)
# response = self.client.get(url, format='json')
# self.assertEqual(response.status_code, status.HTTP_200_OK)
# self.assertEqual(response.data['message'], 'Contributor Stats Fetched')
# self.assertEqual(len(response.data['data']), 1)
# self.assertEqual(response.data['data'][0]['name'], self.contributor.name)
# self.assertEqual(response.data['data'][0]['email'], self.contributor.email)
# self.assertEqual(response.data['data'][0]['contribution_count'], self.contributor.contribution_count)
def test_add_issue(self):
url = reverse('Add Issue')
data = {
'Title': 'Test Issue 2',
'Description': 'Test Issue Description 2',
'opening_id': self.placement.id,
'opening_type': PLACEMENT
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['message'], 'Issue Added')
self.assertEqual(Issues.objects.filter(
student=self.student).count(), 2)
self.assertEqual(Issues.objects.filter(
opening_id=self.placement.id).count(), 1)
self.assertEqual(Issues.objects.filter(
opening_type=PLACEMENT).count(), 1)
def test_add_application_internship(self):
self.internship.additional_info = ["Test"]
self.internship_application.delete()
# deleted existing application
url = reverse('Add Application')
data = {
OPENING_ID: self.internship.id,
OPENING_TYPE: INTERNSHIP,
RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
ADDITIONAL_INFO: [{"Test": "Test"}]
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['message'], 'Application Submitted')
self.assertEqual(InternshipApplication.objects.filter(
student=self.student).count(), 1)
def test_add_application_internship_deadlinePassed(self):
self.internship.deadline_datetime = timezone.now().replace(hour=0, minute=0, second=0, microsecond=0)
self.internship.save()
# deleted existing application
self.internship_application.delete()
url = reverse('Add Application')
data = {
OPENING_ID: self.internship.id,
OPENING_TYPE: INTERNSHIP,
RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
ADDITIONAL_INFO: []
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertEqual(response.data['message'],
'No Internship matches the given query.')
self.assertEqual(InternshipApplication.objects.filter(
student=self.student, internship=self.internship).count(), 0)
def test_add_application_internship_alreadyApplied(self):
url = reverse('Add Application')
data = {
OPENING_ID: self.internship.id,
OPENING_TYPE: INTERNSHIP,
RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
ADDITIONAL_INFO: []
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
self.assertEqual(response.data['message'],
'Application is already Submitted')
self.assertEqual(InternshipApplication.objects.filter(
student=self.student, internship=self.internship).count(), 1)
def test_add_application_internship_notFound(self):
self.internship_application.delete()
url = reverse('Add Application')
data = {
OPENING_ID: self.internship.id,
OPENING_TYPE: INTERNSHIP,
RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
ADDITIONAL_INFO: []
}
data[OPENING_ID] = generateRandomString()
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertEqual(response.data['message'],
'No Internship matches the given query.')
self.assertEqual(InternshipApplication.objects.filter(
student=self.student).count(), 0)
def test_add_application_internship_notApproved(self):
self.internship_application.delete()
url = reverse('Add Application')
data = {
OPENING_ID: self.internship.id,
OPENING_TYPE: INTERNSHIP,
RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
ADDITIONAL_INFO: []
}
self.internship.offer_accepted = False
self.internship.save()
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
self.assertEqual(response.data['message'],
'Internship Not Approved')
self.assertEqual(InternshipApplication.objects.filter(
student=self.student, internship=self.internship).count(), 0)
def test_add_application_internship_notEmailVerified(self):
self.internship_application.delete()
url = reverse('Add Application')
data = {
OPENING_ID: self.internship.id,
OPENING_TYPE: INTERNSHIP,
RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
ADDITIONAL_INFO: []
}
self.internship.email_verified = False
self.internship.save()
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
self.assertEqual(response.data['message'],
'Internship Not Approved')
self.assertEqual(InternshipApplication.objects.filter(
student=self.student, internship=self.internship).count(), 0)
def test_add_application_internship_notRegistered(self):
self.internship_application.delete()
url = reverse('Add Application')
data = {
OPENING_ID: self.internship.id,
OPENING_TYPE: INTERNSHIP,
RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
ADDITIONAL_INFO: []
}
self.student.can_apply_internship = False
self.student.save()
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(response.data['message'],
"Student Can't Apply")
self.assertEqual(InternshipApplication.objects.filter(
student=self.student, internship=self.internship).count(), 0)
def test_add_application_internship_InvalidOpeningtype(self):
self.internship_application.delete()
url = reverse('Add Application')
data = {
OPENING_ID: self.internship.id,
OPENING_TYPE: "Invalid",
RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
ADDITIONAL_INFO: []
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(response.data['message'],
"Something Went Wrong")
self.assertEqual(InternshipApplication.objects.filter(
student=self.student, internship=self.internship).count(), 0)
def test_add_application_internship_InvalidResume(self):
self.internship_application.delete()
url = reverse('Add Application')
data = {
OPENING_ID: self.internship.id,
OPENING_TYPE: INTERNSHIP,
RESUME_FILE_NAME: 'Invalid',
ADDITIONAL_INFO: []
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertEqual(response.data['message'],
"resume_file_name Not Found")
self.assertEqual(InternshipApplication.objects.filter(
student=self.student, internship=self.internship).count(), 0)
def test_add_application_internship_MissingAdditionalInfo(self):
self.internship_application.delete()
url = reverse('Add Application')
self.internship.additional_info = ["Test"]
self.internship.save()
data = {
OPENING_ID: self.internship.id,
OPENING_TYPE: INTERNSHIP,
RESUME_FILE_NAME: '8BSLybntULgrPPm_beehyv.pdf',
ADDITIONAL_INFO: []
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(response.data['message'],
"Something Went Wrong")
self.assertEqual(InternshipApplication.objects.filter(
student=self.student, internship=self.internship).count(), 0)
def test_getStudentProfile(self):
url = reverse('Student Profile')
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.get(url, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['message'], 'Details Found')
self.assertEqual(response.data['details']['id'], self.student.id)
self.assertEqual(response.data['details']['roll_no'],
self.student.roll_no)
self.assertEqual(response.data['details']['name'], self.student.name)
self.assertEqual(response.data['details']['batch'], self.student.batch)
self.assertEqual(response.data['details']['branch'],
self.student.branch)
self.assertEqual(response.data['details']['phone_number'],
self.student.phone_number)
self.assertEqual(response.data['details']
['cpi'], str(self.student.cpi))
for i in range(len(response.data['details']['resume_list'])):
self.assertIn(
response.data['details']['resume_list'][i]['name'], self.student.resumes)
for i in range(len(response.data['details']['offers'])):
self.assertIn(response.data['details']['offers'][i]
['application_id'], self.placement_application.id)
def test_addResume_success(self):
pdf = SimpleUploadedFile(
'kalera.pdf', b'content', content_type='application/pdf')
url = reverse('Upload Resume')
files = {'file': pdf}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, files, format='multipart')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['message'], 'Resume Added')
def test_add_resume_max_limit_reached(self):
pdf = SimpleUploadedFile(
'kalera.pdf', b'content', content_type='application/pdf')
url = reverse('Upload Resume')
files = {'file': pdf}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
self.student.resumes = ['resume1.pdf', 'resume2.pdf', 'resume3.pdf']
self.student.save()
response = self.client.post(url, files, format='multipart')
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(response.data, {
'action': 'Upload Resume', 'message': 'Max Number of Resumes limit reached'})
self.student.refresh_from_db()
self.assertEqual(len(self.student.resumes), 3)
def test_deleteResume_success(self):
destination_path = STORAGE_DESTINATION_RESUMES + \
self.student.id+'/'+"8BSLybntULgrPPm_beehyv.pdf"
# check it whats this above without this test giving error
with open(destination_path, 'w') as f:
f.write('test')
f.close()
# create a file here
url = reverse('Delete Resume')
data = {
'resume_file_name': '8BSLybntULgrPPm_beehyv.pdf'
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['message'], 'Resume Deleted')
self.student.refresh_from_db()
self.assertEqual(self.student.resumes, [])
remove(destination_path)
def test_deleteResume_invalidResume(self):
url = reverse('Delete Resume')
data = {
'resume_file_name': 'Invalid'
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertEqual(response.data['message'],
'Resume Not Found')
self.student.refresh_from_db()
self.assertEqual(self.student.resumes, ['8BSLybntULgrPPm_beehyv.pdf'])
def test_deleteResume_missingResumeinStorage(self):
url = reverse('Delete Resume')
data = {
'resume_file_name': '8BSLybntULgrPPm_beehyv.pdf'
}
self.client.credentials(
HTTP_AUTHORIZATION='Bearer ' + self.student_token)
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertEqual(response.data['message'], 'File Not Found')

View File

@ -0,0 +1,11 @@
from django.urls import path, include
from . import studentViews, studentUrls, companyUrls, adminUrls
urlpatterns = [
path('login/', studentViews.login, name="Login"),
path('refresh_token/', studentViews.refresh, name="Refresh Token"),
path('student/', include(studentUrls)),
path('company/', include(companyUrls)),
path('admin/', include(adminUrls)),
]

View File

@ -0,0 +1,590 @@
import datetime
import json
import logging
import os
import random
import re
import string
import sys
import traceback
from os import path, remove
import background_task
import jwt
import pdfkit
import pytz
import requests as rq
from django.conf import settings
from django.core.mail import EmailMultiAlternatives
from django.forms.models import model_to_dict
from django.http import Http404
from django.shortcuts import get_object_or_404
from django.template.loader import render_to_string
from django.utils.html import strip_tags
from django.utils import timezone
from google.auth.transport import requests
from google.oauth2 import id_token
from rest_framework import status
from rest_framework.response import Response
from .constants import *
from .models import User, PrePlacementOffer, PlacementApplication, Placement, Student, Internship,InternshipApplication
logger = logging.getLogger('db')
def get_token():
def decorator(view_func):
def wrapper_func(request, *args, **kwargs):
try:
authcode = request.data[AUTH_CODE]
data = {
'code': authcode,
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET,
'redirect_uri': REDIRECT_URI,
'grant_type': 'authorization_code'
}
r = rq.post(OAUTH2_API_ENDPOINT, data=data)
if r.status_code == 200:
response = r.json()
token = response[ID_TOKEN]
refresh_token = response[REFRESH_TOKEN]
request.META["HTTP_AUTHORIZATION"] = "Bearer " + token
request.META["MODIFIED"] = "True"
kwargs['refresh_token'] = refresh_token
return view_func(request, *args, **kwargs)
else:
return Response({'action': "Get Token", 'message': "Invalid Auth Code"},
status=status.HTTP_400_BAD_REQUEST)
except Exception as e:
logger.warning("Get Token: " + str(sys.exc_info()))
return Response({'action': "Get Token", 'message': str(e)},
status=status.HTTP_400_BAD_REQUEST)
return wrapper_func
return decorator
def precheck(required_data=None):
if required_data is None:
required_data = []
def decorator(view_func):
def wrapper_func(request, *args, **kwargs):
try:
request_data = None
if request.method == 'GET':
request_data = request.GET
elif request.method == 'POST':
request_data = request.data
if not len(request_data):
request_data = request.POST
if len(request_data):
for i in required_data:
# print(i)
if i not in request_data:
return Response({'action': "Pre check", 'message': str(i) + " Not Found"},
status=status.HTTP_400_BAD_REQUEST)
else:
return Response({'action': "Pre check", 'message': "Message Data not Found"},
status=status.HTTP_400_BAD_REQUEST)
# print("Pre check: " + str(request_data))
return view_func(request, *args, **kwargs)
except:
# print what exception is
print(traceback.format_exc())
logger.warning("Pre check: " + str(sys.exc_info()))
return Response({'action': "Pre check", 'message': "Something went wrong"},
status=status.HTTP_400_BAD_REQUEST)
return wrapper_func
return decorator
def isAuthorized(allowed_users=None):
if allowed_users is None:
allowed_users = []
def decorator(view_func):
def wrapper_func(request, *args, **kwargs):
try:
headers = request.META
if 'HTTP_AUTHORIZATION' in headers:
token_id = headers['HTTP_AUTHORIZATION'][7:]
idinfo = id_token.verify_oauth2_token(token_id, requests.Request(), CLIENT_ID)
email = idinfo[EMAIL]
user = get_object_or_404(User, email=email)
if user:
user.last_login_time = timezone.now()
user.save()
if len(set(user.user_type).intersection(set(allowed_users))) or allowed_users == '*':
if "MODIFIED" in headers:
return view_func(request, user.id, user.email, user.user_type, token_id, *args,
**kwargs)
else:
return view_func(request, user.id, user.email, user.user_type, *args, **kwargs)
else:
raise PermissionError("Access Denied. You are not allowed to use this service")
else:
raise PermissionError("Authorization Header Not Found")
except PermissionError:
return Response({'action': "Is Authorized?", 'message': 'Access Denied'},
status=status.HTTP_401_UNAUTHORIZED)
except 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:
logger.error("Problem with Google Oauth2.0 " + str(e))
return Response({'action': "Is Authorized?", 'message': 'Problem with Google Sign In'},
status=status.HTTP_401_UNAUTHORIZED)
except:
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
return decorator
def isAuthorizedService():
def decorator(view_func):
def wrapper_func(request, *args, **kwargs):
try:
headers = request.META
if 'HTTP_AUTHORIZATION' in headers:
token_id = headers['HTTP_AUTHORIZATION'][7:]
jwt.decode(token_id, os.environ.get("JWT_SECRET_KEY"), algorithms="HS256")
return view_func(request, *args, **kwargs)
else:
raise PermissionError("Authorization Header Not Found")
except:
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
return decorator
def generateRandomString():
try:
N = 15
res = ''.join(random.choices(string.ascii_uppercase + string.ascii_lowercase + string.digits, k=N))
return res
except:
return False
def saveFile(file, location):
prefix = generateRandomString()
file_name = prefix + "_" + file.name.strip()
file_name = re.sub(r'[\\/:*?"<>|]', '_', file_name)
if not path.isdir(location):
os.makedirs(location)
destination_path = location + 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)
return file_name
@background_task.background(schedule=2)
def sendEmail(email_to, subject, data, template, attachment_jnf_response=None):
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)
email_from = settings.EMAIL_HOST_USER
if type(email_to) is list:
recipient_list = [str(email) for email in email_to]
else:
recipient_list = [str(email_to), ]
#batch 100 ppl to send as bcc
for i in range(0,len(recipient_list),100):
msg = EmailMultiAlternatives(subject, text_content, email_from,None,bcc=recipient_list[i:i+100])
msg.attach_alternative(html_content, "text/html")
if attachment_jnf_response:
# logger.info(attachment_jnf_response)
pdf = pdfkit.from_string(attachment_jnf_response['html'], False,
options={"--enable-local-file-access": "", '--dpi': '96'})
msg.attach(attachment_jnf_response['name'], pdf, 'application/pdf')
msg.send()
return True
except:
logger.error("Send Email: " + str(sys.exc_info()))
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(student=student, accepted=True)
PPO_PSU = [i for i in PPO if i.tier == 'psu']
# find length of PPO
if len(selected_companies) + len(PPO) >= MAX_OFFERS_PER_STUDENT:
raise PermissionError("Max Applications Reached for the Season")
if len(selected_companies_PSU) > 0:
raise PermissionError('Selected for PSU Can\'t apply anymore')
if len(PPO_PSU) > 0:
raise PermissionError('Selected for PSU Can\'t apply anymore')
if placement.tier == 'psu':
return True, "Conditions Satisfied"
for i in selected_companies:
if int(i.placement.tier) < int(placement.tier):
return False, "Can't apply for this tier"
for i in PPO:
if int(i.tier) < int(placement.tier):
return False, "Can't apply for this tier"
if student.degree != 'bTech' and not placement.rs_eligible:
raise PermissionError("Can't apply for this placement")
return True, "Conditions Satisfied"
except PermissionError as e:
return False, e
except:
logger.warning("Utils - PlacementApplicationConditions: " + str(sys.exc_info()))
return False, "_"
def InternshipApplicationConditions(student, internship):
try:
selected_companies = InternshipApplication.objects.filter(student=student, selected=True)
if len(selected_companies)>=1:
# print("selected companies > 1")
return False, "You have already secured a Internship"
return True, "Conditions Satisfied"
except PermissionError as e:
return False, e
except:
logger.warning("Utils - InternshipApplicationConditions: " + 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 < 450000: # Open Tier If less than 450,000
return True, "8"
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:
logger.warning("Utils - getTier: " + str(sys.exc_info()))
return False, "_"
def generateOneTimeVerificationLink(email, opening_id, opening_type):
try:
token_payload = {
"email": email,
"opening_id": opening_id,
"opening_type": opening_type,
'exp': datetime.datetime.utcnow() + datetime.timedelta(hours=EMAIL_VERIFICATION_TOKEN_TTL)
}
token = jwt.encode(token_payload, os.environ.get("EMAIL_VERIFICATION_SECRET_KEY"), algorithm="HS256")
link = LINK_TO_EMAIl_VERIFICATION_API.format(token=token)
return True, link
except:
logger.warning("Utils - generateOneTimeVerificationLink: " + str(sys.exc_info()))
return False, "_"
def verify_recaptcha(request):
try:
data = {
'secret': settings.RECAPTCHA_SECRET_KEY,
'response': request
}
r = rq.post('https://www.google.com/recaptcha/api/siteverify', data=data)
result = r.json()
if not result['success']:
logger.warning("Utils - verify_recaptcha: " + str(result))
return result['success']
except:
# get exception line number
logger.warning("Utils - verify_recaptcha: " + str(sys.exc_info()))
return False, "_"
def opening_description_table_html(opening):
# check typing of opening
type = ""
if isinstance(opening, Placement):
type = "Job"
details = model_to_dict(opening, fields=[field.name for field in Placement._meta.fields],
exclude=EXCLUDE_IN_PDF)
elif isinstance(opening, Internship):
type = "Internship"
details = model_to_dict(opening, fields=[field.name for field in Internship._meta.fields],
exclude=EXCLUDE_IN_PDF)
# check typing of opening is query dict
else: # if isinstance(opening, QueryDict):
details = opening
keys = list(details.keys())
newdetails = {"ID": opening.id}
for key in keys:
if isinstance(details[key], list):
details[key] = {"details": details[key], "type": ["list"]}
if key in SPECIAL_FORMAT_IN_PDF:
if key == 'website':
details[key] = {"details": details[key], "type": ["link"]}
else:
details[key] = {"details": [item for item in details[key]["details"]], "type": ["list", "link"],
"link": PDF_FILES_SERVING_ENDPOINT + opening.id + "/"}
new_key = key.replace('_', ' ')
if new_key.endswith(' names'):
new_key = new_key[:-6]
new_key = new_key.capitalize()
newdetails[new_key] = details[key]
imagepath = os.path.abspath('./templates/image.png')
data = {
"data": newdetails,
"imgpath": imagepath,
"type": type
}
return render_to_string(COMPANY_JNF_RESPONSE_TEMPLATE, data)
def placement_eligibility_filters(student, placements):
try:
filtered_placements = []
for placement in placements.iterator():
if PlacementApplicationConditions(student, placement)[0]:
filtered_placements.append(placement)
return filtered_placements
except:
logger.warning("Utils - placement_eligibility_filters: " + str(sys.exc_info()))
return placements
def internship_eligibility_filters(student, internships):
try:
filtered_internships = []
for internship in internships.iterator():
if InternshipApplicationConditions(student, internship)[0]:
filtered_internships.append(internship)
return filtered_internships
except:
logger.warning("Utils - internship_eligibility_filters: " + str(sys.exc_info()))
return internships
@background_task.background(schedule=2)
def send_opening_notifications(opening_id, opening_type=PLACEMENT):
try:
# print(opening_id, opening_type)
if opening_type == PLACEMENT:
opening = get_object_or_404(Placement, id=opening_id)
else:
opening = get_object_or_404(Internship, id=opening_id)
emails=[]
students = Student.objects.all()
for student in students.iterator():
if student.branch in opening.allowed_branch:
if student.degree == 'bTech' or opening.rs_eligible is True:
if (isinstance(opening,Placement) and PlacementApplicationConditions(student, opening)[0]) or (isinstance(opening,Internship) and InternshipApplicationConditions(student, opening)[0]):
try:
student_user = get_object_or_404(User, id=student.id)
emails.append(student_user.email)
#sendEmail(student_user.email, subject, data, NOTIFY_STUDENTS_OPENING_TEMPLATE)
except Http404:
logger.warning('Utils - send_opening_notifications: user not found : ' + student.id)
except Exception as e:
logger.warning('Utils - send_opening_notifications: For Loop' + str(e))
subject = NOTIFY_STUDENTS_OPENING_TEMPLATE_SUBJECT.format(
company_name=opening.company_name)
deadline_datetime = opening.deadline_datetime.astimezone(pytz.timezone('Asia/Kolkata'))
data = {
"company_name": opening.company_name,
"opening_type": "INTERNSHIP" if isinstance(opening, Internship) else "PLACEMENT",
"designation": opening.designation,
"deadline": deadline_datetime.strftime("%A, %-d %B %Y, %-I:%M %p"),
"link": PLACEMENT_OPENING_URL.format(id=opening.designation) if opening_type == PLACEMENT else INTERNSHIP_OPENING_URL.format(id=opening.designation),
}
sendEmail(emails, subject, data, NOTIFY_STUDENTS_OPENING_TEMPLATE) #handled multiple mailings
except:
logger.warning('Utils - send_opening_notifications: ' + str(sys.exc_info()))
return False
def get_eligible_emails(opening_id, opening_type=PLACEMENT,send_all=False):
try:
# print(opening_id, opening_type)
if opening_type == PLACEMENT:
opening = get_object_or_404(Placement, id=opening_id)
else:
opening = get_object_or_404(Internship, id=opening_id)
emails=[]
students = Student.objects.all()
for student in students.iterator():
if student.branch in opening.allowed_branch:
if student.degree == 'bTech' or opening.rs_eligible is True:
if (isinstance(opening,Placement) and PlacementApplicationConditions(student, opening)[0]) or (
isinstance(opening,Internship) and InternshipApplicationConditions(student, opening)[0]):
try:
student_user = get_object_or_404(User, id=student.id)
#if send_all True send all students eligible for the opening
if send_all:
emails.append(student_user.email)
continue
# check if he applied
if opening_type == PLACEMENT:
if PlacementApplication.objects.filter(student=student, placement=opening).exists():
continue
else:
if InternshipApplication.objects.filter(student=student, internship=opening).exists():
continue
emails.append(student_user.email)
except Exception as e:
logger.warning('Utils - send_opening_notifications: For Loop' + str(e))
return False, []
return True, emails
except:
logger.warning('Utils - send_opening_notifications: ' + str(sys.exc_info()))
return False, []
def exception_email(opening):
opening = opening.dict()
data = {
"designation": opening["designation"],
"opening_type": "INTERNSHIP" if opening["opening_type"] == "INF" else "PLACEMENT",
"company_name": opening["company_name"],
}
pdfhtml = opening_description_table_html(opening)
name = opening["company_name"] + '_jnf_response.pdf' if opening[OPENING_TYPE]!="INF" else opening["company_name"] + '_inf_response.pdf'
attachment_jnf_respone = {
"name": name,
"html": pdfhtml,
}
sendEmail("cdc@iitdh.ac.in", COMPANY_OPENING_ERROR_TEMPLATE.format(company_name=opening["company_name"]), data,
COMPANY_OPENING_SUBMITTED_TEMPLATE, attachment_jnf_respone)
def store_all_files(request):
files = request.FILES
data = request.data
# save all the files
if files:
# company details pdf
for file in files.getlist(COMPANY_DETAILS_PDF):
file_location = STORAGE_DESTINATION_COMPANY_ATTACHMENTS + "temp" + '/'
saveFile(file, file_location)
# compensation details pdf
for file in files.getlist(COMPENSATION_DETAILS_PDF):
file_location = STORAGE_DESTINATION_COMPANY_ATTACHMENTS + "temp" + '/'
saveFile(file, file_location)
#stipend details pdf for internships
for file in files.getlist(STIPEND_DETAILS_PDF):
file_location = STORAGE_DESTINATION_COMPANY_ATTACHMENTS + "temp" + '/'
saveFile(file, file_location)
# selection procedure details pdf
for file in files.getlist(SELECTION_PROCEDURE_DETAILS_PDF):
file_location = STORAGE_DESTINATION_COMPANY_ATTACHMENTS + "temp" + '/'
saveFile(file, file_location)
# description pdf
for file in files.getlist(DESCRIPTION_PDF):
file_location = STORAGE_DESTINATION_COMPANY_ATTACHMENTS + "temp" + '/'
saveFile(file, file_location)
def send_email_for_opening(opening):
try:
# Prepare email data and attachment
pdfhtml = opening_description_table_html(opening)
if isinstance(opening, Placement):
name = opening.company_name + '_jnf_response.pdf'
elif isinstance(opening, Internship):
name = opening.company_name + '_inf_response.pdf'
attachment_jnf_respone = {
"name": name,
"html": pdfhtml,
}
data = {
"designation": opening.designation,
"opening_type": "INTERNSHIP" if isinstance(opening, Internship) else "PLACEMENT",
"company_name": opening.company_name,
}
emails = [opening.email] + CDC_REPS_EMAILS
# Send the email
sendEmail(emails,
COMPANY_OPENING_SUBMITTED_TEMPLATE_SUBJECT.format(id=opening.designation, company=opening.company_name), data,
COMPANY_OPENING_SUBMITTED_TEMPLATE, attachment_jnf_respone)
except Exception as e:
# Handle the exception here (e.g., log the error, send an error email, etc.)
print("An error occurred while sending the email:", e)
@background_task.background(schedule=2)
def send_opening_to_notifications_service(id,name,deadline,role,opening_type=PLACEMENT):
data={
"id":id,
"company":name,
"deadline":deadline,
"role":role,
"opening_type":opening_type
}
encoded=jwt.encode(data,os.environ.get("JWT_SECRET_KEY"),algorithm="HS256")
data_={
"token":encoded,
}
resp=rq.post(url=os.environ.get("PUSH_API_URL")+"addopening/",data=data_)
if resp.status_code==200:
print("Notification Sent")
else:
print("Notification Failed")
logger.warning("Utils - send_opening_to_notifications_service: " + str(resp) + "data sent:"+str(data))

View File

@ -0,0 +1,205 @@
"""
Django settings for CDC_Backend project.
Generated by 'django-admin startproject' using Django 2.2.5.
For more information on this file, see
https://docs.djangoproject.com/en/2.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.2/ref/settings/
"""
import os
from dotenv import load_dotenv
load_dotenv("../dexv.env")
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = os.environ.get("SECRET_KEY")
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = os.environ.get('DEBUG') == "True"
ALLOWED_HOSTS = ['cdc.iitdh.ac.in', 'localhost']
ADMINS = [ ('Karthik Mv', '200010030@iitdh.ac.in')]
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'APIs',
'rest_framework',
'corsheaders',
'django_db_logger',
'background_task',
'simple_history',
'import_export',
'django_extensions'
]
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'corsheaders.middleware.CorsPostCsrfMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'simple_history.middleware.HistoryRequestMiddleware',
]
ROOT_URLCONF = 'CDC_Backend.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': ['templates'],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'CDC_Backend.wsgi.application'
# Database
# 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',
# }
}
# Password validation
# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/2.2/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'Asia/Kolkata'
USE_I18N = True
USE_L10N = True
USE_TZ = True
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATICFILES_DIR = (
os.path.join(BASE_DIR, 'static'),
)
CORS_ORIGIN_ALLOW_ALL = False
CORS_ORIGIN_WHITELIST = [
"https://cdc.iitdh.ac.in",
"http://localhost:3000",
"https://localhost:3000"
]
CORS_REPLACE_HTTPS_REFERER = True
CSRF_TRUSTED_ORIGINS = [ "https://cdc.iitdh.ac.in", "http://cdc.iitdh.ac.in"]
EMAIL_BACKEND = ''
if DEBUG:
# file based email backend for development
EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend'
EMAIL_FILE_PATH = './test-emails'
else:
# SMTP backend for production
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_USE_TLS = True
EMAIL_PORT = 587
EMAIL_HOST_USER = os.environ.get("EMAIL") # 'email here'
EMAIL_HOST_PASSWORD = os.environ.get("EMAIL_PASSWORD") # 'password here'
RECAPTCHA_SECRET_KEY = os.environ.get("RECAPTCHA_SECRET_KEY")
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
},
'simple': {
'format': '%(levelname)s %(asctime)s %(message)s'
},
},
'handlers': {
'db_log': {
'level': 'DEBUG',
'class': 'django_db_logger.db_log_handler.DatabaseLogHandler'
},
'mail_admins': {
'level': 'WARNING',
'class': 'django.utils.log.AdminEmailHandler',
}
},
'loggers': {
'db': {
'handlers': ['db_log', 'mail_admins'],
'level': 'DEBUG'
}
}
}
# django_heroku.settings(locals())

View File

@ -0,0 +1,7 @@
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('APIs.urls')),
]

View File

@ -0,0 +1,15 @@
"""
WSGI config for CDC_Backend project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/2.2/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'CDC_Backend.settings')
application = get_wsgi_application()

File diff suppressed because it is too large Load Diff

View File

View File

@ -0,0 +1,16 @@
{
"web": {
"client_id": "956830229554-290mirc16pdhd5j7ph7v7ukibo4t1qcp.apps.googleusercontent.com",
"project_id": "cdc-automation",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_secret": "ZzvcweJylL1IDLUnYOi1ws2W",
"redirect_uris": [
"https://www.getpostman.com/oauth2/callback"
],
"javascript_origins": [
"http://localhost:3000"
]
}
}

View File

@ -0,0 +1,21 @@
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys
def main():
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'CDC_Backend.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()

View File

@ -0,0 +1 @@
gunicorn --certfile=/home/cdc/Desktop/1f9476e3959ebe60.crt --keyfile=/home/cdc/Desktop/star_iitdh_key.key --bind localhost:8000 CDC_Backend.wsgi --access-logfile access.log --error-logfile error.log --forwarded-allow-ips="cdc.iitdh.ac.in"

View File

@ -0,0 +1,70 @@
from APIs.models import Contributor
from django.shortcuts import get_object_or_404
import time
from dotenv import load_dotenv
import requests
import os
load_dotenv("../dev.env")
owner = 'CDC-IITDH'
access_token = os.environ.get("GITHUB_ACCESS_TOKEN")
headers = {'Authorization': "Token " + access_token}
maxRetires = 10
REPEAT_AFTER = 60 * 15 # 15 minutes
def getStats():
try:
stats = {}
repos = ['cdc-placement-website-backend', 'cdc-placement-website-frontend']
for i in repos:
try:
repo_name = i
print(repo_name)
url = f"https://api.github.com/repos/{owner}/{repo_name}/stats/contributors"
retry = 0
contributors = []
while True:
if retry > maxRetires:
break
req = requests.get(url, headers=headers)
contributors = req.json()
if req.status_code != 200:
print("ERROR:", req.json())
retry += 1
elif len(contributors):
break
retry += 1
time.sleep(1)
for contributor in contributors:
if contributor['author']['login'] not in stats:
stats[contributor['author']['login']] = 0
stats[contributor['author']['login']] += contributor['total']
except Exception as e:
print(e)
for i in stats:
try:
contributor = get_object_or_404(Contributor, github_id=i)
contributor.commits = stats[i]
contributor.save()
except:
pass
stats = sorted(stats.items(), key=lambda x: x[1], reverse=True)
for i in stats:
print(i)
except Exception as e:
print(e)
return stats
def run():
while True:
getStats()
print("Sleeping for", REPEAT_AFTER, "seconds")
time.sleep(REPEAT_AFTER)
print("Running send_reminder_mails()")
run()

View File

@ -0,0 +1,63 @@
from APIs.models import Placement, Student, PlacementApplication, User
from APIs.utils import sendEmail, PlacementApplicationConditions
from APIs.constants import *
from django.shortcuts import get_object_or_404
from django.utils import timezone
import time
import pytz
REPEAT_AFTER = 10 * 60
def send_reminder_mails():
placements = Placement.objects.all()
students = Student.objects.all()
for placement in placements.iterator():
print("Processing placement: ", placement)
# if placement is approved and email is verified
if not (placement.offer_accepted and placement.email_verified):
continue
# if placement is not expired
if placement.deadline_datetime < timezone.now():
continue
# send the reminder mail if the deadline is within 24 hours +- ReapetAfter
if timezone.now() - timezone.timedelta(
seconds=REPEAT_AFTER) <= placement.deadline_datetime - timezone.timedelta(days=1) < timezone.now() + \
timezone.timedelta(seconds=REPEAT_AFTER):
for student in students:
try:
# if Application not found then send email
if not PlacementApplication.objects.filter(placement=placement, student=student).exists():
if student.branch in placement.allowed_branch:
if student.degree == 'bTech' or placement.rs_eligible is True:
if PlacementApplicationConditions(student, placement)[0]:
student_user = get_object_or_404(User, id=student.id)
# change timezone to IST
deadline_datetime = placement.deadline_datetime.astimezone(pytz.timezone('Asia/Kolkata'))
data = {
"company_name": placement.company_name,
"opening_type": 'Placement',
"deadline": deadline_datetime.strftime("%A, %-d %B %Y, %-I:%M %p"),
"link": PLACEMENT_OPENING_URL.format(id=placement.id)
}
print("Sending mail to " + student_user.email, "placement id: ", placement.id)
sendEmail(student_user.email,
REMINDER_STUDENTS_OPENING_TEMPLATE_SUBJECT.format(
company_name=placement.company_name),
data, REMINDER_STUDENTS_OPENING_TEMPLATE)
except Exception as e:
print(e)
continue
def run():
while True:
print("Sleeping for", REPEAT_AFTER, "seconds")
time.sleep(REPEAT_AFTER)
print("Running send_reminder_mails()")
send_reminder_mails()

View File

@ -0,0 +1,210 @@
"""
Django settings for CDC_Backend project.
Generated by 'django-admin startproject' using Django 2.2.5.
For more information on this file, see
https://docs.djangoproject.com/en/2.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.2/ref/settings/
"""
import os
from dotenv import load_dotenv
load_dotenv("../dev.env")
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = os.environ.get("SECRET_KEY")
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = os.environ.get('DEBUG') == "True"
ALLOWED_HOSTS = ['cdc.iitdh.ac.in', 'localhost']
ADMINS = [ ('Jaya Surya P', '210020040@iitdh.ac.in')]
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'APIs',
'rest_framework',
'corsheaders',
'django_db_logger',
'background_task',
'simple_history',
'import_export',
'django_extensions',
'django_crontab',
]
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'corsheaders.middleware.CorsPostCsrfMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'simple_history.middleware.HistoryRequestMiddleware',
]
ROOT_URLCONF = 'CDC_Backend.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': ['templates'],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'CDC_Backend.wsgi.application'
# Database
# 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',
# }
}
# Password validation
# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/2.2/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'Asia/Kolkata'
USE_I18N = True
USE_L10N = True
USE_TZ = True
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/
STATIC_URL = '/static_url/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATICFILES_DIR = (
os.path.join(BASE_DIR, 'static'),
)
CORS_ORIGIN_ALLOW_ALL = False
CORS_ORIGIN_WHITELIST = [
"https://cdc.iitdh.ac.in",
"http://localhost:3000",
"https://localhost:3000"
]
CORS_REPLACE_HTTPS_REFERER = True
CSRF_TRUSTED_ORIGINS = [ "https://cdc.iitdh.ac.in", "http://cdc.iitdh.ac.in"]
EMAIL_BACKEND = ''
if DEBUG:
# file based email backend for development
EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend'
EMAIL_FILE_PATH = './test-emails'
else:
# SMTP backend for production
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_USE_TLS = True
EMAIL_PORT = 587
EMAIL_HOST_USER = os.environ.get("EMAIL") # 'email here'
EMAIL_HOST_PASSWORD = os.environ.get("EMAIL_PASSWORD") # 'password here'
RECAPTCHA_SECRET_KEY = os.environ.get("RECAPTCHA_SECRET_KEY")
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
},
'simple': {
'format': '%(levelname)s %(asctime)s %(message)s'
},
},
'handlers': {
'db_log': {
'level': 'DEBUG',
'class': 'django_db_logger.db_log_handler.DatabaseLogHandler'
},
'mail_admins': {
'level': 'WARNING',
'class': 'django.utils.log.AdminEmailHandler',
}
},
'loggers': {
'db': {
'handlers': ['db_log', 'mail_admins'],
'level': 'DEBUG'
}
}
}
# django_heroku.settings(locals())
CRONJOBS = [
('0 8,20 * * *', 'APIs.cron.clean_up_tests')
]

View File

@ -0,0 +1,90 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="x-apple-disable-message-reformatting">
<title></title>
<!--[if mso]>
<noscript>
<xml>
<o:OfficeDocumentSettings>
<o:PixelsPerInch>96</o:PixelsPerInch>
</o:OfficeDocumentSettings>
</xml>
</noscript>
<![endif]-->
<link rel="preconnect" href="https://fonts.gstatic.com">
<link rel="shortcut icon" href="favicon.ico"/>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@500&display=swap" rel="stylesheet">
<style>
table, td, div, h1, p {
font-family: 'Roboto', sans-serif;
}
</style>
</head>
<body style="margin:0;padding:0;">
<table role="presentation" style="width:100%;border-collapse:collapse;border:0;border-spacing:0;background:#ffffff;">
<tr>
<td align="center" style="padding:0;">
<table role="presentation"
style="width:602px;border-collapse:collapse;border:1px solid #334878;border-spacing:0;text-align:left;">
<tr>
<td align="center" style="padding:40px 0 30px 0;background:#334878;">
<img src="https://drive.google.com/uc?id=1QTA6dB7jnsZfU1kzyUqfD_2V5xODpWFt" alt="" width="200"
style="height:auto;display:block;"/>
</td>
</tr>
<tr>
<td style="padding:36px 30px 42px 30px;">
<table role="presentation"
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;">
<tr>
<td style="padding:0 0 36px 0;color:#153643;">
<p style="margin:0 0 12px 0;font-size:16px;line-height:24px;font-family: 'Roboto', sans-serif;">
We have received your {{opening_type}} Notification for {{ designation }}. Kindly verify your email by clicking <a
href="{{ one_time_link }}">here</a>.
</p>
</td>
</tr>
<tr>
<td style="padding:0;">
<table role="presentation"
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;">
<tr>
<td style="width:260px;padding:0;vertical-align:top;color:#334878;">
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td style="padding:30px;background:#334878;">
<table role="presentation"
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;font-size:9px;font-family: 'Roboto', sans-serif;">
<tr>
<td style="padding:0;width:50%;" align="left">
<p style="margin:0;font-size:14px;line-height:16px;font-family: 'Roboto', sans-serif;color:#ffffff;">
&reg; CDC,IIT Dharwad,2021<br/>
</p>
</td>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>

View File

@ -0,0 +1,73 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
#details_table tr:nth-child(even) {
background: #FFF
}
#details_table tr:nth-child(odd) {
background: #bfe3f3
}
#details_table td {
padding: 10px;
width: 50%;
}
#details_table {
border: #334878 1px solid;
border-collapse: collapse;
width: 80%;
margin: auto;
}
</style>
<title>Document</title>
</head>
<body style="margin: 0;font-family: sans-serif;">
<header style="background-color: #334878;"><img style="height: 3cm; margin: auto; display: block; padding: 0.5cm;"
src='{{ imgpath }}' alt="cdc logo"></header>
<h1 style="text-align: center;"> {{type}} Notification Form Response</h1>
<table id="details_table">
{% for key, value in data.items %}
<tr>
<td>
{{ key }}
</td>
<td>
{% if 'list' in value.type %}
{% for item in value.details %}
<li>
{% if 'link' in value.type and value.link %}
<a href="{{ value.link|add:item}}">{{ item|slice:"16:" }}</a>
{% elif 'link' in value.type %}
<a href="{{ item }}">{{ item }}</a>
{% else %}
{{ item }}
{% endif %}
</li>
{% endfor %}
{% else %}
{% if 'link' in value.type %}
<a href="{{ value.details }}">{{ value.details }}</a>
{% else %}
{{ value }}
{% endif %}
{% endif %}
</td>
</tr>
{% endfor %}
</table>
<p style="margin-left: 10%;">In case of any descripency regarding above details, please contact <a
href="mailto:cdc@iitdh.ac.in">cdc@iitdh.ac.in</a>
</p>
</body>
</html>

View File

@ -0,0 +1,135 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="x-apple-disable-message-reformatting">
<title></title>
<!--[if mso]>
<noscript>
<xml>
<o:OfficeDocumentSettings>
<o:PixelsPerInch>96</o:PixelsPerInch>
</o:OfficeDocumentSettings>
</xml>
</noscript>
<![endif]-->
<link rel="preconnect" href="https://fonts.gstatic.com">
<link rel="shortcut icon" href="favicon.ico"/>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@500&display=swap" rel="stylesheet">
<style>
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;
}
</style>
</head>
<body style="margin:0;padding:0;">
<table role="presentation" style="width:100%;border-collapse:collapse;border:0;border-spacing:0;background:#ffffff;">
<tr>
<td align="center" style="padding:0;">
<table role="presentation"
style="width:602px;border-collapse:collapse;border:1px solid #334878;border-spacing:0;text-align:left;">
<tr>
<td align="center" style="padding:40px 0 30px 0;background:#334878;">
<img src="https://drive.google.com/uc?id=1QTA6dB7jnsZfU1kzyUqfD_2V5xODpWFt" alt="" width="200"
style="height:auto;display:block;"/>
</td>
</tr>
<tr>
<td style="padding:36px 30px 42px 30px;">
<table role="presentation"
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;">
<tr>
<td style="padding:0 0 36px 0;color:#153643;">
<h1 style="font-size:24px;margin:0 0 20px 0;font-family: 'Roboto', sans-serif;
">Thank You for filling the form</h1>
<p style="margin:0 0 12px 0;font-size:16px;line-height:24px;font-family: 'Roboto', sans-serif;">
We have received your <b>{{ opening_type }}</b> notification for a
<b>{{ designation }}</b> offer at <b>
{{ company_name }}</b>.
</p>
<p style="margin:0 0 12px 0;font-size:16px;line-height:24px;font-family: 'Roboto', sans-serif;">
We will keep you informed with the updates. If you have any queries, please
feel to
write to
<nobr><u>cdc@iitdh.ac.in</u></nobr>
</p>
<table id="details_table">
{% for key, value in data.items %}
<tr>
<td>
{{ key }}
</td>
<td>
{% if 'list' in value.type %}
{% for item in value.details %}
<li>
{% if 'link' in value.type and value.link %}
<a href="{{ value.link|add:item}}">{{ item }}</a>
{% elif 'link' in value.type %}
<a href="{{ item }}">{{ item }}</a>
{% else %}
{{ item }}
{% endif %}
</li>
{% endfor %}
{% else %}
{% if 'link' in value.type %}
<a href="{{ value.details }}">{{ value.details }}</a>
{% else %}
{{ value }}
{% endif %}
{% endif %}
</td>
</tr>
{% endfor %}
</table>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td style="padding:30px;background:#334878;">
<table role="presentation"
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;font-size:9px;font-family: 'Roboto', sans-serif;">
<tr>
<td style="padding:0;width:50%;" align="left">
<p style="margin:0;font-size:14px;line-height:16px;font-family: 'Roboto', sans-serif;color:#ffffff;">
&reg; CDC,IIT Dharwad,2021<br/>
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View File

@ -0,0 +1,87 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="x-apple-disable-message-reformatting">
<title></title>
<!--[if mso]>
<noscript>
<xml>
<o:OfficeDocumentSettings>
<o:PixelsPerInch>96</o:PixelsPerInch>
</o:OfficeDocumentSettings>
</xml>
</noscript>
<![endif]-->
<link rel="preconnect" href="https://fonts.gstatic.com">
<link rel="shortcut icon" href="favicon.ico"/>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@500&display=swap" rel="stylesheet">
<style>
table, td, div, h1, p {
font-family: 'Roboto', sans-serif;
}
</style>
</head>
<body style="margin:0;padding:0;">
<table role="presentation" style="width:100%;border-collapse:collapse;border:0;border-spacing:0;background:#ffffff;">
<tr>
<td align="center" style="padding:0;">
<table role="presentation"
style="width:602px;border-collapse:collapse;border:1px solid #334878;border-spacing:0;text-align:left;">
<tr>
<td align="center" style="padding:40px 0 30px 0;background:#334878;">
<img src="https://drive.google.com/uc?id=1QTA6dB7jnsZfU1kzyUqfD_2V5xODpWFt" alt="" width="200"
style="height:auto;display:block;"/>
</td>
</tr>
<tr>
<td style="padding:36px 30px 42px 30px;">
<table role="presentation"
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;">
<tr>
<td style="padding:0 0 36px 0;color:#153643;">
<h1 style="font-size:24px;margin:0 0 20px 0;font-family: 'Roboto', sans-serif;
">{{ opening_type }} Opportunity at {{ company_name }}</h1>
<p style="margin:0 0 12px 0;font-size:16px;line-height:24px;font-family: 'Roboto', sans-serif;">
Greetings of the day. Hope you are fine and doing well !
</p>
<p style="text-indent: 4ch; margin:0 0 12px 0;font-size:16px;line-height:24px;font-family: 'Roboto', sans-serif;">
CDC is excited to announce that <b>{{ company_name }}</b> is interested in
recruiting <b>{{ designation }}</b> from IIT Dharwad.
More details can be found in the CDC Web Portal.
</p>
<p style="margin:0 0 12px 0;font-size:16px;line-height:24px;font-family: 'Roboto', sans-serif;">
Interested students can apply before <b>{{ deadline }}</b> in the <a
href="{{ link }}">CDC-Web Portal</a>.
</p>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td style="padding:30px;background:#334878;">
<table role="presentation"
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;font-size:9px;font-family: 'Roboto', sans-serif;">
<tr>
<td style="padding:0;width:50%;" align="left">
<p style="margin:0;font-size:14px;line-height:16px;font-family: 'Roboto', sans-serif;color:#ffffff;">
&reg; CDC,IIT Dharwad,2022<br/>
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>

View File

@ -0,0 +1,117 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="x-apple-disable-message-reformatting">
<title></title>
<!--[if mso]>
<noscript>
<xml>
<o:OfficeDocumentSettings>
<o:PixelsPerInch>96</o:PixelsPerInch>
</o:OfficeDocumentSettings>
</xml>
</noscript>
<![endif]-->
<link rel="preconnect" href="https://fonts.gstatic.com">
<link rel="shortcut icon" href="favicon.ico"/>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@500&display=swap" rel="stylesheet">
<style>
table, td, div, h1, p {
font-family: 'Roboto', sans-serif;
}
</style>
</head>
<body style="margin:0;padding:0;">
<table role="presentation" style="width:100%;border-collapse:collapse;border:0;border-spacing:0;background:#ffffff;">
<tr>
<td align="center" style="padding:0;">
<table role="presentation"
style="width:602px;border-collapse:collapse;border:1px solid #334878;border-spacing:0;text-align:left;">
<tr>
<td align="center" style="padding:40px 0 30px 0;background:#334878;">
<img src="https://drive.google.com/uc?id=1QTA6dB7jnsZfU1kzyUqfD_2V5xODpWFt" alt="" width="200"
style="height:auto;display:block;"/>
</td>
</tr>
<tr>
<td style="padding:36px 30px 42px 30px;">
<table role="presentation"
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;">
<tr>
<td style="padding:0 0 36px 0;color:#153643;">
<h1 style="font-size:24px;margin:0 0 20px 0;font-family: 'Roboto', sans-serif;
">Hello, Folks</h1>
<p style="margin:0 0 12px 0;font-size:16px;line-height:24px;font-family: 'Roboto', sans-serif;">
We have received a issue regarding a <b>{{ application_type }}</b> opening at
<b>
{{ company_name }}</b> From {{name}}.
{% if additional_info %}
We received these additional details
<br>
<p style="margin:0 0 12px 0;font-size:16px;line-height:24px;font-family:
'Roboto', sans-serif;text-align: center">
<table style="border:solid 1px; margin: auto; text-align: center;width: 80%;
border-radius:15px; background-color: #e0e3ee">
{% for i,j in additional_info.items %}
<tr>
<td style="padding:8px 10px;color:#153643; ">{{ i }}:</td>
<td style="padding:8px 10px;color:#153643;">{{ j }}</td>
</tr>
{% endfor %}
</table>
{% endif %}
</p>
</p>
<p style="margin:0 0 12px 0;font-size:16px;line-height:24px;font-family: 'Roboto', sans-serif;">
please look into it and take necessary actions.
get in touch with the student at at <nobr><u>{{ email }}</u></nobr>
</p>
</td>
</tr>
<tr>
<td style="padding:0;">
<table role="presentation"
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;">
<tr>
<td style="width:260px;padding:0;vertical-align:top;color:#334878;">
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td style="padding:30px;background:#334878;">
<table role="presentation"
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;font-size:9px;font-family: 'Roboto', sans-serif;">
<tr>
<td style="padding:0;width:50%;" align="left">
<p style="margin:0;font-size:14px;line-height:16px;font-family: 'Roboto', sans-serif;color:#ffffff;">
&reg; CDC,IIT Dharwad,2021<br/>
</p>
</td>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>

View File

@ -0,0 +1,86 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="x-apple-disable-message-reformatting">
<title></title>
<!--[if mso]>
<noscript>
<xml>
<o:OfficeDocumentSettings>
<o:PixelsPerInch>96</o:PixelsPerInch>
</o:OfficeDocumentSettings>
</xml>
</noscript>
<![endif]-->
<link rel="preconnect" href="https://fonts.gstatic.com">
<link rel="shortcut icon" href="favicon.ico"/>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@500&display=swap" rel="stylesheet">
<style>
table, td, div, h1, p {
font-family: 'Roboto', sans-serif;
}
</style>
</head>
<body style="margin:0;padding:0;">
<table role="presentation" style="width:100%;border-collapse:collapse;border:0;border-spacing:0;background:#ffffff;">
<tr>
<td align="center" style="padding:0;">
<table role="presentation"
style="width:602px;border-collapse:collapse;border:1px solid #334878;border-spacing:0;text-align:left;">
<tr>
<td align="center" style="padding:40px 0 30px 0;background:#334878;">
<img src="https://drive.google.com/uc?id=1QTA6dB7jnsZfU1kzyUqfD_2V5xODpWFt" alt="" width="200"
style="height:auto;display:block;"/>
</td>
</tr>
<tr>
<td style="padding:36px 30px 42px 30px;">
<table role="presentation"
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;">
<tr>
<td style="padding:0 0 36px 0;color:#153643;">
<h1 style="font-size:24px;margin:0 0 20px 0;font-family: 'Roboto', sans-serif;
">Hey, {{ student_name }}</h1>
<p style="margin:0 0 12px 0;font-size:16px;line-height:24px;font-family: 'Roboto', sans-serif;">
We regret to inform you that you have not been selected for
<b>{{ designation }}</b> role at <b>{{ company_name }}</b>.
CDC will keep bringing more such opportunities for you in the future.
</td>
</tr>
<tr>
<td style="padding:0;">
<table role="presentation"
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;">
<tr>
<td style="width:260px;padding:0;vertical-align:top;color:#334878;">
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td style="padding:30px;background:#334878;">
<table role="presentation"
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;font-size:9px;font-family: 'Roboto', sans-serif;">
<tr>
<td style="padding:0;width:50%;" align="left">
<p style="margin:0;font-size:14px;line-height:16px;font-family: 'Roboto', sans-serif;color:#ffffff;">
&reg; CDC,IIT Dharwad,2021<br/>
</p>
</td>
</tr>
</table>
</td>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>

View File

@ -0,0 +1,85 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="x-apple-disable-message-reformatting">
<title></title>
<!--[if mso]>
<noscript>
<xml>
<o:OfficeDocumentSettings>
<o:PixelsPerInch>96</o:PixelsPerInch>
</o:OfficeDocumentSettings>
</xml>
</noscript>
<![endif]-->
<link rel="preconnect" href="https://fonts.gstatic.com">
<link rel="shortcut icon" href="favicon.ico"/>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@500&display=swap" rel="stylesheet">
<style>
table, td, div, h1, p {
font-family: 'Roboto', sans-serif;
}
</style>
</head>
<body style="margin:0;padding:0;">
<table role="presentation" style="width:100%;border-collapse:collapse;border:0;border-spacing:0;background:#ffffff;">
<tr>
<td align="center" style="padding:0;">
<table role="presentation"
style="width:602px;border-collapse:collapse;border:1px solid #334878;border-spacing:0;text-align:left;">
<tr>
<td align="center" style="padding:40px 0 30px 0;background:#334878;">
<img src="https://drive.google.com/uc?id=1QTA6dB7jnsZfU1kzyUqfD_2V5xODpWFt" alt="" width="200"
style="height:auto;display:block;"/>
</td>
</tr>
<tr>
<td style="padding:36px 30px 42px 30px;">
<table role="presentation"
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;">
<tr>
<td style="padding:0 0 36px 0;color:#153643;">
<h1 style="font-size:24px;margin:0 0 20px 0;font-family: 'Roboto', sans-serif;
">Hey, {{ student_name }}</h1>
<p style="margin:0 0 12px 0;font-size:16px;line-height:24px;font-family: 'Roboto', sans-serif;">
Congratulations, You have been selected for the <b>{{ designation }}</b> at
<b>{{ company_name }}</b>.<br>
</td>
</tr>
<tr>
<td style="padding:0;">
<table role="presentation"
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;">
<tr>
<td style="width:260px;padding:0;vertical-align:top;color:#334878;">
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td style="padding:30px;background:#334878;">
<table role="presentation"
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;font-size:9px;font-family: 'Roboto', sans-serif;">
<tr>
<td style="padding:0;width:50%;" align="left">
<p style="margin:0;font-size:14px;line-height:16px;font-family: 'Roboto', sans-serif;color:#ffffff;">
&reg; CDC,IIT Dharwad,2021<br/>
</p>
</td>
</tr>
</table>
</td>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>

View File

@ -0,0 +1,118 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="x-apple-disable-message-reformatting">
<title></title>
<!--[if mso]>
<noscript>
<xml>
<o:OfficeDocumentSettings>
<o:PixelsPerInch>96</o:PixelsPerInch>
</o:OfficeDocumentSettings>
</xml>
</noscript>
<![endif]-->
<link rel="preconnect" href="https://fonts.gstatic.com">
<link rel="shortcut icon" href="favicon.ico"/>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@500&display=swap" rel="stylesheet">
<style>
table, td, div, h1, p {
font-family: 'Roboto', sans-serif;
}
</style>
</head>
<body style="margin:0;padding:0;">
<table role="presentation" style="width:100%;border-collapse:collapse;border:0;border-spacing:0;background:#ffffff;">
<tr>
<td align="center" style="padding:0;">
<table role="presentation"
style="width:602px;border-collapse:collapse;border:1px solid #334878;border-spacing:0;text-align:left;">
<tr>
<td align="center" style="padding:40px 0 30px 0;background:#334878;">
<img src="https://drive.google.com/uc?id=1QTA6dB7jnsZfU1kzyUqfD_2V5xODpWFt" alt="" width="200"
style="height:auto;display:block;"/>
</td>
</tr>
<tr>
<td style="padding:36px 30px 42px 30px;">
<table role="presentation"
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;">
<tr>
<td style="padding:0 0 36px 0;color:#153643;">
<h1 style="font-size:24px;margin:0 0 20px 0;font-family: 'Roboto', sans-serif;
">Hello, {{ name }}</h1>
<p style="margin:0 0 12px 0;font-size:16px;line-height:24px;font-family: 'Roboto', sans-serif;">
We have received your application for a <b>{{ application_type }}</b> offer at
<b>
{{ company_name }}</b>.
{% if additional_info_items %}
We received these additional details
<br>
<p style="margin:0 0 12px 0;font-size:16px;line-height:24px;font-family:
'Roboto', sans-serif;text-align: center">
<table style="border:solid 1px; margin: auto; text-align: center;width: 80%;
border-radius:15px; background-color: #e0e3ee">
{% for i,j in additional_info.items %}
<tr>
<td style="padding:8px 10px;color:#153643; ">{{ i }}:</td>
<td style="padding:8px 10px;color:#153643;">{{ j }}</td>
</tr>
{% endfor %}
</table>
{% endif %}
</p>
</p>
<p style="margin:0 0 12px 0;font-size:16px;line-height:24px;font-family: 'Roboto', sans-serif;">
We will keep you informed with the updates. If you have any queries, please
feel to
write to
<nobr><u>cdc.support@iitdh.ac.in</u></nobr>
</p>
</td>
</tr>
<tr>
<td style="padding:0;">
<table role="presentation"
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;">
<tr>
<td style="width:260px;padding:0;vertical-align:top;color:#334878;">
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td style="padding:30px;background:#334878;">
<table role="presentation"
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;font-size:9px;font-family: 'Roboto', sans-serif;">
<tr>
<td style="padding:0;width:50%;" align="left">
<p style="margin:0;font-size:14px;line-height:16px;font-family: 'Roboto', sans-serif;color:#ffffff;">
&reg; CDC,IIT Dharwad,2021<br/>
</p>
</td>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>

View File

@ -0,0 +1,124 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="x-apple-disable-message-reformatting">
<title></title>
<!--[if mso]>
<noscript>
<xml>
<o:OfficeDocumentSettings>
<o:PixelsPerInch>96</o:PixelsPerInch>
</o:OfficeDocumentSettings>
</xml>
</noscript>
<![endif]-->
<link rel="preconnect" href="https://fonts.gstatic.com">
<link rel="shortcut icon" href="favicon.ico"/>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@500&display=swap" rel="stylesheet">
<style>
table, td, div, h1, p {
font-family: 'Roboto', sans-serif;
}
</style>
</head>
<body style="margin:0;padding:0;">
<table role="presentation" style="width:100%;border-collapse:collapse;border:0;border-spacing:0;background:#ffffff;">
<tr>
<td align="center" style="padding:0;">
<table role="presentation"
style="width:602px;border-collapse:collapse;border:1px solid #334878;border-spacing:0;text-align:left;">
<tr>
<td align="center" style="padding:40px 0 30px 0;background:#334878;">
<img src="https://drive.google.com/uc?id=1QTA6dB7jnsZfU1kzyUqfD_2V5xODpWFt" alt="" width="200"
style="height:auto;display:block;"/>
</td>
</tr>
<tr>
<td style="padding:36px 30px 42px 30px;">
<table role="presentation"
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;">
<tr>
<td style="padding:0 0 36px 0;color:#153643;">
<h1 style="font-size:24px;margin:0 0 20px 0;font-family: 'Roboto', sans-serif;
">Hello, {{ name }}</h1>
<p style="margin:0 0 12px 0;font-size:16px;line-height:24px;font-family: 'Roboto', sans-serif;">
We have received some update in your application for a <b>{{ application_type }}</b> offer at
<b>
{{ company_name }}</b>.
<table style="border:solid 1px; margin: auto; text-align: center;width: 80%;
border-radius:15px; background-color: #e0e3ee">
<tr>
<td style="padding:8px 10px;color:#153643; "> resume:</td>
<td style="padding:8px 10px;color:#153643;">{{ resume }}</td>
</tr>
</table>
{% if additional_info_items %}
We received these additional details
<br>
<table style="border:solid 1px; margin: auto; text-align: center;width: 80%;
border-radius:15px; background-color: #e0e3ee">
<p style="margin:0 0 12px 0;font-size:16px;line-height:24px;font-family:
'Roboto', sans-serif;text-align: center">
{% for i,j in additional_info_items.items %}
<tr>
<td style="padding:8px 10px;color:#153643; ">{{ i }}:</td>
<td style="padding:8px 10px;color:#153643;">{{ j }}</td>
</tr>
{% endfor %}
</table>
{% endif %}
</p>
</p>
<p style="margin:0 0 12px 0;font-size:16px;line-height:24px;font-family: 'Roboto', sans-serif;">
We will keep you informed with the updates. If you have any queries, please
feel to
write to
<nobr><u>cdc.support@iitdh.ac.in</u></nobr>
</p>
</td>
</tr>
<tr>
<td style="padding:0;">
<table role="presentation"
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;">
<tr>
<td style="width:260px;padding:0;vertical-align:top;color:#334878;">
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td style="padding:30px;background:#334878;">
<table role="presentation"
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;font-size:9px;font-family: 'Roboto', sans-serif;">
<tr>
<td style="padding:0;width:50%;" align="left">
<p style="margin:0;font-size:14px;line-height:16px;font-family: 'Roboto', sans-serif;color:#ffffff;">
&reg; CDC,IIT Dharwad,2021<br/>
</p>
</td>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>

View File

@ -0,0 +1,118 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="x-apple-disable-message-reformatting">
<title></title>
<!--[if mso]>
<noscript>
<xml>
<o:OfficeDocumentSettings>
<o:PixelsPerInch>96</o:PixelsPerInch>
</o:OfficeDocumentSettings>
</xml>
</noscript>
<![endif]-->
<link rel="preconnect" href="https://fonts.gstatic.com">
<link rel="shortcut icon" href="favicon.ico"/>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@500&display=swap" rel="stylesheet">
<style>
table, td, div, h1, p {
font-family: 'Roboto', sans-serif;
}
</style>
</head>
<body style="margin:0;padding:0;">
<table role="presentation" style="width:100%;border-collapse:collapse;border:0;border-spacing:0;background:#ffffff;">
<tr>
<td align="center" style="padding:0;">
<table role="presentation"
style="width:602px;border-collapse:collapse;border:1px solid #334878;border-spacing:0;text-align:left;">
<tr>
<td align="center" style="padding:40px 0 30px 0;background:#334878;">
<img src="https://drive.google.com/uc?id=1QTA6dB7jnsZfU1kzyUqfD_2V5xODpWFt" alt="" width="200"
style="height:auto;display:block;"/>
</td>
</tr>
<tr>
<td style="padding:36px 30px 42px 30px;">
<table role="presentation"
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;">
<tr>
<td style="padding:0 0 36px 0;color:#153643;">
<h1 style="font-size:24px;margin:0 0 20px 0;font-family: 'Roboto', sans-serif;
">Hello, {{ name }}</h1>
<p style="margin:0 0 12px 0;font-size:16px;line-height:24px;font-family: 'Roboto', sans-serif;">
We have received your issue regarding a <b>{{ application_type }}</b> opening at
<b>
{{ company_name }}</b>.
{% if additional_info %}
We received these additional details
<br>
<p style="margin:0 0 12px 0;font-size:16px;line-height:24px;font-family:
'Roboto', sans-serif;text-align: center">
<table style="border:solid 1px; margin: auto; text-align: center;width: 80%;
border-radius:15px; background-color: #e0e3ee">
{% for i,j in additional_info.items %}
<tr>
<td style="padding:8px 10px;color:#153643; ">{{ i }}:</td>
<td style="padding:8px 10px;color:#153643;">{{ j }}</td>
</tr>
{% endfor %}
</table>
{% endif %}
</p>
</p>
<p style="margin:0 0 12px 0;font-size:16px;line-height:24px;font-family: 'Roboto', sans-serif;">
We will get back to you if we find it legitimate. If you have any queries, please
feel to
write to
<nobr><u>cdc.support@iitdh.ac.in</u></nobr>
</p>
</td>
</tr>
<tr>
<td style="padding:0;">
<table role="presentation"
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;">
<tr>
<td style="width:260px;padding:0;vertical-align:top;color:#334878;">
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td style="padding:30px;background:#334878;">
<table role="presentation"
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;font-size:9px;font-family: 'Roboto', sans-serif;">
<tr>
<td style="padding:0;width:50%;" align="left">
<p style="margin:0;font-size:14px;line-height:16px;font-family: 'Roboto', sans-serif;color:#ffffff;">
&reg; CDC,IIT Dharwad,2021<br/>
</p>
</td>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>

View File

@ -0,0 +1,77 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="x-apple-disable-message-reformatting">
<title></title>
<!--[if mso]>
<noscript>
<xml>
<o:OfficeDocumentSettings>
<o:PixelsPerInch>96</o:PixelsPerInch>
</o:OfficeDocumentSettings>
</xml>
</noscript>
<![endif]-->
<link rel="preconnect" href="https://fonts.gstatic.com">
<link rel="shortcut icon" href="favicon.ico"/>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@500&display=swap" rel="stylesheet">
<style>
table, td, div, h1, p {
font-family: 'Roboto', sans-serif;
}
</style>
</head>
<body style="margin:0;padding:0;">
<table role="presentation" style="width:100%;border-collapse:collapse;border:0;border-spacing:0;background:#ffffff;">
<tr>
<td align="center" style="padding:0;">
<table role="presentation"
style="width:602px;border-collapse:collapse;border:1px solid #334878;border-spacing:0;text-align:left;">
<tr>
<td align="center" style="padding:40px 0 30px 0;background:#334878;">
<img src="https://drive.google.com/uc?id=1QTA6dB7jnsZfU1kzyUqfD_2V5xODpWFt" alt="" width="200"
style="height:auto;display:block;"/>
</td>
</tr>
<tr>
<td style="padding:36px 30px 42px 30px;">
<table role="presentation"
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;">
<tr>
<td style="padding:0 0 36px 0;color:#153643;">
<h1 style="font-size:24px;margin:0 0 20px 0;font-family: 'Roboto', sans-serif;
">{{ opening_type }} Opportunity at {{ company_name }}</h1>
<p style="margin:0 0 12px 0;font-size:16px;line-height:24px;font-family: 'Roboto', sans-serif;">
Gentle reminder to fill out the application form.
Interested students can apply before <b>{{ deadline }}</b> in the <a
href="{{ link }}">CDC-webportal</a>.
</p>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td style="padding:30px;background:#334878;">
<table role="presentation"
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;font-size:9px;font-family: 'Roboto', sans-serif;">
<tr>
<td style="padding:0;width:50%;" align="left">
<p style="margin:0;font-size:14px;line-height:16px;font-family: 'Roboto', sans-serif;color:#ffffff;">
&reg; CDC,IIT Dharwad,2022<br/>
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>

View File

@ -0,0 +1,7 @@
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('APIs.urls')),
]

View File

@ -0,0 +1,15 @@
"""
WSGI config for CDC_Backend project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/2.2/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'CDC_Backend.settings')
application = get_wsgi_application()

1462
CDC_Backend/README.md Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

1332
CDC_Backend/access.log.save Normal file

File diff suppressed because it is too large Load Diff

104099
CDC_Backend/access.log.save.1 Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,16 @@
{
"web": {
"client_id": "956830229554-290mirc16pdhd5j7ph7v7ukibo4t1qcp.apps.googleusercontent.com",
"project_id": "cdc-automation",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_secret": "ZzvcweJylL1IDLUnYOi1ws2W",
"redirect_uris": [
"https://www.getpostman.com/oauth2/callback"
],
"javascript_origins": [
"http://localhost:3000"
]
}
}

View File

View File

@ -0,0 +1,10 @@
from django.contrib import admin
# Register your models here.
from .models import *
admin.site.register(Internship)
admin.site.register(Season)
admin.site.register(InternshipApplication)

View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class InternapisConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'internAPIs'

View File

@ -0,0 +1,7 @@
from django.urls import path
from . import companyViews
urlpatterns = [
path('addInternship/', companyViews.addInternship, name="Add Internship"),
]

View File

@ -0,0 +1,4 @@
def addInternship(request):
pass

View File

@ -0,0 +1,189 @@
import os
BRANCH_CHOICES = [
["CSE", "CSE"],
["EE", "EE"],
["ME", "ME"],
['MMAE', 'MMAE'],
['EP', 'EP'],
]
BRANCHES = [
"CSE",
"EE",
"MMAE",
"EP"
]
BATCH_CHOICES = [
["2021", "2021"],
["2020", "2020"],
["2019", "2019"],
["2018", "2018"],
["2017", "2017"],
]
OFFER_CITY_TYPE = [
['Domestic', 'Domestic'],
['International', 'International']
]
FACILITIES_PROVIDED = [
['Accommodation', 'Accommodation'],
['Food', 'Food'],
['Transport', 'Transport'],
['Medical', 'Medical'],
]
TOTAL_FACILITIES = 4
TIERS = [
['psu', 'PSU'],
['1', 'Tier 1'],
['2', 'Tier 2'],
['3', 'Tier 3'],
['4', 'Tier 4'],
['5', 'Tier 5'],
['6', 'Tier 6'],
['7', 'Tier 7'],
]
SEASON_CHOICES = (
['summer', 'Summer'],
['winter', 'Winter'],
['autumn', 'Autumn'],
['spring', 'Spring'],
)
DEGREE_CHOICES = [
['bTech', 'B.Tech'],
['ms/phd', 'MS/ PhD'],
]
TOTAL_BRANCHES = 4 # Total No of Branches
TOTAL_BATCHES = 5 # Total No of Batches
CDC_MAIl_ADDRESS = '2000'
# To be Configured Properly
CLIENT_ID = os.environ.get('GOOGLE_OAUTH_CLIENT_ID') # Google Login Client ID
# To be Configured Properly
PLACEMENT_OPENING_URL = "https://cdc.iitdh.ac.in/portal/student/dashboard/placements/{id}" # On frontend, this is the URL to be opened
LINK_TO_STORAGE_COMPANY_ATTACHMENT = "https://cdc.iitdh.ac.in/storage/Company_Attachments/"
LINK_TO_STORAGE_RESUME = "https://cdc.iitdh.ac.in/storage/Resumes/"
LINK_TO_APPLICATIONS_CSV = "https://cdc.iitdh.ac.in/storage/Application_CSV/"
LINK_TO_EMAIl_VERIFICATION_API = "https://cdc.iitdh.ac.in/portal/company/verifyEmail?token={token}"
PDF_FILES_SERVING_ENDPOINT = 'https://cdc.iitdh.ac.in/storage/Company_Attachments/' # TODO: Change this to actual URL
EMAIL = "email"
STUDENT = 'student'
ADMIN = 'admin'
SUPER_ADMIN = 's_admin'
COMPANY = 'company'
TIER = 'tier'
# To be Configured Properly
FOURTH_YEAR = '2020'
MAX_OFFERS_PER_STUDENT = 2
MAX_RESUMES_PER_STUDENT = 3
EMAIL_VERIFICATION_TOKEN_TTL = 48 # in hours
INF_TEXT_MAX_CHARACTER_COUNT = 100
INF_TEXTMEDIUM_MAX_CHARACTER_COUNT = 200
INF_TEXTAREA_MAX_CHARACTER_COUNT = 1000
INF_SMALLTEXT_MAX_CHARACTER_COUNT = 50
STORAGE_DESTINATION_RESUMES = "./Storage/Resumes/"
STORAGE_DESTINATION_COMPANY_ATTACHMENTS = './Storage/Company_Attachments/'
STORAGE_DESTINATION_APPLICATION_CSV = './Storage/Application_CSV/'
TOKEN = 'token'
RESUME_FILE_NAME = 'resume_file_name'
APPLICATION_ID = "application_id"
OPENING_ID = "opening_id"
ADDITIONAL_INFO = "additional_info"
FIELD = "field"
STATUS_ACCEPTING_APPLICATIONS = "Accepting Applications"
PLACEMENT = "Placement"
COMPANY_NAME = "company_name"
ADDRESS = "address"
COMPANY_TYPE = "company_type"
NATURE_OF_BUSINESS = "nature_of_business"
TYPE_OF_ORGANISATION = "type_of_organisation"
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'
JOB_LOCATION = 'job_location'
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'
RS_ELIGIBLE = 'rs_eligible'
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'
RECAPTCHA_VALUE = 'recaptchakey'
STUDENT_LIST = "student_list"
STUDENT_ID = "student_id"
STUDENT_SELECTED = "student_selected"
EXCLUDE_IN_PDF = ['id', 'is_company_details_pdf', 'offer_accepted', 'is_description_pdf',
'is_compensation_details_pdf', 'is_selection_procedure_details_pdf',
'email_verified', 'created_at']
SPECIAL_FORMAT_IN_PDF = ['website', 'company_details_pdf_names', 'description_pdf_names',
'compensation_details_pdf_names',
'selection_procedure_details_pdf_names']
COMPANY_OPENING_ERROR_TEMPLATE = "Alert! Error submitting opening for {company_name}."
COMPANY_OPENING_SUBMITTED_TEMPLATE_SUBJECT = "Notification Submitted - {id} - Career Development Cell, IIT Dharwad"
STUDENT_APPLICATION_STATUS_TEMPLATE_SUBJECT = 'Application Status - {company_name} - {id}'
STUDENT_APPLICATION_SUBMITTED_TEMPLATE_SUBJECT = 'CDC - Application Submitted - {company_name}'
STUDENT_APPLICATION_UPDATED_TEMPLATE_SUBJECT = 'CDC - Application Updated - {company_name}'
COMPANY_EMAIl_VERIFICATION_TEMPLATE_SUBJECT = 'Email Verification - Career Development Cell, IIT Dharwad'
NOTIFY_STUDENTS_OPENING_TEMPLATE_SUBJECT = 'Placement Opportunity at {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'
STUDENT_APPLICATION_UPDATED_TEMPLATE = 'student_application_updated.html'
COMPANY_EMAIL_VERIFICATION_TEMPLATE = 'company_email_verification.html'
COMPANY_JNF_RESPONSE_TEMPLATE = 'company_jnf_response.html'
NOTIFY_STUDENTS_OPENING_TEMPLATE = 'notify_students_new_opening.html'
APPLICATION_CSV_COL_NAMES = ['Applied At', 'Roll No.', 'Name', 'Email', 'Phone Number', 'Branch', 'Batch', 'CPI',
'Resume', 'Selected', ]

View File

@ -0,0 +1,187 @@
from django.db import models
# Create your models here.
from django.contrib.postgres.fields import ArrayField
from django.db import models
from django.utils import timezone
from simple_history.models import HistoricalRecords
from .constants import *
#import models from other apps
from APIs.models import User,Student
# Create your models here.
class Internship(models.Model):
id = models.CharField(blank=False, primary_key=True, max_length=15) #unique id for each internship
# Company Details
company_name = models.CharField(blank=False, max_length=INF_SMALLTEXT_MAX_CHARACTER_COUNT)
address = models.CharField(blank=False, max_length=INF_TEXTAREA_MAX_CHARACTER_COUNT)
company_type = models.CharField(blank=False, max_length=INF_SMALLTEXT_MAX_CHARACTER_COUNT)
nature_of_business = models.CharField(blank=False, max_length=INF_SMALLTEXT_MAX_CHARACTER_COUNT, default="")
type_of_organisation = models.CharField(max_length=INF_SMALLTEXT_MAX_CHARACTER_COUNT, default="", blank=False)
website = models.CharField(blank=True, max_length=INF_TEXT_MAX_CHARACTER_COUNT)
company_details = models.CharField(max_length=INF_TEXTAREA_MAX_CHARACTER_COUNT, default=None, null=True, blank=True)
company_details_pdf_names = ArrayField(
models.CharField(null=True, default=None, max_length=INF_TEXT_MAX_CHARACTER_COUNT), size=5,
default=list, blank=True)
is_company_details_pdf = models.BooleanField(blank=False, default=False)
#Company Address
city = models.CharField(blank=False, max_length=INF_SMALLTEXT_MAX_CHARACTER_COUNT, default="")
state = models.CharField(blank=False, max_length=INF_SMALLTEXT_MAX_CHARACTER_COUNT, default="")
country = models.CharField(blank=False, max_length=INF_SMALLTEXT_MAX_CHARACTER_COUNT, default="")
pin_code = models.IntegerField(blank=False, default=None, null=True)
# selection process
selection_procedure_rounds = ArrayField(
models.CharField(null=True, default=None, max_length=INF_TEXT_MAX_CHARACTER_COUNT), size=10,
default=list, blank=True)
selection_procedure_details = models.CharField(blank=True, max_length=INF_TEXTAREA_MAX_CHARACTER_COUNT)
selection_procedure_details_pdf_names = ArrayField(
models.CharField(null=True, default=None, max_length=INF_TEXT_MAX_CHARACTER_COUNT),
size=5, default=list, blank=True)
is_selection_procedure_details_pdf = models.BooleanField(blank=False, default=False)
#Internship Details
description_pdf_names = ArrayField(
models.CharField(null=True, default=None, max_length=INF_TEXT_MAX_CHARACTER_COUNT), size=5, default=list,
blank=True)
is_description_pdf = models.BooleanField(blank=False, default=False)
description = models.CharField(blank=False, max_length=INF_TEXTAREA_MAX_CHARACTER_COUNT, default=None, null=True)
interning_period_from = models.DateField(blank=False, default=None, null=True)
interning_period_to = models.DateField(blank=False, default=None, null=True)
season = models.CharField(blank=False, max_length=10, choices=SEASON_CHOICES, default=None)
is_work_from_home = models.BooleanField(blank=False, default=False)
sophomore_eligible = models.BooleanField(blank=False, default=False)
tentative_no_of_offers = models.IntegerField(blank=False, default=None, null=True)
stipend_description_pdf_names=ArrayField(
models.CharField(null=True, default=None, max_length=INF_TEXT_MAX_CHARACTER_COUNT), size=5, default=list,
blank=True)
is_stipend_description_pdf = models.BooleanField(blank=False, default=False)
stipend=models.IntegerField(blank=False, default=None, null=True)
facilities_provided=ArrayField(
models.CharField(choices=FACILITIES_PROVIDED, blank=False, max_length=20),
size=TOTAL_FACILITIES,
default=list
)
additional_facilities = models.CharField(blank=True, max_length=INF_TEXTAREA_MAX_CHARACTER_COUNT, default=None, null=True)
academic_requirements = models.CharField(blank=True, max_length=INF_TEXTAREA_MAX_CHARACTER_COUNT, default=None, null=True)
#contact details of company person
contact_person_name = models.CharField(blank=False, max_length=INF_TEXT_MAX_CHARACTER_COUNT)
phone_number = models.PositiveBigIntegerField(blank=False)
email = models.EmailField(blank=False)
contact_person_designation = models.CharField(blank=False, max_length=INF_SMALLTEXT_MAX_CHARACTER_COUNT, default="")
telephone_number = models.PositiveBigIntegerField(blank=True, default=None, null=True)
email_verified = models.BooleanField(blank=False, default=False)
#history
created_at = models.DateTimeField(blank=False, default=None, null=True)
updated_at = models.DateTimeField(blank=False, default=None, null=True)
changed_by = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True)
history = HistoricalRecords(user_model=User)
def format(self):
if self.company_name is not None:
self.company_name = self.company_name.strip()[:INF_SMALLTEXT_MAX_CHARACTER_COUNT]
if self.company_type is not None:
self.company_type = self.company_type.strip()[:INF_SMALLTEXT_MAX_CHARACTER_COUNT]
if self.company_details is not None:
self.company_details = self.company_details.strip()[:INF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.address is not None:
self.address = self.address.strip()[:INF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.nature_of_business is not None:
self.nature_of_business = self.nature_of_business.strip()[:INF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.type_of_organisation is not None:
self.type_of_organisation = self.type_of_organisation.strip()[:INF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.website is not None:
self.website = self.website.strip()[:INF_TEXT_MAX_CHARACTER_COUNT]
if self.contact_person_name is not None:
self.contact_person_name = self.contact_person_name.strip()[:INF_TEXT_MAX_CHARACTER_COUNT]
if self.city is not None:
self.city = self.city.strip()[:INF_SMALLTEXT_MAX_CHARACTER_COUNT]
if self.state is not None:
self.state = self.state.strip()[:INF_SMALLTEXT_MAX_CHARACTER_COUNT]
if self.country is not None:
self.country = self.country.strip()[:INF_SMALLTEXT_MAX_CHARACTER_COUNT]
if self.city_type is not None:
self.city_type = self.city_type.strip()[:INF_SMALLTEXT_MAX_CHARACTER_COUNT]
if self.selection_procedure_details is not None:
self.selection_procedure_details = self.selection_procedure_details.strip()[:INF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.description is not None:
self.description = self.description.strip()[:INF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.additional_facilities is not None:
self.additional_facilities = self.additional_facilities.strip()[:INF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.academic_requirements is not None:
self.academic_requirements = self.academic_requirements.strip()[:INF_TEXTAREA_MAX_CHARACTER_COUNT]
if self.contact_person_designation is not None:
self.contact_person_designation = self.contact_person_designation.strip()[:INF_SMALLTEXT_MAX_CHARACTER_COUNT]
@property
def _history_user(self):
return self.changed_by
@_history_user.setter
def _history_user(self, value):
if isinstance(value, User):
self.changed_by = value
else:
self.changed_by = None
def save(self, *args, **kwargs):
''' On save, add timestamps '''
if not self.created_at:
self.created_at = timezone.now()
self.format()
self.updated_at = timezone.now()
return super(Internship, self).save(*args, **kwargs)
def __str__(self):
return self.company_name + " - " + self.id
class Season(models.Model):
season = models.CharField(max_length=10, choices=SEASON_CHOICES, unique=True)
student = models.ForeignKey(Student, on_delete=models.CASCADE, default=None)
def __str__(self):
return self.season + " Season - " + self.student.id
class InternshipApplication(models.Model):
id = models.CharField(blank=False, primary_key=True, max_length=15) #unique id for each internship
internship=models.ForeignKey(Internship,blank=False, on_delete=models.CASCADE, default=None)
student=models.ForeignKey(Student,blank=False, on_delete=models.CASCADE, default=None)
resume = models.CharField(max_length=INF_TEXT_MAX_CHARACTER_COUNT, blank=False, null=True, default=None)
additional_info = models.JSONField(blank=True, null=True, default=None)
selected = models.BooleanField(null=True, default=None, blank=True)
offer_accepted = models.BooleanField(null=True, default=None, blank=True) # True if offer accepted, False if rejected, None if not yet decided
applied_at = models.DateTimeField(blank=False, default=None, null=True)
updated_at = models.DateTimeField(blank=False, default=None, null=True)
changed_by = models.ForeignKey(User, blank=False, on_delete=models.RESTRICT, default=None, null=True)
history = HistoricalRecords(user_model=User)
def save(self, *args, **kwargs):
''' On save, add timestamps '''
if not self.applied_at:
self.applied_at = timezone.now()
self.updated_at = timezone.now()
return super(InternshipApplication, self).save(*args, **kwargs)
@property
def _history_user(self):
return self.changed_by
@_history_user.setter
def _history_user(self, value):
if isinstance(value, User):
self.changed_by = value
else:
self.changed_by = None
class Meta:
verbose_name_plural = "Internship Applications"
unique_together = ('internship', 'student')
def __str__(self):
return self.internship.company_name + " - " + self.student.name

View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

View File

@ -0,0 +1,7 @@
from django.urls import path, include
from . import companyUrls
urlpatterns = [
path('company/', include(companyUrls)),
]

View File

@ -0,0 +1,3 @@
from django.shortcuts import render
# Create your views here.

21
CDC_Backend/manage.py Normal file
View File

@ -0,0 +1,21 @@
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys
def main():
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'CDC_Backend.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()

1
CDC_Backend/run_prod.sh Normal file
View File

@ -0,0 +1 @@
gunicorn --certfile=/home/cdc/Desktop/1f9476e3959ebe60.crt --keyfile=/home/cdc/Desktop/star_iitdh_key.key --bind localhost:8000 CDC_Backend.wsgi --access-logfile access.log --error-logfile error.log --forwarded-allow-ips="cdc.iitdh.ac.in"

View File

View File

@ -0,0 +1,70 @@
from APIs.models import Contributor
from django.shortcuts import get_object_or_404
import time
from dotenv import load_dotenv
import requests
import os
load_dotenv("../dev.env")
owner = 'CDC-IITDH'
access_token = os.environ.get("GITHUB_ACCESS_TOKEN")
headers = {'Authorization': "Token " + access_token}
maxRetires = 10
REPEAT_AFTER = 60 * 15 # 15 minutes
def getStats():
try:
stats = {}
repos = ['cdc-placement-website-backend', 'cdc-placement-website-frontend']
for i in repos:
try:
repo_name = i
print(repo_name)
url = f"https://api.github.com/repos/{owner}/{repo_name}/stats/contributors"
retry = 0
contributors = []
while True:
if retry > maxRetires:
break
req = requests.get(url, headers=headers)
contributors = req.json()
if req.status_code != 200:
print("ERROR:", req.json())
retry += 1
elif len(contributors):
break
retry += 1
time.sleep(1)
for contributor in contributors:
if contributor['author']['login'] not in stats:
stats[contributor['author']['login']] = 0
stats[contributor['author']['login']] += contributor['total']
except Exception as e:
print(e)
for i in stats:
try:
contributor = get_object_or_404(Contributor, github_id=i)
contributor.commits = stats[i]
contributor.save()
except:
pass
stats = sorted(stats.items(), key=lambda x: x[1], reverse=True)
for i in stats:
print(i)
except Exception as e:
print(e)
return stats
def run():
while True:
getStats()
print("Sleeping for", REPEAT_AFTER, "seconds")
time.sleep(REPEAT_AFTER)
print("Running send_reminder_mails()")
run()

View File

@ -0,0 +1,63 @@
from APIs.models import Placement, Student, PlacementApplication, User
from APIs.utils import sendEmail, PlacementApplicationConditions
from APIs.constants import *
from django.shortcuts import get_object_or_404
from django.utils import timezone
import time
import pytz
REPEAT_AFTER = 10 * 60
def send_reminder_mails():
placements = Placement.objects.all()
students = Student.objects.all()
for placement in placements.iterator():
print("Processing placement: ", placement)
# if placement is approved and email is verified
if not (placement.offer_accepted and placement.email_verified):
continue
# if placement is not expired
if placement.deadline_datetime < timezone.now():
continue
# send the reminder mail if the deadline is within 24 hours +- ReapetAfter
if timezone.now() - timezone.timedelta(
seconds=REPEAT_AFTER) <= placement.deadline_datetime - timezone.timedelta(days=1) < timezone.now() + \
timezone.timedelta(seconds=REPEAT_AFTER):
for student in students:
try:
# if Application not found then send email
if not PlacementApplication.objects.filter(placement=placement, student=student).exists():
if student.branch in placement.allowed_branch:
if student.degree == 'bTech' or placement.rs_eligible is True:
if PlacementApplicationConditions(student, placement)[0]:
student_user = get_object_or_404(User, id=student.id)
# change timezone to IST
deadline_datetime = placement.deadline_datetime.astimezone(pytz.timezone('Asia/Kolkata'))
data = {
"company_name": placement.company_name,
"opening_type": 'Placement',
"deadline": deadline_datetime.strftime("%A, %-d %B %Y, %-I:%M %p"),
"link": PLACEMENT_OPENING_URL.format(id=placement.id)
}
print("Sending mail to " + student_user.email, "placement id: ", placement.id)
sendEmail(student_user.email,
REMINDER_STUDENTS_OPENING_TEMPLATE_SUBJECT.format(
company_name=placement.company_name),
data, REMINDER_STUDENTS_OPENING_TEMPLATE)
except Exception as e:
print(e)
continue
def run():
while True:
print("Sleeping for", REPEAT_AFTER, "seconds")
time.sleep(REPEAT_AFTER)
print("Running send_reminder_mails()")
send_reminder_mails()

View File

@ -0,0 +1,90 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="x-apple-disable-message-reformatting">
<title></title>
<!--[if mso]>
<noscript>
<xml>
<o:OfficeDocumentSettings>
<o:PixelsPerInch>96</o:PixelsPerInch>
</o:OfficeDocumentSettings>
</xml>
</noscript>
<![endif]-->
<link rel="preconnect" href="https://fonts.gstatic.com">
<link rel="shortcut icon" href="favicon.ico"/>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@500&display=swap" rel="stylesheet">
<style>
table, td, div, h1, p {
font-family: 'Roboto', sans-serif;
}
</style>
</head>
<body style="margin:0;padding:0;">
<table role="presentation" style="width:100%;border-collapse:collapse;border:0;border-spacing:0;background:#ffffff;">
<tr>
<td align="center" style="padding:0;">
<table role="presentation"
style="width:602px;border-collapse:collapse;border:1px solid #334878;border-spacing:0;text-align:left;">
<tr>
<td align="center" style="padding:40px 0 30px 0;background:#334878;">
<img src="https://drive.google.com/uc?id=1QTA6dB7jnsZfU1kzyUqfD_2V5xODpWFt" alt="" width="200"
style="height:auto;display:block;"/>
</td>
</tr>
<tr>
<td style="padding:36px 30px 42px 30px;">
<table role="presentation"
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;">
<tr>
<td style="padding:0 0 36px 0;color:#153643;">
<p style="margin:0 0 12px 0;font-size:16px;line-height:24px;font-family: 'Roboto', sans-serif;">
We have received your {{opening_type}} Notification for {{ designation }}. Kindly verify your email by clicking <a
href="{{ one_time_link }}">here</a>.
</p>
</td>
</tr>
<tr>
<td style="padding:0;">
<table role="presentation"
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;">
<tr>
<td style="width:260px;padding:0;vertical-align:top;color:#334878;">
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td style="padding:30px;background:#334878;">
<table role="presentation"
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;font-size:9px;font-family: 'Roboto', sans-serif;">
<tr>
<td style="padding:0;width:50%;" align="left">
<p style="margin:0;font-size:14px;line-height:16px;font-family: 'Roboto', sans-serif;color:#ffffff;">
&reg; CDC,IIT Dharwad,2021<br/>
</p>
</td>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>

View File

@ -0,0 +1,73 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
#details_table tr:nth-child(even) {
background: #FFF
}
#details_table tr:nth-child(odd) {
background: #bfe3f3
}
#details_table td {
padding: 10px;
width: 50%;
}
#details_table {
border: #334878 1px solid;
border-collapse: collapse;
width: 80%;
margin: auto;
}
</style>
<title>Document</title>
</head>
<body style="margin: 0;font-family: sans-serif;">
<header style="background-color: #334878;"><img style="height: 3cm; margin: auto; display: block; padding: 0.5cm;"
src='{{ imgpath }}' alt="cdc logo"></header>
<h1 style="text-align: center;"> {{type}} Notification Form Response</h1>
<table id="details_table">
{% for key, value in data.items %}
<tr>
<td>
{{ key }}
</td>
<td>
{% if 'list' in value.type %}
{% for item in value.details %}
<li>
{% if 'link' in value.type and value.link %}
<a href="{{ value.link|add:item}}">{{ item|slice:"16:" }}</a>
{% elif 'link' in value.type %}
<a href="{{ item }}">{{ item }}</a>
{% else %}
{{ item }}
{% endif %}
</li>
{% endfor %}
{% else %}
{% if 'link' in value.type %}
<a href="{{ value.details }}">{{ value.details }}</a>
{% else %}
{{ value }}
{% endif %}
{% endif %}
</td>
</tr>
{% endfor %}
</table>
<p style="margin-left: 10%;">In case of any descripency regarding above details, please contact <a
href="mailto:cdc@iitdh.ac.in">cdc@iitdh.ac.in</a>
</p>
</body>
</html>

View File

@ -0,0 +1,135 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="x-apple-disable-message-reformatting">
<title></title>
<!--[if mso]>
<noscript>
<xml>
<o:OfficeDocumentSettings>
<o:PixelsPerInch>96</o:PixelsPerInch>
</o:OfficeDocumentSettings>
</xml>
</noscript>
<![endif]-->
<link rel="preconnect" href="https://fonts.gstatic.com">
<link rel="shortcut icon" href="favicon.ico"/>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@500&display=swap" rel="stylesheet">
<style>
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;
}
</style>
</head>
<body style="margin:0;padding:0;">
<table role="presentation" style="width:100%;border-collapse:collapse;border:0;border-spacing:0;background:#ffffff;">
<tr>
<td align="center" style="padding:0;">
<table role="presentation"
style="width:602px;border-collapse:collapse;border:1px solid #334878;border-spacing:0;text-align:left;">
<tr>
<td align="center" style="padding:40px 0 30px 0;background:#334878;">
<img src="https://drive.google.com/uc?id=1QTA6dB7jnsZfU1kzyUqfD_2V5xODpWFt" alt="" width="200"
style="height:auto;display:block;"/>
</td>
</tr>
<tr>
<td style="padding:36px 30px 42px 30px;">
<table role="presentation"
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;">
<tr>
<td style="padding:0 0 36px 0;color:#153643;">
<h1 style="font-size:24px;margin:0 0 20px 0;font-family: 'Roboto', sans-serif;
">Thank You for filling the form</h1>
<p style="margin:0 0 12px 0;font-size:16px;line-height:24px;font-family: 'Roboto', sans-serif;">
We have received your <b>{{ opening_type }}</b> notification for a
<b>{{ designation }}</b> offer at <b>
{{ company_name }}</b>.
</p>
<p style="margin:0 0 12px 0;font-size:16px;line-height:24px;font-family: 'Roboto', sans-serif;">
We will keep you informed with the updates. If you have any queries, please
feel to
write to
<nobr><u>cdc@iitdh.ac.in</u></nobr>
</p>
<table id="details_table">
{% for key, value in data.items %}
<tr>
<td>
{{ key }}
</td>
<td>
{% if 'list' in value.type %}
{% for item in value.details %}
<li>
{% if 'link' in value.type and value.link %}
<a href="{{ value.link|add:item}}">{{ item }}</a>
{% elif 'link' in value.type %}
<a href="{{ item }}">{{ item }}</a>
{% else %}
{{ item }}
{% endif %}
</li>
{% endfor %}
{% else %}
{% if 'link' in value.type %}
<a href="{{ value.details }}">{{ value.details }}</a>
{% else %}
{{ value }}
{% endif %}
{% endif %}
</td>
</tr>
{% endfor %}
</table>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td style="padding:30px;background:#334878;">
<table role="presentation"
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;font-size:9px;font-family: 'Roboto', sans-serif;">
<tr>
<td style="padding:0;width:50%;" align="left">
<p style="margin:0;font-size:14px;line-height:16px;font-family: 'Roboto', sans-serif;color:#ffffff;">
&reg; CDC,IIT Dharwad,2021<br/>
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View File

@ -0,0 +1,87 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="x-apple-disable-message-reformatting">
<title></title>
<!--[if mso]>
<noscript>
<xml>
<o:OfficeDocumentSettings>
<o:PixelsPerInch>96</o:PixelsPerInch>
</o:OfficeDocumentSettings>
</xml>
</noscript>
<![endif]-->
<link rel="preconnect" href="https://fonts.gstatic.com">
<link rel="shortcut icon" href="favicon.ico"/>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@500&display=swap" rel="stylesheet">
<style>
table, td, div, h1, p {
font-family: 'Roboto', sans-serif;
}
</style>
</head>
<body style="margin:0;padding:0;">
<table role="presentation" style="width:100%;border-collapse:collapse;border:0;border-spacing:0;background:#ffffff;">
<tr>
<td align="center" style="padding:0;">
<table role="presentation"
style="width:602px;border-collapse:collapse;border:1px solid #334878;border-spacing:0;text-align:left;">
<tr>
<td align="center" style="padding:40px 0 30px 0;background:#334878;">
<img src="https://drive.google.com/uc?id=1QTA6dB7jnsZfU1kzyUqfD_2V5xODpWFt" alt="" width="200"
style="height:auto;display:block;"/>
</td>
</tr>
<tr>
<td style="padding:36px 30px 42px 30px;">
<table role="presentation"
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;">
<tr>
<td style="padding:0 0 36px 0;color:#153643;">
<h1 style="font-size:24px;margin:0 0 20px 0;font-family: 'Roboto', sans-serif;
">{{ opening_type }} Opportunity at {{ company_name }}</h1>
<p style="margin:0 0 12px 0;font-size:16px;line-height:24px;font-family: 'Roboto', sans-serif;">
Greetings of the day. Hope you are fine and doing well !
</p>
<p style="text-indent: 4ch; margin:0 0 12px 0;font-size:16px;line-height:24px;font-family: 'Roboto', sans-serif;">
CDC is excited to announce that <b>{{ company_name }}</b> is interested in
recruiting <b>{{ designation }}</b> from IIT Dharwad.
More details can be found in the CDC Web Portal.
</p>
<p style="margin:0 0 12px 0;font-size:16px;line-height:24px;font-family: 'Roboto', sans-serif;">
Interested students can apply before <b>{{ deadline }}</b> in the <a
href="{{ link }}">CDC-Web Portal</a>.
</p>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td style="padding:30px;background:#334878;">
<table role="presentation"
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;font-size:9px;font-family: 'Roboto', sans-serif;">
<tr>
<td style="padding:0;width:50%;" align="left">
<p style="margin:0;font-size:14px;line-height:16px;font-family: 'Roboto', sans-serif;color:#ffffff;">
&reg; CDC,IIT Dharwad,2022<br/>
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>

View File

@ -0,0 +1,117 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="x-apple-disable-message-reformatting">
<title></title>
<!--[if mso]>
<noscript>
<xml>
<o:OfficeDocumentSettings>
<o:PixelsPerInch>96</o:PixelsPerInch>
</o:OfficeDocumentSettings>
</xml>
</noscript>
<![endif]-->
<link rel="preconnect" href="https://fonts.gstatic.com">
<link rel="shortcut icon" href="favicon.ico"/>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@500&display=swap" rel="stylesheet">
<style>
table, td, div, h1, p {
font-family: 'Roboto', sans-serif;
}
</style>
</head>
<body style="margin:0;padding:0;">
<table role="presentation" style="width:100%;border-collapse:collapse;border:0;border-spacing:0;background:#ffffff;">
<tr>
<td align="center" style="padding:0;">
<table role="presentation"
style="width:602px;border-collapse:collapse;border:1px solid #334878;border-spacing:0;text-align:left;">
<tr>
<td align="center" style="padding:40px 0 30px 0;background:#334878;">
<img src="https://drive.google.com/uc?id=1QTA6dB7jnsZfU1kzyUqfD_2V5xODpWFt" alt="" width="200"
style="height:auto;display:block;"/>
</td>
</tr>
<tr>
<td style="padding:36px 30px 42px 30px;">
<table role="presentation"
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;">
<tr>
<td style="padding:0 0 36px 0;color:#153643;">
<h1 style="font-size:24px;margin:0 0 20px 0;font-family: 'Roboto', sans-serif;
">Hello, Folks</h1>
<p style="margin:0 0 12px 0;font-size:16px;line-height:24px;font-family: 'Roboto', sans-serif;">
We have received a issue regarding a <b>{{ application_type }}</b> opening at
<b>
{{ company_name }}</b> From {{name}}.
{% if additional_info %}
We received these additional details
<br>
<p style="margin:0 0 12px 0;font-size:16px;line-height:24px;font-family:
'Roboto', sans-serif;text-align: center">
<table style="border:solid 1px; margin: auto; text-align: center;width: 80%;
border-radius:15px; background-color: #e0e3ee">
{% for i,j in additional_info.items %}
<tr>
<td style="padding:8px 10px;color:#153643; ">{{ i }}:</td>
<td style="padding:8px 10px;color:#153643;">{{ j }}</td>
</tr>
{% endfor %}
</table>
{% endif %}
</p>
</p>
<p style="margin:0 0 12px 0;font-size:16px;line-height:24px;font-family: 'Roboto', sans-serif;">
please look into it and take necessary actions.
get in touch with the student at at <nobr><u>{{ email }}</u></nobr>
</p>
</td>
</tr>
<tr>
<td style="padding:0;">
<table role="presentation"
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;">
<tr>
<td style="width:260px;padding:0;vertical-align:top;color:#334878;">
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td style="padding:30px;background:#334878;">
<table role="presentation"
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;font-size:9px;font-family: 'Roboto', sans-serif;">
<tr>
<td style="padding:0;width:50%;" align="left">
<p style="margin:0;font-size:14px;line-height:16px;font-family: 'Roboto', sans-serif;color:#ffffff;">
&reg; CDC,IIT Dharwad,2021<br/>
</p>
</td>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>

Some files were not shown because too many files have changed in this diff Show More