# Learner Promotion System - Complete Implementation

## Overview
A batch learner promotion system that allows administrators to:
- Create annual learner promotions (typically on January 1st)
- Track learner progression through academic levels (Form 1→2→3→4→L6→U6)
- Carry forward financial balances to the next level
- Batch approve or individually manage promotion requests
- View promotion history and audit trail

## Features Implemented

### 1. Database Schema Updates
- **Table**: `learner_promotions` (existing) - Enhanced with workflow columns:
  - `status`: ENUM('pending', 'approved', 'rejected') - Default: 'pending'
  - `balance_before`: DECIMAL(10,2) - Balance at time of promotion request
  - `balance_carried`: DECIMAL(10,2) - Amount carried to next class
  - `created_by`: INT(11) - Admin who created the promotion request
  - `approved_by`: INT(11) - Admin who approved it
  - `created_at`: TIMESTAMP - When promotion was created
  - `approved_at`: DATETIME - When it was approved
  - Indexes on: status, learner_id, promotion_year

### 2. PHP Helper Functions (in admin.php)

#### `get_learner_balance_for_class($pdo, $learner_id, $class_id): float`
- Calculates total balance for a learner in a specific class
- Balance = Total Payments Received - Total Invoiced Amount
- Returns 0 if no balance or if calculation fails
- Pulls from `fee_payments` and `fee_invoices` tables

#### `get_next_class($pdo, $current_class_id): ?int`
- Determines the next form/level for a learner
- Class progression: 1North → 2North → 3North → 4North → L6 → U6
- Returns NULL if learner is in U6 (final form) or invalid class
- Case-insensitive class name matching

#### `get_pending_promotions($pdo): array`
- Retrieves all pending promotions ready for approval
- Includes: learner name, class names, balance, guardian contact, created date
- Joins with users table to show who created the promotion
- Ordered by creation date (newest first)

#### `create_batch_promotions($pdo, $admin_id): int`
- Creates pending promotions for all eligible learners
- Filters: Only non-frozen learners
- Checks: Prevents duplicate promotions in same year
- Calculates: Current balance for each learner
- Returns: Count of promotions created
- Transaction-safe with rollback on error

#### `approve_promotion($pdo, $promotion_id, $admin_id): bool`
- Approves a single promotion:
  1. Updates `learners.class_id` to new class
  2. Sets promotion status to 'approved'
  3. Records approval timestamp and admin ID
  4. Logs action to system_logs
- Transaction-safe with explicit error handling
- Returns true/false for success

#### `approve_all_promotions($pdo, $admin_id): int`
- Batch approval of all pending promotions
- Iterates through pending promotions and approves each
- Returns count of successfully approved promotions
- Transaction-safe with rollback on error

### 3. HTTP Handlers (POST requests)

#### `create_batch_promotions`
- POST parameter only
- Creates promotion batch for current year
- Redirects to adminLearnerPromotionsView
- Shows success/info alert with count

#### `approve_promotion`
- POST parameters: `promotion_id` (required)
- Approves single promotion
- Redirects to adminLearnerPromotionsView
- Shows success/error alert

#### `approve_all_promotions`
- POST parameter only
- Batch approves all pending promotions
- Redirects to adminLearnerPromotionsView
- Shows success/info alert with count

#### `reject_promotion`
- POST parameters: `promotion_id` (required), `rejection_reason` (optional)
- Marks promotion as 'rejected'
- Appends reason to promotion note field
- Doesn't affect learner class (must be approved to move class)

### 4. Admin View: adminLearnerPromotionsView

#### Layout
- Header with description
- Action buttons (Create Batch, Approve All)
- Pending Promotions section (table)
- Promotion History section (table)

#### Pending Promotions Table
Columns: Student | Reg Number | From Class | To Class | Balance to Carry | Guardian Contact | Created | Action

Actions per row:
- **Approve** button: Immediate approval via POST
- **Reject** button: Toggles rejection form
- Rejection form (initially hidden):
  - Textarea for rejection reason
  - Confirm Reject button

#### Promotion History Table
Shows approved and rejected promotions
Columns: Student | Reg Number | From Class | To Class | Balance Carried | Status | Approved Date | Approved By

#### Data Queries
1. `$pendingPromotions` - Via `get_pending_promotions()` function
2. `$promotionHistory` - Direct query, last 100 records, ordered by approval date DESC

### 5. Navigation Integration
- Added to `$allowedAdminViews` array
- Added navigation button: "Learner Promotions" 
- Positioned after "Student Transfers" in menu
- Uses CSS class 'panel desk-view' for consistent styling

### 6. JavaScript Enhancements
- `toggleRejectForm(btn)` function:
  - Shows/hides rejection reason form
  - Toggles button text and styling
  - Called via onclick attribute on Reject buttons

## Workflow

### For Administrators:

1. **Annual Process (Jan 1st)**
   - Click "Create Batch Promotions" button
   - System generates pending promotion records for all learners
   - Each promotion shows learner name, class progression, and balance to carry

2. **Review & Approve**
   - Option A: "Approve All" - Batch approve all pending
   - Option B: Review individually, approve or reject each
   - Upon approval:
     - Learner's class_id is updated
     - Balance is recorded in promotion record
     - Action is logged to system_logs

3. **Rejections (if needed)**
   - Click "Reject" on a promotion
   - Enter rejection reason (optional)
   - Promotion status changes to 'rejected'
   - Learner stays in current class
   - Can create new promotion later

4. **View History**
   - See all approved/rejected promotions
   - View when promotion was approved and by whom
   - Track balances carried forward

### For Learners:
- Automatically moved to new class upon admin approval
- Financial balance carries forward to new class
- No manual class change needed by parents

## Financial Impact

### Balance Carryover
- Calculated at promotion creation time
- Based on formula: Payments Received - Total Invoiced for that class
- Minimum balance: 0 (never negative)
- Carried to new class in learner's financial record
- Appears when viewing learner fees in new class

### Affected Tables
- `learners` - class_id updated on approval
- `learner_promotions` - new status/audit fields
- `fee_payments`/`fee_invoices` - balance calculations reference
- `system_logs` - promotion approval logged

## Error Handling
- Graceful handling of missing learners or classes
- Transaction rollback on any database error
- Alert messages for success/failure scenarios
- No data loss on rejection (promotional records preserved)

## Audit Trail
- Created by: Admin user ID
- Approved by: Admin user ID  
- Timestamps: created_at, approved_at
- System logs: Action recorded with learner details and balance info

## Security
- Only admins can create/approve/reject promotions
- POST-based actions prevent accidental GET requests
- Transaction boundaries ensure data consistency
- Input validation on promotion IDs and reasons

## Testing Checklist
1. ✓ Migration runs successfully
2. ✓ Buttons appear in admin menu
3. ✓ Create batch promotions works
4. ✓ View loads with pending promotions
5. ✓ Approve single promotion updates class
6. ✓ Approve all promotions processes batch
7. ✓ Reject promotion sets status correctly
8. ✓ Balance calculations are accurate
9. ✓ System logs entries created
10. ✓ Promotion history displays correctly
11. ✓ No duplicate promotions in same year
12. ✓ U6 learners don't get promotions
13. ✓ Frozen learners excluded from batch

## Files Modified
1. `admin.php` - Main implementation
   - Added 6 helper functions (~250 lines)
   - Added 4 POST handlers (~50 lines)
   - Added 2 data queries (~30 lines)
   - Added adminLearnerPromotionsView HTML section (~180 lines)
   - Added JavaScript toggle function (~20 lines)
   - Added navigation button
   - Added view ID to allowed array

2. `migrations/001_add_promotion_workflow.php` - NEW
   - Database schema updates
   - Adds approval workflow columns to learner_promotions

## Future Enhancements
1. Automated promotion on Jan 1st (cron job)
2. Email notifications to parents on promotion
3. Bulk import of promotion exceptions
4. Class-level promotion statistics
5. API endpoints for third-party integrations
6. Promotion reversal capability
7. Custom promotion schedules (mid-year transitions)
