v1.9.3 Technical Notes
This document is for developers and system administrators. End users should refer to the CA System Guide and School Admin Guide instead.
This document captures technical decisions, migrations, and upgrade considerations for the v1.9.3 release.
Database Migrations Requiredโ
The following migrations must be run when upgrading to v1.9.3.
1. School Database Migrations (Multi-Tenant)โ
These run on each school's database (eschool_saas_*):
php artisan migrate:school
Migrations included:
-
2026_04_28_131900_version1_9_3_create_terms_table.php- Creates
termstable for Term Exams (multi-tenant per school)
- Creates
-
2026_04_28_132000_version1_9_3_create_continuous_assessments_table.php- Creates
continuous_assessmentstable for CA configuration
- Creates
-
2026_04_28_132100_version1_9_3_modify_exam_tables_for_ca.php- Adds
term_idandexam_weightagetoexams - Adds
ca_typeandtotal_markstoexam_marks - Adds
term_total,session_cumulative_average,session_position,term_idtoexam_results
- Adds
2. Main Database Migrationโ
This runs on the main database (stage4sch or production equivalent):
php artisan migrate
Migration:
2026_04_30_000000_add_syllabus_permissions_to_existing_schools.php- Iterates all installed schools
- Adds syllabus permissions to each school's School Admin role
- Required for schools created before v1.9.2
Architecture Decisionsโ
Multi-Tenant Permissionsโ
Each school has its own database containing:
permissionstablerolestablerole_has_permissionstable
The main database only contains the Super Admin role and global permissions. When adding new permissions for a feature:
- Update
SchoolDataService::createSchoolDatabaseData()for new schools - Create a backfill migration for existing schools (see syllabus permissions migration as reference)
Term Exam Architectureโ
Term Exams are stored in school databases (per-tenant), NOT the main database:
- Allows each school to have its own term structure
- Maintains data isolation between schools
- Foreign keys to local exam tables work properly
- Cross-database foreign keys are avoided
Why this matters: A previous attempt placed Term Exams in the main database, causing SQL errors when joining with school-specific exam tables.
CA-Aware Result Calculationโ
The publishExamResult method uses COALESCE for backward compatibility:
SUM(COALESCE(exam_marks.total_marks, exam_timetables.total_marks)) as total_marks
This pattern:
- Prefers
exam_marks.total_marks(per-CA value, set during marks entry) - Falls back to
exam_timetables.total_marks(subject's pre-defined max) - Allows mixed CA-enabled and traditional exams in the same system
Upgrade Considerationsโ
For Hosted Deploymentsโ
- Pull latest code from staging branch
- Install/update dependencies:
composer install --no-dev --optimize-autoloader
npm install --production - Run migrations:
php artisan migrate
php artisan migrate:school - Clear all caches:
php artisan cache:clear
php artisan config:clear
php artisan view:clear
php artisan route:clear - Verify by logging in as a School Admin and checking:
- Manage Term Exams menu visible (under Offline Exam)
- Manage Syllabus menu visible (under Class)
- CA Configuration accessible from Manage Exam
Browser Cache Considerationsโ
Several frontend assets now use cache busting via filemtime():
custom.jsvalidate.jsfunction.jscommon.js
This ensures users get fresh JavaScript without manually clearing browser cache. After deployment, the version query string will change automatically.
Known Issues Resolvedโ
SQL Ambiguous Column Errorโ
Error:
SQLSTATE[23000]: Integrity constraint violation: 1052
Column 'total_marks' in SELECT is ambiguous
Cause: Both exam_marks and exam_timetables have total_marks column after CA migration.
Fix: Explicit table prefix and COALESCE in ExamController@publishExamResult and related queries.
Spatie Permission Cacheโ
After running the syllabus permissions migration, the Spatie permission cache may be stale.
Resolution:
php artisan permission:cache-reset
Or manually clear cache:
php artisan cache:clear
jQuery Repeater Single-Item Edge Caseโ
The jQuery repeater plugin (used in Class Subject form) sometimes serializes single items as objects instead of arrays.
Defensive code added in ClassSchoolController@classSubjectUpdate:
// Handle single-item serialization edge case
if (is_array($subjects) && isset($subjects['id'])) {
$subjects = [$subjects];
}
File Referenceโ
Key Files Modified in v1.9.3โ
Backend:
app/Http/Controllers/Exam/ExamController.php- CA support, SQL fixesapp/Http/Controllers/ContinuousAssessmentController.php- CA configuration APIapp/Http/Controllers/TermController.php- Term Exam managementapp/Http/Controllers/ClassSchoolController.php- Validation fixesapp/Models/Term.php,ContinuousAssessment.php- New modelsapp/Services/ResultService.php- CA calculationsapp/Services/HelpService.php- In-app help systemapp/Console/Commands/GenerateHelpContent.php- Help generation
Frontend:
resources/views/exams/partials/ca_configuration_modal.blade.phpresources/views/exams/index.blade.php- Term Exam selector, Configure CAs buttonresources/views/exams/upload-marks.blade.php- CA Type selectorresources/views/terms/index.blade.php- Term Exams managementresources/views/components/help-tooltip.blade.php- Reusable tooltippublic/assets/js/custom/custom.js- Repeater fixespublic/assets/js/custom/validate.js- Duplicate validation fixpublic/assets/css/custom.css- Modal styling, tooltip z-index
Support & Troubleshootingโ
For end-user troubleshooting, see:
For developer questions, contact the engineering team or refer to inline code comments in the modified files.
Last Updated: v1.9.3 release Next Review: v1.10.0 release planning