# Admin Workflows — Figma Production Specs

---

## 1. TEACHER INVITATION WORKFLOW

```
Admin ADM-07: Clicks "Invite Teacher"
    │
    │ Modal opens: Enter email
    │ Admin enters email, clicks "Send Invitation"
    │
    ▼
Backend: TeacherInvitationService
    ├── Creates teacher_invitations record
    ├── Hashed token generated (72-hour expiry)
    ├── Invitation email sent via TxtConnect/SMTP
    └── Audit log entry created
    │
    ▼
Teacher receives email
    │ "You've been invited to join RP Learning Portal"
    │ Link: /invite/{token}
    │
    ▼
Teacher: /invite/{token}
    ├── Token validated
    ├── Landing page shown (INV-01)
    │   "Dr. Mensah has invited you to join..."
    │   [Accept Invitation & Complete Profile]
    │
    ▼
Teacher: /invite/{token}/register (INV-02)
    ├── Full name (pre-filled from invitation)
    ├── Password
    ├── Date of birth
    ├── Phone number
    ├── Qualifications
    ├── Bio
    └── Upload CV (Spatie Media Library)
    │
    ▼
Account created
    ├── Role: teacher
    ├── Status: pending
    ├── Token marked as used
    └── Audit log entry
    │
    ▼
Admin ADM-07: Sees teacher in "Pending Approval" tab
    │
    │ Reviews profile + CV
    │ Clicks [Approve]
    │
    ▼
Teacher status: pending → active
    ├── Teacher notified: "Your account has been approved"
    ├── Teacher can now log in
    └── Audit log entry
```

### Invitation Lifecycle

| Stage | Status | Visible In |
|-------|--------|------------|
| Email sent | pending | ADM-07 "Pending Approval" tab |
| Teacher registered | pending | ADM-07 "Pending Approval" tab |
| Admin approved | active | ADM-07 "Active" tab |
| Token expired (72h) | expired | Auto-cleaned, not visible |

---

## 2. INVOICE GENERATION WORKFLOW

```
Admin ADM-22: Clicks "Generate Invoices"
    │
    │ Modal: Select parameters
    │ ├── Academic Year + Term
    │ ├── Fee Structure (or all active)
    │ ├── Class (or all)
    │ └── Due Date
    │
    │ Preview shows: 245 students, ₵ 196,000 estimated
    │
    ▼
Admin clicks [Generate 245 Invoices]
    │
    ▼
Backend: InvoiceGeneratorService
    ├── For each student with active fee assignment:
    │   ├── generateInvoiceNumber() → INV-2026-NNNN
    │   ├── Create invoice record (status: draft)
    │   ├── addItemsFromFeeAssignments() → line items
    │   ├── getPrimaryGuardian() → FK to parent
    │   └── set due_date
    │
    ├── Batch: 245 invoices created
    │
    ├── Status: draft → sent (auto-send)
    │   sendInvoice() for each:
    │   ├── Email to primary guardian with PDF attachment
    │   ├── In-app notification
    │   └── Audit log entry
    │
    └── Admin sees: "245 invoices generated and sent"
    │
    ▼
Parents receive:
    ├── Email: "New Invoice: INV-2026-XXXX"
    │   PDF attachment
    │   [Pay Now] link → PAR-10
    ├── Dashboard KPI updated
    └── PAR-08 shows new invoice
```

### Invoice Status Transitions

```
Draft → Sent → Partially Paid → Paid
  ↓       ↓         ↓            ↓
  │       │         │            │
  │ Edit  │ Remind  │ Pay more   │ Receipt
  │ only  │         │            │ generated
  │       ↓         │
  │    Overdue      │
  │    (auto, after │
  │     due date)   │
  │                 │
  └─ Cancel ────────┘
         ↓
     Cancelled
         ↓
     Refunded (if payment existed)
```

---

## 3. PAYROLL PROCESSING WORKFLOW

```
Admin ADM-25: Creates payroll period
    │ Name: "June 2026"
    │ Dates: Jun 1–30
    │ Status: Draft
    │
    ▼
Admin ADM-25: Clicks [View] → ADM-26
    │
    │ ADM-26: Period is empty (Draft)
    │ No calculations yet
    │
    ▼
Admin clicks [Preview Payroll]
    │
    ▼
Backend: PayrollCalculatorService.preview()
    ├── For each active teacher:
    │   ├── Count sessions in date range
    │   ├── Calculate session_gross (sessions × rate)
    │   ├── Calculate private_session_gross
    │   ├── Total gross_earnings
    │   ├── Read CURRENT admin_fee_percentage
    │   ├── Calculate admin_fee_amount
    │   └── Calculate net_earnings
    │
    ├── Returns collection of preview calculations
    └── Status: Draft → Preview
    │
    ▼
Admin ADM-26: Reviews preview
    ├── Sees waterfall chart (Gross → Fees → Net)
    ├── Sees teacher table with all figures
    ├── Can click [Adjust] on individual teacher
    │   → Add adjustment (bonus/deduction)
    │   → Logged in audit trail
    ├── Admin fee % shows "Captured at execution time"
    │
    ▼
Admin clicks [Process Payroll]
    │
    │ Confirmation modal:
    │ "Process payroll for June 2026?"
    │ "15 teachers — Total net: ₵ 15,640"
    │ "This action cannot be undone."
    │ [Cancel] [Process Payroll]
    │
    ▼
Backend: PayrollCalculatorService.processPayroll()
    ├── For each teacher:
    │   ├── Create payroll_calculations record
    │   │   ├── Snapshot admin_fee_percentage_applied
    │   │   │   (CRITICAL: This value is frozen here)
    │   │   ├── Store session_breakdown JSON
    │   │   └── Create payroll_audit_logs entry
    │   │
    │   └── Create payroll_transactions record
    │
    ├── Status: Preview → Processing → Completed
    │
    └── Admin sees: "Payroll processed successfully"
    │
    ▼
Admin can now:
    ├── [Export to Excel] → download spreadsheet
    ├── [Send Payslips] → email PDF payslips to all teachers
    └── [View Audit Trail] → who did what, when
```

### Critical Business Rule: Admin Fee Snapshot

```
WHEN admin fee percentage changes:
│
├── PayrollAuditLog ALWAYS created BEFORE update
│   ├── before_value: "12%"
│   ├── after_value: "15%"
│   ├── changed_by: Admin
│   └── reason: (required)
│
WHEN payroll is processed:
│
├── admin_fee_percentage_applied = CURRENT rate at processing time
├── This value is IMMUTABLE after processing
├── Historical payrolls ALWAYS show the rate that was applied
└── Never overwritten by current rate
```

---

## 4. STUDENT ENROLLMENT WORKFLOW

```
Admin ADM-06: Clicks [+ Enroll Student]
    │
    │ Modal: Select student, class, academic year
    │
    ▼
Backend: Enrollment
    ├── Creates enrollment record
    ├── Links student to class
    ├── Assigns fee structures (if applicable)
    ├── Audit log entry
    └── Notification to teacher: "New student enrolled"
    │
    ▼
Student appears in:
    ├── ADM-09 (Students List)
    ├── ADM-06 (Enrollment Manager)
    ├── Teacher's TCH-07 (My Students)
    ├── Student's STU-01 (Dashboard)
    └── Parent's PAR-01 (Command Center)
```

### Transfer Workflow

```
Admin ADM-09: Clicks [Transfer] on student
    │
    │ Modal: Select new class
    │
    ▼
Backend: Transfer
    ├── Current enrollment → status: transferred
    ├── New enrollment created
    ├── Fee structures reassessed
    ├── Audit log entry
    └── Notifications:
        ├── Teacher (old class): "Student transferred out"
        ├── Teacher (new class): "Student transferred in"
        └── Parent: "Amara has been transferred to JSS 2"
```

---

## 5. INTERVENTION ESCALATION WORKFLOW

```
Teacher creates intervention (TCH-19)
    │
    ▼
Intervention Active
    ├── Teacher tracks progress
    ├── Parent receives action items
    ├── OPS recalculated periodically
    │
    ▼
If OPS improves:
    ├── Risk level decreases
    ├── Intervention can be marked Complete
    └── Resolution recorded
    │
    ▼
If OPS does NOT improve:
    │
    │ Teacher decides to escalate:
    │ [Escalate to Admin] → ADM-19
    │
    ▼
Admin ADM-19: Sees escalated intervention
    │
    ├── Reviews case details
    ├── Views OPS trend
    ├── Views intervention history
    │
    ├── Options:
    │   ├── [Reassign Teacher] → different teacher
    │   ├── [Escalate to Principal] → external escalation
    │   ├── [Archive] → close without resolution
    │   └── [Create New Intervention] → different approach
    │
    ▼
Admin takes action
    ├── Notifications sent
    ├── Audit log entry
    └── Intervention status updated
```

---

## 6. ANNOUNCEMENT WORKFLOW

```
Admin ADM-27: Creates announcement
    │
    ├── Title + Body + Target + Urgency
    ├── [Publish Now] or [Schedule]
    │
    ▼
Backend: Announcement
    ├── Record created
    ├── If published immediately:
    │   ├── Status: published
    │   ├── Published_at: now()
    │   └── Notification sent to target audience
    │
    ├── If scheduled:
    │   ├── Status: scheduled
    │   ├── published_at: scheduled time
    │   └── Scheduled job publishes at time
    │
    ▼
Recipients see:
    ├── In-app: Notification bell + notification center
    ├── Email: If email enabled for announcements
    ├── System banner: If urgent (top of all portals)
    └── Announcement feed: If in their target audience
```

---

## 7. SETTINGS UPDATE WORKFLOW

```
Admin ADM-29: Updates settings
    │
    ├── Any tab: Branding, School Info, OPS, etc.
    ├── Makes changes
    ├── Clicks [Save]
    │
    ▼
Backend: Settings Update
    ├── Validates input
    ├── Updates school_settings table
    ├── Audit log entry: "settings.updated"
    │
    ├── Special handling for:
    │   ├── OPS weights: Recalculates all student OPS
    │   ├── Paystack: Verifies API keys
    │   ├── Zoom: Verifies SDK keys
    │   ├── Email: Tests SMTP connection
    │   └── SMS: Tests TxtConnect connection
    │
    └── Success toast: "Settings saved ✓"
```

---

## 8. PAYMENT REFUND WORKFLOW

```
Admin ADM-24: Clicks [Refund] on payment
    │
    │ Refund Modal:
    │ ├── Original payment details shown
    │ ├── Refund amount (can be partial)
    │ ├── Reason (required)
    │ └── ⚠ "Refund will be processed through Paystack"
    │
    ▼
Admin clicks [Process Refund]
    │
    ▼
Backend: Refund
    ├── Paystack refund API called
    ├── Payment record updated: status → refunded
    ├── Invoice record updated:
    │   ├── Status: refunded (if full) or partially_paid
    │   └── Payment history updated
    ├── Audit log entry
    │
    ▼
Notifications:
    ├── Parent: "Payment of ₵ 500 has been refunded"
    ├── Admin: "Refund processed successfully"
    └── Receipt generated for refund
```

---

## 9. AUDIT LOG VIEWING WORKFLOW

```
Admin ADM-28: Views audit logs
    │
    ├── Default view: Last 7 days, all events
    ├── Filter by: User, Event, Module, Date, IP
    │
    │ Click row → Detail modal
    │ Shows: Before/After values, user agent, IP
    │
    ├── [Export to Excel] → download filtered results
    └── [Export to PDF] → generate report
    │
    Note: "Audit logs are immutable.
           They cannot be modified or deleted by anyone,
           including administrators."
```

---

## 10. CROSS-PORTAL NOTIFICATION FLOW

```
Event occurs (e.g., payment received)
    │
    ├── System determines recipients:
    │   ├── Parent (primary guardian) — Financial
    │   ├── Admin — Financial
    │   └── Teacher (if related to student) — Academic
    │
    ├── For each recipient:
    │   ├── Check notification_preferences
    │   ├── Determine channels: In-App / Email / SMS
    │   │
    │   ├── In-App: Write to notifications table
    │   │   └── Appears in NotificationBell
    │   │
    │   ├── Email: Queue email job
    │   │   └── Sent via SMTP/TxtConnect
    │   │
    │   └── SMS: Queue SMS job
    │       └── Sent via TxtConnect
    │
    └── Audit log entry: "notification.sent"
```

---

## 11. ADMIN PORTAL RESPONSIVE BEHAVIOR

### Mobile Bottom Navigation

```
[Dashboard] [Students] [Finance] [Settings] [More]
```

### Desktop Sidebar Collapse

```
Expanded (260px):
├── Icon + Label for each menu item
├── Grouped sections:
│   ├── Dashboard
│   ├── Academic (Years, Subjects, Classes, Enrollment)
│   ├── People (Teachers, Students, Parents)
│   ├── Operations (Timetable, Sessions, Assignments, Exams, Resources)
│   ├── Analytics (OPS, Interventions)
│   ├── Finance (Invoices, Payments)
│   ├── Payroll (Periods, Compensation)
│   └── System (Announcements, Audit Logs, Settings)

Collapsed (64px):
├── Icons only
├── Tooltip on hover: "Academic Years"
├── Active item: Highlighted background
└── Group dividers visible
```

### Tablet Layout

```
┌───────────────────────────────────────┐
│  Sidebar collapsed (64px icons)       │
│                                       │
│  [Page header + KPIs]                 │
│  [Tables: Full width, scrollable]     │
│  [Modals: 80% width]                  │
│                                       │
└───────────────────────────────────────┘
```

### Mobile Layout

```
┌─────────────────────┐
│  Topbar only        │
│  [Page header]      │
│                     │
│  [KPIs: 2×3 grid]  │
│  [Content stacked]  │
│  [Tables: cards]    │
│  [Modals: full]     │
│                     │
│  [Bottom nav]       │
└─────────────────────┘