# Pipeline Module (Read-Only Endpoint)

> Phase 2 scope: **read-only JSON endpoint** only.
> Full admin UI (drag-and-drop stage editor) is deferred to [Phase 3](../phases/phase3.md#33-pipeline-management-ui).

---

## Routes

```php
// CrmApp/Pipeline/routes/tenant.php
Route::middleware(['web', ..., 'auth', 'verified'])->group(function () {
    Route::get('pipelines', [PipelineController::class, 'index'])->name('pipelines.index');
    Route::get('pipelines/{pipeline}', [PipelineController::class, 'show'])->name('pipelines.show');
});
```

---

## Controller

```php
class PipelineController extends Controller
{
    public function index(Request $request): JsonResponse
    {
        $type = $request->get('type');  // 'lead' | 'deal' | null for all

        $pipelines = Pipeline::with('stages')
            ->when($type, fn ($q) => $q->where('pipeline_type', $type))
            ->orderBy('is_default', 'desc')
            ->get();

        return response()->json(PipelineResource::collection($pipelines));
    }

    public function show(Pipeline $pipeline): JsonResponse
    {
        return response()->json(new PipelineResource($pipeline->load('stages')));
    }
}
```

---

## `PipelineResource`

```php
public function toArray($request): array
{
    return [
        'id'            => $this->id,
        'name'          => $this->name,
        'slug'          => $this->slug,
        'pipeline_type' => $this->pipeline_type,
        'is_default'    => $this->is_default,
        'stages'        => PipelineStageResource::collection($this->whenLoaded('stages')),
    ];
}
```

---

## Frontend Usage

Deal/Board.tsx + Lead/Index.tsx both call this endpoint to populate pipeline selectors:

```ts
// pipelines endpoint always returns JSON — called via axios, not Inertia visit
const { data } = await axios.get(route('pipelines.index', { type: 'deal' }));
```

Or, pass pipeline data directly from the controller as Inertia props to avoid extra roundtrip:
```php
// In DealController::index()
'pipelines' => PipelineResource::collection(Pipeline::where('pipeline_type', 'deal')->get()),
```

---

## Notes

- `Pipeline::defaultForType(string $type)` is defined in `PipelineService` (Phase 1)
- Stage data is needed in frontend for column headings — always eager load `with('stages')`
- Phase 3 will add: POST/PUT/DELETE routes, StageController, drag-and-drop UI
