# Learner Promotion System - Quick Start & Testing

## Quick Setup

### 1. Database Migration
```bash
cd c:\xampp\htdocs\mavela
php migrations/001_add_promotion_workflow.php
```

Expected output:
```
✓ Executed: ALTER TABLE learner_promotions...
✓ Executed: ALTER TABLE learner_promotions...
...
✓ Migration completed successfully!
```

### 2. Access the Feature
1. Login to admin.php with admin credentials
2. Look for new menu item: **"Learner Promotions"** 
   - Located in admin dashboard sidebar after "Student Transfers"
3. Click it to open the promotion management view

## Testing Steps

### Test 1: Create Batch Promotions
**Objective**: Verify that batch promotion creation works

Steps:
1. Navigate to Learner Promotions view
2. Click button: "Create Batch Promotions (Jan 1st)"
3. Should see alert: "Created X pending learner promotions for this year"
4. Refresh page - should now show promotions in "Pending Promotions" table

Expected behavior:
- All non-frozen learners get promotion records (except those in U6)
- Each promotion shows learner name, from/to class, balance
- Table shows Guardian name and phone
- Created date is today's date

### Test 2: View Pending Promotions
**Objective**: Verify data display and calculations

Check in the pending table:
- ✓ Learner names display correctly
- ✓ Registration numbers visible
- ✓ Class names (e.g., "1North" → "2North")
- ✓ Balance to Carry shows USD amount (green chip)
- ✓ Guardian information populated
- ✓ Created date shows recent date
- ✓ Each row has Approve and Reject buttons

### Test 3: Approve Single Promotion
**Objective**: Verify learner class update on individual approval

Steps:
1. Find a pending promotion in the table
2. Click the "Approve" button for that row
3. Should see alert: "Learner promotion approved successfully"
4. Refresh page
5. Promotion moves from "Pending" to "Promotion History"
6. Check in student records that learner's class updated

Expected behavior:
- Promotion status changes to 'approved'
- Learner's class_id in learners table updated
- Timestamp recorded (approved_at)
- Entry appears in history with approver name and date
- System log records the action

### Test 4: Approve All Pending (Batch)
**Objective**: Verify batch approval workflow

Steps:
1. Create batch promotions if none exist
2. Click "Approve All X Pending" button (where X = count)
3. Should see alert: "Batch approved X learner promotions"
4. Refresh page - pending table should be empty
5. All promotions now in "Promotion History"

Expected behavior:
- All pending promotions processed
- All learners moved to next class
- All records show current approval date and admin name

### Test 5: Reject Promotion
**Objective**: Verify rejection workflow with reason tracking

Steps:
1. Create batch promotions if needed
2. Click "Reject" button on a pending promotion
3. Hidden form appears with reason textarea
4. Enter rejection reason (e.g., "Student transferring out")
5. Click "Confirm Reject" button
6. Should see alert: "Promotion rejected successfully"

Expected behavior:
- Promotion status changes to 'rejected'
- Rejection reason appended to note field
- Learner stays in original class (NOT moved)
- Entry appears in history with 'rejected' status
- Can create new promotion later if needed

### Test 6: Check Financial Balance Carryover
**Objective**: Verify balance calculations and carrying

Steps:
1. Create an invoice for a learner in their current class
2. Make a partial payment on that invoice
3. Create batch promotions
4. In pending list, check "Balance to Carry"
5. Should show: USD (Amount Paid - Amount Invoiced)
6. Approve the promotion
7. Check learner's financial record in new class
8. Verify balance appears in new class financial history

Expected balance formula:
```
Balance = Total Payments (in USD) - Total Invoiced (in USD)
Minimum = 0 (never negative)
```

### Test 7: Promotion History
**Objective**: Verify audit trail and history

Check history table displays:
- ✓ All approved promotions with timestamps
- ✓ Approved By shows admin name
- ✓ Status shows "approved" or "rejected"
- ✓ Balance carried shown correctly
- ✓ Ordered by most recent first

### Test 8: Edge Cases

**Test 8a: U6 Learners (Last Form)**
- Create batch promotions
- Verify no U6 learners get promotions (they can't progress)
- Check only Forms 1-5 and L6 get promotions

**Test 8b: Frozen Learners**
- Freeze a learner (set is_frozen = 1)
- Create batch promotions
- Verify frozen learner NOT in promotion list

**Test 8c: Duplicate Prevention**
- Create batch promotions
- Try creating again immediately
- Should show: "No new promotions needed..."
- No duplicate promotions created

**Test 8d: Zero Balance Learners**
- Create learner with no fee records
- Create batch promotions
- Verify shows "No balance" in carry field
- Can still approve - balance just shows as $0

## Data Verification (Direct Database Queries)

### Check Promotion Records
```sql
SELECT id, learner_id, from_class_id, to_class_id, status, 
       balance_carried, approved_by, approved_at
FROM learner_promotions
ORDER BY created_at DESC
LIMIT 10;
```

### Verify Learner Class Updates
```sql
SELECT l.id, l.reg_number, l.full_name, l.class_id, c.name
FROM learners l
JOIN classes c ON c.id = l.class_id
WHERE l.id IN (SELECT learner_id FROM learner_promotions WHERE status = 'approved')
LIMIT 10;
```

### Check System Logs
```sql
SELECT actor_id, action, details, created_at
FROM system_logs
WHERE action = 'learner_promotion_approved'
ORDER BY created_at DESC
LIMIT 10;
```

## Common Issues & Troubleshooting

### Issue: No pending promotions appear after Create
**Possible causes**:
- All learners are frozen
- All learners already have pending promotions
- Migration didn't run properly
- Check: `SELECT COUNT(*) FROM learners WHERE is_frozen = 0;`

### Issue: "Could not approve promotion" error
**Possible causes**:
- Promotion already approved
- Database connection issue
- Invalid promotion ID
- Check: Verify promotion exists and status = 'pending'

### Issue: Balance shows as 0 for all learners
**Possible causes**:
- No fee_payments records
- No fee_invoices records
- Query returning NULL
- Check: `SELECT * FROM fee_payments WHERE learner_id = X;`

### Issue: U6 learners getting promoted
**Possible causes**:
- Class names don't match expected format
- Next class lookup failing
- Check: Verify class names in database match code

### Issue: Learner class not updating
**Possible causes**:
- Approval transaction rolled back
- Database permissions issue
- SQL error in UPDATE statement
- Check system_logs for error details

## Performance Notes

- Batch promotion creation: O(n) where n = number of non-frozen learners
- For 100 learners: ~1-2 seconds
- Batch approval: O(m) where m = number of pending promotions
- Index on (status, learner_id, promotion_year) improves query speed

## Security

- Only accessible to admin role users
- All actions logged to system_logs
- Balance calculations read-only (no direct balance manipulation)
- Promotion approval is transaction-safe
- SQL injection prevention via prepared statements

## Support

For issues or questions, check:
1. PHP error logs: `c:\xampp\logs\php_error.log`
2. System logs in admin view
3. Database logs
4. Browser developer console (F12)
