From 051ea4b1f3442839113bdfbee15ab778b956d369 Mon Sep 17 00:00:00 2001 From: Joshkovu Date: Fri, 1 May 2026 11:35:31 +0300 Subject: [PATCH 1/2] feat: implement evaluation models, viewsets, and permissions for internship grading and assessment tracking --- ...valuations_college_finalresults_college.py | 25 +++++++++++++ logify-backend/apps/evaluations/models.py | 20 ++++++++++- logify-backend/apps/evaluations/views.py | 36 ++++++++++++------- 3 files changed, 67 insertions(+), 14 deletions(-) create mode 100644 logify-backend/apps/evaluations/migrations/0005_evaluations_college_finalresults_college.py diff --git a/logify-backend/apps/evaluations/migrations/0005_evaluations_college_finalresults_college.py b/logify-backend/apps/evaluations/migrations/0005_evaluations_college_finalresults_college.py new file mode 100644 index 0000000..124f4a4 --- /dev/null +++ b/logify-backend/apps/evaluations/migrations/0005_evaluations_college_finalresults_college.py @@ -0,0 +1,25 @@ +# Generated by Django 6.0.4 on 2026-05-01 08:32 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('academics', '0003_remove_departments_institution_colleges_and_more'), + ('evaluations', '0004_auto_20260429_2011'), + ] + + operations = [ + migrations.AddField( + model_name='evaluations', + name='college', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='academics.colleges'), + ), + migrations.AddField( + model_name='finalresults', + name='college', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='academics.colleges'), + ), + ] diff --git a/logify-backend/apps/evaluations/models.py b/logify-backend/apps/evaluations/models.py index 85a0c6b..80f4c01 100644 --- a/logify-backend/apps/evaluations/models.py +++ b/logify-backend/apps/evaluations/models.py @@ -1,4 +1,4 @@ -from apps.academics.models import Institutions, Programmes +from apps.academics.models import Colleges, Institutions, Programmes from apps.accounts.models import User from apps.placements.models import InternshipPlacements from django.db import models @@ -98,8 +98,17 @@ class Evaluations(models.Model): submitted_at = models.DateTimeField(null=True, blank=True) updated_at = models.DateTimeField(auto_now=True) total_score = models.FloatField() + college = models.ForeignKey(Colleges, on_delete=models.CASCADE, null=True, blank=True) created_at = models.DateTimeField(auto_now_add=True) + def save(self, *args, **kwargs): + if not self.college_id and self.placement_id: + try: + self.college = self.placement.programme.department.college + except Exception: + pass + super().save(*args, **kwargs) + def __str__(self): return f"Evaluation by {self.evaluator.email} " f"for {self.placement.internship_title}" @@ -146,7 +155,16 @@ class FinalResults(models.Model): final_score = models.FloatField() final_grade = models.CharField(max_length=255) remarks = models.TextField(blank=True, null=True) + college = models.ForeignKey(Colleges, on_delete=models.CASCADE, null=True, blank=True) computed_at = models.DateTimeField(auto_now_add=True) + def save(self, *args, **kwargs): + if not self.college_id and self.placement_id: + try: + self.college = self.placement.programme.department.college + except Exception: + pass + super().save(*args, **kwargs) + def __str__(self): return f"Final Result for {self.placement.internship_title}" diff --git a/logify-backend/apps/evaluations/views.py b/logify-backend/apps/evaluations/views.py index 2a10c0a..62a30a6 100644 --- a/logify-backend/apps/evaluations/views.py +++ b/logify-backend/apps/evaluations/views.py @@ -1,8 +1,4 @@ -from apps.accounts.access import ( - get_programme_ids_for_college, - get_user_college_id, - get_user_institution_id, -) +from apps.accounts.access import get_user_college_id, get_user_institution_id from apps.accounts.models import User from apps.accounts.permissions import ( IsAcademicSupervisor, @@ -62,13 +58,9 @@ def get_admin_college_placement_filter(user): if institution_id is None or admin_college_id is None: return None - programme_ids = get_programme_ids_for_college(admin_college_id) - if not programme_ids: - return None - return { "placement__institution_id": institution_id, - "placement__programme_id__in": programme_ids, + "college_id": admin_college_id, } @@ -118,7 +110,13 @@ def get_queryset(self): if user.role == User.STUDENT: # type: ignore return Evaluations.objects.filter(placement__intern=user) elif user.role == User.ACADEMIC_SUPERVISOR: # type: ignore - return Evaluations.objects.filter(placement__academic_supervisor=user) + college_id = get_user_college_id(user) + if college_id is None: + return Evaluations.objects.none() + return Evaluations.objects.filter( + placement__academic_supervisor=user, + college_id=college_id, + ) elif user.role == User.WORKPLACE_SUPERVISOR: # type: ignore return Evaluations.objects.filter(placement__workplace_supervisor=user) elif user.role == User.INTERNSHIP_ADMIN: # type: ignore @@ -144,7 +142,13 @@ def get_queryset(self): elif user.role == User.STUDENT: queryset = queryset.filter(evaluation__placement__intern=user) elif user.role == User.ACADEMIC_SUPERVISOR: - queryset = queryset.filter(evaluation__placement__academic_supervisor=user) + college_id = get_user_college_id(user) + if college_id is None: + return EvaluationScores.objects.none() + queryset = queryset.filter( + evaluation__placement__academic_supervisor=user, + evaluation__college_id=college_id, + ) elif user.role == User.WORKPLACE_SUPERVISOR: queryset = queryset.filter(evaluation__placement__workplace_supervisor=user) elif user.role == User.INTERNSHIP_ADMIN: @@ -177,7 +181,13 @@ def get_queryset(self): if user_role == User.STUDENT: return FinalResults.objects.filter(placement__intern=user) elif user_role == User.ACADEMIC_SUPERVISOR: - return FinalResults.objects.filter(placement__academic_supervisor=user) + college_id = get_user_college_id(user) + if college_id is None: + return FinalResults.objects.none() + return FinalResults.objects.filter( + placement__academic_supervisor=user, + college_id=college_id, + ) elif user_role == User.WORKPLACE_SUPERVISOR: return FinalResults.objects.filter(placement__workplace_supervisor=user) elif user_role == User.INTERNSHIP_ADMIN: From bde9e4a27fdbdb82700a241125cf70d3599a2e5f Mon Sep 17 00:00:00 2001 From: Joshkovu Date: Fri, 1 May 2026 11:36:30 +0300 Subject: [PATCH 2/2] feat: add college foreign key to evaluations and finalresults models --- ...valuations_college_finalresults_college.py | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/logify-backend/apps/evaluations/migrations/0005_evaluations_college_finalresults_college.py b/logify-backend/apps/evaluations/migrations/0005_evaluations_college_finalresults_college.py index 124f4a4..1eeea63 100644 --- a/logify-backend/apps/evaluations/migrations/0005_evaluations_college_finalresults_college.py +++ b/logify-backend/apps/evaluations/migrations/0005_evaluations_college_finalresults_college.py @@ -7,19 +7,29 @@ class Migration(migrations.Migration): dependencies = [ - ('academics', '0003_remove_departments_institution_colleges_and_more'), - ('evaluations', '0004_auto_20260429_2011'), + ("academics", "0003_remove_departments_institution_colleges_and_more"), + ("evaluations", "0004_auto_20260429_2011"), ] operations = [ migrations.AddField( - model_name='evaluations', - name='college', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='academics.colleges'), + model_name="evaluations", + name="college", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + to="academics.colleges", + ), ), migrations.AddField( - model_name='finalresults', - name='college', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='academics.colleges'), + model_name="finalresults", + name="college", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + to="academics.colleges", + ), ), ]