# Disconnection Methods Configuration - Implementation Guide

**Date**: May 25, 2026  
**Status**: ✅ **COMPLETE**

---

## 📋 Overview

The Disconnection Management System now supports **two flexible disconnection methods**:

1. **Fixed Day of Month** - Disconnect on a specific day each month (original method)
2. **Days After Due Date** - Disconnect X days after the billing due date (new method)

This allows companies to choose the billing and disconnection strategy that best fits their operations.

---

## 🔧 Implementation Details

### **New Database Fields**

**Migration**: `2026_05_25_000001_add_disconnection_by_due_date_to_companies.php`

**Changes to `companies` table**:
```sql
ALTER TABLE companies ADD COLUMN disconnection_by_due_date BOOLEAN DEFAULT false;
ALTER TABLE companies ADD COLUMN disconnection_days_after_due INT DEFAULT 15;
```

| Column | Type | Default | Description |
|--------|------|---------|-------------|
| `disconnection_by_due_date` | Boolean | false | If true, use days after due date; if false, use fixed day of month |
| `disconnection_days_after_due` | Integer | 15 | Number of days after due date to trigger disconnection |

### **Updated Models**

#### **Company Model** (`app/Models/Company.php`)
```php
protected $fillable = [
    // ... existing fields
    'disconnection_by_due_date',
    'disconnection_days_after_due',
];

protected $casts = [
    // ... existing casts
    'disconnection_by_due_date' => 'boolean',
    'disconnection_days_after_due' => 'integer',
];
```

#### **Billing Model** (`app/Models/Billing.php`)
**New Methods:**
```php
/**
 * Get effective disconnection date based on company settings
 */
public function getEffectiveDisconnectionDate()

/**
 * Check if billing is eligible for disconnection using effective date
 */
public function isEligibleForDisconnectionByEffectiveDate(): bool
```

### **Updated Service Logic**

#### **LatePaymentService** (`app/Services/LatePaymentService.php`)
**Enhanced Method: `getDisconnectionEligibleBillings()`**

```php
private function getDisconnectionEligibleBillings(Company $company): Collection
{
    $query = Billing::where('company_id', $company->id)
        ->where('status', '!=', 'paid')
        ->where('status', '!=', 'draft')
        ->where('balance', '>', 0);

    if ($company->disconnection_by_due_date) {
        // Calculate: due_date + disconnection_days_after_due
        $disconnectionDate = now()->subDays($company->disconnection_days_after_due);
        $query->where('due_date', '<', $disconnectionDate);
    } else {
        // Use the fixed disconnection_date field (original logic)
        $query->where('disconnection_date', '<', now());
    }

    return $query->orderBy('due_date')->get();
}
```

**How It Works:**

**Method 1: Fixed Day of Month** (`disconnection_by_due_date = false`)
- Uses the existing `disconnection_date` field on billing
- Disconnects on a specific day each month
- Example: Disconnect all unpaid on the 25th of each month

**Method 2: Days After Due Date** (`disconnection_by_due_date = true`)
- Calculates disconnection based on due_date + days
- Formula: `due_date + disconnection_days_after_due < now()`
- Example: Due date is 15th, disconnect after 15 days = 30th of same month

### **Company Settings Form**

**Location**: `resources/views/company/settings/edit.blade.php`

**New UI Section: "Disconnection Method"**
- Radio button to select disconnection method
- "Fixed Day of Month" option - uses existing disconnection_days
- "Days After Due Date" option - uses new disconnection_days_after_due
- Input field for "Days After Due Date to Disconnect" (shows/hides based on selection)
- JavaScript to toggle visibility of the new field
- Updated preview showing current configuration

---

## 📊 Configuration Examples

### **Example 1: Fixed Day of Month (Original)**
```
billing_due_days: 15
disconnection_days: 25
disconnection_by_due_date: false (or 0)
disconnection_days_after_due: 15 (not used)

Result:
- Bills due: 15th of each month
- Disconnect on: 25th of each month (if unpaid)
- This is independent of when payment is due
```

### **Example 2: Days After Due Date**
```
billing_due_days: 15
disconnection_days: 25 (not used)
disconnection_by_due_date: true (or 1)
disconnection_days_after_due: 15

Result:
- Bills due: 15th of each month
- Disconnect on: 15th + 15 days = 30th of each month (if unpaid)
- Dynamically calculated based on actual due date
```

### **Example 3: Quick Disconnection After Due**
```
billing_due_days: 1
disconnection_days: 5 (not used)
disconnection_by_due_date: true
disconnection_days_after_due: 5

Result:
- Bills due: 1st of each month
- Disconnect on: 1st + 5 days = 6th of each month (if unpaid)
- Fast collection with short grace period
```

### **Example 4: Extended Grace Period**
```
billing_due_days: 1
disconnection_days: 30 (not used)
disconnection_by_due_date: true
disconnection_days_after_due: 30

Result:
- Bills due: 1st of each month
- Disconnect on: 1st + 30 days = ~31st of each month (if unpaid)
- Full month grace period after due date
```

---

## 🔄 Data Flow

### **Processing Logic**

```
Monthly Scheduled Task (payments:process-late)
        ↓
ProcessCompanyLatePayments()
        ↓
getDisconnectionEligibleBillings()
        ↓
    Check: Is disconnection_by_due_date true?
        ↙                           ↘
    YES (Days After Due Date)     NO (Fixed Day)
        ↓                           ↓
Calculate:                      Compare:
due_date + X days              disconnection_date < now()
        ↓
    Find billings past this date
        ↓
    Create disconnection notices
        ↓
    Set disconnection_status = 'notice_sent'
        ↓
    Log to payments table
```

---

## 💾 Database Migration

```bash
php artisan migrate
```

**Before:**
```
companies table:
- billing_due_days (already existed)
- disconnection_days (already existed)
```

**After:**
```
companies table:
- billing_due_days
- disconnection_days
- disconnection_by_due_date (NEW)
- disconnection_days_after_due (NEW)
```

---

## 📋 Company Settings UI Changes

### **Before**
- Only one disconnection option: "Disconnection Day of Month"
- Fixed monthly schedule

### **After**
- Two disconnection methods available
- Radio buttons to select method
- Conditional fields based on selection
- Dynamic preview showing configuration
- JavaScript to handle show/hide logic

### **Form Elements**

```blade
<input type="radio" name="disconnection_by_due_date" value="0" />
<!-- Fixed Day of Month -->

<input type="radio" name="disconnection_by_due_date" value="1" />
<!-- Days After Due Date -->

<input type="number" name="disconnection_days_after_due" />
<!-- Shown only when Days After Due Date is selected -->
```

---

## 📈 Business Impact

### **Flexibility**
- ✅ Support different billing strategies per company
- ✅ Adapt to local regulations and practices
- ✅ Easy to switch between methods

### **Accuracy**
- ✅ Days After Due Date is more precise
- ✅ Accounts for different due dates per client
- ✅ Grace period is always from due date

### **Scalability**
- ✅ Supports multiple companies with different methods
- ✅ No conflicts between strategies
- ✅ Clear audit trail

---

## 🧪 Testing Scenarios

### **Scenario 1: Switch from Fixed to Days After Due**
```
Current: Disconnect on 25th, Bills due 15th, Today is 20th
New: Disconnect 15 days after due (May 30th), Bills due 15th

Before: 20th → nothing happens
After: 20th → nothing happens (still 10 days from due)
       30th → disconnection triggered
```

### **Scenario 2: Existing Billings with New Setting**
```
Old billings have fixed disconnection_date
New billings calculate based on due_date + days

Both methods coexist without conflict
```

### **Scenario 3: Grace Period Calculation**
```
Due date: May 15
Days after: 10
Disconnection: May 25 (15 + 10)

If paid on May 24: OK, no disconnection
If unpaid on May 25: Disconnection notice
If unpaid on May 26: Actual disconnection possible
```

---

## ✅ Verification Checklist

- ✅ Migration file created
- ✅ Company model updated with new fields
- ✅ Billing model enhanced with helper methods
- ✅ LatePaymentService logic updated
- ✅ Company settings form UI updated
- ✅ JavaScript for field visibility added
- ✅ Preview section updated
- ✅ Database changes documented
- ✅ Examples provided
- ✅ Role-based access maintained

---

## 📊 Technical Specifications

| Aspect | Details |
|--------|---------|
| **Migration Number** | 2026_05_25_000001 |
| **Table Modified** | companies |
| **Fields Added** | 2 |
| **Model Updates** | Company, Billing |
| **Service Updates** | LatePaymentService |
| **View Updates** | company/settings/edit.blade.php |
| **JavaScript** | Yes (toggle logic) |
| **Backward Compatible** | Yes (default to false) |
| **Breaking Changes** | None |

---

## 🚀 Deployment Steps

1. **Backup Database**
   ```bash
   # Take backup before migration
   mysqldump -u root -p billing_db > backup.sql
   ```

2. **Run Migration**
   ```bash
   php artisan migrate
   ```

3. **Update Company Settings** (Optional)
   - Navigate to Company Settings
   - Select "Days After Due Date" if desired
   - Set the number of days
   - Save

4. **Test**
   ```bash
   # Run the scheduled command
   php artisan payments:process-late --company-id=1
   ```

5. **Monitor**
   - Check logs for any issues
   - Verify disconnection notices are created correctly
   - Monitor different companies with different methods

---

## 🐛 Troubleshooting

| Issue | Solution |
|-------|----------|
| Disconnections not triggered | Check disconnection_by_due_date setting |
| Field not showing | Verify JavaScript is enabled |
| Setting not saving | Check form validation |
| Old billings not disconnecting | Use fixed day method for backward compatibility |
| Calculation wrong | Verify due_date is set correctly on billing |

---

## 📞 Support

**Questions?**
- Check the company settings form
- Review the preview section
- See examples above
- Check LatePaymentService logic

---

## 📝 Summary

**What's New**:
- Two disconnection methods available
- Flexible configuration per company
- Accurate grace period calculation
- Dynamic UI based on selection
- Full backward compatibility

**Implementation Complete**: ✅
**Status**: Production Ready
**Risk Level**: Low (backward compatible)

