# Instructor Portal Audit

Date: 2026-05-05

## Status

Overall status: partially complete, now safer for production use after this pass.

The platform has two instructor-facing route groups:

- `/teacher` is the canonical modern portal for dashboard, sessions, attendance, attendance history, cohorts, materials, payouts, profile, and security.
- `/instructor` is a backward-compatible legacy portal. It remains available, but the public header and login now send instructors/teachers to `/teacher`.

## Evidence

- Routes are defined in `routes/instructor.php`.
- Modern attendance pages live in `app/Livewire/Teacher/*`.
- Legacy cohort/material/announcement/payout pages live in `app/Livewire/Instructor/*`.
- Assignment isolation is centralized in `app/Domain/Attendance/AttendanceAssignmentService.php`.
- Attendance persistence is centralized in `app/Domain/Attendance/AttendanceWorkflowService.php`.
- Instructor payout v2 models are `InstructorContract`, `PayoutPlan`, `PayoutScheduleItem`, and `InstructorPayout`.

## Fixes Applied

- Legacy instructor pages now use `AttendanceAssignmentService`, so a teacher assigned through `cohort_instructors` can access only their own cohorts.
- Public/login redirects now route `teacher` and `instructor` roles to `teacher.dashboard`.
- Attendance notifications are triggered from `AttendanceWorkflowService` after commit for:
  - `attendance.confirmed`
  - `session.first_attended`
- WhatsApp notification failures are logged and do not block attendance saving.
- Instructor material download authorization now uses assignment rules and increments download count.
- Instructor announcements now save to the real schema: `author_id`, `content`, and `published_at`.
- Instructor payout page now uses `cohort.course` instead of the invalid `cohort.session.course`.
- Payout policy is registered and allows `teacher` / `instructor` to view only their own payouts.
- Missing AR/FR translation keys were added for payouts/material status.
- Legacy instructor Blade links that referenced removed route names now point to the active teacher session/cohort routes.
- Regression coverage now includes teacher cohort materials and announcements pages for assigned teachers.

## Remaining Gaps

- There are still two financial payout implementations:
  - `App\Services\Billing\InstructorPayoutService` is the active v2 flow and its tests pass.
  - `App\Services\Finance\InstructorPayoutService` is a legacy-only flow with no current app references. Its old test is explicitly skipped to avoid treating removed v1 tables as an active production failure.
- Telegram exists as a platform messaging channel, but instructor attendance currently triggers WhatsApp workflow events only. Telegram delivery depends on existing messaging workflow templates and enabled student Telegram identities.
- `/instructor` routes are still kept for backward compatibility. A future cleanup can convert them to redirects after confirming no old links are used.

## Verification

Passing:

```bash
php artisan test tests/Feature/Teacher/TeacherAttendanceFlowTest.php tests/Unit/Attendance/AttendanceScheduleServiceTest.php tests/Unit/Attendance/AttendanceInsightsServiceTest.php tests/Feature/Billing/InstructorPayoutServiceTest.php tests/Feature/Billing/InstructorPayoutWorkflowTest.php
```

Result: 20 passed, 45 assertions.

Legacy-only suite:

```bash
php artisan test tests/Feature/Finance/InstructorPayoutTest.php
```

Reason: it targets the old `instructor_payout_items`/`rate` contract model that was superseded by payout v2 migrations, so it is marked skipped until the legacy class is removed or migrated.
