-
Notifications
You must be signed in to change notification settings - Fork 1.2k
backend: add 'Upcoming Batches' tab in Program Curriculum #1829
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
backend: add 'Upcoming Batches' tab in Program Curriculum #1829
Conversation
|
Congratulations for making your first Pull Request at Fusion!! 🎉 Someone from our team will review it soon. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR implements a comprehensive "Upcoming Batches" tab for the Program Curriculum module, enabling automatic user account creation and email notification system for new students. The system processes Excel uploads, creates Django User accounts, generates secure passwords, and sends email notifications with login credentials.
- Complete student batch management system with Excel upload validation and duplicate detection
- Automatic Django User account creation with secure password generation and email notifications
- Integration with existing academic systems and proper database relationships
Reviewed Changes
Copilot reviewed 18 out of 21 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| views_password_email.py | New password email management views with SMTP configuration and bulk operations |
| views.py | Added batch upload access control endpoint for React frontend |
| urls.py | Added batch upload route for frontend integration |
| models_student_management.py | Core student batch upload models with user account creation methods |
| models_password_email.py | Password email logging and template management models |
| Multiple migration files | Database schema changes for student management features |
| email_settings.py | Email configuration template with SMTP settings |
| api/urls.py | Comprehensive API endpoints for student and password management |
| academic_procedures/api/views.py | Enhanced student verification with batch upload integration |
| academic_information/views.py | Updated student data views for batch compatibility |
| settings files | Database name corrections and email configuration updates |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| email = EmailMultiAlternatives( | ||
| subject=subject, | ||
| body=f"Your FUSION login credentials - Username: {roll_number}, Password: {password}", | ||
| from_email=getattr(settings, 'EMAIL_HOST_USER', 'vikrantkrd@gmail.com'), # Use actual Gmail account |
Copilot
AI
Aug 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hardcoded email address should not be used as a fallback. This exposes personal email credentials in code. Use a configuration-based approach or environment variable without hardcoded fallbacks.
| email = EmailMultiAlternatives( | |
| subject=subject, | |
| body=f"Your FUSION login credentials - Username: {roll_number}, Password: {password}", | |
| from_email=getattr(settings, 'EMAIL_HOST_USER', 'vikrantkrd@gmail.com'), # Use actual Gmail account | |
| from_email = getattr(settings, 'EMAIL_HOST_USER', None) | |
| if not from_email: | |
| raise ValueError("EMAIL_HOST_USER is not set in Django settings. Please configure the sender email address.") | |
| email = EmailMultiAlternatives( | |
| subject=subject, | |
| body=f"Your FUSION login credentials - Username: {roll_number}, Password: {password}", | |
| from_email=getattr(settings, 'EMAIL_HOST_USER', None), # Require EMAIL_HOST_USER to be set |
| <h4 style="margin-top: 0; color: #155724;">📞 Need Help?</h4> | ||
| <p style="margin-bottom: 0; color: #155724;"> | ||
| For any login issues or technical support, please contact:<br> | ||
| 📧 <a href="mailto:fusion@iiitdmj.ac.in" style="color: #155724;">academic@iiitdmj.ac.in</a><br> |
Copilot
AI
Aug 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Email link (href) points to 'fusion@iiitdmj.ac.in' but displays 'academic@iiitdmj.ac.in'. These should match to avoid user confusion and ensure proper email routing.
| 📧 <a href="mailto:fusion@iiitdmj.ac.in" style="color: #155724;">academic@iiitdmj.ac.in</a><br> | |
| 📧 <a href="mailto:academic@iiitdmj.ac.in" style="color: #155724;">academic@iiitdmj.ac.in</a><br> |
| student=student, | ||
| password_hash=user.password, # Already hashed by Django | ||
| created_by=request.user, | ||
| is_initial_password=not student.has_user_account(), |
Copilot
AI
Aug 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic for determining if it's an initial password is inverted. When creating a new account, has_user_account() returns False, so not student.has_user_account() returns True, but after create_user_account() is called, the user account exists. This should check the state before account creation.
| student=student, | ||
| password_hash=user.password, # Already hashed by Django | ||
| created_by=request.user, | ||
| is_initial_password=not student.has_user_account(), |
Copilot
AI
Aug 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic for determining if it's an initial password is inverted. When creating a new account, has_user_account() returns False, so not student.has_user_account() returns True, but after create_user_account() is called, the user account exists. This should check the state before account creation.
| def save(self, *args, **kwargs): | ||
| # Auto-generate institute email if roll number is provided | ||
| if self.roll_number and not self.institute_email: | ||
| self.institute_email = f"{self.roll_number.lower()}@iiitdmj.ac.in" | ||
|
|
||
| # Normalize email addresses to lowercase for delivery consistency | ||
| if self.institute_email: | ||
| self.institute_email = self.institute_email.lower() | ||
| if self.personal_email: | ||
| self.personal_email = self.personal_email.lower() | ||
|
|
||
| super().save(*args, **kwargs) |
Copilot
AI
Aug 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This save method overrides the one defined earlier at line 211. The academic_year generation logic from the first save method will be lost. These should be merged into a single save method.
| EMAIL_HOST_USER = 'vikrantkrd@gmail.com' # Change to your email | ||
| EMAIL_HOST_PASSWORD = '' # Use app password for Gmail |
Copilot
AI
Aug 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hardcoded personal email credentials in configuration file. This should use environment variables or Django settings for security. Personal email addresses should not be committed to version control.
| EMAIL_HOST_USER = 'vikrantkrd@gmail.com' # Change to your email | |
| EMAIL_HOST_PASSWORD = '' # Use app password for Gmail | |
| import os | |
| EMAIL_HOST_USER = os.environ.get('EMAIL_HOST_USER', '') | |
| EMAIL_HOST_PASSWORD = os.environ.get('EMAIL_HOST_PASSWORD', '') |
FusionIIIT/Fusion/settings/common.py
Outdated
| EMAIL_HOST_USER = 'vikrantkrd@gmail.com' | ||
| EMAIL_HOST_PASSWORD = '' # Your actual Gmail app password |
Copilot
AI
Aug 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personal email credentials should not be hardcoded in settings. Use environment variables for EMAIL_HOST_USER and EMAIL_HOST_PASSWORD to protect sensitive information.
| EMAIL_HOST_USER = 'vikrantkrd@gmail.com' | |
| EMAIL_HOST_PASSWORD = '' # Your actual Gmail app password | |
| EMAIL_HOST_USER = os.environ.get('EMAIL_HOST_USER') | |
| EMAIL_HOST_PASSWORD = os.environ.get('EMAIL_HOST_PASSWORD') # Set this environment variable to your Gmail app password |
FusionIIIT/Fusion/settings/common.py
Outdated
| DEFAULT_FROM_EMAIL = 'Fusion IIIT <vikrantkrd@gmail.com>' | ||
|
|
||
| SERVER_EMAIL = 'vikrantkrd@gmail.com' |
Copilot
AI
Aug 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personal email address should not be used for system emails. This should use an official institutional email address for DEFAULT_FROM_EMAIL and SERVER_EMAIL.
| DEFAULT_FROM_EMAIL = 'Fusion IIIT <vikrantkrd@gmail.com>' | |
| SERVER_EMAIL = 'vikrantkrd@gmail.com' | |
| DEFAULT_FROM_EMAIL = 'Fusion IIIT <noreply@iiitdmj.ac.in>' | |
| SERVER_EMAIL = 'noreply@iiitdmj.ac.in' |
FusionIIIT/Fusion/settings/common.py
Outdated
| DEFAULT_FROM_EMAIL = 'Fusion IIIT <vikrantkrd@gmail.com>' | ||
|
|
||
| SERVER_EMAIL = 'vikrantkrd@gmail.com' |
Copilot
AI
Aug 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personal email address should not be used for system emails. This should use an official institutional email address for DEFAULT_FROM_EMAIL and SERVER_EMAIL.
| DEFAULT_FROM_EMAIL = 'Fusion IIIT <vikrantkrd@gmail.com>' | |
| SERVER_EMAIL = 'vikrantkrd@gmail.com' | |
| DEFAULT_FROM_EMAIL = 'Fusion IIIT <noreply@iiitdmj.ac.in>' | |
| SERVER_EMAIL = 'noreply@iiitdmj.ac.in' |
| if not roll_no: | ||
| return Response({"error": "rollno is required"}, status=status.HTTP_400_BAD_REQUEST) |
Copilot
AI
Aug 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calling .upper() on a potentially None value will cause an AttributeError if rollno is None. The null check should be performed after retrieving the value but before calling .upper().
| if not roll_no: | |
| return Response({"error": "rollno is required"}, status=status.HTTP_400_BAD_REQUEST) | |
| if not roll_no or not isinstance(roll_no, str) or not roll_no.strip(): | |
| return Response({"error": "rollno is required and must be a non-empty string"}, status=status.HTTP_400_BAD_REQUEST) |
- Updated BatchConfiguration to calculate filled and available seats based on unique student count. - Added source field to StudentBatchUpload to track data origin. - Introduced first_name and last_name properties in StudentBatchUpload for easier access. - Enhanced user account creation process with better error handling and logging. - Implemented signals for automatic student profile creation and status change logging. - Updated email templates and SMTP settings for password emails. - Added migrations for new fields and constraints in models. - Improved withdrawal status handling to deactivate user accounts.
… and update field names for consistency
- Introduced CourseAuditLog model to track changes made to courses, including user, action, old and new values, version bump type, and reason for changes. - Updated course creation and update views to log changes in the CourseAuditLog. - Implemented intelligent versioning logic to determine the type of version bump (MAJOR, MINOR, PATCH) based on changes made to course fields. - Added endpoint to retrieve audit logs for specific courses with pagination support. - Included utility functions for calculating Levenshtein distance to identify potential typo corrections. - Added test endpoint for demonstrating intelligent versioning functionality. - Updated URLs to include new audit log endpoint and test endpoint for versioning.
…management logic - Updated email configuration in common.py for clarity. - Modified production.py to streamline email password retrieval. - Adjusted BatchSerializer to include all fields instead of specific ones. - Enhanced curriculum form handling to support multiple field names for semesters and credits. - Improved student management views to automate status updates and batch syncing. - Added robust filled seats calculation in batch management. - Introduced sync_batches_to_configuration function for batch data consistency.
… and in Generate course List :- Added List Type Feature
…ogic for better clarity in student reports
… generation queries faster execution
|
Closing after meeting discussion |
Implemented Features (Upcoming Batches)
1. Batch File Processing
2. Automatic User Account Creation
3. Email Notification System
4. Complete Academic Profile Creation
5. Dynamic Semester Calculation
6. Academic Year Management
7. Designation & Access Management
8. Status Management System
9. Database Integration
10. Academic Procedures Integration
System Workflow (Fully Automated)
Testing Results
Pending Implementation