## Console Commands & Available Traits

### ProcessesMultipleTenants Trait

**Location:** `src/App/Traits/ProcessesMultipleTenants.php`  
**Documentation:** `docs/development/PROCESSES_MULTIPLE_TENANTS_TRAIT.md`

**When creating or editing console commands that iterate over multiple tenants:**

✅ **RECOMMENDED:** Use the `ProcessesMultipleTenants` trait instead of manual iteration

**Benefits:**
- Eliminates ~50-100 lines of boilerplate per command
- Standardized error handling and logging
- Automatic tenant connection management
- Built-in statistics (processed/failed/total)
- Consistent logging format across all tenant operations

**Quick Example:**
```php
use App\Traits\ProcessesMultipleTenants;

class YourCommand extends Command
{
    use ProcessesMultipleTenants;
    
    public function handle()
    {
        // Instead of manual Instance::chunk() + foreach + try/catch
        // Just use:
        $this->processTenants(function($tenant) {
            // Your business logic here
            $this->processData($tenant);
        });
    }
}
```

**Current Adoption:** 0/20 commands (gradual migration recommended)  
**Commands that should use it:** Any command iterating over `Instance::chunk()`, `Instance::all()`, or foreach tenants

**Rule:** When reviewing or creating tenant-processing commands, suggest using this trait to reduce code duplication and improve consistency.

---

### Dynamic Step Denominators in Multi-Step CLI Commands

**Rule:** When a console command has optional steps controlled by a flag, step labels MUST use a runtime-computed denominator — not a hardcoded one.

**Anti-pattern:**
```php
// ❌ BAD — hardcoded /3 in early steps, /4 in the optional step
$this->line("[1/3] Step one...");
$this->line("[2/3] Step two...");
$this->line("[3/3] Step three...");
if (!$this->option('skip-optional')) {
    $this->line("[4/4] Optional step..."); // contradicts the /3 above
}
```

**Correct pattern:**
```php
// ✅ GOOD — single source of truth for total step count
$totalSteps = $this->option('skip-optional') ? 3 : 4;
$this->line("[1/{$totalSteps}] Step one...");
$this->line("[2/{$totalSteps}] Step two...");
$this->line("[3/{$totalSteps}] Step three...");
if (!$this->option('skip-optional')) {
    $this->line("[4/{$totalSteps}] Optional step...");
}
```

**Why:** A static denominator that does not reflect the actual execution plan misleads developers reading the output — the step counter appears to jump or show an impossible total. The dynamic denominator is computed once and used everywhere, making it accurate in all invocation modes.

