Skip to content
Merged
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
cf756e8
Merged upstream and integrated PhD backend features
kotangale237 Mar 14, 2026
461cfc7
Resolved migration conflicts and merged branches
kotangale237 Mar 14, 2026
5866382
Merge branch 'FusionIIIT:prod/acad-react' into prod/acad-react
kotangale237 Apr 11, 2026
693ccdc
feat(placement): integrate placement cell API module from PR #1916
vikrantwiz02 Jun 20, 2026
737b933
test(placement): add reliable, runnable placement_cell test suite
vikrantwiz02 Jun 20, 2026
2674040
feat(placement): add setup_placement_roles command and document roles
vikrantwiz02 Jun 20, 2026
2679337
Add off-campus placements and announcements to placement cell
vikrantwiz02 Jun 21, 2026
9dacbf5
Add published-CPI student view and Excel export to placement cell
vikrantwiz02 Jun 21, 2026
9e2b4c4
Speed up published-CPI student loading with caching
vikrantwiz02 Jun 21, 2026
f6c7557
Add branches reference endpoint for placement forms
vikrantwiz02 Jun 21, 2026
642f155
Add free-form placement calendar events (CRUD)
vikrantwiz02 Jun 21, 2026
c19d91b
Validate batch_id on the published-CPI export endpoint
vikrantwiz02 Jun 21, 2026
dfeb6b1
Document the placement cell module (features, roles, API, setup)
vikrantwiz02 Jun 21, 2026
e7bc94e
Merge pull request #1923 from vikrantwiz02/placement-pbi-v1
vikrantwiz02 Jun 21, 2026
d8c6ee7
Merge pull request #1924 from FusionIIIT/placement-pbi-v1
vikrantwiz02 Jun 21, 2026
a8f4c96
Merge remote-tracking branch 'upstream/prod/acad-react' into prod/aca…
kotangale237 Jul 5, 2026
7ee4673
Implement PhD thesis submission workflow (Student -> Supervisor -> De…
kotangale237 Jul 5, 2026
c43e666
Pending programme_curriculum batch-management changes
kotangale237 Jul 5, 2026
91d9b57
Add PhD thesis review workflow (examiner invitations, review models, …
kotangale237 Jul 9, 2026
4f72377
Merge pull request #1928 from kotangale237/phd
vikrantwiz02 Jul 9, 2026
13295b1
Merge pull request #1929 from vikrantwiz02/sections
vikrantwiz02 Jul 9, 2026
279ebbd
Merge remote-tracking branch 'upstream/prod/acad-react' into prod/aca…
kotangale237 Jul 19, 2026
626ace4
Merge branch 'prod/acad-react' into phd
kotangale237 Jul 19, 2026
7339f69
Add comprehensive exam, open seminar, teaching credit, and PhD course…
kotangale237 Jul 19, 2026
28d8498
Merge prod/acad-react into prod-test
vikrantwiz02 Jul 19, 2026
a04b5e2
Merge phd (PR #1934) into prod-test
vikrantwiz02 Jul 19, 2026
d28ab34
Redesign Comprehensive Exam and Open Seminar: RPC/DPGC/PGCS/Dean flow
kotangale237 Jul 23, 2026
2ad9970
Merge remote-tracking branch 'upstream/prod-test' into sections
vikrantwiz02 Jul 23, 2026
d749bb9
Merge pull request #1935 from vikrantwiz02/sections
vikrantwiz02 Jul 23, 2026
d5ee956
Merge pull request #1936 from kotangale237/phd
vikrantwiz02 Jul 23, 2026
fc51dde
Build review-detail media URL from the request instead of a settings …
kotangale237 Jul 23, 2026
1019af3
Merge pull request #1937 from kotangale237/phd
vikrantwiz02 Jul 23, 2026
fa07b7c
Add PG thesis submission + examiner panel workflow; misc fixes across…
kotangale237 Aug 4, 2026
29151df
Merge remote-tracking branch 'upstream/prod/acad-react' into phd
kotangale237 Aug 4, 2026
64dee84
Merge remote-tracking branch 'upstream/prod-test' into phd
kotangale237 Aug 5, 2026
e05f805
Merge remote-tracking branch 'upstream/prod/acad-react' into prod/aca…
kotangale237 Aug 5, 2026
ae4e9e5
Merge branch 'prod/acad-react' into phd
kotangale237 Aug 5, 2026
a413ff7
Harden review findings: authz, atomicity, transcript credit reconcile
vikrantwiz02 Aug 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions FusionIIIT/Fusion/settings/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,20 @@
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TIMEZONE = 'Asia/Calcutta'

# Base URL of the React frontend, used to build links (e.g. emailed thesis
# examiner invitation/review links) that must point at frontend pages rather
# than raw backend API endpoints.
FRONTEND_URL = os.environ.get('FRONTEND_URL', 'http://localhost:5173')

CELERY_BEAT_SCHEDULE = {
'leave-migration-task': {
'task': 'applications.leave.tasks.execute_leave_migrations',
'schedule': crontab(minute='1', hour='0')
},
'phd-thesis-review-invitations-task': {
'task': 'applications.academic_procedures.tasks.process_review_invitations',
'schedule': crontab(minute='0', hour='2')
}
}

Expand Down
5 changes: 5 additions & 0 deletions FusionIIIT/Fusion/settings/development.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@

ALLOWED_HOSTS = ['*']

# Local dev has no real SMTP credentials (EMAIL_HOST_PASSWORD is only set in
# production.py from the environment), so outgoing mail is printed to the
# runserver console instead of actually being sent.
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
Expand Down
2 changes: 1 addition & 1 deletion FusionIIIT/Fusion/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
url(r'^complaint/', include('applications.complaint_system.urls')),
url(r'^healthcenter/', include('applications.health_center.urls')),
url(r'^leave/', include('applications.leave.urls')),
url(r'^placement/', include('applications.placement_cell.urls')),
url(r'^placement/', include('applications.placement_cell.api.urls')),
url(r'^filetracking/', include('applications.filetracking.urls')),
url(r'^spacs/', include('applications.scholarships.urls')),
url(r'^visitorhostel/', include('applications.visitor_hostel.urls')),
Expand Down
28 changes: 25 additions & 3 deletions FusionIIIT/applications/academic_information/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse, JsonResponse
from django.db.models import Q
from applications.academic_procedures.api.views import role_required
from applications.globals.decorators import role_required
from applications.globals.api.views import resolve_audience_recipients
from notifications.signals import notify
from django.core.cache import cache
from django.db import connection, transaction

Expand Down Expand Up @@ -756,7 +758,9 @@ def generate_xlsheet_api(request):
if programme_type.upper() == 'UG':
sql += " AND s.programme IN ('B.Tech', 'B.Des')"
elif programme_type.upper() == 'PG':
sql += " AND s.programme IN ('M.Tech', 'M.Des', 'PhD')"
sql += " AND s.programme IN ('M.Tech', 'M.Des')"
elif programme_type.upper() == 'PHD':
sql += " AND s.programme = 'PhD'"
else:
sql += " AND s.programme = %s"
params.append(programme_type)
Expand Down Expand Up @@ -1253,10 +1257,28 @@ def list_calendar(request):
@authentication_classes([TokenAuthentication])
@role_required(['acadadmin'])
def add_calendar(request):
Calendar.objects.create(
audience_type = request.data.get('audience_type', 'all')
calendar_event = Calendar.objects.create(
description=request.data.get('description'),
from_date=request.data.get('from_date'),
to_date=request.data.get('to_date'),
audience_type=audience_type,
target_role_id=request.data.get('target_role'),
target_department_id=request.data.get('target_department'),
target_batch_id=request.data.get('target_batch'),
)
if audience_type == 'individual':
calendar_event.target_users.set(request.data.get('target_users', []))

recipients = resolve_audience_recipients(calendar_event)
notify.send(
sender=request.user,
recipient=recipients,
verb=calendar_event.description,
description=f"{calendar_event.from_date} to {calendar_event.to_date}",
url='',
module='Academic Calendar',
role=calendar_event.target_role.name if audience_type == 'role' and calendar_event.target_role else None,
)
return Response({'message': 'Created successfully!'})

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 3.1.5 on 2026-03-06 11:25

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('academic_information', '0001_initial'),
]

operations = [
migrations.AlterField(
model_name='student',
name='specialization',
field=models.CharField(choices=[('Power and Control', 'Power and Control'), ('Power & Control', 'Power & Control'), ('Microwave and Communication Engineering', 'Microwave and Communication Engineering'), ('Communication and Signal Processing', 'Communication and Signal Processing'), ('Micro-nano Electronics', 'Micro-nano Electronics'), ('Nanoelectronics and VLSI Design', 'Nanoelectronics and VLSI Design'), ('CAD/CAM', 'CAD/CAM'), ('Design', 'Design'), ('Manufacturing', 'Manufacturing'), ('Manufacturing and Automation', 'Manufacturing and Automation'), ('CSE', 'CSE'), ('AI & ML', 'AI & ML'), ('Data Science', 'Data Science'), ('Mechatronics', 'Mechatronics'), ('MDes', 'MDes'), ('None', 'None'), ('', 'No Specialization')], default='', max_length=40, null=True),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Generated by Django 3.1.5 on 2026-03-14 16:04

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('academic_information', '0002_thesis_registration_models'),
('academic_information', '0002_auto_20260210_1820'),
]

operations = [
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Generated by Django 3.1.5 on 2026-08-03 09:30

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('programme_curriculum', '0045_rename_progress_seminar_to_seminar'),
('globals', '0008_announcement'),
('academic_information', '0003_merge_20260314_1604'),
]

operations = [
migrations.AddField(
model_name='calendar',
name='audience_type',
field=models.CharField(choices=[('all', 'Everyone'), ('role', 'Specific Role'), ('batch', 'Specific Batch'), ('department', 'Specific Department'), ('individual', 'Specific Individuals')], default='all', max_length=20),
),
migrations.AddField(
model_name='calendar',
name='target_batch',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='programme_curriculum.batch'),
),
migrations.AddField(
model_name='calendar',
name='target_department',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='globals.departmentinfo'),
),
migrations.AddField(
model_name='calendar',
name='target_role',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='globals.designation'),
),
migrations.AddField(
model_name='calendar',
name='target_users',
field=models.ManyToManyField(blank=True, related_name='targeted_calendar_events', to=settings.AUTH_USER_MODEL),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Generated by Django 3.1.5 on 2026-08-05 22:16

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('academic_information', '0003_merge_20260314_1604'),
('academic_information', '0003_student_section'),
]

operations = [
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Generated by Django 3.1.5 on 2026-08-04 23:35

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('academic_information', '0003_student_section'),
('academic_information', '0004_auto_20260803_0930'),
]

operations = [
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Generated by Django 3.1.5 on 2026-08-05 22:20

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('academic_information', '0004_merge_20260805_2216'),
('academic_information', '0005_merge_20260804_2335'),
]

operations = [
]
18 changes: 16 additions & 2 deletions FusionIIIT/applications/academic_information/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from django.db import models
from django.contrib.auth.models import User

from applications.globals.models import ExtraInfo, Faculty
from applications.globals.models import ExtraInfo, Faculty, Designation, DepartmentInfo

from applications.programme_curriculum.models import Batch

Expand Down Expand Up @@ -282,10 +283,23 @@ def __str__(self):


class Calendar(models.Model):


AUDIENCE_CHOICES = (
('all', 'Everyone'),
('role', 'Specific Role'),
('batch', 'Specific Batch'),
('department', 'Specific Department'),
('individual', 'Specific Individuals'),
)

from_date = models.DateField()
to_date = models.DateField()
description = models.CharField(max_length=40)
audience_type = models.CharField(max_length=20, choices=AUDIENCE_CHOICES, default='all')
target_role = models.ForeignKey(Designation, null=True, blank=True, on_delete=models.SET_NULL)
target_department = models.ForeignKey(DepartmentInfo, null=True, blank=True, on_delete=models.SET_NULL)
target_batch = models.ForeignKey(Batch, null=True, blank=True, on_delete=models.SET_NULL)
target_users = models.ManyToManyField(User, blank=True, related_name='targeted_calendar_events')

class Meta:
db_table = 'Calendar'
Expand Down
2 changes: 1 addition & 1 deletion FusionIIIT/applications/academic_information/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Student_attendance)
from ..academic_procedures.models import (BranchChange, CoursesMtech, FinalRegistrations, InitialRegistration, StudentRegistrationChecks,
Register, Thesis, FinalRegistration, ThesisTopicProcess,
Constants, FeePayments, TeachingCreditRegistration, SemesterMarks,
Constants, FeePayments, TeachingCreditRegistration, SemesterMarks,
MarkSubmissionCheck, Dues,AssistantshipClaim, MTechGraduateSeminarReport,
PhDProgressExamination,CourseRequested, course_registration, MessDue, Assistantship_status , backlog_course,)

Expand Down
Loading
Loading