Files
ladill-frontdesk/app/Http/Controllers/Api/VisitController.php
T
isaaccladandCursor 9e2d79936c
Deploy Ladill Frontdesk / deploy (push) Failing after 35s
Test / test (push) Failing after 2m45s
Initial Ladill Frontdesk release with deploy pipeline.
Visitor management app with SSO, kiosk, badges, reports, and Gitea CI deploy to frontdesk.ladill.com.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-27 20:37:15 +00:00

146 lines
5.2 KiB
PHP

<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Api\Concerns\ScopesToOwner;
use App\Http\Controllers\Controller;
use App\Models\Organization;
use App\Models\Visit;
use App\Services\Frontdesk\VisitCheckInService;
use App\Services\Frontdesk\VisitCheckOutService;
use App\Services\Frontdesk\VisitLifecycleService;
use App\Services\Frontdesk\VisitScheduleService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class VisitController extends Controller
{
use ScopesToOwner;
public function index(Request $request): JsonResponse
{
$owner = $this->ownerRef($request);
$visits = Visit::owned($owner)
->with(['visitor', 'host'])
->when($request->status, fn ($q, $s) => $q->where('status', $s))
->latest()
->paginate(min((int) $request->query('per_page', 25), 100));
return response()->json($visits);
}
public function store(Request $request, VisitCheckInService $checkIn, VisitScheduleService $scheduler): JsonResponse
{
$owner = $this->ownerRef($request);
$organization = Organization::owned($owner)->findOrFail($request->integer('organization_id'));
$source = (string) $request->attributes->get('service_caller', 'api');
if ($request->filled('external_ref')) {
$existing = Visit::owned($owner)
->where('organization_id', $organization->id)
->where('external_ref', $request->string('external_ref'))
->where('source', $source)
->with(['visitor', 'host'])
->first();
if ($existing) {
return response()->json($existing);
}
}
if ($request->boolean('schedule')) {
$validated = $request->validate([
'organization_id' => ['required', 'integer'],
'external_ref' => ['nullable', 'string', 'max:128'],
'visitor_id' => ['nullable', 'integer'],
'full_name' => ['required_without:visitor_id', 'string', 'max:255'],
'company' => ['nullable', 'string'],
'phone' => ['nullable', 'string'],
'email' => ['nullable', 'email'],
'host_id' => ['nullable', 'integer'],
'branch_id' => ['nullable', 'integer'],
'visitor_type' => ['required', 'string'],
'purpose' => ['nullable', 'string'],
'scheduled_at' => ['required', 'date'],
'notes' => ['nullable', 'string'],
'integration_metadata' => ['nullable', 'array'],
]);
$visit = $scheduler->schedule($owner, $organization, [
...$validated,
'source' => $source,
]);
return response()->json($visit->load(['visitor', 'host']), 201);
}
$validated = $request->validate([
'organization_id' => ['required', 'integer'],
'external_ref' => ['nullable', 'string', 'max:128'],
'full_name' => ['required', 'string', 'max:255'],
'company' => ['nullable', 'string'],
'phone' => ['nullable', 'string'],
'email' => ['nullable', 'email'],
'host_id' => ['nullable', 'integer'],
'visitor_type' => ['required', 'string'],
'purpose' => ['nullable', 'string'],
'integration_metadata' => ['nullable', 'array'],
'policies_accepted' => ['nullable', 'boolean'],
]);
$visit = $checkIn->checkIn($owner, $organization, [
...$validated,
'source' => $source,
'policies_accepted' => $validated['policies_accepted'] ?? true,
]);
return response()->json($visit->load(['visitor', 'host']), 201);
}
public function show(Request $request, Visit $visit): JsonResponse
{
$this->authorizeOwner($request, $visit);
return response()->json($visit->load(['visitor', 'host']));
}
public function checkOut(Request $request, Visit $visit, VisitCheckOutService $checkOut): JsonResponse
{
$this->authorizeOwner($request, $visit);
return response()->json($checkOut->checkOut($visit));
}
public function activate(Request $request, Visit $visit, VisitLifecycleService $lifecycle): JsonResponse
{
$this->authorizeOwner($request, $visit);
$visit = $lifecycle->checkInFromSchedule($visit);
return response()->json($visit->load(['visitor', 'host']));
}
public function approve(Request $request, Visit $visit, VisitLifecycleService $lifecycle): JsonResponse
{
$this->authorizeOwner($request, $visit);
$visit = $lifecycle->approve($visit);
return response()->json($visit->load(['visitor', 'host']));
}
public function cancel(Request $request, Visit $visit, VisitLifecycleService $lifecycle): JsonResponse
{
$this->authorizeOwner($request, $visit);
$validated = $request->validate([
'reason' => ['nullable', 'string', 'max:500'],
]);
return response()->json(
$lifecycle->cancel($visit, null, $validated['reason'] ?? null)->load(['visitor', 'host']),
);
}
}