$data */ public function schedule(string $ownerRef, Organization $organization, array $data, ?string $actorRef = null): Visit { return DB::transaction(function () use ($ownerRef, $organization, $data, $actorRef) { $visitor = $this->checkIns->resolveVisitorForSchedule($ownerRef, $organization, $data); $this->watchlist->assertCanCheckIn($visitor); $scheduledAt = isset($data['scheduled_at']) ? Carbon::parse($data['scheduled_at']) : now(); $status = $scheduledAt->startOfDay()->isAfter(now()->startOfDay()) ? Visit::STATUS_SCHEDULED : Visit::STATUS_EXPECTED; $visit = Visit::create([ 'owner_ref' => $ownerRef, 'organization_id' => $organization->id, 'branch_id' => $data['branch_id'] ?? null, 'visitor_id' => $visitor->id, 'host_id' => $data['host_id'] ?? null, 'visitor_type' => $data['visitor_type'] ?? 'visitor', 'status' => $status, 'purpose' => $data['purpose'] ?? null, 'expected_duration_minutes' => (int) ($data['expected_duration_minutes'] ?? config('frontdesk.kiosk.default_visit_duration_minutes', 60)), 'scheduled_at' => $scheduledAt, 'notes' => $data['notes'] ?? null, 'external_ref' => $data['external_ref'] ?? null, 'source' => $data['source'] ?? null, 'integration_metadata' => $data['integration_metadata'] ?? null, ]); AuditLog::record( $ownerRef, 'visit.scheduled', $organization->id, $actorRef, Visit::class, $visit->id, ['visitor' => $visitor->full_name, 'scheduled_at' => $scheduledAt->toIso8601String()], ); if ($status === Visit::STATUS_EXPECTED) { $this->notifications->visitorExpected($visit); } return $visit->load(['visitor', 'host']); }); } }