# Automatic M-Pesa Payment Matching System

## Overview

This system automatically matches and processes M-Pesa payments using **national ID numbers only**. Payments can be matched even if the ID number was added to the system **after** the payment was made.

## Key Features

1. **ID-Only Matching**: Uses national ID number (bill_ref_number) to match payments to borrowers
2. **Retry Functionality**: Payments can be retried even if they failed initially
3. **Automatic Processing**: When ID matches, payment is processed immediately
4. **Manual Retry Buttons**: UI buttons to retry matching for individual payments

## How It Works

### Payment Flow

1. **Payment Received**: M-Pesa sends callback with `BillRefNumber` (national ID used as account number)
2. **ID Matching**: System matches `bill_ref_number` to client's `id_number` (case-insensitive)
3. **Automatic Processing**:
   - ✅ If ID matches → Payment processed immediately, repayment created
   - ❌ If ID doesn't match → Transaction marked as `failed` (can be retried later)

### Retry Functionality

If a payment fails because the ID wasn't found, you can:
1. Add the client with that ID number to the system
2. Click the **"Retry"** button on the payment
3. The system will automatically match and process the payment

## Scripts

### 1. Auto Match Pending Payments Script

**File**: `auto_match_pending_payments.py`

**Purpose**: Automatically processes all pending/failed M-Pesa payments

**Usage**:
```bash
python auto_match_pending_payments.py
```

**What it does**:
- Finds all transactions without repayments
- Clears previous matching attempts
- Retries matching by ID number
- Processes payments that now match
- Shows summary of successes and failures

**When to use**:
- After adding new clients with ID numbers
- To batch process all pending payments
- To retry payments that failed initially

## UI Features

### Retry Buttons

Retry buttons appear on:
- **Callbacks Page**: Each transaction without a repayment has a "Retry" button
- **Transactions Page**: All transactions without repayments show retry option
- **Transaction Detail Page**: Reprocess button available

### How to Use Retry

1. Navigate to **Payments → M-Pesa Callbacks** or **Payments → Transactions**
2. Find a transaction without a repayment (shows "No Repayment" or "Failed")
3. Click the **"Retry"** button (yellow/orange button with refresh icon)
4. Confirm the reprocessing
5. System will attempt to match by ID number again

## Code Changes

### 1. `loans/models.py`

**Updated `process_payment()` method**:
- Added `force_rematch` parameter
- Automatically clears borrower/loan if retrying
- Allows matching even if ID was added after payment

**Updated `match_borrower()` method**:
- Simplified to only match by ID number
- Case-insensitive matching
- No phone number matching (since phones are hashed)

### 2. `payments/views.py`

**Updated `reprocess_transaction()` view**:
- Always uses `force_rematch=True` when retrying
- Better error messages
- Redirects back to callbacks page if needed

### 3. Templates

**Updated templates to show retry buttons**:
- `templates/payments/callbacks.html` - Retry button for all unmatched transactions
- `templates/payments/transactions.html` - Retry button for all transactions without repayments
- `templates/payments/reprocess_transaction.html` - Better instructions about retry functionality

## Example Scenarios

### Scenario 1: ID Added After Payment

1. Payment received with ID: `40178864`
2. System tries to match → No borrower found → Marked as `failed`
3. Later, client is registered with ID: `40178864`
4. Admin clicks **"Retry"** button on the payment
5. System matches ID → Payment processed → Repayment created ✅

### Scenario 2: Batch Processing

1. Multiple payments failed because IDs weren't in system
2. Admin adds all clients with their ID numbers
3. Runs `python auto_match_pending_payments.py`
4. All payments that now match are processed automatically ✅

### Scenario 3: Case Sensitivity

1. Payment received with ID: `B500Y` (uppercase)
2. Client registered with ID: `b500y` (lowercase)
3. System matches (case-insensitive) → Payment processed ✅

## Transaction Statuses

- **`processed`**: Payment successfully matched and repayment created
- **`failed`**: No borrower found with matching ID (can be retried)
- **`pending`**: Initial status when callback received
- **`confirmed`**: Callback confirmed but not yet processed

## Troubleshooting

### Payment Still Not Matching After Retry

1. **Check ID Number**: Verify the `bill_ref_number` in the transaction matches the client's `id_number` exactly (case-insensitive)
2. **Check Client Status**: Ensure client is active (not pending_approval, inactive, etc.)
3. **Check Active Loans**: Client must have at least one active loan
4. **Check Processing Notes**: Look at the transaction's processing_notes for specific error messages

### Running the Auto-Match Script

```bash
# Make sure you're in the project directory
cd /path/to/branch-system

# Run the script
python auto_match_pending_payments.py
```

The script will:
- Show progress for each transaction
- Display success/failure messages
- Provide a summary at the end

## Best Practices

1. **Regular Batch Processing**: Run the auto-match script regularly after adding new clients
2. **Check Failed Payments**: Review failed payments periodically to identify missing ID numbers
3. **Verify ID Numbers**: Ensure clients are registered with correct ID numbers
4. **Use Retry Buttons**: After adding a client, use retry buttons to match their pending payments

## Files Modified

- `loans/models.py` - Updated payment processing logic
- `payments/views.py` - Updated reprocess view
- `templates/payments/callbacks.html` - Added retry buttons
- `templates/payments/transactions.html` - Added retry buttons
- `templates/payments/reprocess_transaction.html` - Updated instructions
- `auto_match_pending_payments.py` - New script for batch processing

## Summary

The system now:
- ✅ Matches payments by ID number only
- ✅ Allows retrying payments even if ID was added later
- ✅ Provides UI buttons for manual retry
- ✅ Includes script for batch processing
- ✅ Automatically processes when ID matches
- ✅ No pending approval system - immediate processing

