Skip to main content

Overview

The MeseroController (Waiter Controller) handles operations for restaurant waiters/servers, including table management and reservation assignment. Location: app/Http/Controllers/MeseroController.php Route Prefix: /mesero Middleware: auth, role:mesero

Table Management

viewTables()

Display all tables in the restaurant. Route: GET /mesero/tables Route Name: mesero.tables Implementation:
public function viewTables()
{
    $tables = Table::all();
    return view('mesero.meseromesas', compact('tables'));
}
tables
Collection
Collection of all Table models with their current status, seats, and details

storeTable()

Create a new table. Route: POST /mesero/tables Route Name: mesero.tables.store Implementation:
public function storeTable(Request $request)
{
    $request->validate([
        'name' => 'required|string|max:255',
        'number' => 'required|integer|unique:tables,number',
        'type' => 'required|string',
        'seats' => 'required|integer',
        'status' => 'required|string',
    ]);

    Table::create($request->all());

    return redirect()->route('meseromesas')->with('success', 'Mesa agregada correctamente.');
}
Validation Rules:
name
string
required
Table name or identifier (max 255 characters)
number
integer
required
Unique table number (must be unique across all tables)
type
string
required
Table type (e.g., “interior”, “exterior”, “VIP”, “terraza”)
seats
integer
required
Number of seats/capacity
status
string
required
Initial table status
Request Example:
{
  "name": "Mesa Premium 5",
  "number": 5,
  "type": "VIP",
  "seats": 6,
  "status": "disponible"
}

updateTable()

Update an existing table’s information. Route: PUT /mesero/tables/{id} Route Name: mesero.tables.update Implementation:
public function updateTable(Request $request, $id)
{
    $request->validate([
        'name' => 'required|string|max:255',
        'number' => 'required|integer|unique:tables,number,' . $id,
        'type' => 'required|string',
        'seats' => 'required|integer',
        'status' => 'required|string|in:available,occupied,reservada',
    ]);

    $table = Table::findOrFail($id);

    // Asegúrate de actualizar campos individuales para evitar errores
    $table->name = $request->input('name');
    $table->number = $request->input('number');
    $table->type = $request->input('type');
    $table->seats = $request->input('seats');
    $table->status = $request->input('status');
    $table->save();

    return redirect()->route('meseromesas')->with('success', 'Mesa actualizada correctamente.');
}
Validation Rules:
id
integer
required
Table ID to update (URL parameter)
name
string
required
Table name (max 255 characters)
number
integer
required
Table number (unique, except for current table)
type
string
required
Table type
seats
integer
required
Number of seats
status
enum
required
Table status - must be one of:
  • available - Table is available
  • occupied - Table is currently in use
  • reservada - Table is reserved
Request Example:
{
  "name": "Mesa 5 - Actualizada",
  "number": 5,
  "type": "interior",
  "seats": 4,
  "status": "occupied"
}

deleteTable()

Delete a table from the system. Route: DELETE /mesero/tables/{id} Route Name: mesero.tables.delete Implementation:
public function deleteTable($id)
{
    $table = Table::findOrFail($id);
    $table->delete();

    return redirect()->route('meseromesas')->with('success', 'Mesa eliminada correctamente.');
}
id
integer
required
Table ID to delete
Note: Deleting a table will fail if it has foreign key constraints (e.g., active reservations).

Reservation Management

meseroviewreservation()

Display all reservations with available tables for assignment. Route: GET /mesero/reservations Route Name: mesero.reservations Implementation:
public function meseroviewreservation()
{
    // Obtener todas las reservaciones y las mesas disponibles
    $reservations = Reservation::with('table')->get();
    $tables = Table::where('status', 'disponible')->get();

    // Pasar las variables a la vista
    return view('mesero.meseroreservation', compact('reservations', 'tables'));
}
reservations
Collection
Collection of all Reservation models with eager-loaded table relationshipsEach reservation includes:
  • id - Reservation ID
  • name - Guest name
  • email - Guest email
  • phone - Contact phone
  • guest - Number of guests
  • date - Reservation date
  • time - Reservation time
  • message - Special requests
  • table_id - Assigned table ID (nullable)
  • table - Related Table model (if assigned)
tables
Collection
Collection of available tables (status = ‘disponible’) that can be assigned to reservations

assignTable()

Assign a table to a reservation. Validates that the number of guests matches the table’s seat capacity. Route: POST /mesero/reservations/{reservationId}/assign-table Route Name: mesero.reservations.assign Implementation:
public function assignTable(Request $request, $reservationId)
{
    $reservation = Reservation::findOrFail($reservationId);
    $table = Table::findOrFail($request->table_id);

    // Verificar si el número de invitados coincide con el número de asientos
    if ($reservation->guest == $table->seats) {
        // Asignar la mesa a la reservación
        $reservation->table_id = $table->id;
        $reservation->save();

        // Marcar la mesa como reservada
        $table->status = 'reservada';
        $table->save();

        return response()->json([
            'success' => true,
            'table_name' => $table->name,
            'user_name' => $reservation->name,
        ]);
    } else {
        return response()->json([
            'success' => false,
            'message' => 'El número de invitados no coincide con los asientos de la mesa.',
        ]);
    }
}
Parameters:
reservationId
integer
required
Reservation ID to assign table to (URL parameter)
table_id
integer
required
Table ID to assign (request body)
Request Example:
{
  "table_id": 5
}
Success Response:
{
  "success": true,
  "table_name": "Mesa VIP 5",
  "user_name": "John Doe"
}
success
boolean
Indicates whether the assignment was successful
table_name
string
Name of the assigned table
user_name
string
Name of the guest who made the reservation
Error Response:
{
  "success": false,
  "message": "El número de invitados no coincide con los asientos de la mesa."
}
success
boolean
False when assignment fails
message
string
Error message explaining why the assignment failed
Business Logic:
  1. Validates that the reservation exists
  2. Validates that the table exists
  3. Critical validation: Checks if reservation.guest (number of guests) exactly matches table.seats (table capacity)
  4. If match:
    • Assigns table_id to the reservation
    • Changes table status to 'reservada'
    • Returns success with table and guest names
  5. If no match:
    • Returns error message
    • No changes are made to reservation or table

Additional Controllers

The system also includes a dashboard controller for waiters:

Mesero\DashboardController

Location: app/Http/Controllers/Mesero/DashboardController.php Route: GET /admin/dashboard (unified panel) Implementation:
public function index(): View
{
    $tablesCount = Table::count();
    $reservedCount = Table::where('status', 'reservada')->count();
    $availableCount = Table::where('status', 'disponible')->count();
    $reservationsToday = Reservation::whereDate('date', now()->toDateString())->count();

    return view('mesero.meserohome', compact(
        'tablesCount',
        'reservedCount',
        'availableCount',
        'reservationsToday'
    ));
}
Dashboard Metrics:
tablesCount
integer
Total number of tables in the restaurant
reservedCount
integer
Number of currently reserved tables
availableCount
integer
Number of available tables
reservationsToday
integer
Number of reservations scheduled for today

Data Models

Table Model

class Table extends Model
{
    protected $fillable = [
        'name',
        'number',
        'type',
        'seats',
        'status',
    ];

    public function reservations()
    {
        return $this->hasMany(Reservation::class);
    }
}

Reservation Model

class Reservation extends Model
{
    protected $fillable = [
        'name',
        'email',
        'phone',
        'guest',
        'date',
        'time',
        'message',
        'table_id',
    ];

    protected $casts = [
        'date' => 'date',
        'time' => 'datetime',
    ];

    public function table()
    {
        return $this->belongsTo(Table::class);
    }
}

Table Status Flow

Available
  • Table is free and ready for customers
  • Can be assigned to new reservations
  • Default status for new tables

Usage Examples

Assign Table via AJAX

fetch(`/mesero/reservations/${reservationId}/assign-table`, {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content
    },
    body: JSON.stringify({ table_id: tableId })
})
.then(response => response.json())
.then(data => {
    if (data.success) {
        alert(`Mesa ${data.table_name} asignada a ${data.user_name}`);
    } else {
        alert(data.message);
    }
});

Update Table Status

<form action="{{ route('mesero.tables.update', $table->id) }}" method="POST">
    @csrf
    @method('PUT')
    <input type="hidden" name="name" value="{{ $table->name }}">
    <input type="hidden" name="number" value="{{ $table->number }}">
    <input type="hidden" name="type" value="{{ $table->type }}">
    <input type="hidden" name="seats" value="{{ $table->seats }}">
    <select name="status">
        <option value="available">Disponible</option>
        <option value="occupied">Ocupada</option>
        <option value="reservada">Reservada</option>
    </select>
    <button type="submit">Actualizar</button>
</form>

Build docs developers (and LLMs) love