# Penalty System - Full Implementation Guide

## Overview

The penalty system has been fully implemented with both automatic and manual penalty application capabilities. This allows the system to automatically charge penalties for overdue loans or let admins apply penalties manually based on the loan product configuration.

## Features Implemented

### 1. Penalty Modes

Each loan product can be configured with one of two penalty modes:

- **Automatic Mode**: Penalties are automatically applied daily by a Celery task
- **Manual Mode**: Admins must manually apply penalties through the UI

### 2. Penalty Frequency

Penalties can be calculated based on different frequencies:

- **Daily**: Penalty rate applied per day overdue
- **Weekly**: Penalty rate applied per week overdue  
- **Monthly**: Penalty rate applied per month overdue

### 3. Database Changes

#### LoanProduct Model
- `penalty_mode`: CharField - 'auto' or 'manual'
- `penalty_frequency`: CharField - 'daily', 'weekly', or 'monthly'
- `late_payment_penalty`: Updated help text to reflect frequency-based calculation

#### PenaltyCharge Model
- `is_automatic`: BooleanField - Whether penalty was applied automatically
- `applied_by`: ForeignKey to User - Who applied manual penalty
- `reason`: TextField - Reason for manual penalty or notes

### 4. Automatic Penalty Application

#### Celery Tasks (`loans/tasks.py`)

**apply_automatic_penalties()**
- Runs daily at 1:00 AM (configurable in celery.py)
- Finds all active overdue loans with automatic penalty mode
- Calculates and applies penalties based on product settings
- Creates audit logs for each penalty applied
- Prevents duplicate penalties on the same day

**send_penalty_notifications()**
- Runs daily at 9:00 AM
- Sends SMS notifications to borrowers about applied penalties
- Can be integrated with your SMS service

#### Celery Configuration (`branch_system/celery.py`)
- Configured to run automatic penalty application daily
- Uses Africa/Nairobi timezone
- Includes task monitoring and time limits

### 5. Manual Penalty Application

#### Views (`loans/penalty_views.py`)

**apply_manual_penalty()**
- Allows staff to manually apply penalties to any loan
- Requires penalty amount and reason
- Records who applied the penalty
- Creates audit log

**calculate_suggested_penalty()**
- Shows suggested penalty based on product settings
- Helps admins determine appropriate penalty amount

**delete_penalty()**
- Allows deletion of manual penalties only
- Automatic penalties cannot be deleted (for audit trail)
- Creates audit log of deletion

**penalty_history()**
- Shows complete penalty history for a loan
- Distinguishes between automatic and manual penalties

### 6. User Interface

#### Enhanced Loan Detail Page
- Shows penalty mode (Auto/Manual badge)
- Displays total penalties prominently
- Shows suggested penalty for overdue loans
- Lists all penalties with type indicators (Auto/Manual)
- "Apply Penalty" button for staff (when loan is overdue)
- Delete button for manual penalties

#### Apply Penalty Modal
- Pre-fills suggested penalty amount
- Requires reason for penalty
- Shows loan details and days overdue
- Easy to use interface

### 7. URL Routes

```python
# Penalty Management
path('<uuid:loan_id>/penalty/apply/', apply_manual_penalty, name='apply_manual_penalty')
path('<uuid:loan_id>/penalty/calculate/', calculate_suggested_penalty, name='calculate_suggested_penalty')
path('<uuid:loan_id>/penalty/history/', penalty_history, name='penalty_history')
path('penalty/<uuid:penalty_id>/delete/', delete_penalty, name='delete_penalty')
```

## Setup Instructions

### 1. Run Migrations

```bash
python manage.py migrate
```

This will add the new fields to LoanProduct and PenaltyCharge models.

### 2. Configure Loan Products

Update each loan product with:
- Penalty mode (auto/manual)
- Penalty frequency (daily/weekly/monthly)
- Penalty rate percentage

### 3. Install and Configure Celery

#### Install Celery and Redis

```bash
pip install celery redis
```

#### Install Redis Server

**Windows:**
```bash
# Download Redis for Windows or use WSL
# Or use Docker:
docker run -d -p 6379:6379 redis
```

**Linux/Mac:**
```bash
sudo apt-get install redis-server  # Ubuntu/Debian
brew install redis  # Mac
```

#### Update Settings

Add to your settings.py:

```python
# Celery Configuration
CELERY_BROKER_URL = 'redis://localhost:6379/0'
CELERY_RESULT_BACKEND = 'redis://localhost:6379/0'
CELERY_ACCEPT_CONTENT = ['json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TIMEZONE = 'Africa/Nairobi'
```

### 4. Start Celery Workers

#### Development

```bash
# Start Celery worker
celery -A branch_system worker -l info

# Start Celery beat (scheduler) in another terminal
celery -A branch_system beat -l info
```

#### Production

Use a process manager like Supervisor or systemd:

**Supervisor Example:**

```ini
[program:celery_worker]
command=/path/to/venv/bin/celery -A branch_system worker -l info
directory=/path/to/project
user=www-data
autostart=true
autorestart=true
redirect_stderr=true
stdout_logfile=/var/log/celery/worker.log

[program:celery_beat]
command=/path/to/venv/bin/celery -A branch_system beat -l info
directory=/path/to/project
user=www-data
autostart=true
autorestart=true
redirect_stderr=true
stdout_logfile=/var/log/celery/beat.log
```

### 5. Test the System

#### Test Manual Penalty Application

1. Navigate to an overdue loan
2. Click "Apply Penalty" button
3. Enter penalty amount and reason
4. Submit and verify penalty is recorded

#### Test Automatic Penalty Application

```bash
# Run the task manually to test
python manage.py shell
>>> from loans.tasks import apply_automatic_penalties
>>> result = apply_automatic_penalties()
>>> print(result)
```

Or use the management command:

```bash
python manage.py apply_penalties --dry-run
```

## Usage Examples

### Example 1: Daily Penalty (Boost Product)

**Configuration:**
- Penalty Mode: Automatic
- Penalty Frequency: Daily
- Penalty Rate: 2.0%

**Calculation:**
- Outstanding: KES 10,000
- Days Overdue: 5
- Penalty = 10,000 × 0.02 × 5 = KES 1,000

### Example 2: Weekly Penalty (Mwamba Product)

**Configuration:**
- Penalty Mode: Manual
- Penalty Frequency: Weekly
- Penalty Rate: 5.0%

**Calculation:**
- Outstanding: KES 50,000
- Days Overdue: 14 (2 weeks)
- Penalty = 50,000 × 0.05 × 2 = KES 5,000

### Example 3: Monthly Penalty (Imara Product)

**Configuration:**
- Penalty Mode: Automatic
- Penalty Frequency: Monthly
- Penalty Rate: 10.0%

**Calculation:**
- Outstanding: KES 100,000
- Days Overdue: 45 (1.5 months, rounded to 2)
- Penalty = 100,000 × 0.10 × 2 = KES 20,000

## Monitoring and Maintenance

### Check Celery Status

```bash
# Check if workers are running
celery -A branch_system inspect active

# Check scheduled tasks
celery -A branch_system inspect scheduled
```

### View Penalty Logs

Check the audit logs in the admin panel or database:

```sql
SELECT * FROM audit_logs 
WHERE action IN ('penalty_applied', 'manual_penalty_applied', 'penalty_deleted')
ORDER BY created_at DESC;
```

### Monitor Penalty Application

```sql
-- Check penalties applied today
SELECT l.loan_number, pc.amount, pc.is_automatic, pc.applied_date
FROM penalty_charges pc
JOIN loans l ON pc.loan_id = l.id
WHERE DATE(pc.applied_date) = CURDATE()
ORDER BY pc.applied_date DESC;
```

## Troubleshooting

### Penalties Not Being Applied Automatically

1. Check if Celery worker and beat are running
2. Verify Redis is running: `redis-cli ping` (should return PONG)
3. Check Celery logs for errors
4. Verify loan products have penalty_mode='auto'
5. Ensure loans are actually overdue

### Duplicate Penalties

The system prevents duplicate penalties on the same day. If you see duplicates:
1. Check the `applied_date` field
2. Verify the duplicate prevention logic in `apply_automatic_penalties()`

### Manual Penalty Not Showing

1. Verify you're logged in as staff
2. Check if loan is marked as overdue
3. Verify the penalty was saved to database
4. Clear browser cache and refresh

## Best Practices

1. **Test in Development First**: Always test penalty calculations with dry-run before production
2. **Monitor Regularly**: Check penalty application logs daily for the first week
3. **Communicate with Borrowers**: Ensure borrowers understand the penalty structure
4. **Audit Trail**: Never delete automatic penalties - they provide important audit trail
5. **Backup Before Changes**: Always backup database before modifying penalty settings
6. **Review Penalty Rates**: Regularly review if penalty rates are appropriate and compliant

## Future Enhancements

Potential improvements to consider:

1. **Grace Period**: Add configurable grace period before penalties start
2. **Maximum Penalty Cap**: Set maximum penalty amount or percentage
3. **Penalty Waivers**: Allow staff to waive penalties with approval workflow
4. **SMS Integration**: Complete SMS notification integration
5. **Email Notifications**: Add email notifications for penalties
6. **Penalty Reports**: Create dedicated penalty reports and analytics
7. **Penalty Reversal**: Add ability to reverse penalties with proper authorization

## Support

For issues or questions:
1. Check the audit logs for detailed error messages
2. Review Celery logs: `/var/log/celery/`
3. Check Django logs for application errors
4. Verify database migrations are up to date
