Intégration fonctionnalites V1
This commit is contained in:
@@ -0,0 +1,276 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Supervisor;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Controllers\Supervisor\Concerns\ScopesSupervisorResources;
|
||||
use App\Models\Establishment;
|
||||
use App\Services\GeocodingService;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Inertia\Inertia;
|
||||
use Inertia\Response;
|
||||
|
||||
class OrganizationPageController extends Controller
|
||||
{
|
||||
use ScopesSupervisorResources;
|
||||
|
||||
public function __construct(private GeocodingService $geocoding) {}
|
||||
|
||||
public function index(Request $request): Response
|
||||
{
|
||||
$supervisor = $this->supervisor();
|
||||
|
||||
$baseQuery = Establishment::query()
|
||||
->where('organization_id', $supervisor->organization_id);
|
||||
|
||||
if ($supervisor->establishment_id !== null) {
|
||||
$baseQuery->where('id', $supervisor->establishment_id);
|
||||
}
|
||||
|
||||
$totalCount = (clone $baseQuery)->count();
|
||||
$viewMode = $totalCount === 1 ? 'single' : 'list';
|
||||
|
||||
$canManageEstablishments = $this->canManageEstablishments();
|
||||
$canCreateEstablishments = $this->canCreateEstablishments();
|
||||
|
||||
if ($viewMode === 'single') {
|
||||
$establishment = (clone $baseQuery)->withCount('machines')->first();
|
||||
|
||||
return Inertia::render('Supervisor/Organizations/Index', [
|
||||
'establishments' => [$this->formatEstablishment($establishment)],
|
||||
'viewMode' => 'single',
|
||||
'canManageEstablishments' => $canManageEstablishments,
|
||||
'canCreateEstablishments' => $canCreateEstablishments,
|
||||
'filters' => [],
|
||||
]);
|
||||
}
|
||||
|
||||
$query = (clone $baseQuery)->withCount('machines');
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$search = $request->string('search');
|
||||
$query->where(function ($builder) use ($search) {
|
||||
$builder->where('name', 'like', "%{$search}%")
|
||||
->orWhere('address', 'like', "%{$search}%")
|
||||
->orWhere('city', 'like', "%{$search}%")
|
||||
->orWhere('zip_code', 'like', "%{$search}%");
|
||||
});
|
||||
}
|
||||
|
||||
if ($request->has('is_active') && $request->string('is_active')->toString() !== '') {
|
||||
$query->where('is_active', $request->boolean('is_active'));
|
||||
}
|
||||
|
||||
$establishments = $query
|
||||
->tap(fn ($builder) => $this->applySort($request, $builder, [
|
||||
'name' => 'name',
|
||||
'city' => 'city',
|
||||
'machines_count' => 'machines_count',
|
||||
'is_active' => 'is_active',
|
||||
], 'name', 'asc'))
|
||||
->paginate($this->supervisorListPerPage($request))
|
||||
->withQueryString()
|
||||
->through(fn (Establishment $establishment) => $this->formatEstablishment($establishment));
|
||||
|
||||
return Inertia::render('Supervisor/Organizations/Index', [
|
||||
'establishments' => $establishments,
|
||||
'viewMode' => 'list',
|
||||
'canManageEstablishments' => $canManageEstablishments,
|
||||
'canCreateEstablishments' => $canCreateEstablishments,
|
||||
'filters' => [
|
||||
'search' => $request->string('search')->toString() ?: null,
|
||||
'is_active' => $request->has('is_active') && $request->string('is_active')->toString() !== ''
|
||||
? ($request->boolean('is_active') ? '1' : '0')
|
||||
: null,
|
||||
'sort' => $request->string('sort')->toString() ?: 'name',
|
||||
'direction' => $request->string('direction')->toString() === 'desc' ? 'desc' : 'asc',
|
||||
'per_page' => $this->supervisorListPerPage($request),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function searchAddresses(Request $request): JsonResponse
|
||||
{
|
||||
abort_unless($this->canManageEstablishments(), 403);
|
||||
|
||||
$validated = $request->validate([
|
||||
'q' => ['required', 'string', 'min:3', 'max:200'],
|
||||
]);
|
||||
|
||||
return response()->json(
|
||||
$this->geocoding->search($validated['q']),
|
||||
);
|
||||
}
|
||||
|
||||
public function storeEstablishment(Request $request): RedirectResponse
|
||||
{
|
||||
abort_unless($this->canManageEstablishments(), 403);
|
||||
abort_if($this->supervisor()->establishment_id !== null, 403);
|
||||
|
||||
$validated = $this->prepareEstablishmentData(
|
||||
$request->validate($this->establishmentRules()),
|
||||
);
|
||||
$validated['organization_id'] = $this->supervisor()->organization_id;
|
||||
|
||||
Establishment::query()->create($validated);
|
||||
|
||||
return redirect()->route('supervisor.organizations.index')
|
||||
->with('success', 'Enseigne créée.');
|
||||
}
|
||||
|
||||
public function updateEstablishment(Request $request, int $id): RedirectResponse
|
||||
{
|
||||
abort_unless($this->canManageEstablishments(), 403);
|
||||
|
||||
$establishment = $this->findAccessibleEstablishment($id);
|
||||
$validated = $this->prepareEstablishmentData(
|
||||
$request->validate($this->establishmentRules()),
|
||||
);
|
||||
|
||||
if (! empty($validated['is_active']) && ! $establishment->is_active) {
|
||||
$this->validateEstablishmentReadyForActivation($validated, $establishment);
|
||||
}
|
||||
|
||||
$establishment->update($validated);
|
||||
|
||||
return redirect()->route('supervisor.organizations.index')
|
||||
->with('success', 'Enseigne mise à jour.');
|
||||
}
|
||||
|
||||
public function toggleEstablishmentActive(int $id): RedirectResponse
|
||||
{
|
||||
abort_unless($this->canManageEstablishments(), 403);
|
||||
|
||||
$establishment = $this->findAccessibleEstablishment($id);
|
||||
$isActive = ! $establishment->is_active;
|
||||
|
||||
if ($isActive) {
|
||||
$this->validateEstablishmentReadyForActivation([
|
||||
'name' => $establishment->name,
|
||||
'address' => $establishment->address,
|
||||
'timezone' => $establishment->timezone,
|
||||
], $establishment);
|
||||
}
|
||||
|
||||
$establishment->update(['is_active' => $isActive]);
|
||||
|
||||
return redirect()->route('supervisor.organizations.index')
|
||||
->with('success', $isActive ? 'Enseigne réactivée.' : 'Enseigne désactivée.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function formatEstablishment(Establishment $establishment): array
|
||||
{
|
||||
return [
|
||||
'id' => $establishment->id,
|
||||
'uuid' => $establishment->uuid,
|
||||
'name' => $establishment->name,
|
||||
'address' => $establishment->address,
|
||||
'city' => $establishment->city,
|
||||
'zip_code' => $establishment->zip_code,
|
||||
'latitude' => $establishment->latitude !== null ? (float) $establishment->latitude : null,
|
||||
'longitude' => $establishment->longitude !== null ? (float) $establishment->longitude : null,
|
||||
'timezone' => $establishment->timezone,
|
||||
'is_active' => $establishment->is_active,
|
||||
'machines_count' => $establishment->machines_count,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function establishmentRules(): array
|
||||
{
|
||||
return [
|
||||
'name' => ['required', 'string', 'max:200'],
|
||||
'address' => ['required', 'string'],
|
||||
'city' => ['nullable', 'string', 'max:100'],
|
||||
'zip_code' => ['nullable', 'string', 'max:10'],
|
||||
'timezone' => ['required', 'string', 'max:50'],
|
||||
'is_active' => ['boolean'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $validated
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function prepareEstablishmentData(array $validated): array
|
||||
{
|
||||
$coordinates = $this->geocoding->geocode(
|
||||
$validated['address'],
|
||||
$validated['city'] ?? null,
|
||||
$validated['zip_code'] ?? null,
|
||||
);
|
||||
|
||||
$validated['latitude'] = $coordinates['latitude'] ?? null;
|
||||
$validated['longitude'] = $coordinates['longitude'] ?? null;
|
||||
|
||||
return $validated;
|
||||
}
|
||||
|
||||
private function findAccessibleEstablishment(int $id): Establishment
|
||||
{
|
||||
$supervisor = $this->supervisor();
|
||||
|
||||
return Establishment::query()
|
||||
->where('id', $id)
|
||||
->where('organization_id', $supervisor->organization_id)
|
||||
->when($supervisor->establishment_id, fn ($query) => $query->where('id', $supervisor->establishment_id))
|
||||
->firstOrFail();
|
||||
}
|
||||
|
||||
private function canCreateEstablishments(): bool
|
||||
{
|
||||
$supervisor = $this->supervisor();
|
||||
|
||||
if ($supervisor->role === 'viewer') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return in_array($supervisor->role, ['owner', 'platform_admin'], true)
|
||||
&& $supervisor->establishment_id === null;
|
||||
}
|
||||
|
||||
private function canManageEstablishments(): bool
|
||||
{
|
||||
return $this->supervisor()->role !== 'viewer';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $data
|
||||
*/
|
||||
private function validateEstablishmentReadyForActivation(array $data, Establishment $establishment): void
|
||||
{
|
||||
$validator = validator(
|
||||
$data,
|
||||
[
|
||||
'name' => ['required', 'string', 'max:200'],
|
||||
'address' => ['required', 'string'],
|
||||
'timezone' => ['required', 'string', 'max:50'],
|
||||
],
|
||||
[
|
||||
'name.required' => 'Le nom est requis pour réactiver l\'enseigne.',
|
||||
'address.required' => 'L\'adresse est requise pour réactiver l\'enseigne.',
|
||||
'timezone.required' => 'Le fuseau horaire est requis pour réactiver l\'enseigne.',
|
||||
],
|
||||
);
|
||||
|
||||
if ($validator->fails()) {
|
||||
throw ValidationException::withMessages($validator->errors()->toArray());
|
||||
}
|
||||
|
||||
$establishment->loadMissing('organization');
|
||||
|
||||
if (! $establishment->organization?->is_active) {
|
||||
throw ValidationException::withMessages([
|
||||
'is_active' => 'L\'organisation doit être active pour réactiver cette enseigne.',
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user