Teren-app/app/Http/Controllers/SegmentController.php
2025-10-22 23:20:04 +02:00

159 lines
6.0 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Http\Requests\StoreSegmentRequest;
use App\Http\Requests\UpdateSegmentRequest;
use App\Models\Segment;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Inertia\Inertia;
class SegmentController extends Controller
{
public function index()
{
// Fetch active segments with number of active contracts and total balance sum of those contracts
// A contract is considered in a segment when the pivot is active=true.
$segments = Segment::query()
->where('active', true)
->withCount(['contracts as contracts_count' => function ($q) {
// On some drivers, wherePivot can compile oddly inside withCount; target the pivot table directly
$q->where('contract_segment.active', '=', 1);
}])
->get(['id', 'name', 'description']);
// Compute total balance per segment for active contracts
$balances = DB::table('segments')
->join('contract_segment', 'contract_segment.segment_id', '=', 'segments.id')
->join('contracts', 'contracts.id', '=', 'contract_segment.contract_id')
->leftJoin('accounts', 'accounts.contract_id', '=', 'contracts.id')
->where('segments.active', '=', 1)
->where('contract_segment.active', '=', 1)
->groupBy('segments.id')
->pluck(DB::raw('COALESCE(SUM(accounts.balance_amount),0) as total_balance'), 'segments.id');
$segments = $segments->map(function ($seg) use ($balances) {
$seg->total_balance = (string) ($balances[$seg->id] ?? 0);
return $seg;
});
return Inertia::render('Segments/Index', [
'segments' => $segments,
]);
}
public function show(\App\Models\Segment $segment)
{
// Retrieve contracts that are active in this segment, eager-loading required relations
$search = request('search');
$clientFilter = request('client') ?? request('client_id'); // support either ?client=<uuid|id> or ?client_id=<id>
$contractsQuery = \App\Models\Contract::query()
->whereHas('segments', function ($q) use ($segment) {
$q->where('segments.id', $segment->id)
->where('contract_segment.active', '=', 1);
})
->with([
'clientCase.person',
'clientCase.client.person',
'type',
'account',
])
->latest('id');
// Optional filter by client (accepts numeric id or client uuid)
if (! empty($clientFilter)) {
$contractsQuery->whereHas('clientCase.client', function ($q) use ($clientFilter) {
if (is_numeric($clientFilter)) {
$q->where('clients.id', (int) $clientFilter);
} else {
$q->where('clients.uuid', $clientFilter);
}
});
}
if (! empty($search)) {
$contractsQuery->where(function ($qq) use ($search) {
$qq->where('contracts.reference', 'ilike', '%'.$search.'%')
->orWhereHas('clientCase.person', function ($p) use ($search) {
$p->where('full_name', 'ilike', '%'.$search.'%');
})
->orWhereHas('clientCase.client.person', function ($p) use ($search) {
$p->where('full_name', 'ilike', '%'.$search.'%');
});
});
}
$contracts = $contractsQuery
->paginate(15)
->withQueryString();
// Mirror client onto the contract to simplify frontend access (c.client.person.full_name)
$items = collect($contracts->items());
$items->each(function ($contract) {
if ($contract->relationLoaded('clientCase') && $contract->clientCase) {
$contract->setRelation('client', $contract->clientCase->client);
}
});
if (method_exists($contracts, 'setCollection')) {
$contracts->setCollection($items);
}
// Build a full client list for this segment (not limited to current page) for the dropdown
$clients = \App\Models\Client::query()
->whereHas('clientCases.contracts.segments', function ($q) use ($segment) {
$q->where('segments.id', $segment->id)
->where('contract_segment.active', '=', 1);
})
->with(['person:id,full_name'])
->get(['uuid', 'person_id'])
->map(function ($c) {
return [
'uuid' => (string) $c->uuid,
'name' => (string) optional($c->person)->full_name,
];
})
->sortBy('name', SORT_NATURAL | SORT_FLAG_CASE)
->values();
return Inertia::render('Segments/Show', [
'segment' => $segment->only(['id', 'name', 'description']),
'contracts' => $contracts,
'clients' => $clients,
]);
}
public function settings(Request $request)
{
return Inertia::render('Settings/Segments/Index', [
'segments' => Segment::query()->get(),
]);
}
public function store(StoreSegmentRequest $request)
{
$data = $request->validated();
Segment::create([
'name' => $data['name'],
'description' => $data['description'] ?? null,
'active' => $data['active'] ?? true,
]);
return to_route('settings.segments')->with('success', 'Segment created');
}
public function update(UpdateSegmentRequest $request, Segment $segment)
{
$data = $request->validated();
$segment->update([
'name' => $data['name'],
'description' => $data['description'] ?? null,
'active' => $data['active'] ?? $segment->active,
'exclude' => $data['exclude'] ?? $segment->exclude,
]);
return to_route('settings.segments')->with('success', 'Segment updated');
}
}