Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/AndresLopezCorrales/Boletilandia/llms.txt

Use this file to discover all available pages before exploring further.

The Sales Analytics page gives admins an instant visual snapshot of how much revenue each event has generated from ticket sales. It is rendered as an interactive Highcharts column chart that maps every event name to the total peso value of all seats sold for that event.

Accessing the Chart

Navigate to Ventas de Eventos in the admin navigation bar, or visit the route directly:
GET /admin-grafica_eventos
This route is protected by the admin middleware. Unauthenticated users and non-admin accounts will receive a 401 response. The route is handled by GraficaController::verGrafica() (App\Http\Controllers\Grafica\GraficaController).

How the Query Works

verGrafica() builds a single query that joins three tables — seccions, asientos, and eventos — and aggregates revenue only for seats that have been sold:
1

Join tables

Starts from Seccion, inner-joins asientos on asientos.seccion_id = seccions.id, then inner-joins eventos on eventos.id = seccions.evento_id.
2

Filter sold seats

Applies a WHERE asientos.disponibilidad_asiento = 0 filter. A value of 0 indicates the seat has been purchased; available seats carry a different value and are excluded.
3

Group and aggregate

Groups results by seccions.evento_id and eventos.NombreEvento, then selects eventos.NombreEvento and SUM(seccions.precio) as total_precio to produce one total-revenue row per event.
4

Format for the chart

The resulting collection is converted to a flat PHP array keyed by event name using pluck('total_precio', 'NombreEvento'), with each value cast to an integer via intval(). This $resultados array is passed directly to the view.

verGrafica() Method

// app/Http/Controllers/Grafica/GraficaController.php
public function verGrafica(Request $request)
{
    $totalesPorEvento = Seccion::join('asientos', 'asientos.seccion_id', '=', 'seccions.id')
        ->join('eventos', 'eventos.id', '=', 'seccions.evento_id')
        ->where('asientos.disponibilidad_asiento', 0)
        ->groupBy('seccions.evento_id', 'eventos.NombreEvento')
        ->select('eventos.NombreEvento', DB::raw('SUM(seccions.precio) as total_precio'))
        ->get();

    // Formatear los resultados como un array con el nombre del evento como clave
    $resultados = $totalesPorEvento->pluck('total_precio', 'NombreEvento')
        ->map(function ($value) {
            return intval($value); // Convertir el valor a entero
        })->toArray();

    return view('admin.grafica_eventos', compact('resultados'));
}

What the Chart Shows

The admin.grafica_eventos view receives the $resultados array and passes it to a Highcharts column chart rendered inside a full-width <div id="container">:
  • X-axis — event names (the keys of $resultados), labelled “Eventos”
  • Y-axis — total pesos generated, labelled “Pesos Generados”
  • Tooltip — appends the suffix ” Pesos MX” to each column value on hover
  • Chart title“Venta totales - Eventos” (left-aligned)
The chart data is injected server-side using Blade’s @json directive:
{{-- resources/views/admin/grafica_eventos.blade.php --}}
var eventoKeys = @json(array_keys($resultados)); //Llaves de eventos (nombres)
var eventoValues = @json(array_values($resultados)); //Valores de venta de cada concierto (cuanto se vendió)

Highcharts.chart('container', {
    chart: {
        type: 'column'
    },
    title: {
        text: 'Venta totales - Eventos',
        align: 'left'
    },
    xAxis: {
        categories: eventoKeys, //Nombre evento
        crosshair: true,
        accessibility: {
            description: 'Eventos'
        }
    },
    yAxis: {
        min: 0,
        title: {
            text: 'Pesos Generados'
        }
    },
    tooltip: {
        valueSuffix: ' Pesos MX'
    },
    plotOptions: {
        column: {
            pointPadding: 0.2,
            borderWidth: 0
        }
    },
    series: [
        {
            name: 'Eventos',
            data: eventoValues //Dinero generado
        }
    ]
});
The chart only includes events that have at least one sold seat (disponibilidad_asiento = 0). Events with no sales are absent from both the query results and the chart entirely.

Limitations

The current analytics implementation has several boundaries to be aware of:
  • Sold seats only — the query filters exclusively on disponibilidad_asiento = 0. Any seat that remains available is not counted toward revenue, regardless of whether it was ever reserved.
  • No refund or cancellation tracking — there is no cancellation or refund state in the asientos table. Once a seat is marked as sold (disponibilidad_asiento = 0), it permanently contributes to the revenue total even if the purchase was later reversed outside the application.
  • Section price, not ticket price — the SUM aggregates seccions.precio (the price assigned to the section), not a dedicated ticket-price column on the asientos table. All seats within a section are assumed to share the same price.
  • Integer truncation — revenue totals are cast with intval(), so fractional peso amounts are truncated rather than rounded.

Build docs developers (and LLMs) love