diff --git a/CDC_Backend/APIs/adminUrls.py b/CDC_Backend/APIs/adminUrls.py
index 587c1bb..da8acd6 100644
--- a/CDC_Backend/APIs/adminUrls.py
+++ b/CDC_Backend/APIs/adminUrls.py
@@ -15,4 +15,5 @@ urlpatterns = [
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"),
]
diff --git a/CDC_Backend/APIs/adminViews.py b/CDC_Backend/APIs/adminViews.py
index e4f0cc2..e935e8d 100644
--- a/CDC_Backend/APIs/adminViews.py
+++ b/CDC_Backend/APIs/adminViews.py
@@ -429,3 +429,205 @@ def getStudentApplication(request, id, email, user_type):
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,
+ "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,
+ "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)
diff --git a/CDC_Backend/APIs/models.py b/CDC_Backend/APIs/models.py
index 9b15724..77d8c6a 100644
--- a/CDC_Backend/APIs/models.py
+++ b/CDC_Backend/APIs/models.py
@@ -276,3 +276,16 @@ class PrePlacementOffer(models.Model):
self.changed_by = value
else:
self.changed_by = None
+
+
+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
\ No newline at end of file
diff --git a/CDC_Backend/APIs/serializers.py b/CDC_Backend/APIs/serializers.py
index 1447d6d..bc8cbaa 100644
--- a/CDC_Backend/APIs/serializers.py
+++ b/CDC_Backend/APIs/serializers.py
@@ -162,7 +162,8 @@ class PlacementApplicationSerializer(serializers.ModelSerializer):
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}
+ ele = {'link': LINK_TO_STORAGE_RESUME + urllib.parse.quote(str(obj.student.roll_no) + "/" + obj.resume),
+ 'name': obj.resume}
return ele
class Meta:
@@ -185,3 +186,9 @@ class PlacementApplicationSerializerForAdmin(serializers.ModelSerializer):
class Meta:
model = PlacementApplication
exclude = ['placement', 'resume']
+
+
+class ContributorSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = Contributor
+ fields = '__all__'
diff --git a/CDC_Backend/APIs/studentUrls.py b/CDC_Backend/APIs/studentUrls.py
index 45b3619..8a1acce 100644
--- a/CDC_Backend/APIs/studentUrls.py
+++ b/CDC_Backend/APIs/studentUrls.py
@@ -10,4 +10,5 @@ urlpatterns = [
path("deleteResume/", studentViews.deleteResume, name="Upload Resume"),
path("submitApplication/", studentViews.submitApplication, name="Submit Application"),
path("deleteApplication/", studentViews.deleteApplication, name="Delete Application"),
+ path("getContributorStats/", studentViews.getContributorStats, name="Get Contributor Stats"),
]
diff --git a/CDC_Backend/APIs/studentViews.py b/CDC_Backend/APIs/studentViews.py
index 45993a5..c68d846 100644
--- a/CDC_Backend/APIs/studentViews.py
+++ b/CDC_Backend/APIs/studentViews.py
@@ -230,4 +230,20 @@ def deleteApplication(request, id, email, user_type):
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)
\ No newline at end of file
diff --git a/CDC_Backend/APIs/utils.py b/CDC_Backend/APIs/utils.py
index 2f5c6fc..be57175 100644
--- a/CDC_Backend/APIs/utils.py
+++ b/CDC_Backend/APIs/utils.py
@@ -172,12 +172,17 @@ def PlacementApplicationConditions(student, placement):
selected_companies = PlacementApplication.objects.filter(student=student, selected=True)
selected_companies_PSU = [i for i in selected_companies if i.placement.tier == 'psu']
PPO = PrePlacementOffer.objects.filter(student=student, accepted=True)
+ 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"
@@ -186,7 +191,7 @@ def PlacementApplicationConditions(student, placement):
return False, "Can't apply for this tier"
for i in PPO:
- if int(i.placement.tier) < int(placement.tier):
+ if int(i.tier) < int(placement.tier):
return False, "Can't apply for this tier"
if student.degree != 'bTech' and not placement.rs_eligible:
diff --git a/CDC_Backend/CDC_Backend/settings.py b/CDC_Backend/CDC_Backend/settings.py
index 154e430..9b2ee68 100644
--- a/CDC_Backend/CDC_Backend/settings.py
+++ b/CDC_Backend/CDC_Backend/settings.py
@@ -30,6 +30,7 @@ DEBUG = os.environ.get('DEBUG') == "True"
ALLOWED_HOSTS = ['cdc.iitdh.ac.in', 'localhost']
+ADMINS = [('Gowtham Sai', '190010036@iitdh.ac.in'), ('Karthik Mv', '200010030@iitdh.ac.in')]
# Application definition
INSTALLED_APPS = [
@@ -47,6 +48,8 @@ INSTALLED_APPS = [
'simple_history',
'import_export',
'django_extensions',
+ "django_extensions"
+
]
MIDDLEWARE = [
@@ -185,14 +188,13 @@ LOGGING = {
'class': 'django_db_logger.db_log_handler.DatabaseLogHandler'
},
'mail_admins': {
- 'level': 'ERROR',
+ 'level': 'WARNING',
'class': 'django.utils.log.AdminEmailHandler',
- 'include_html': True,
}
},
'loggers': {
'db': {
- 'handlers': ['db_log'],
+ 'handlers': ['db_log', 'mail_admins'],
'level': 'DEBUG'
}
}
diff --git a/CDC_Backend/scripts/__init__.py b/CDC_Backend/scripts/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/CDC_Backend/scripts/get_contributor_stats.py b/CDC_Backend/scripts/get_contributor_stats.py
new file mode 100644
index 0000000..ef98c88
--- /dev/null
+++ b/CDC_Backend/scripts/get_contributor_stats.py
@@ -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()
\ No newline at end of file
diff --git a/README.md b/README.md
index bae49a2..1c41ba8 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,8 @@ python# CDC - Backend
### Setup
1. Download the Repository to your local machine
-2. Create a Virtual Environment in the [CDC_Backend](./) folder with this command below
+2. Make Sure u have downloaded python from python.org or windows store.
+3. Create a Virtual Environment in the [CDC_Backend](./) folder with this command below
`python -m venv venv`
3. Activate the environment with this command
`.\venv\Scripts\activate` (for WINDOWS)
@@ -14,6 +15,17 @@ python# CDC - Backend
`pip install -r requirements.txt `
5. Ensure that you have the PostgreSQL installed on your machine and is running on PORT **5432**
6. Make sure to give the correct database credentials in [settings.py](./CDC_Backend/CDC_Backend/settings.py)(https://www.youtube.com/watch?v=bE9h6aAky4s&t=193s)
+7. Run these following commands below. (The same are there in setup.sh for linux users and setup.bat for windows users)
+```cd CDC_Backend
+python manage.py flush --no-input
+python manage.py makemigrations
+python manage.py migrate
+python manage.py collectstatic --noinput
+mkdir Storage
+python manage.py makemigrations APIs
+```
+
+
### Running the Application
@@ -28,13 +40,20 @@ python# CDC - Backend
1. You can access the admin panel by running the server and opening
2. Run `python manage.py createsuperuser` to create a user to access the admin panel.
-3. Set up the Username and Password
-4. You can log in and change the database values anytime.
+3. if there is an error due to time then sync your machine time .
+4. Set up the Username and Password
+5. You can log in and change the database values anytime.
+6. Create your id as insitute Roll No for both admin and student .
+7. if you are still getting an error ,open inspect and see in network
+And then recognize it
+8.Check the client link in dev.env in backend and .env in frontend is the same
+
# Error
1.make sure that your machine time and google time are same ,if not go to setting of date and time and sync this
2.make sure u have used same id for both student and Admin that is your iitfh roll_no
3. same client link in .env of frontend or constants.py of bakcend
+
### Deploying
1. Add the hosted domain name in `ALLOWED_HOSTS` in [settings.py](./CDC_Backend/CDC_Backend/settings.py)
diff --git a/doc/setup/postgres.md b/doc/setup/postgres.md
index d3dba5e..8941fa6 100644
--- a/doc/setup/postgres.md
+++ b/doc/setup/postgres.md
@@ -1,6 +1,6 @@
typical conf file for pg_hba.conf for dev work.
-
+```
# TYPE DATABASE USER ADDRESS METHOD
# "local" is for Unix domain socket connections only
@@ -13,4 +13,5 @@ host all all ::1/128 md5
# replication privilege.
local replication all peer
host replication all 127.0.0.1/32 ident
-host replication all ::1/128 ident
\ No newline at end of file
+host replication all ::1/128 ident
+```