Executive Summary
PADS (Performance Appraisal & Development System) is a fully standalone Django 5 application for managing faculty self-assessment cycles, multi-tier review workflows (Faculty → HoD → Central Team → Principal), and institutional reporting. Campus+ is a Django 3.2 monolith serving KCT students and staff with hostel, transport, biometric, court-booking, and lending modules.
The integration goal is to make PADS a native sub-system of Campus+ — accessible via a new /pads/ URL namespace, authenticated through Campus+'s existing session/SSO pipeline, and rendered inside Campus+'s sb-admin-2 sidebar layout so it feels native to staff users already familiar with the platform.
Integration Strategy at a Glance
- Auth: Campus+ wins. PADS's custom
Useris replaced by aStaffProfileOneToOneField pointing at Campus+'sauth.User. PADS role flags (is_group_admin,is_inst_admin) become fields onStaffProfile. - Models with name clashes (
Institution,Department): PADS's versions are renamed with aPadsprefix (PadsInstitution,PadsDepartment) or mapped to Campus+ equivalents where fields align. - URL namespace: All PADS URLs live under
/pads/with app_namepads. - Templates: All PADS templates are rewritten to extend Campus+'s
main.htmlusing sb-admin-2 Bootstrap 4 components. PADS's own Bootstrap 5 + HTMX stack is migrated progressively. - Celery: PADS Celery tasks are merged into Campus+'s existing Celery beat schedule.
- Middleware: PADS's
InstitutionContextMiddlewareandAuditMiddlewareare ported and appended to Campus+'sMIDDLEWARElist.
Feature Mapping Table
Every PADS feature is mapped to its integration approach, the Campus+ components it touches, and the effort level.
| PADS Feature | PADS Source | Integration Approach | Campus+ Touch Points | Effort |
|---|---|---|---|---|
| Login / Logout | accounts/views.py — login_view, logout_view |
Drop — Campus+ already handles login (social_django + session). PADS login page is not needed. | KCT_Entrance_CRM/urls.py landing view |
None |
| Dashboard (role-aware) | accounts/views.py — dashboard(), dashboard/index.html |
Adapt — Port PADS dashboard as a new /pads/ landing page. Extend main.html, replace Bootstrap 5 components with Bootstrap 4 equivalents. |
main.html, new template pads/dashboard.html |
Medium |
| Custom User Model | accounts/models.py — User(AbstractUser) with employee_code, is_group_admin, is_inst_admin |
Replace — Use Campus+'s auth.User. Move employee_code and role flags to a new PadsStaffProfile model (OneToOneField to auth.User). The existing PADS StaffProfile already covers most of this. |
base_app/models.py, settings.py |
High |
| Microsoft SSO (allauth) | accounts/adapters.py — PADSSocialAccountAdapter |
Evaluate — Campus+ already has Azure AD SSO via social_django. PADS's allauth-based SSO is a duplicate. Either reuse social_django's Azure pipeline for staff sign-in or accept both pipelines coexisting (riskier). |
settings.py SOCIAL_AUTH pipeline |
High |
| Institution Management | institutions/models.py — Institution; institutions/middleware.py |
Merge/Rename — PADS Institution clashes with base_app.Institution. Port as pads_institution (or map to existing if field semantics align). Port InstitutionContextMiddleware with a pads_ prefix on session key. |
base_app/models.py, middleware list |
Medium |
| Staff Roster (list, filter, export) | staff/views.py — staff_list, staff_export |
Adapt — Port views under /pads/staff/. Reuse main.html + DataTables (already in Campus+). Rename PADS Department / Designation models to avoid clash with base_app.Department. |
base_app.Department conflict, DataTables |
Medium |
| Staff Excel Import | staff/importers.py, staff/views.py — staff_import, staff_import_validate |
Adapt — Port HTMX-based import UI under /pads/staff/import/. HTMX is already loaded in main.html (v1.7), so partial-response pattern works. Upgrade HTMX version to match PADS's 1.9 usage. |
HTMX version difference, file upload settings | Medium |
| Assessment Management (CRUD) | assessments/views.py, assessments/models.py |
Adapt — Port under /pads/assessments/. Assessment, Category, Criterion, CriterionField, ScoringMatrix models migrate as-is (no name conflicts). Views rewritten to extend main.html. |
None (no model conflicts) | Medium |
| Criterion Targeting | assessments/models.py — Criterion.matches(), Criterion.is_visible_to() |
Port as-is — Business logic in model methods; no framework dependency. Migrations port cleanly after model rename resolution. | M2M to renamed Department/Designation | Low |
| Faculty Self-Assessment Form | submissions/views.py — submission_fill(), submissions/fill.html |
Heavy Adapt — The most complex PADS template (~600 lines, heavy Alpine.js + HTMX for dynamic criterion entry). Must be rewritten using Bootstrap 4 tab/card structure from main.html. Alpine.js and Chart.js dependencies need to be added to main.html. |
main.html needs Alpine.js + Chart.js added |
High |
| Scoring Engine | submissions/scoring.py |
Port as-is — Pure Python, no framework ties. One adjustment needed: USE_TZ=False in Campus+ may cause issues with timezone-aware datetime comparisons in scoring; add django.utils.timezone guards. |
USE_TZ mismatch |
Low |
| Duplicate Detection | submissions/scoring.py — detect_duplicate() |
Port as-is | None | Low |
| HoD Review Queue | reviews/views.py — hod_queue(), review_submission() |
Adapt — Port views; map HoD role to Campus+ UserGroup or a new StaffProfile.role field. Rewrite templates with Bootstrap 4. |
Role mapping to Campus+ groups | Medium |
| Central Team Review Queue | reviews/views.py — central_queue() |
Adapt — Same pattern as HoD queue. | Role mapping | Low |
| Principal Queue & Final Approval | reviews/views.py — principal_queue() |
Adapt — A Principal UserGroup already exists in Campus+ permission_objects.py. Map PADS principal role to this group. |
Campus+ UserGroup "Principal" |
Low |
| Email Notifications | notifications/service.py |
Port as-is — Already uses iQube API at 10.1.76.76:25001, same infrastructure as Campus+. Update hardcoded base URLs to use Campus+'s CAMPUS_BASE_URL setting. |
settings.CAMPUS_BASE_URL |
Low |
| Deadline Reminder Celery Task | notifications/tasks.py |
Merge — Add entry to Campus+'s CELERY_BEAT_SCHEDULE dict with pads.notifications.tasks.send_deadline_reminders. |
settings.py CELERY_BEAT_SCHEDULE |
Low |
| Reports & Excel Export | reports/views.py — assessment_excel() |
Port as-is — openpyxl already in Campus+ requirements. No UI template needed (streams file download). | openpyxl version (Campus+ 3.1.2 vs PADS 3.1.5) | Low |
| Audit Log | audit/models.py, audit/middleware.py |
Adapt — Rename to PadsAuditLog to avoid potential future collision. Port AuditMiddleware as a new middleware in Campus+ settings. |
Middleware list order | Low |
| Admin: Create Admin Users | accounts/views.py — admin_create() |
Adapt — Replace PADS custom admin create with a Campus+ pattern: create auth.User, assign to a PADS-specific UserGroup, create StaffProfile. |
Campus+ UserGroup model | Medium |
| Institution Context Switching | institutions/views.py — switch() |
Adapt — Port under /pads/institutions/switch/. Prefix session key to pads_active_institution_id to avoid collision with any future session use. |
Session key namespace | Low |
| PADS Base Template | templates/base/base.html |
Replace — All PADS templates must extend main.html instead. PADS's design system (green CSS variables, card-pads classes, etc.) is adapted or inlined per template. |
All 23 PADS templates | High |
Conflict Analysis
A. Model Conflicts
INSTALLED_APPS.
| Model Name | Campus+ Version | PADS Version | Conflict Type | Resolution |
|---|---|---|---|---|
Institution |
base_app.Institution: name (CharField max 50) |
institutions.Institution: code (SlugField), name (200), email_domain, short_name, is_active |
Name collision + schema mismatch | Rename PADS model to PadsInstitution in pads.institutions app. Evaluate whether Campus+ base_app.Institution can be enriched with PADS's extra fields to avoid two institution tables. |
Department |
base_app.Department: name, Institution FK, department_head_email, biometric ZK fields (zk_uid, zk_department_code) |
staff.Department: institution FK, code (SlugField), name, is_active |
Name collision + schema mismatch | Rename PADS model to PadsDepartment. The ZK biometric fields in Campus+'s version make direct reuse impossible without complicating PADS logic. |
User model |
auth.User (default Django); extended via base_app.UserRecord OneToOneField (related_name="associated_user") |
accounts.User: AbstractUser with employee_code, is_group_admin, is_inst_admin, phone |
AUTH_USER_MODEL conflict — critical | Campus+ wins. PADS must drop its custom User model. Extra fields (employee_code, role flags) move to PadsStaffProfile which maintains OneToOneField to auth.User. |
StaffProfile |
No equivalent in Campus+ | staff.StaffProfile: OneToOneField to accounts.User, institution, department, designation, role |
No collision but FK target must change | Change user FK from accounts.User to auth.User. Rename to PadsStaffProfile to be explicit about ownership. |
Designation |
None in Campus+ | staff.Designation: institution, code, name, rank, is_active |
No collision | Rename to PadsDesignation for consistent namespacing. |
Assessment, Category, Criterion, etc. |
None in Campus+ | Full PADS domain models | No collision | Port as-is under the new pads.* app namespace. No renames needed for these models. |
AuditLog |
No equivalent (Campus+ has no request-level audit model) | audit.AuditLog: user, path, status_code, ip, created_at |
No collision | Rename to PadsAuditLog to namespace clearly. Port as-is. |
DEFAULT_AUTO_FIELD |
AutoField (32-bit int PKs) |
BigAutoField (64-bit int PKs) |
Schema mismatch on new tables | PADS models can keep BigAutoField by setting per-app default_auto_field in each PADS AppConfig. No migration impact on existing Campus+ tables. |
C. URL Conflicts
| PADS URL Path | Campus+ Collision? | Resolution |
|---|---|---|
/ (dashboard) | Yes — Campus+ landing page at / | PADS dashboard moves to /pads/ |
/login/ | Yes — Campus+ landing/login at / | Drop PADS login; use Campus+'s |
/logout/ | Yes — Campus+ /logout/ | Drop PADS logout; use Campus+'s {% url 'logout' %} |
/staff/ | No — not used in Campus+ | Namespace to /pads/staff/ |
/assessments/ | No | Namespace to /pads/assessments/ |
/submissions/ | No | Namespace to /pads/submissions/ |
/reviews/ | No | Namespace to /pads/reviews/ |
/reports/ | No | Namespace to /pads/reports/ |
/audit/ | No | Namespace to /pads/audit/ |
/institutions/ | No | Namespace to /pads/institutions/ |
/admins/ | No | Namespace to /pads/admins/ |
/accounts/ | Partial — allauth occupies /accounts/ in PADS; Campus+ does not have this path but social_django uses /social-auth/ | Drop allauth from integration; redirect rules added for any inbound allauth callbacks. |
/admin/ | Yes — same Django admin | Single /admin/ — PADS models are registered in Campus+'s admin site. |