166 lines
4.7 KiB
PHP
166 lines
4.7 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Api;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\Guest;
|
|
use App\Models\GuestVisit;
|
|
use App\Models\GuestTag;
|
|
use App\Models\GuestNote;
|
|
use App\Services\GuestSearch;
|
|
use App\Services\CrossSellEngine;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Validator;
|
|
use SimpleSoftwareIO\QrCode\Facades\QrCode;
|
|
|
|
class GuestController extends Controller
|
|
{
|
|
protected $guestSearch;
|
|
protected $crossSellEngine;
|
|
|
|
public function __construct(GuestSearch $guestSearch, CrossSellEngine $crossSellEngine)
|
|
{
|
|
$this->guestSearch = $guestSearch;
|
|
$this->crossSellEngine = $crossSellEngine;
|
|
}
|
|
|
|
public function search(Request $request)
|
|
{
|
|
$query = $request->get('q');
|
|
if (!$query) {
|
|
return response()->json([]);
|
|
}
|
|
|
|
$guests = $this->guestSearch->search($query);
|
|
return response()->json($guests);
|
|
}
|
|
|
|
public function show($id)
|
|
{
|
|
$guest = Guest::with(['tier', 'visits.venue', 'tags', 'notes.staff'])->findOrFail($id);
|
|
|
|
return response()->json($guest);
|
|
}
|
|
|
|
public function store(Request $request)
|
|
{
|
|
$validator = Validator::make($request->all(), [
|
|
'name' => 'required|string|max:255',
|
|
'phone' => 'required|string|max:20',
|
|
'venue_id' => 'required|exists:venues,id',
|
|
]);
|
|
|
|
if ($validator->fails()) {
|
|
return response()->json($validator->errors(), 422);
|
|
}
|
|
|
|
$guest = Guest::create([
|
|
'name' => $request->name,
|
|
'phone' => $request->phone,
|
|
'email' => $request->email,
|
|
'nationality' => $request->nationality,
|
|
'language' => $request->language,
|
|
'birthday' => $request->birthday,
|
|
'marketing_consent' => $request->marketing_consent ?? false,
|
|
]);
|
|
|
|
$guest->generateLoyaltyId();
|
|
|
|
// Create initial visit
|
|
GuestVisit::create([
|
|
'guest_id' => $guest->id,
|
|
'venue_id' => $request->venue_id,
|
|
'visit_date' => now(),
|
|
'visit_type' => 'registration',
|
|
]);
|
|
|
|
return response()->json($guest, 201);
|
|
}
|
|
|
|
public function checkin(Request $request, $id)
|
|
{
|
|
$validator = Validator::make($request->all(), [
|
|
'venue_id' => 'required|exists:venues,id',
|
|
'spend_amount' => 'numeric|min:0',
|
|
'visit_type' => 'required|in:stay,dining,bar,beach,pool,watersports',
|
|
'room_number' => 'nullable|string',
|
|
'notes' => 'nullable|string',
|
|
]);
|
|
|
|
if ($validator->fails()) {
|
|
return response()->json($validator->errors(), 422);
|
|
}
|
|
|
|
$visit = GuestVisit::create([
|
|
'guest_id' => $id,
|
|
'venue_id' => $request->venue_id,
|
|
'visit_date' => now(),
|
|
'spend_amount' => $request->spend_amount ?? 0,
|
|
'visit_type' => $request->visit_type,
|
|
'room_number' => $request->room_number,
|
|
'notes' => $request->notes,
|
|
]);
|
|
|
|
// Update lifetime spend
|
|
$guest = Guest::find($id);
|
|
$guest->lifetime_spend = $guest->visits()->sum('spend_amount');
|
|
$guest->save();
|
|
|
|
return response()->json($visit, 201);
|
|
}
|
|
|
|
public function getCrossSellSuggestions($id)
|
|
{
|
|
$suggestions = $this->crossSellEngine->getSuggestions($id);
|
|
return response()->json($suggestions);
|
|
}
|
|
|
|
public function addTags(Request $request, $id)
|
|
{
|
|
$validator = Validator::make($request->all(), [
|
|
'tags' => 'required|array',
|
|
'tags.*' => 'string',
|
|
]);
|
|
|
|
if ($validator->fails()) {
|
|
return response()->json($validator->errors(), 422);
|
|
}
|
|
|
|
foreach ($request->tags as $tagName) {
|
|
GuestTag::firstOrCreate([
|
|
'guest_id' => $id,
|
|
'tag_name' => $tagName,
|
|
]);
|
|
}
|
|
|
|
return response()->json(['message' => 'Tags added successfully']);
|
|
}
|
|
|
|
public function addNote(Request $request, $id)
|
|
{
|
|
$validator = Validator::make($request->all(), [
|
|
'note_text' => 'required|string',
|
|
]);
|
|
|
|
if ($validator->fails()) {
|
|
return response()->json($validator->errors(), 422);
|
|
}
|
|
|
|
$note = GuestNote::create([
|
|
'guest_id' => $id,
|
|
'note_text' => $request->note_text,
|
|
'staff_id' => auth()->id(),
|
|
]);
|
|
|
|
return response()->json($note, 201);
|
|
}
|
|
|
|
public function generateQrCode($id)
|
|
{
|
|
$guest = Guest::findOrFail($id);
|
|
$qrCode = QrCode::size(200)->generate($guest->loyalty_id);
|
|
|
|
return response($qrCode)->header('Content-Type', 'image/svg+xml');
|
|
}
|
|
}
|