Commit - 21-06-24
This commit is contained in:
commit
52abf6e967
|
@ -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
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -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)
|
|
@ -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"),
|
||||||
|
]
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
|
@ -0,0 +1,6 @@
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class ApisConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'APIs'
|
|
@ -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"),
|
||||||
|
]
|
|
@ -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)
|
|
@ -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)
|
|
@ -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())
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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__'
|
|
@ -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")
|
||||||
|
]
|
|
@ -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)
|
|
@ -0,0 +1 @@
|
||||||
|
# Create your tests here.
|
File diff suppressed because it is too large
Load Diff
|
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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')
|
|
@ -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)),
|
||||||
|
]
|
|
@ -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))
|
||||||
|
|
Binary file not shown.
|
@ -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)
|
|
@ -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"),
|
||||||
|
]
|
|
@ -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)
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class ApisConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'APIs'
|
|
@ -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"),
|
||||||
|
]
|
|
@ -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)
|
|
@ -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)
|
|
@ -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"
|
||||||
|
|
|
@ -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__'
|
|
@ -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")
|
||||||
|
]
|
|
@ -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
|
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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')
|
|
@ -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)),
|
||||||
|
]
|
|
@ -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))
|
||||||
|
|
|
@ -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())
|
|
@ -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')),
|
||||||
|
]
|
|
@ -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
|
@ -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"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
|
@ -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()
|
|
@ -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"
|
|
@ -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()
|
|
@ -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()
|
||||||
|
|
|
@ -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')
|
||||||
|
]
|
|
@ -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;">
|
||||||
|
® CDC,IIT Dharwad,2021<br/>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -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>
|
|
@ -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;">
|
||||||
|
® 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 |
|
@ -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;">
|
||||||
|
® CDC,IIT Dharwad,2022<br/>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -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;">
|
||||||
|
® CDC,IIT Dharwad,2021<br/>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -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;">
|
||||||
|
® CDC,IIT Dharwad,2021<br/>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -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;">
|
||||||
|
® CDC,IIT Dharwad,2021<br/>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -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;">
|
||||||
|
® CDC,IIT Dharwad,2021<br/>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -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;">
|
||||||
|
® CDC,IIT Dharwad,2021<br/>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -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;">
|
||||||
|
® CDC,IIT Dharwad,2021<br/>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -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;">
|
||||||
|
® CDC,IIT Dharwad,2022<br/>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -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')),
|
||||||
|
]
|
|
@ -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
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -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"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)
|
|
@ -0,0 +1,6 @@
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class InternapisConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'internAPIs'
|
|
@ -0,0 +1,7 @@
|
||||||
|
from django.urls import path
|
||||||
|
|
||||||
|
from . import companyViews
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path('addInternship/', companyViews.addInternship, name="Add Internship"),
|
||||||
|
]
|
|
@ -0,0 +1,4 @@
|
||||||
|
|
||||||
|
|
||||||
|
def addInternship(request):
|
||||||
|
pass
|
|
@ -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', ]
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
|
@ -0,0 +1,7 @@
|
||||||
|
from django.urls import path, include
|
||||||
|
|
||||||
|
from . import companyUrls
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path('company/', include(companyUrls)),
|
||||||
|
]
|
|
@ -0,0 +1,3 @@
|
||||||
|
from django.shortcuts import render
|
||||||
|
|
||||||
|
# Create your views here.
|
|
@ -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()
|
|
@ -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"
|
|
@ -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()
|
|
@ -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()
|
||||||
|
|
|
@ -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;">
|
||||||
|
® CDC,IIT Dharwad,2021<br/>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -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>
|
|
@ -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;">
|
||||||
|
® 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 |
|
@ -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;">
|
||||||
|
® CDC,IIT Dharwad,2022<br/>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -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;">
|
||||||
|
® 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
Loading…
Reference in New Issue