diff --git a/FusionIIIT/applications/iwdModuleV2/migrations/0002_auto_20241015_1451.py b/FusionIIIT/applications/iwdModuleV2/migrations/0002_auto_20241015_1451.py deleted file mode 100644 index 8a5daed35..000000000 --- a/FusionIIIT/applications/iwdModuleV2/migrations/0002_auto_20241015_1451.py +++ /dev/null @@ -1,89 +0,0 @@ -# Generated by Django 3.1.5 on 2024-10-15 14:51 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('iwdModuleV2', '0001_initial'), - ] - - operations = [ - migrations.AddField( - model_name='pageonedetails', - name='page_id', - field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, to='iwdModuleV2.projects'), - ), - migrations.AddField( - model_name='pagethreedetails', - name='page_id', - field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, to='iwdModuleV2.projects'), - ), - migrations.AddField( - model_name='pagetwodetails', - name='page_id', - field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, to='iwdModuleV2.projects'), - ), - migrations.AlterField( - model_name='addendum', - name='key', - field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='iwdModuleV2.projects'), - ), - migrations.AlterField( - model_name='agreement', - name='key', - field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='iwdModuleV2.projects'), - ), - migrations.AlterField( - model_name='corrigendumtable', - name='key', - field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='iwdModuleV2.projects'), - ), - migrations.AlterField( - model_name='financialbiddetails', - name='key', - field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='iwdModuleV2.projects'), - ), - migrations.AlterField( - model_name='letterofintentdetails', - name='key', - field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='iwdModuleV2.projects'), - ), - migrations.AlterField( - model_name='nooftechnicalbidtimes', - name='key', - field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='iwdModuleV2.projects'), - ), - migrations.AlterField( - model_name='pageonedetails', - name='id', - field=models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), - ), - migrations.AlterField( - model_name='pagethreedetails', - name='id', - field=models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), - ), - migrations.AlterField( - model_name='pagetwodetails', - name='id', - field=models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), - ), - migrations.AlterField( - model_name='prebiddetails', - name='key', - field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='iwdModuleV2.projects'), - ), - migrations.AlterField( - model_name='technicalbiddetails', - name='key', - field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='iwdModuleV2.projects'), - ), - migrations.AlterField( - model_name='workorderform', - name='key', - field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='iwdModuleV2.projects'), - ), - ] diff --git a/FusionIIIT/applications/scholarships/api/serializers.py b/FusionIIIT/applications/scholarships/api/serializers.py new file mode 100644 index 000000000..7cf36f45e --- /dev/null +++ b/FusionIIIT/applications/scholarships/api/serializers.py @@ -0,0 +1,85 @@ +from rest_framework import serializers +from applications.academic_information.models import Student +from applications.globals.models import ExtraInfo +from applications.scholarships.models import Award_and_scholarship,Previous_winner,Mcm,Director_silver,Director_gold,Notional_prize,Proficiency_dm,Release + +class McmStatusUpdateSerializer(serializers.ModelSerializer): + class Meta: + model = Mcm + fields = ['status'] + + def validate_status(self, value): + valid_statuses = ['ACCEPTED', 'REJECTED', 'UNDER_REVIEW'] + if value not in valid_statuses: + raise serializers.ValidationError(f"Status must be one of {valid_statuses}.") + return value + +class DirectorSilverDecisionSerializer(serializers.ModelSerializer): + class Meta: + model = Director_silver + fields = ['id', 'status'] + + def validate_status(self, value): + if value not in ['ACCEPTED', 'REJECTED']: + raise serializers.ValidationError("Status must be either 'ACCEPTED' or 'REJECTED'.") + return value + +class DMProficiencyDecisionSerializer(serializers.ModelSerializer): + class Meta: + model = Proficiency_dm + fields = ['id', 'status'] + + def validate_status(self, value): + if value not in ['ACCEPTED', 'REJECTED']: + raise serializers.ValidationError("Status must be either 'ACCEPTED' or 'REJECTED'.") + return value + +class ReleaseSerializer(serializers.ModelSerializer): + class Meta: + model = Release + fields = '__all__' + +# This serializer is used for editing the catalog by convenor and assistant +class AwardAndScholarshipSerializer(serializers.ModelSerializer): + class Meta: + model = Award_and_scholarship + fields = '_all_' + +# this serializer is used for showing data on catalog form +class AwardAndScholarshipSerializer(serializers.ModelSerializer): + class Meta: + model = Award_and_scholarship + fields = ['id', 'award_name', 'catalog'] + extra_kwargs = { + 'catalog': {'required': True, 'allow_null': False} # Make catalog optional + } + +class PreviousWinnerSerializer(serializers.ModelSerializer): + class Meta: + model = Previous_winner + fields = ['student', 'programme', 'year', 'award_id'] + +class McmSerializer(serializers.ModelSerializer): + class Meta: + model = Mcm + fields = '__all__' + +class DirectorSilverSerializer(serializers.ModelSerializer): + class Meta: + model = Director_silver + fields = '__all__' + +class DirectorGoldSerializer(serializers.ModelSerializer): + class Meta: + model = Director_gold + fields = '__all__' + +class NotionalPrizeSerializer(serializers.ModelSerializer): + class Meta: + model = Notional_prize + fields = '__all__' + +class ProficiencyDmSerializer(serializers.ModelSerializer): + class Meta: + model = Proficiency_dm + fields = '__all__' diff --git a/FusionIIIT/applications/scholarships/api/urls.py b/FusionIIIT/applications/scholarships/api/urls.py new file mode 100644 index 000000000..630953067 --- /dev/null +++ b/FusionIIIT/applications/scholarships/api/urls.py @@ -0,0 +1,24 @@ +from django.conf.urls import url + +from . import views +from applications.scholarships.api.views import GetWinnersView +from applications.scholarships.api.views import create_award,McmUpdateView, McmRetrieveView, DirectorSilverRetrieveView,DirectorSilverUpdateView,DirectorGoldRetrieveView,DirectorGoldUpdateView,ProficiencyDmRetrieveView,ProficiencyDmUpdateView,AwardAndScholarshipCreateView,DirectorSilverMarksheetView,DirectorGoldMarksheetView +from applications.scholarships.api.views import ScholarshipDetailView,StudentDetailView,DirectorSilverDetailView,DirectorGoldDetailView,DirectorGoldListView,ReleaseCreateView,McmStatusUpdateView,DirectorSilverDecisionView,DirectorGoldAcceptRejectView,DirectorSilverListView,GetReleaseByAwardView,McmDocumentsRetrieveView +app_name = 'spacs' + +urlpatterns = [ + + # url(r'^$', views.spacs, name='spacs'), + # url(r'^student_view/$', views.student_view, name='student_view'), + # url(r'^convener_view/$', views.convener_view, name='convener_view'), + # url(r'^staff_view/$', views.staff_view, name='staff_view'), + # url(r'^stats/$', views.stats, name='stats'), + # url(r'^convenerCatalogue/$', views.convenerCatalogue, name='convenerCatalogue'), + # url(r'^getWinners/$', views.getWinners, name='getWinners'), + # url(r'^get_MCM_Flag/$', views.get_MCM_Flag, name='get_MCM_Flag'), + # url(r'^getConvocationFlag/$', views.getConvocationFlag, name='getConvocationFlag'), + # url(r'^getContent/$', views.getContent, name='getContent'), + # url(r'^updateEndDate/$', views.updateEndDate, name='updateEndDate'), + url('get-winners/', GetWinnersView.as_view(), name='get-winners') + +] \ No newline at end of file diff --git a/FusionIIIT/applications/scholarships/api/views.py b/FusionIIIT/applications/scholarships/api/views.py new file mode 100644 index 000000000..c1ee16c7e --- /dev/null +++ b/FusionIIIT/applications/scholarships/api/views.py @@ -0,0 +1,524 @@ +from rest_framework.views import APIView +from rest_framework.response import Response +from rest_framework.decorators import api_view +from rest_framework import status +from applications.scholarships.models import Previous_winner, Award_and_scholarship,Mcm,Director_gold,Notional_prize,Director_silver,Proficiency_dm,Release +from rest_framework.views import APIView +from rest_framework.response import Response +from rest_framework.permissions import IsAuthenticated +from .serializers import DirectorSilverDecisionSerializer, DMProficiencyDecisionSerializer +from rest_framework import status +from applications.academic_information.models import Spi, Student +from applications.globals.models import (Designation, ExtraInfo, + HoldsDesignation) +from rest_framework import viewsets +from applications.scholarships.api.serializers import PreviousWinnerSerializer,AwardAndScholarshipSerializer,McmSerializer,NotionalPrizeSerializer,DirectorGoldSerializer,DirectorSilverSerializer,ProficiencyDmSerializer,ReleaseSerializer,McmStatusUpdateSerializer +from django.shortcuts import get_object_or_404 +import datetime + +#This api is for invite application +class ReleaseCreateView(APIView): + def post(self, request): + serializer = ReleaseSerializer(data=request.data) + if serializer.is_valid(): + serializer.save() # Save the data to the database + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + +#This API is for editing the catalogue by convenor and assistant and saving in the database +class AwardAndScholarshipCreateView(APIView): + def post(self, request, pk=None): + # Check if pk is provided, if yes, try to update the existing entry + pk=request.data.get("id") + if pk is not None: + award = get_object_or_404(Award_and_scholarship, pk=pk) + # Update the existing entry + serializer = AwardAndScholarshipSerializer(award, data=request.data, partial=True) + else: + # If pk is not provided, create a new entry + serializer = AwardAndScholarshipSerializer(data=request.data) + + if serializer.is_valid(): + serializer.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) # 201 Created response + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) # 400 Bad Request if data is invalid + +#This api for fetching the award and scholarship catalogue from the database +class create_award(APIView): + + def get(self, request, *args, **kwargs): + awards = Award_and_scholarship.objects.all() # Fetch all awards + serializer = AwardAndScholarshipSerializer(awards, many=True) # Serialize the awards + return Response(serializer.data, status=status.HTTP_200_OK) + +#This api is for Previous Winner +class GetWinnersView(APIView): + + def post(self, request, *args, **kwargs): + award_id = request.data.get('award_id') + batch_year = int(request.data.get('batch')) + programme_name = request.data.get('programme') + + try: + award = Award_and_scholarship.objects.get(id=award_id) + except Award_and_scholarship.DoesNotExist: + return Response({'result': 'Failure', 'error': 'Award not found'}, status=status.HTTP_404_NOT_FOUND) + + winners = Previous_winner.objects.select_related('student', 'award_id').filter( + year=batch_year, award_id=award, programme=programme_name + ) + + context = { + 'student_name': [], + 'student_program': [], + 'roll': [] + } + + if winners.exists(): + for winner in winners: + extra_info = ExtraInfo.objects.get(id=winner.student_id) + student_id = Student.objects.get(id=extra_info) + student_name = extra_info.user.first_name + student_roll = winner.student_id + student_program = student_id.programme + + context['student_name'].append(student_name) + context['roll'].append(student_roll) + context['student_program'].append(student_program) + print(student_roll) + + context['result'] = 'Success' + return Response(context, status=status.HTTP_200_OK) + + else: + return Response({'result': 'Failure', 'error': 'No winners found'}, status=status.HTTP_404_NOT_FOUND) + +class McmUpdateView(APIView): + def post(self, request): + print(request.data) + request.data['student']=request.user.username + serializer = McmSerializer(data=request.data) + if serializer.is_valid(): + mcm_instance = serializer.save() + return Response(McmSerializer(mcm_instance).data, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + +class McmRetrieveView(APIView): + def post(self, request): + roll_number = request.user.username + + if not roll_number: + return Response({"detail": "Roll number is required."}, status=status.HTTP_400_BAD_REQUEST) + + mcm_data = Mcm.objects.filter(student=roll_number) + + if not mcm_data.exists(): + return Response({"detail": "No Mcm data found for this roll number."}, status=status.HTTP_404_NOT_FOUND) + + serializer = McmSerializer(mcm_data, many=True) + + return Response(serializer.data, status=status.HTTP_200_OK) + +class DirectorSilverRetrieveView(APIView): + def post(self, request): + roll_number = request.user.username + + if not roll_number: + return Response({"detail": "Roll number is required."}, status=status.HTTP_400_BAD_REQUEST) + + director_silver_data = Director_silver.objects.filter(student=roll_number) + + if not director_silver_data.exists(): + return Response({"detail": "No Director Silver data found for this roll number."}, status=status.HTTP_404_NOT_FOUND) + + serializer = DirectorSilverSerializer(director_silver_data, many=True) + + return Response(serializer.data, status=status.HTTP_200_OK) + +class DirectorSilverUpdateView(APIView): + def post(self, request): + request.data['student']=request.user.username + request.data['date']= datetime.date.today() + serializer = DirectorSilverSerializer(data=request.data) + if serializer.is_valid(): + director_silver_instance = serializer.save() + return Response(DirectorSilverSerializer(director_silver_instance).data, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + +class DirectorGoldRetrieveView(APIView): + def post(self, request): + roll_number = request.user.username + + if not roll_number: + return Response({"detail": "Roll number is required."}, status=status.HTTP_400_BAD_REQUEST) + + director_gold_data = Director_gold.objects.filter(student=roll_number) + + if not director_gold_data.exists(): + return Response({"detail": "No Director Gold data found for this roll number."}, status=status.HTTP_404_NOT_FOUND) + + serializer = DirectorGoldSerializer(director_gold_data, many=True) + + return Response(serializer.data, status=status.HTTP_200_OK) + +class DirectorGoldUpdateView(APIView): + def post(self, request): + request.data['student']=request.user.username + serializer = DirectorGoldSerializer(data=request.data) + if serializer.is_valid(): + director_gold_instance = serializer.save() + return Response(DirectorGoldSerializer(director_gold_instance).data, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + +class ProficiencyDmUpdateView(APIView): + def post(self, request): + request.data['student']=request.user.username + print(request.data) + serializer = ProficiencyDmSerializer(data=request.data) + if serializer.is_valid(): + proficiency_dm_instance = serializer.save() + return Response(ProficiencyDmSerializer(proficiency_dm_instance).data, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + +class ProficiencyDmRetrieveView(APIView): + def post(self, request): + roll_number = request.user.username + + if not roll_number: + return Response({"detail": "Roll number is required."}, status=status.HTTP_400_BAD_REQUEST) + + proficiency_dm_data = Proficiency_dm.objects.filter(student=roll_number) + + if not proficiency_dm_data.exists(): + return Response({"detail": "No Proficiency DM data found for this roll number."}, status=status.HTTP_404_NOT_FOUND) + + serializer = ProficiencyDmSerializer(proficiency_dm_data, many=True) + + return Response(serializer.data, status=status.HTTP_200_OK) + +#This api for showing the list of student who has applied for mcm scholarship to convenor assistant +class ScholarshipDetailView(APIView): + def get(self, request): + # Fetch all records from the Mcm table + mcm_data = Mcm.objects.all() + # Serialize the data + serializer = McmSerializer(mcm_data, many=True) + # Return the serialized data as a response + return Response(serializer.data, status=status.HTTP_200_OK) + +class DirectorGoldListView(APIView): + def get(self, request): + # Fetch all entries + director_gold_entries = Director_gold.objects.all() + # Serialize all entries + serializer = DirectorGoldSerializer(director_gold_entries, many=True) + # Return the serialized data as a response + return Response(serializer.data, status=status.HTTP_200_OK) + +class DMProficiencyListView(APIView): + def get(self, request): + # Fetch all entries + proficiency_dm_entries = Proficiency_dm.objects.all() + # Serialize all entries + serializer = ProficiencyDmSerializer(proficiency_dm_entries, many=True) + # Return the serialized data as a response + return Response(serializer.data, status=status.HTTP_200_OK) + +#This api is for showing the all the documnet to the convenor or assistant submitted by the student in browse application +class StudentDetailView(APIView): + def post(self, request): + student_id = request.data.get('student_id') + if not student_id: + return Response({"error": "Student ID is required."}, status=status.HTTP_400_BAD_REQUEST) + + try: + mcm_entry = Mcm.objects.get(student_id=student_id) + except Mcm.DoesNotExist: + return Response({"error": "No record found for the given student ID."}, status=status.HTTP_404_NOT_FOUND) + + serializer = McmSerializer(mcm_entry) + return Response(serializer.data, status=status.HTTP_200_OK) + +#This api is for showing the list of student who has applied for director silver in browse application in convenor and assistant +class DirectorSilverDetailView(APIView): + def post(self, request): + student_id = request.data.get('student_id') + + if not student_id: + return Response({"error": "Student ID is required."}, status=status.HTTP_400_BAD_REQUEST) + + try: + director_silver_entry = Director_silver.objects.get(student__id=student_id) + except Director_silver.DoesNotExist: + return Response({"error": "No record found for the given student ID."}, status=status.HTTP_404_NOT_FOUND) + + serializer = DirectorSilverSerializer(director_silver_entry) + return Response(serializer.data, status=status.HTTP_200_OK) + +#This api is for showing the list of student who has applied for director gold in browse application in convenor and assistant +class DirectorGoldDetailView(APIView): + def post(self, request): + student_id = request.data.get('student_id') + + if not student_id: + return Response({"error": "Student ID is required."}, status=status.HTTP_400_BAD_REQUEST) + + try: + director_gold_entry = Director_gold.objects.get(student__id=student_id) + except Director_gold.DoesNotExist: + return Response({"error": "No record found for the given student ID."}, status=status.HTTP_404_NOT_FOUND) + + serializer = DirectorGoldSerializer(director_gold_entry) + return Response(serializer.data, status=status.HTTP_200_OK) + +class GetReleaseByAwardView(APIView): + def post(self, request, *args, **kwargs): + # Get the award name from the request + award_name = request.data.get('award') + + # Check if the award variable is provided + if not award_name: + return Response( + {'result': 'Failure', 'error': 'Award is a required field'}, + status=status.HTTP_400_BAD_REQUEST + ) + + # Fetch records from the Release table where the award matches + releases = Release.objects.filter(award=award_name) + + # Check if any records were found + if releases.exists(): + # Build the response data + data = [] + for release in releases: + data.append({ + 'id': release.id, + 'date_time': release.date_time, + 'programme': release.programme, + 'startdate': release.startdate, + 'enddate': release.enddate, + 'award': release.award, + 'remarks': release.remarks, + 'batch': release.batch, + 'notif_visible': release.notif_visible, + }) + + return Response({'result': 'Success', 'data': data}, status=status.HTTP_200_OK) + + # If no records found + return Response( + {'result': 'Failure', 'error': 'No releases found for the specified award'}, + status=status.HTTP_404_NOT_FOUND + ) + +#This api for MCM status that is accept, reject and under review +class McmStatusUpdateView(APIView): + def post(self, request): + # Fetch the Mcm instance based on the provided primary key (pk) + mcm_instance = get_object_or_404(Mcm,id=request.data.get('id')) + + # Deserialize the input data with the existing object + serializer = McmStatusUpdateSerializer(mcm_instance, data=request.data, partial=True) + + # Validate the data + if serializer.is_valid(): + # Save the updated status + serializer.save() + return Response({"message": "Status updated successfully", "data": serializer.data}, status=status.HTTP_200_OK) + + # Return validation errors + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + +#This api for Director silver accepting and rejecting the application by convenor and assistant +class DirectorSilverDecisionView(APIView): + def post(self, request): + # Deserialize the request data + serializer = DirectorSilverDecisionSerializer(data=request.data) + + if serializer.is_valid(): + try: + # Retrieve the Director_silver instance using the provided id + director_silver = Director_silver.objects.get(id=request.data['id']) + + # Update the status field + director_silver.status = serializer.validated_data['status'] + director_silver.save() + + return Response({"message": f"Application has been {director_silver.status.lower()}."}, + status=status.HTTP_200_OK) + + except Director_silver.DoesNotExist: + return Response({"error": "Director_silver entry not found."}, + status=status.HTTP_404_NOT_FOUND) + + # If the data is invalid + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + +class DMProficiencyDecisionView(APIView): + def post(self, request): + # Deserialize the request data + serializer = DMProficiencyDecisionSerializer(data=request.data) + + if serializer.is_valid(): + try: + # Retrieve the Proficiency_dm instance using the provided id + proficiency_dm = Proficiency_dm.objects.get(id=request.data['id']) + + # Update the status field + proficiency_dm.status = serializer.validated_data['status'] + proficiency_dm.save() + + return Response({"message": f"Application has been {proficiency_dm.status.lower()}."}, + status=status.HTTP_200_OK) + + except Proficiency_dm.DoesNotExist: + return Response({"error": "Proficiency_dm entry not found."}, + status=status.HTTP_404_NOT_FOUND) + + # If the data is invalid + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + +##This api for Director gold accepting and rejecting the application by convenor and assistant +class DirectorGoldAcceptRejectView(APIView): + def post(self, request): + # Get the ID of the Director_gold entry to update + director_gold_id = request.data.get('id') + action = request.data.get('action') # 'accept' or 'reject' + + # Check if the action is valid + if action not in ['accept', 'reject']: + return Response({'error': 'Invalid action. Please choose either "accept" or "reject".'}, status=status.HTTP_400_BAD_REQUEST) + + try: + # Fetch the Director_gold entry from the database using the ID + director_gold = Director_gold.objects.get(id=director_gold_id) + except Director_gold.DoesNotExist: + return Response({'error': 'Director_gold entry not found.'}, status=status.HTTP_404_NOT_FOUND) + + # Update the status based on the action + if action == 'accept': + director_gold.status = 'ACCEPTED' + else: + director_gold.status = 'REJECTED' + + # Save the updated Director_gold entry + director_gold.save() + + # Return the updated entry as a response + serializer = DirectorGoldSerializer(director_gold) + return Response(serializer.data, status=status.HTTP_200_OK) + +#API View to list all entries of the Director_silver model. +class DirectorSilverListView(APIView): + """ + API View to list all entries of the Director_silver model. + """ + def get(self, request): + director_silver_entries = Director_silver.objects.all() + serializer = DirectorSilverSerializer(director_silver_entries, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + +class GetReleaseByAwardView(APIView): + + def post(self, request, *args, **kwargs): + # Get the award name from the request + award_name = request.data.get('award') + + # Check if the award variable is provided + if not award_name: + return Response( + {'result': 'Failure', 'error': 'Award is a required field'}, + status=status.HTTP_400_BAD_REQUEST + ) + + # Fetch records from the Release table where the award matches + releases = Release.objects.filter(award=award_name) + + # Check if any records were found + if releases.exists(): + # Build the response data + data = [] + for release in releases: + data.append({ + 'id': release.id, + 'date_time': release.date_time, + 'programme': release.programme, + 'startdate': release.startdate, + 'enddate': release.enddate, + 'award': release.award, + 'remarks': release.remarks, + 'batch': release.batch, + 'notif_visible': release.notif_visible, + }) + + return Response({'result': 'Success', 'data': data}, status=status.HTTP_200_OK) + + # If no records found + return Response( + {'result': 'Failure', 'error': 'No releases found for the specified award'}, + status=status.HTTP_404_NOT_FOUND + ) + +class McmDocumentsRetrieveView(APIView): + permission_classes = [IsAuthenticated] + + def post(self, request): + roll_number = request.data.get("roll") # Roll number from request body + + if not roll_number: + return Response({"detail": "Roll number is required."}, status=status.HTTP_400_BAD_REQUEST) + + mcm_instance = get_object_or_404(Mcm, student__id=roll_number) + + documents = { + "income_certificate": bytes(mcm_instance.income_certificate).decode('utf-8') if mcm_instance.income_certificate else None, + "marksheet": bytes(mcm_instance.Marksheet).decode('utf-8') if mcm_instance.Marksheet else None, + "bank_details": bytes(mcm_instance.Bank_details).decode('utf-8') if mcm_instance.Bank_details else None, + "affidavit": bytes(mcm_instance.Affidavit).decode('utf-8') if mcm_instance.Affidavit else None, + "aadhar_card": bytes(mcm_instance.Aadhar_card).decode('utf-8') if mcm_instance.Aadhar_card else None, + "fee_receipt": bytes(mcm_instance.Fee_Receipt).decode('utf-8') if mcm_instance.Fee_Receipt else None, + } + + return Response(documents, status=status.HTTP_200_OK) + +class DirectorSilverMarksheetView(APIView): + permission_classes = [IsAuthenticated] + + def post(self, request): + roll_number = request.data.get('roll') # Get roll number from POST request body + + if not roll_number: + return Response({"error": "Roll number is required"}, status=400) + + director_silver_entry = get_object_or_404(Director_silver, student_id=roll_number) + + marksheet_data = director_silver_entry.Marksheet + if marksheet_data: + marksheet_str = bytes(marksheet_data).decode('utf-8') # Convert memoryview to bytes first, then decode + else: + marksheet_str = None + + return Response({ + "marksheet": marksheet_str, + }) + +class DirectorGoldMarksheetView(APIView): + permission_classes = [IsAuthenticated] + + def post(self, request): + roll_number = request.data.get("roll") # Get roll number from POST request body + + if not roll_number: + return Response({"error": "Roll number is required"}, status=400) + + record = get_object_or_404(Director_gold, student_id=roll_number) + + marksheet_data = record.Marksheet + if marksheet_data: + marksheet_str = bytes(marksheet_data).decode('utf-8') # Convert memoryview to bytes first, then decode + else: + marksheet_str = None + + return Response({ + "marksheet": marksheet_str, + }, status=200) diff --git a/FusionIIIT/applications/scholarships/models.py b/FusionIIIT/applications/scholarships/models.py index 9f81e976e..88c174678 100755 --- a/FusionIIIT/applications/scholarships/models.py +++ b/FusionIIIT/applications/scholarships/models.py @@ -1,17 +1,19 @@ import datetime - from django.db import models - from applications.academic_information.models import Student from applications.globals.models import ExtraInfo - class Constants: STATUS_CHOICES = ( ('Complete', 'COMPLETE'), ('Incomplete', 'INCOMPLETE'), ('Reject', 'REJECT'), - ('Accept', 'ACCEPT') + ('Accept', 'ACCEPT'), + ('ACCEPT', 'Accept'), + ('REJECT', 'Reject'), + ('ACCEPTED', 'Accepted'), + ('REJECTED', 'Rejected'), + ('UNDER_REVIEW', 'Under Review') ) TIME = ( @@ -67,7 +69,6 @@ class Constants: ('OWNED', 'OWNED') ) - class Award_and_scholarship(models.Model): award_name = models.CharField(max_length=100, default='') catalog = models.TextField(max_length=5000) @@ -78,7 +79,6 @@ class Meta: def __str__(self): return self.award_name - class Mcm(models.Model): brother_name = models.CharField(max_length=30, null=True) brother_occupation = models.TextField(max_length=100, null=True) @@ -108,30 +108,32 @@ class Mcm(models.Model): loan_amount = models.IntegerField(blank=True, null=True) college_fee = models.IntegerField(blank=True, null=True) college_name = models.CharField(max_length=30, null=True) - income_certificate = models.FileField(null=True, blank=True) - forms = models.FileField(null=True, blank=True) - status = models.CharField(max_length=10, choices=Constants.STATUS_CHOICES, default='INCOMPLETE') + income_certificate = models.FileField(null=False, blank=False, default='', upload_to='scholarships/mcm/income_certificate/') + Marksheet = models.FileField(null=False, blank=False, default='', upload_to='scholarships/mcm/marksheet/') + Bank_details = models.FileField(null=False, blank=False, default='', upload_to='scholarships/mcm/bank_details/') + Affidavit = models.FileField(null=False, blank=False, default='', upload_to='scholarships/mcm/affidavit/') + Aadhar_card = models.FileField(null=False, blank=False, default='', upload_to='scholarships/mcm/aadhar_card/') + Fee_Receipt = models.FileField(null=False, blank=False, default='', upload_to='scholarships/mcm/fee_receipt/') + forms = models.CharField(max_length=100, null=True, blank=True) + status = models.CharField(max_length=20, choices=Constants.STATUS_CHOICES, default='INCOMPLETE') student = models.ForeignKey(Student, on_delete=models.CASCADE, related_name='mcm_info') annual_income = models.IntegerField(default=0) date = models.DateField(default=datetime.date.today) award_id = models.ForeignKey(Award_and_scholarship, default=4, on_delete=models.CASCADE) - class Meta: db_table = 'Mcm' def __str__(self): return str(self.student) - class Notional_prize(models.Model): spi = models.FloatField() cpi = models.FloatField() year = models.CharField(max_length=10, choices=Constants.BATCH) award_id = models.ForeignKey(Award_and_scholarship, default=4, on_delete=models.CASCADE) - class Meta: db_table = 'Notional_prize' @@ -145,7 +147,6 @@ class Previous_winner(models.Model): class Meta: db_table = 'Previous_winner' - class Release(models.Model): date_time = models.DateTimeField(default=datetime.datetime.now, blank=True) programme = models.CharField(max_length=10,default='B.Tech') @@ -190,10 +191,10 @@ class Director_silver(models.Model): nearest_railwaystation = models.TextField(max_length=30, default='station') correspondence_address = models.TextField(max_length=150, null=True) student = models.ForeignKey(Student, on_delete=models.CASCADE) - award_id = models.ForeignKey(Award_and_scholarship, on_delete=models.CASCADE) + award_id = models.ForeignKey(Award_and_scholarship, on_delete=models.CASCADE, default=3) award_type = models.CharField(max_length=50, null=True) - status = models.CharField(max_length=10, choices=Constants.STATUS_CHOICES,default='INCOMPLETE') - relevant_document = models.FileField(null=True, blank=True) + status = models.CharField(max_length=20, choices=Constants.STATUS_CHOICES,default='INCOMPLETE') + Marksheet = models.FileField(null=False, blank=False, default='', upload_to='scholarships/director_silver/marksheet/') date = models.DateField(default=datetime.date.today) financial_assistance = models.TextField(max_length=1000 ,null=True) grand_total = models.IntegerField(null=True) @@ -201,28 +202,26 @@ class Director_silver(models.Model): justification = models.TextField(max_length=1000, null=True) outside_achievements = models.TextField(max_length=1000, null=True) - class Meta: db_table = 'Director_silver' - class Proficiency_dm(models.Model): - relevant_document = models.FileField(null=True, blank=True) + Marksheet = models.FileField(null=False, blank=False, default='', upload_to='scholarships/proficiency_dm/marksheet/') title_name = models.CharField(max_length=30, null=True) student = models.ForeignKey(Student, on_delete=models.CASCADE) - award_id = models.ForeignKey(Award_and_scholarship, on_delete=models.CASCADE) + award_id = models.ForeignKey(Award_and_scholarship, on_delete=models.CASCADE, default=4) award_type = models.CharField(max_length=50, null=True) - status = models.CharField(max_length=10, choices=Constants.STATUS_CHOICES,default='INCOMPLETE') + status = models.CharField(max_length=20, choices=Constants.STATUS_CHOICES,default='INCOMPLETE') nearest_policestation = models.TextField(max_length=30, default='station') nearest_railwaystation = models.TextField(max_length=30, default='station') correspondence_address = models.TextField(max_length=150, null=True) no_of_students = models.IntegerField(default=1) date = models.DateField(default=datetime.date.today) - roll_no1 = models.IntegerField(default=0) - roll_no2 = models.IntegerField(default=0) - roll_no3 = models.IntegerField(default=0) - roll_no4 = models.IntegerField(default=0) - roll_no5 = models.IntegerField(default=0) + roll_no1 = models.CharField(max_length=30, null=True) + roll_no2 = models.CharField(max_length=30, null=True) + roll_no3 = models.CharField(max_length=30, null=True) + roll_no4 = models.CharField(max_length=30, null=True) + roll_no5 = models.CharField(max_length=30, null=True) financial_assistance = models.TextField(max_length=1000 ,null=True) brief_description = models.TextField(max_length=1000 ,null=True) justification = models.TextField(max_length=1000 ,null=True) @@ -231,10 +230,10 @@ class Proficiency_dm(models.Model): cse_topic = models.CharField(max_length=25,null=True) mech_topic = models.CharField(max_length=25,null=True) design_topic = models.CharField(max_length=25,null=True) - ece_percentage = models.IntegerField(null=True) - cse_percentage = models.IntegerField(null=True) - mech_percentage = models.IntegerField(null=True) - design_percentage = models.IntegerField(null=True) + ece_percentage = models.FloatField(null=True) + cse_percentage = models.FloatField(null=True) + mech_percentage = models.FloatField(null=True) + design_percentage = models.FloatField(null=True) correspondence_address = models.CharField(max_length=100, null=True) financial_assistance = models.TextField(max_length=1000, null=True) grand_total = models.IntegerField(null=True) @@ -245,14 +244,13 @@ class Proficiency_dm(models.Model): class Meta: db_table = 'Proficiency_dm' - class Director_gold(models.Model): student = models.ForeignKey(Student, on_delete=models.CASCADE) - status = models.CharField(max_length=10,choices=Constants.STATUS_CHOICES, default='INCOMPLETE') + status = models.CharField(max_length=20,choices=Constants.STATUS_CHOICES, default='INCOMPLETE') correspondence_address = models.TextField(max_length=40, default='address') nearest_policestation = models.TextField(max_length=30, default='station') nearest_railwaystation = models.TextField(max_length=30, default='station') - relevant_document = models.FileField(null=True, blank=True) + Marksheet = models.FileField(null=False, blank=False, default='', upload_to='scholarships/director_gold/marksheet/') date = models.DateField(default=datetime.date.today) award_id = models.ForeignKey(Award_and_scholarship, default=4, on_delete=models.CASCADE) financial_assistance = models.TextField(max_length=1000 ,null=True) diff --git a/FusionIIIT/applications/scholarships/urls.py b/FusionIIIT/applications/scholarships/urls.py index 121cdd116..e7f5d77b4 100755 --- a/FusionIIIT/applications/scholarships/urls.py +++ b/FusionIIIT/applications/scholarships/urls.py @@ -1,6 +1,12 @@ from django.conf.urls import url +from django.urls import path, include +from rest_framework.routers import DefaultRouter from . import views +from applications.scholarships.api.views import GetWinnersView +from applications.scholarships.api.views import create_award,McmUpdateView, McmRetrieveView, DirectorSilverRetrieveView,DirectorSilverUpdateView,DirectorGoldRetrieveView,DirectorGoldUpdateView,ProficiencyDmRetrieveView,ProficiencyDmUpdateView,AwardAndScholarshipCreateView,DirectorSilverMarksheetView,DirectorGoldMarksheetView +from applications.scholarships.api.views import ScholarshipDetailView,StudentDetailView,DirectorSilverDetailView,DirectorGoldDetailView,DirectorGoldListView,DMProficiencyListView,ReleaseCreateView,McmStatusUpdateView,DirectorSilverDecisionView,DMProficiencyDecisionView,DirectorGoldAcceptRejectView,DirectorSilverListView,GetReleaseByAwardView,McmDocumentsRetrieveView +# ,DirectorSilverAcceptRejectView app_name = 'spacs' @@ -17,5 +23,65 @@ url(r'^getConvocationFlag/$', views.getConvocationFlag, name='getConvocationFlag'), url(r'^getContent/$', views.getContent, name='getContent'), url(r'^updateEndDate/$', views.updateEndDate, name='updateEndDate'), + #app --> api created by 2022 batch + url(r'get-winners/', GetWinnersView.as_view(), name='get-winners'), + url(r'create-award/', create_award.as_view(), name='create-award'), + url(r'mcm_update/', McmUpdateView.as_view(), name='mcm-update'), + url(r'mcm_show/', McmRetrieveView.as_view(), name='mcm-show'), + url(r'directorsilver_show/', DirectorSilverRetrieveView.as_view(), name='director-silver--show'), + url(r'directorsilver_update/', DirectorSilverUpdateView.as_view(), name='director-silver-update'), + url(r'directorgold_show/', DirectorGoldRetrieveView.as_view(), name='director-gold-show'), + url(r'directorgold_update/', DirectorGoldUpdateView.as_view(), name='director-gold-update'), + url(r'proficiencydm_update/', ProficiencyDmUpdateView.as_view(), name='proficiency-dm-update'), + url(r'proficiencydm_show/', ProficiencyDmRetrieveView.as_view(), name='proficiency-dm-update'), + # path('award/', AwardAndScholarshipCreateView.as_view(), name='award-create'), # URL for convenor catalog + + # path('scholarship-details/', ScholarshipDetailView.as_view(), name='scholarship-list'), + # path('director_gold_list/', DirectorGoldListView.as_view(), name='director_gold_list'), + # #path('scholarship-details//', ScholarshipDetailView.as_view(), name='scholarship-detail'), + # url(r'student_file_show/', StudentDetailView.as_view(), name='student-file-show'), + # path('director_silver_show/', DirectorSilverDetailView.as_view(), name='director_silver_detail'), + # path('director_gold_view/', DirectorGoldDetailView.as_view(), name='director_gold_detail'), + # path(r'release', ReleaseCreateView.as_view(), name='release_create'), + + # below this line all api's are for convenor and assistant + + # edit and save the catalog by convenor or assistant + path('award/', AwardAndScholarshipCreateView.as_view(), name='award-create'), + + # to show all the applications of mcm to the convenor and assistant + path('scholarship-details/', ScholarshipDetailView.as_view(), name='scholarship-list'), + #path('scholarship-details//', ScholarshipDetailView.as_view(), name='scholarship-detail'), + + # to show all the application of director's gold to + path('director_gold_list/', DirectorGoldListView.as_view(), name='director_gold_list'), + + # to show the all submit details of a particular student to convenor and assistant + url(r'student_file_show/', StudentDetailView.as_view(), name='student-file-show'), + + # to show the all submit details of a particular student about director's silver to convenor and assistant + path('director_silver_show/', DirectorSilverDetailView.as_view(), name='director_silver_detail'), + + # to show the all submit details of a particular student about director's gold to convenor and assistant + path('director_gold_view/', DirectorGoldDetailView.as_view(), name='director_gold_detail'), + + # Api for invite appication usecase + path('release', ReleaseCreateView.as_view(), name='release_create'), + + # to get the data from relaese table according to the name of award and scholarship + path('releases/get-by-award/', GetReleaseByAwardView.as_view(), name='get-release-by-award'), + + + # url(r'student_file_show/', StudentDetailView.as_view(), name='student-file-show'), + path('mcm/status-update/', McmStatusUpdateView.as_view(), name='mcm-status-update'), + path('api/director_silver/decision/', DirectorSilverDecisionView.as_view(), name='director_silver_decision'), + path('director-gold/accept-reject/', DirectorGoldAcceptRejectView.as_view(), name='director-gold-accept-reject'), + path('api/dm-proficiency/decsion/', DMProficiencyDecisionView.as_view(), name='proficiency-dm-decision'), + path('director-silver/', DirectorSilverListView.as_view(), name='director-silver-list'), + # path('director-silver/accept-reject/', DirectorSilverAcceptRejectView.as_view(), name='director-silver-accept-reject'), + path('mcm/documents/', McmDocumentsRetrieveView.as_view(), name='mcm-documents'), + path('medals/marksheet/', DirectorSilverMarksheetView.as_view(), name='director_silver_marksheet'), + path('medals/marksheet/gold/', DirectorGoldMarksheetView.as_view(), name='director_gold_marksheet'), + path('dm-proficiency-list/', DMProficiencyListView.as_view(), name='proficiency-dm'), ] \ No newline at end of file diff --git a/FusionIIIT/applications/scholarships/views.py b/FusionIIIT/applications/scholarships/views.py index bbcbffb16..b0897bede 100755 --- a/FusionIIIT/applications/scholarships/views.py +++ b/FusionIIIT/applications/scholarships/views.py @@ -100,10 +100,10 @@ def convener_view(request): # It updates the student Notification table on the spacs head sending the mcm invitation if batch == 'all': active_batches = range(datetime.datetime.now().year - 4 , datetime.datetime.now().year + 1) - query = reduce(or_, (Q(id__id__startswith=int(batch)-2000) for batch in active_batches)) + query = reduce(or_, (Q(id_id_startswith=int(batch)-2000) for batch in active_batches)) recipient = Student.objects.filter(programme=programme).filter(query) else: - recipient = Student.objects.filter(programme=programme, id__id__startswith=int(batch)-2000) + recipient = Student.objects.filter(programme=programme, id_id_startswith=int(batch)-2000) # Notification starts convenor = request.user @@ -569,7 +569,7 @@ def submitMCM(request): ).filter(award="Merit-cum-Means Scholarship") for release in releases: if Mcm.objects.select_related('award_id','student').filter( - Q(date__gte=release.startdate, date__lte=release.enddate) + Q(date_gte=release.startdate, date_lte=release.enddate) ).filter(student=request.user.extrainfo.student): # if len(Mcm.objects.filter(student = request.user.extrainfo.student)) > 0: Mcm.objects.select_related('award_id','student').filter( @@ -710,7 +710,7 @@ def submitGold(request): releases = Release.objects.filter(Q(startdate__lte=datetime.datetime.today().strftime( '%Y-%m-%d'), enddate__gte=datetime.datetime.today().strftime('%Y-%m-%d'))).filter(award="Convocation Medals") for release in releases: - existingRelease = Director_gold.objects.select_related('student','award_id').filter(Q(date__gte=release.startdate, date__lte=release.enddate)).filter(student=request.user.extrainfo.student) + existingRelease = Director_gold.objects.select_related('student','award_id').filter(Q(date_gte=release.startdate, date_lte=release.enddate)).filter(student=request.user.extrainfo.student) if existingRelease: existingRelease.update( student=student_id, @@ -805,7 +805,7 @@ def submitSilver(request): releases = Release.objects.filter(Q(startdate__lte=datetime.datetime.today().strftime( '%Y-%m-%d'), enddate__gte=datetime.datetime.today().strftime('%Y-%m-%d'))).filter(award="Convocation Medals") for release in releases: - existingRelease = Director_silver.objects.select_related('student','award_id').filter(Q(date__gte=release.startdate, date__lte=release.enddate)).filter(student=request.user.extrainfo.student) + existingRelease = Director_silver.objects.select_related('student','award_id').filter(Q(date_gte=release.startdate, date_lte=release.enddate)).filter(student=request.user.extrainfo.student) if existingRelease: existingRelease.update( student=student_id, @@ -922,7 +922,7 @@ def submitDM(request): releases = Release.objects.filter(Q(startdate__lte=datetime.datetime.today().strftime( '%Y-%m-%d'), enddate__gte=datetime.datetime.today().strftime('%Y-%m-%d'))).filter(award="Convocation Medals") for release in releases: - existingRelease = Proficiency_dm.objects.select_related('student','award_id').filter(Q(date__gte=release.startdate, date__lte=release.enddate)).filter(student=request.user.extrainfo.student) + existingRelease = Proficiency_dm.objects.select_related('student','award_id').filter(Q(date_gte=release.startdate, date_lte=release.enddate)).filter(student=request.user.extrainfo.student) if existingRelease: existingRelease.update( title_name=title_name,