# `AdministratorPromotionController` plan

## Scope
- **Controller**: `app/Http/Controllers/Api/Administrator/AdministratorPromotionController.php`
- **Purpose**: admin/registrar API to manage promotion records and parent enrollment lifecycle.
- **Primary dependencies**:
  - Query/detail: `PromotionQueryService`
  - Eligibility evaluation: `PromotionEligibilityService`
  - Status transitions: `PromotionStatusService`
  - Parent enrollment workflow: `PromotionEnrollmentService`
  - Reminders: `PromotionReminderService`
  - Auditing: `PromotionAuditService`
  - Level mapping: `LevelProgressionService`
- **Models**:
  - `StudentPromotionRecord`
  - `PromotionAuditLog`
  - `PromotionReminderLog`

## Routes
All routes are under:
- Base prefix: `/api/v1/administrator/promotions`
- Middleware: `auth:api`, `admin.access`

Endpoints:
- Listing & detail
  - `GET /api/v1/administrator/promotions/` → `index`
  - `GET /api/v1/administrator/promotions/summary` → `summary`
  - `GET /api/v1/administrator/promotions/{promotionId}` → `show`
- Eligibility & status
  - `POST /api/v1/administrator/promotions/evaluate` → `evaluate`
  - `PATCH /api/v1/administrator/promotions/{promotionId}/status` → `updateStatus`
- Deadlines
  - `POST /api/v1/administrator/promotions/deadlines` → `setDeadline` (bulk/single via body)
  - `POST /api/v1/administrator/promotions/{promotionId}/deadline` → `setDeadline` (single)
  - `POST /api/v1/administrator/promotions/deadlines/expire` → `expireDeadlines`
- Enrollment steps (admin override)
  - `PATCH /api/v1/administrator/promotions/{promotionId}/enrollment-steps` → `adminCompleteEnrollment`
- Reminders & audit
  - `POST /api/v1/administrator/promotions/{promotionId}/reminders` → `sendReminder`
  - `GET /api/v1/administrator/promotions/{promotionId}/reminders` → `reminders`
  - `POST /api/v1/administrator/promotions/reminders/dispatch` → `dispatchScheduledReminders`
  - `GET /api/v1/administrator/promotions/{promotionId}/audit` → `audit`
- Level progressions (mapping current level → promoted level)
  - `GET /api/v1/administrator/promotions/levels/` → `levelProgressions`
  - `POST /api/v1/administrator/promotions/levels/` → `upsertLevelProgression`
  - `POST /api/v1/administrator/promotions/levels/seed` → `seedLevelProgressions`

## Authentication & authorization
- Admin access enforced by route middleware.
- `getCurrentUserId()` used for attribution in audit logs and updates.

## Requests/validation
Validated via `FormRequest` classes:
- `index` / `summary`: `AdminListPromotionsRequest` (`filters()`)
- `evaluate`: `EvaluateEligibilityRequest` (supports scope: `student`, `class_section`, `school_year`)
- `updateStatus`: `UpdatePromotionStatusRequest` (supports `force` + `notes`)
- `setDeadline`: `SetEnrollmentDeadlineRequest` (supports `apply_to` modes and optional `promotion_ids`)
- `sendReminder`: `SendReminderRequest` (type, subject/message, channels)
- `adminCompleteEnrollment`: `ParentEnrollmentStepRequest` (`steps()`)
- `upsertLevelProgression`: `UpsertLevelProgressionRequest`

## Response shapes
This controller uses legacy `{ ok: ... }` shapes (not Base API envelope).

- `index`:
  - `{ ok:true, data:[StudentPromotionResource...], pagination:{page, per_page, total, total_pages}, counts_by_status }`
- `show`:
  - `{ ok:true, data: StudentPromotionResource }`
- `summary`:
  - `{ ok:true, counts_by_status, total }`
- `evaluate`:
  - `{ ok:true, result:{ scope, ... } }`
- `updateStatus`:
  - `{ ok:true, data: StudentPromotionResource }`
  - Errors:
    - 422 for invalid args
    - 409 for transition conflicts
- `setDeadline`:
  - `{ ok:true, updated, promotion_ids:[...] }`
- `sendReminder`:
  - `{ ok:true, reminder: PromotionReminderResource }`
- `dispatchScheduledReminders` / `expireDeadlines`:
  - `{ ok:true, result }`
- `reminders`:
  - `{ ok:true, reminders:[PromotionReminderResource...] }`
- `audit`:
  - `{ ok:true, entries:[PromotionAuditLogResource...] }`
- `adminCompleteEnrollment`:
  - `{ ok:true, data: StudentPromotionResource }` (409 on conflict)
- `levelProgressions`:
  - `{ ok:true, levels:[LevelProgressionResource...] }`
- `upsertLevelProgression`:
  - `{ ok:true, level: LevelProgressionResource }`
- `seedLevelProgressions`:
  - `{ ok:true, created }`

## Side effects
- Deadline updates are wrapped in `DB::transaction` and log audit entries via `PromotionAuditService`.
- Reminder sending records `PromotionReminderLog` and may send via multiple channels.
- Status transitions update `StudentPromotionRecord` and write audit entries via services.

## Error handling expectations
- `findOrFail()` returns 404 `{ ok:false, message:"Promotion record not found." }`.
- `evaluate()` catches unexpected errors and returns 500 with generic message.
- `sendReminder()` catches unexpected errors and returns 500 with generic message.

## Test plan (feature)
- AuthZ:
  - Non-admin users denied by middleware.
- List & filters:
  - Pagination and `counts_by_status` match expected totals.
- Evaluate:
  - Each scope returns expected payload keys; unexpected errors return 500.
- Status transitions:
  - Valid transitions succeed; invalid args return 422; invalid transitions return 409.
- Deadlines:
  - Single record update; bulk update by year; bulk update by list.
  - Audit log created for each updated record.
- Reminders:
  - Manual reminder creates log and returns resource.
  - Dispatch scheduled reminders returns summary result.
- Enrollment steps:
  - Admin patch updates steps and returns updated record; conflicts return 409.
- Levels:
  - List returns mappings; upsert creates/updates; seed inserts defaults.

