v1.0
Reference
Admin

DAC Academy — Operational Risk Guide


RISK 1: Duplicate Lead Creation

Severity: Medium Scenario: Staff creates a lead with same (branch, parentPhone, studentName) as existing lead System Response: Unique constraint violation → error "A unique constraint was violated — duplicate data detected" Recovery: Edit the existing lead rather than creating duplicate Prevention: System checks duplicate at DB level; staff should search before creating


RISK 2: Duplicate Transaction ID

Severity: High (Financial) Scenario: Staff enters same transactionId for two different payments System Response: Unique partial index violation → error Recovery: Use a different transaction ID or omit it Prevention: Always use unique transaction IDs from payment gateway/bank


RISK 3: Batch Full — Race Condition

Severity: High Scenario: Two staff members submit admissions for same batch simultaneously System Response: Second submission hits row-level lock and sees updated count → "Batch is at full capacity" Recovery: Select a different batch or increase batch capacity in Settings Prevention: Monitor batch enrollment counts; set realistic capacity limits


RISK 4: Overpayment

Severity: High (Financial) Scenario: Staff records payment larger than remaining balance System Response: DB CHECK constraint violation → error Recovery: Reduce payment amount to remainingPaise or less Prevention: System shows remaining balance before payment entry


RISK 5: Voiding Without Receipt Cancellation

Severity: High (Financial) Scenario: Staff voids an installment but receipt remains valid System Response: Installment is voided (voidedAt, voidedBy, voidReason set). fee_record aggregates recalculated. Receipt is NOT voided. Recovery: If receipt needs cancellation, it must be voided separately (NO UI for this — requires DB) Prevention: Understand that voiding ≠ receipt cancellation. Receipts are immutable.


RISK 6: Accidental Override of Batch Default Fees

Severity: Medium Scenario: Staff enters ₹1 as admission fee, overrides batch defaults System Response: Uses staff-entered value (since > 0) instead of batch defaults Recovery: Cannot change admission fee after creation (admission is historical snapshot). Adjust via ad-hoc fee on fee record. Prevention: Enter 0 to use batch defaults; only override with explicit intent


RISK 7: Parent Account Created with Wrong Email

Severity: Medium Scenario: Staff types wrong email in admission form → parent account created with misspelled email System Response: Parent account created, temp password generated, linked to student Recovery: Create new parent account with correct email. Old account remains orphaned. Prevention: Verify email twice before submission


RISK 8: Admission PDF Generation Failure

Severity: Low Scenario: Fire-and-forget PDF generation fails due to R2/network issue System Response: Admission is already created. PDF is not stored. receipts.pdfStoragePath remains null. Recovery: PDF can be regenerated by viewing/downloading receipt (calls PDF endpoint which regenerates) Prevention: N/A — fire-and-forget is by design


RISK 9: Student Promoted to Non-Existent Session

Severity: Medium Scenario: Staff tries to promote student when next session doesn't exist System Response: Error — cannot promote without a destination session Recovery: Admin must create and activate the next academic session first Prevention: Plan session calendar ahead of promotion season


RISK 10: Receipt Sequence Gap

Severity: Low Scenario: Transaction rollback after receipt number was consumed System Response: Receipt number sequence increments but transaction is rolled back Effect: Receipt numbers will have gaps (e.g., 0042, 0044, 0045) Recovery: No recovery needed — gaps are expected and normal


RISK 11: Staff Accessing Wrong Branch Data

Severity: Medium Scenario: Counselor assigned to Branch A accidentally views Branch B data System Response: Counselors have cross-branch READ access — they CAN see all branches Risk: Read access is open; only write access is restricted Prevention: Manual oversight; branch filter in UI helps but doesn't prevent


RISK 12: Warden Not Assigned to a Hostel

Severity: High Scenario: Warden account created without hostelId System Response: Warden cannot access any students, outings, or medical requests — "You are not assigned to a hostel" Recovery: Admin must edit the warden user and assign a hostel in /users Prevention: Always assign hostelId when creating warden accounts


RISK 13: Batch Left Open for Too Long

Severity: Low Scenario: Batch status stays 'upcoming' after orientation System Response: No automatic status change — batch stays 'upcoming' Recovery: Admin manually changes batch status in Settings Prevention: Develop a batch status update SOP


RISK 14: Removing Student with Fee Arrears

Severity: High (Financial) Scenario: Staff marks student as "left" without clearing fee dues System Response: Application checks for arrears before allowing lifecycle transition Recovery: Clear fees first, then mark student status Prevention: Always verify fee clearance during status transitions


RISK 15: Duplicate Aadhaar Registration

Severity: High Scenario: Same student registered twice with same Aadhaar System Response: Partial unique index on aadharHash prevents duplicate entries Recovery: System prevents this — no action needed Prevention: N/A — enforced at DB level


RISK 16: Deactivated User Still Has Active Sessions

Severity: Medium Scenario: User account deactivated while logged in System Response: On next request, middleware checks isActive=false → redirects to /login. Current JWT may remain valid until expiry. Recovery: User is logged out on next request Prevention: Inform users before deactivating their account


RISK 17: WhatsApp Notification Silent Failure

Severity: Low Scenario: WhatsApp API unavailable, notification queue item fails after 3 retries System Response: Job marked as 'failed'. No automatic retry after exhaustion. Recovery: Manual retry via DB (update jobs set status='pending' where status='failed') Prevention: Monitor WhatsApp log for failed messages


RISK 18: Non-Terminal Lead Can Be Converted Multiple Times

Severity: High Scenario: Staff navigates to /admissions/new?leadId=X twice System Response: First admission creates student, updates lead to 'admitted'. Second attempt finds lead already admitted. Recovery: System prevents this — admission page checks alreadyAdmitted flag Prevention: N/A — system has guard


RISK 19: Student Photo Uploaded Without Admission Completion

Severity: Low Scenario: Student photo uploaded to R2 but admission transaction fails System Response: Cleanup code deletes the uploaded photo Recovery: Automatic — no action needed Prevention: N/A — cleanup is automatic


RISK 20: Financial Data Display — Historical vs Live Confusion

Severity: High (Financial Misunderstanding) Scenario: Staff looks at admission record's fee fields thinking they're current System Response: Admission records show SNAPSHOT at admission time. Live data is in fee_records. UI Note: Student detail page shows both: admission fee fields labeled as "Admission Fee Snapshot" and live fee record data Prevention: Always use fee_records for current financial status


RISK 21: Orphaned Registration Without Admission

Severity: Medium Scenario: Lead registered (paid fee) but never admitted System Response: Registration record exists, receipt exists, but no student/admission created Recovery: Staff converts lead to admission normally — registration is linked Prevention: Follow up on registered leads within 30 days


RISK 22: Inconsistent Student Session Status

Severity: Medium Scenario: Student promoted but previous session's status not updated System Response: Promotion creates NEW student_session for new session; OLD session retains its status Recovery: Old session status should be manually updated to 'completed' Prevention: Promotion workflow should be enhanced to close previous session


RISK 23: No Audit Log Cleanup

Severity: Low Scenario: Audit log grows unbounded over years System Response: No retention policy implemented Recovery: Manual cleanup or implement retention policy Prevention: Monitor audit log size; implement archival strategy


RISK 24: Phone Number Validation Rejects Valid International Numbers

Severity: Low Scenario: Parent has non-Indian phone number System Response: toE164() validation may fail if number doesn't match expected patterns Recovery: Error shown: "Invalid phone number" Prevention: Ensure international format with country code (+1, +44, etc.)


RISK 25: Receipt PDF Downloaded for Voided Receipt

Severity: Medium Scenario: Receipt is voided but PDF is still downloadable System Response: PDF endpoint does NOT check isVoided status Recovery: Manual — implement void check in PDF endpoint Prevention: N/A — current implementation gap


RISK 26: Unable to Change Student Branch

Severity: Medium Scenario: Student needs to transfer from Branch A to Branch B System Response: Student edit form rejects branch changes with "Branch changes are not allowed through student edit" Recovery: No dedicated branch transfer workflow exists. Requires DB-level change. Prevention: N/A — feature gap


RISK 27: Soft-Deleted Records in Queries

Severity: Low Scenario: Staff wonders why a record is missing System Response: Most queries filter isDeleted = false automatically Recovery: Check DB directly for soft-deleted records Prevention: N/A — soft delete is by design


RISK 28: Lead Status Backward Transition Possible for "Lost"

Severity: Low Scenario: Lost lead can be set back to new/contacted/interested System Response: Allowed — lost has special reversion logic Recovery: N/A — intentional design for re-engagement Prevention: N/A


RISK 29: Student Edit Form Shows Hostel Fields for Day Scholars

Severity: Low Scenario: Editing a day-scholar student shows hostel fields (hidden behind hostelOpted toggle) System Response: Form works correctly — hostel fields only appear when hostelOpted is true Risk: Low — UI handles this correctly


RISK 30: Enrollment Number Not Unique

Severity: Low Scenario: Two students may share same first 8 UUID characters System Response: Enrollment number is id.substring(0, 8).toUpperCase() — not guaranteed unique Recovery: Use full UUID for unique identification Prevention: Inform staff that enrollment numbers are display-only identifiers


RISK 31: GST Settings Affect All New Admissions

Severity: Medium Scenario: Admin changes GST settings mid-year System Response: New admissions use the NEW GST rate. Existing admissions' GST is historical snapshot. Recovery: N/A — by design. Only new admissions affected. Prevention: Communicate GST changes before implementation


RISK 32: Installment Auto-Generation May Create Misaligned Dates

Severity: Low Scenario: Batch payment schedule has percentages that don't divide remaining amount evenly System Response: Last installment takes the remainder (no even-split logic) Recovery: Manually adjust installment amounts after creation Prevention: Review batch payment schedule before admissions


RISK 33: Empty Counselor Route Directory

Severity: Low Scenario: Someone navigates to /counselor/ System Response: 404 — directory has no route files Recovery: Counselors use the main admin layout Prevention: N/A — intentional empty directory