HEX
Server: Apache/2.4.41 (Ubuntu)
System: Linux ip-172-31-42-149 5.15.0-1084-aws #91~20.04.1-Ubuntu SMP Fri May 2 07:00:04 UTC 2025 aarch64
User: ubuntu (1000)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: /var/www/vhost/disk-apps/comfama.sports-crowd.com/app/Http/Controllers/ReportInternalController.php
<?php

namespace App\Http\Controllers;

use App\MatchEvent;
use App\Parameter;
use Carbon\Carbon;
use ExcelReport;
use PdfReport;
use DB;
use Webklex\PDFMerger\Facades\PDFMergerFacade as PDFMerger;

class ReportInternalController extends Controller
{

    private $__TICKETSTATUSVALID = [1];

    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $events = MatchEvent::select('id', 'name', 'event_start', 'active')->orderBy('active', 'desc')->orderBy('created_at', 'desc')->get();
        return view("reports_internal.reports_internal", compact('events'));
    }

    public function generateReport($type, $event_id)
    {
        ini_set('memory_limit', '2048M');
        $this->parameters = Parameter::first();
        switch ($type) {
            case 'anulada':
                return $this->reportReversedAndReject($event_id);
                break;
            case 'cortesia':
                return $this->reportCourtesy($event_id);
                break;
            case 'vendida':
                return $this->reportTicketsSold($event_id);
                break;
            case 'consolidado':
                return $this->reportTicketsConsolidated($event_id);
                break;
            case 'venta-libre-y-credito':
                return $this->reportTicketsOverTheCounterAndCredit($event_id);
                break;
            case 'abonado':
                return $this->reportTicketsSubscriber($event_id);
                break;
            case 'ingreso-tribuna':
                return $this->reportTicketsByGrandstand($event_id);
                break;
        }
    }

    public function reportReversedAndReject($event_id)
    {
        $title = "Ticket reversados y anulados";
        $event = MatchEvent::find($event_id);
        $meta = [ // For displaying filters description on header
            'Evento' => $title . ' - ' . $event->name,
            'Fecha impresión reporte' => Carbon::now()->format('d/m/Y H:i:s'),
            'Tipo' => 'Tickets Reversados y anulados'
        ];

        // Query a mostrar en el reporte
        $queryBuilder = DB::table('tickets')
            ->select([
                'tickets.id', 'match_events.name', 'match_events.code', 'tickets.zone', 'tickets.code_ticket', 'tickets.special_text', 'tickets.code_seat', 'tickets.price', 'tickets.created_at AS fecha_compra',
                'users.first_name', 'users.last_name', 'users.document', 'ticket_types.name AS type_ticket', 's.zone_id', 'tickets.letter_seat as letter', 'z.zone_id as id_sub_zone', 'zsub.name as tribune', 'ticket_mains.payment_reference'
            ])
            ->join('ticket_mains', 'tickets.ticket_main_id', '=', 'ticket_mains.id')
            ->join('match_events', 'tickets.match_event_id', '=', 'match_events.id')
            ->join('users', 'tickets.user_id', '=', 'users.id')
            ->join('ticket_types', 'tickets.ticket_type_id', '=', 'ticket_types.id')
            ->join('seats as s', 'tickets.seat_id', '=', 's.id')
            ->join('zones as z', 's.zone_id', '=', 'z.id')
            ->join('zones as zsub', 'z.zone_id', '=', 'zsub.id')
            ->where('tickets.match_event_id', $event_id) // Del evento
            ->where(function ($query) {
                $query->where('tickets.ticket_status_id', 3)  // ANULADO
                    ->orWhere('tickets.ticket_status_id', 4); // REVERSADO
            });

        $columns = [
            'ID'                    => 'id',
            'Nombre Evento'         => 'name',
            'Codigo evento'         => 'code',
            'Tribuna'               => 'tribune',
            'Sector'                => 'zone',
            'Silla'                 => 'code_seat',
            'Fila'                  => 'letter',
            'Tipo de boleta'        => 'type_ticket',
            'Código ticket'         => 'code_ticket',
            'Boleta Especial'       => 'special_text',
            'Ref. de pago'          => 'payment_reference',
            'Precio'                => 'price',
            'Fecha compra'          => 'fecha_compra',
            'Nombres Usuario'       => function ($obj) {
                return $this->clean($obj->first_name);
            },
            'Apellidos Usuario'     => function ($obj) {
                return $this->clean($obj->last_name);
            },
            'Documento'             => 'document',
        ];

        $name = stripslashes(str_replace('/', '', $event->name));
        return ExcelReport::of($title, $meta, $queryBuilder, $columns)->download($name . ' - Reversados y anulados');
    }

    public function reportCourtesy($event_id)
    {
        $title = "Tickets de cortesía";
        $event = MatchEvent::find($event_id);
        $meta = [ // For displaying filters description on header
            'Evento' => $title . ' - ' . $event->name,
            'Fecha impresión reporte' => Carbon::now()->format('d/m/Y H:i:s'),
            'Tipo' => 'Tickets cortesia'
        ];

        // Query a mostrar en el reporte
        $queryBuilder = DB::table('tickets')
            ->select([
                'tickets.id', 'match_events.name', 'match_events.code', 'tickets.zone', 'tickets.code_ticket', 'tickets.special_text', 'tickets.code_seat', 'tickets.price', 'tickets.created_at AS fecha_compra',
                'users.first_name', 'users.last_name', 'users.document', 'ticket_types.name AS type_ticket', 's.zone_id', 'tickets.letter_seat as letter', 'z.zone_id as id_sub_zone', 'zsub.name as tribune'
            ])
            ->join('match_events', 'tickets.match_event_id', '=', 'match_events.id')
            ->join('users', 'tickets.user_id', '=', 'users.id')
            ->join('ticket_types', 'tickets.ticket_type_id', '=', 'ticket_types.id')
            ->join('seats as s', 'tickets.seat_id', '=', 's.id')
            ->join('zones as z', 's.zone_id', '=', 'z.id')
            ->join('zones as zsub', 'z.zone_id', '=', 'zsub.id')
            ->where('tickets.match_event_id', $event_id) // Del evento
            ->where(function ($query) {
                $query->where('tickets.ticket_status_id', 1)  // Comprado
                    ->orWhere('tickets.ticket_status_id', 2); // Ingresado
            }) //
            ->where(function ($query) {
                $query->where('tickets.ticket_type_id', 3);  // Cortesia
            });

        $columns = [
            'ID'                    => 'id',
            'Nombre Evento'         => 'name',
            'Codigo evento'         => 'code',
            'Tribuna'               => 'tribune',
            'Sector'                => 'zone',
            'Silla'                 => 'code_seat',
            'Fila'                  => 'letter',
            'Tipo de boleta'        => 'type_ticket',
            'Código ticket'         => 'code_ticket',
            'Boleta Especial'       => 'special_text',
            'Precio'                => 'price',
            'Fecha compra'          => 'fecha_compra',
            'Nombres Usuario'       => function ($obj) {
                return $this->clean($obj->first_name);
            },
            'Apellidos Usuario'     => function ($obj) {
                return $this->clean($obj->last_name);
            },
            'Documento'             => 'document',
        ];

        $name = stripslashes(str_replace('/', '', $event->name));
        return ExcelReport::of($title, $meta, $queryBuilder, $columns)
            ->download($name . ' - Cortesias');
    }

    public function reportTicketsSold($event_id)
    {
        $title = "Ticket vendidos";
        $event = MatchEvent::find($event_id);

        $meta = [ // For displaying filters description on header
            'Evento' => $title . ' - ' . $event->name,
            'Fecha impresión reporte' => Carbon::now()->format('d/m/Y H:i:s'),
            'Tipo' => 'Tickets vendidos'
        ];

        DB::statement("SET sql_mode = ''");
        // Query a mostrar en el reporte
        $queryBuilder = DB::table('tickets')
            ->select([
                'tickets.id', 'match_events.name', 'match_events.code', 'tickets.zone', 'tickets.code_ticket', 'tickets.special_text', 'tickets.code_seat', 'tickets.price', DB::raw('DATE(tickets.created_at) AS fecha_compra'), DB::raw('TIME(tickets.created_at) AS hora_compra'), 'tickets.confirm_stadium_ticket',
                'users.first_name', 'users.last_name', 'users.document', 'dt.name AS document_type', 'ticket_types.name AS type_ticket', 's.zone_id', 'tickets.letter_seat as letter', 'z.zone_id as id_sub_zone', 'zsub.name as tribune',
                DB::raw('IF(tm.pin_tercero IS NOT NULL AND tm.reference_tercero IS NOT NULL, "Tercero", "Pasarela") as f_pago'), DB::raw('IF(tm.payment_reference IS NOT NULL, tm.payment_reference, tm.reference_tercero) as payment_reference'), 'users.email', 'users.phone', 'ui.dob', DB::raw('CONCAT(seller.first_name, " ", seller.last_name) AS sellerFullName'), 'seller.email AS sellerEmail',
                'tm.total', DB::raw('GROUP_CONCAT(DISTINCT(tags.name)) AS segmentation')
            ])
            ->join('ticket_mains as tm', 'tickets.ticket_main_id', '=', 'tm.id')
            ->join('match_events', 'tickets.match_event_id', '=', 'match_events.id')
            ->join('users', 'tickets.user_id', '=', 'users.id')
            ->leftJoin('document_types as dt', 'users.document_type_id', '=', 'dt.id')
            ->leftJoin('user_informations as ui', 'users.id', '=', 'ui.user_id')
            ->leftJoin('users as seller', 'tm.seller_user_id', '=', 'seller.id')
            ->leftJoin('user_tags', 'users.id', '=', 'user_tags.user_id')
            ->leftJoin('tags', 'user_tags.tag_id', '=', 'tags.id')
            ->join('ticket_types', 'tickets.ticket_type_id', '=', 'ticket_types.id')
            ->join('seats as s', 'tickets.seat_id', '=', 's.id')
            ->join('zones as z', 's.zone_id', '=', 'z.id')
            ->join('zones as zsub', 'z.zone_id', '=', 'zsub.id')
            ->where('tickets.match_event_id', $event_id) // Del evento
            ->where(function ($query) {
                $query->where('tickets.ticket_status_id', 1)  // Comprado
                    ->orWhere('tickets.ticket_status_id', 2); // Ingresado
            })
            ->where(function ($query) {
                $query->where('tickets.ticket_type_id', 1)  //  Venta libre
                    ->orWhere('tickets.ticket_type_id', 2) // Abonados
                    ->orWhere('tickets.ticket_type_id', 4); // Crédito
            })
            ->groupBy('tickets.id')
            ->orderBy('fecha_compra', 'DESC');
        DB::statement("SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'");

        $columns = [
            'ID'                    => 'id',
            'Nombre Evento'         => 'name',
            'Codigo evento'         => 'code',
            'Tribuna'               => 'tribune',
            'Sector'                => 'zone',
            'Silla'                 => 'code_seat',
            'Fila'                  => 'letter',
            'Tipo de boleta'        => 'type_ticket',
            'Código ticket'         => 'code_ticket',
            'Boleta Especial'       => 'special_text',
            'Ref. de pago'          => 'payment_reference',
            'Precio'                => 'price',
            'Fecha compra'          => 'fecha_compra',
            'Hora compra'           => 'hora_compra',
            'Forma pago'            => 'f_pago',
            'Nombres Usuario' => function ($obj) {
                return $this->clean($obj->first_name);
            },
            'Apellidos Usuario' => function ($obj) {
                return $this->clean($obj->last_name);
            },
            'Documento'             => 'document',
            'Tipo Documento'        => 'document_type',
            'Email'                 => 'email',
            'Fecha Nacimiento'      => 'dob',
            'Telefono'              => 'phone',
            'Segmentación'          => 'segmentation',
            'Nombres Vendedor'      => 'sellerFullName',
            'Email Vendedor'        => 'sellerEmail',
            'Ingreso al estadio'    => 'confirm_stadium_ticket',
            'Precio total compra'   => 'total'
        ];

        $name = stripslashes(str_replace('/', '', $event->name));
        return ExcelReport::of($title, $meta, $queryBuilder, $columns)
            ->download($name . ' - Vendidas');
    }

    public function reportTicketsConsolidated($event_id)
    {
        $title = "Reporte consolidado";
        $event = MatchEvent::find($event_id);

        $meta = [ // For displaying filters description on header
            'Evento' => $title . ' - ' . $event->name . '(' . $event->id . ')',
            'Fecha evento' => $event->event_start,
            'Código evento' => $event->code,
            'Fecha impresión reporte' => Carbon::now()->format('d/m/Y H:i:s'),
            'Tipo' => 'Tickets vendidos'
        ];

        DB::statement("SET sql_mode = ''");
        $queryBuilder = DB::table('tickets')
            ->select(
                'match_events.name',
                'match_events.code',
                DB::raw("SUBSTRING_INDEX(z.name, '_', 1) as name_sub"),
                'zsub.name as zone',
                DB::raw('SUM(tickets.price) as total'),
                DB::raw("IF(ticket_mains.pin_tercero IS NOT NULL || ticket_mains.pin_internal IS NOT NULL, 'Efectivo', IF(tickets.ticket_type_id = 4, 'Crédito', 'Pasarela')) as f_pago"),
                DB::raw("IF(ticket_mains.payment_reference IS NOT NULL, 'Aplicación', 'Taquilla') as way_payment"),
                DB::raw('COUNT(tickets.id) as t_tickets')
            )
            ->join('ticket_mains', 'tickets.ticket_main_id', '=', 'ticket_mains.id')
            ->join('match_events', 'tickets.match_event_id', '=', 'match_events.id')
            ->join('seats as s', 'tickets.seat_id', '=', 's.id')
            ->join('zones as z', 's.zone_id', '=', 'z.id')
            ->join('zones as zsub', 'z.zone_id', '=', 'zsub.id')
            ->where('tickets.match_event_id', $event_id) // Del evento
            ->where(function ($query) {
                $query->where('tickets.ticket_status_id', 1)    // Comprado
                    ->orWhere('tickets.ticket_status_id', 2);   // Ingresado
            })
            ->where(function ($query) {
                $query->where('tickets.ticket_type_id', 1)      //  Venta libre
                    ->orWhere('tickets.ticket_type_id', 2)      // Abonados
                    ->orWhere('tickets.ticket_type_id', 4);     // Crédito
            })
            ->groupBy('zsub.id', 'match_events.name', 'match_events.code', 'zsub.name', DB::raw("SUBSTRING_INDEX(z.name, '_', 1)"), 'f_pago', 'way_payment')
            ->orderBy('zsub.name', 'ASC')
            ->orderBy(DB::raw("SUBSTRING_INDEX(z.name, '_', 1)"), 'ASC');
        DB::statement("SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'");

        $columns = [
            'Nombre Evento' => 'name',
            'Codigo evento' => 'code',
            'Tribuna' => 'zone',
            'Sector' => 'name_sub',
            'Forma pago' => 'f_pago',
            'Medio de Compra' => 'way_payment',
            'Cant. Tickets' => 't_tickets',
            'Total' => 'total'
        ];

        return PdfReport::of($title, $meta, $queryBuilder, $columns)
            ->editColumns(['Total'], [ // Mass edit column
                'class' => 'right bold padding'
            ])
            ->editColumns(['Cant. Tickets'], [ // Mass edit column
                'class' => 'right bold'
            ])
            ->setCss([
                '.padding' => 'padding: 0px 0px 0px 85px;',
            ])
            ->showTotal([ // Used to sum all value on specified column on the last table (except using groupBy method). 'point' is a type for displaying total with a thousand separator
                'Total' => 'point', // if you want to show dollar sign ($) then use 'Total Balance' => '$'
                'Cant. Tickets' => 'point'
            ])
            ->download('Reporte consolidado - ' . $event->name);
    }

    public function reportTicketsOverTheCounterAndCredit($event_id)
    {
        $title = "Reporte Venta Libre Y Crédito";
        $event = MatchEvent::find($event_id);

        $meta = [ // For displaying filters description on header
            'Evento' => $title . ' - ' . $event->name . '(' . $event->id . ')',
            'Fecha evento' => $event->event_start,
            'Código evento' => $event->code,
            'Fecha impresión reporte' => Carbon::now()->format('d/m/Y H:i:s'),
            'Tipo' => 'Tickets vendidos'
        ];

        DB::statement("SET sql_mode = ''");
        $queryBuilder = DB::table('tickets')
            ->select(
                'match_events.name',
                'match_events.code',
                DB::raw("SUBSTRING_INDEX(z.name, '_', 1) as name_sub"),
                'zsub.name as zone',
                DB::raw('SUM(tickets.price) as total'),
                DB::raw("IF(ticket_mains.pin_tercero IS NOT NULL || ticket_mains.pin_internal IS NOT NULL, 'Efectivo', IF(tickets.ticket_type_id = 4, 'Crédito', 'Pasarela')) as f_pago"),
                DB::raw("IF(ticket_mains.payment_reference IS NOT NULL, 'Aplicación', 'Taquilla') as way_payment"),
                DB::raw('COUNT(tickets.id) as t_tickets')
            )
            ->join('ticket_mains', 'tickets.ticket_main_id', '=', 'ticket_mains.id')
            ->join('match_events', 'tickets.match_event_id', '=', 'match_events.id')
            ->join('seats as s', 'tickets.seat_id', '=', 's.id')
            ->join('zones as z', 's.zone_id', '=', 'z.id')
            ->join('zones as zsub', 'z.zone_id', '=', 'zsub.id')
            ->where('tickets.match_event_id', $event_id)        // Del evento
            ->where(function ($query) {
                $query->where('tickets.ticket_status_id', 1)    // Comprado
                    ->orWhere('tickets.ticket_status_id', 2);   // Ingresado
            })
            ->where(function ($query) {
                $query->where('tickets.ticket_type_id', 1)      // Venta libre
                    ->orWhere('tickets.ticket_type_id', 4);     // Crédito
            })
            ->groupBy('zsub.id', 'match_events.name', 'match_events.code', 'zsub.name', DB::raw("SUBSTRING_INDEX(z.name, '_', 1)"), 'f_pago', 'way_payment')
            ->orderBy('zsub.name', 'ASC')
            ->orderBy(DB::raw("SUBSTRING_INDEX(z.name, '_', 1)"), 'ASC');
        DB::statement("SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'");

        $columns = [
            'Nombre Evento' => 'name',
            'Codigo evento' => 'code',
            'Tribuna' => 'zone',
            'Sector' => 'name_sub',
            'Forma pago' => 'f_pago',
            'Medio de Compra' => 'way_payment',
            'Cant. Tickets' => 't_tickets',
            'Total' => 'total'
        ];

        return PdfReport::of($title, $meta, $queryBuilder, $columns)
            ->editColumns(['Total'], [ // Mass edit column
                'class' => 'right bold padding'
            ])
            ->editColumns(['Cant. Tickets'], [ // Mass edit column
                'class' => 'right bold'
            ])
            ->setCss([
                '.padding' => 'padding: 0px 0px 0px 85px;',
            ])
            ->showTotal([ // Used to sum all value on specified column on the last table (except using groupBy method). 'point' is a type for displaying total with a thousand separator
                'Total' => 'point', // if you want to show dollar sign ($) then use 'Total Balance' => '$'
                'Cant. Tickets' => 'point'
            ])
            ->download('Reporte Venta Libre Y Crédito - ' . $event->name);
    }

    public function reportTicketsSubscriber($event_id)
    {
        $title = "Reporte Abonados";
        $event = MatchEvent::find($event_id);

        $meta = [ // For displaying filters description on header
            'Evento' => $title . ' - ' . $event->name . '(' . $event->id . ')',
            'Fecha evento' => $event->event_start,
            'Código evento' => $event->code,
            'Fecha impresión reporte' => Carbon::now()->format('d/m/Y H:i:s'),
            'Tipo' => 'Tickets vendidos'
        ];

        DB::statement("SET sql_mode = ''");
        $queryBuilder = DB::table('tickets')
            ->select(
                'match_events.name',
                'match_events.code',
                DB::raw("SUBSTRING_INDEX(z.name, '_', 1) as name_sub"),
                'zsub.name as zone',
                DB::raw('SUM(tickets.price) as total'),
                DB::raw("IF(ticket_mains.pin_tercero IS NOT NULL || ticket_mains.pin_internal IS NOT NULL, 'Efectivo', IF(tickets.ticket_type_id = 4, 'Crédito', 'Pasarela')) as f_pago"),
                DB::raw("IF(ticket_mains.payment_reference IS NOT NULL, 'Aplicación', 'Taquilla') as way_payment"),
                DB::raw('COUNT(tickets.id) as t_tickets')
            )
            ->join('ticket_mains', 'tickets.ticket_main_id', '=', 'ticket_mains.id')
            ->join('match_events', 'tickets.match_event_id', '=', 'match_events.id')
            ->join('seats as s', 'tickets.seat_id', '=', 's.id')
            ->join('zones as z', 's.zone_id', '=', 'z.id')
            ->join('zones as zsub', 'z.zone_id', '=', 'zsub.id')
            ->where('tickets.match_event_id', $event_id)                // Del evento
            ->where(function ($query) {
                $query->where('tickets.ticket_status_id', 1)            // Comprado
                    ->orWhere('tickets.ticket_status_id', 2);           // Ingresado
            })
            ->where(function ($query) {
                $query->orWhere('tickets.ticket_type_id', 2);           // Abonados
            })
            ->groupBy('zsub.id', 'match_events.name', 'match_events.code', 'zsub.name', DB::raw("SUBSTRING_INDEX(z.name, '_', 1)"), 'f_pago', 'way_payment')
            ->orderBy('zsub.name', 'ASC')
            ->orderBy(DB::raw("SUBSTRING_INDEX(z.name, '_', 1)"), 'ASC');
        DB::statement("SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'");

        $columns = [
            'Nombre Evento' => 'name',
            'Codigo evento' => 'code',
            'Tribuna' => 'zone',
            'Sector' => 'name_sub',
            'Forma pago' => 'f_pago',
            'Medio de Compra' => 'way_payment',
            'Cant. Tickets' => 't_tickets',
            'Total' => 'total'
        ];

        return PdfReport::of($title, $meta, $queryBuilder, $columns)
            ->editColumns(['Total'], [ // Mass edit column
                'class' => 'right bold padding'
            ])
            ->editColumns(['Cant. Tickets'], [ // Mass edit column
                'class' => 'right bold'
            ])
            ->setCss([
                '.padding' => 'padding: 0px 0px 0px 85px;',
            ])
            ->showTotal([ // Used to sum all value on specified column on the last table (except using groupBy method). 'point' is a type for displaying total with a thousand separator
                'Total' => 'point', // if you want to show dollar sign ($) then use 'Total Balance' => '$'
                'Cant. Tickets' => 'point'
            ])
            ->download('Reporte Abonados - ' . $event->name);
    }

    public function reportTicketsByGrandstand($event_id)
    {
        $title = "Reporte ingresos por tribuna";
        $event = MatchEvent::find($event_id);
        $date = Carbon::now()->format('Y-m-d H:i:s');

        $meta = [
            'Evento' => $event->name . '(' . $event->id . ')',
            'Fecha evento' => $event->event_start,
            'Código evento' => $event->code,
            'Fecha impresión reporte' => $date,
            'Descripcion' => 'Porcentaje ingresos por tribuna'
        ];

        $pathReportPercentage = '/public/tickets_tmp/' . time() . '-p.pdf';
        $queryBuilderPercentage = DB::table('tickets')
            ->select(DB::raw('CONCAT("Tribuna ",zsub.name) as grandstand'), DB::raw('ROUND((IFNULL(SUM(tv.validation_state), SUM(IF(tickets.confirm_stadium_ticket = "CONFIRMADO", 1, 0)))/(COUNT(*))*100), 2) AS percentage'))
            ->leftJoin('ticket_validation_histories AS tv', function ($join) {
                $join->on('tickets.id', '=', 'tv.ticket_id')->where('tv.validation_state', '=', 1);
            })
            ->join('ticket_types as tt', 'tickets.ticket_type_id', '=', 'tt.id')
            ->join('seats as s', 'tickets.seat_id', '=', 's.id')
            ->join('zones as z', 's.zone_id', '=', 'z.id')
            ->join('zones as zsub', 'z.zone_id', '=', 'zsub.id')
            ->where('tickets.match_event_id', $event_id)
            ->whereIn('tickets.ticket_status_id', $this->__TICKETSTATUSVALID)
            ->groupBy('zsub.name')
            ->orderBy('zsub.name', 'ASC');

        $columnsPercentage = [
            'Tribuna' => 'grandstand',
            'Porcentaje' => 'percentage'
        ];

        PdfReport::of($title, $meta, $queryBuilderPercentage, $columnsPercentage)
            ->showNumColumn(false)
            ->editColumn('Porcentaje', [
                'class' => 'right bold',
                'displayAs' => function ($result) {
                    return $result->percentage . ' %';
                }
            ])
            ->store($pathReportPercentage);

        $meta = [
            'Evento' => $event->name . '(' . $event->id . ')',
            'Fecha evento' => $event->event_start,
            'Código evento' => $event->code,
            'Fecha impresión reporte' => $date,
            'Descripcion' => 'Total ingresos por tribuna y tipo'
        ];

        $queryBuilder = DB::table('tickets')
            ->select(DB::raw('CONCAT("Tribuna ",zsub.name) as grandstand'), 'tt.name as type', DB::raw('COUNT(*) as sales'), DB::raw('IFNULL(SUM(tv.validation_state), SUM(IF(tickets.confirm_stadium_ticket = "CONFIRMADO", 1, 0))) AS receipts'))
            ->leftJoin('ticket_validation_histories AS tv', function ($join) {
                $join->on('tickets.id', '=', 'tv.ticket_id')->where('tv.validation_state', '=', 1);
            })
            ->join('ticket_types as tt', 'tickets.ticket_type_id', '=', 'tt.id')
            ->join('seats as s', 'tickets.seat_id', '=', 's.id')
            ->join('zones as z', 's.zone_id', '=', 'z.id')
            ->join('zones as zsub', 'z.zone_id', '=', 'zsub.id')
            ->where('tickets.match_event_id', $event_id)
            ->whereIn('tickets.ticket_status_id', $this->__TICKETSTATUSVALID)
            ->groupBy('zsub.name', 'tt.name')
            ->orderBy('zsub.name', 'ASC');

        $columns = [
            'Tribuna' => 'grandstand',
            'Tipo' => 'type',
            'Total Boletas' => 'sales',
            'Total Ingresos' => 'receipts'
        ];

        $pathReport = '/public/tickets_tmp/' . time() . '.pdf';
        PdfReport::of($title, $meta, $queryBuilder, $columns)
            ->showNumColumn(false)
            ->editColumn('Total Boletas', [
                'class' => 'right bold',
            ])
            ->editColumn('Total Ingresos', [
                'class' => 'right bold',
            ])
            ->showTotal([
                'Total Boletas' => 'point',
                'Total Ingresos' => 'point',
            ])
            ->store($pathReport);

        $pdf = PDFMerger::init();
        $pdf->addPDF(storage_path() . '/app' . $pathReport, 'all');
        $pdf->addPDF(storage_path() . '/app' . $pathReportPercentage, 'all');
        $fileName = $title . ' - ' . $event->name . '.pdf';
        $pdf->merge();
        $pdf->save(storage_path() . '/app/public/tickets_tmp/' . $fileName);
        return response()->download(storage_path() . '/app/public/tickets_tmp/' . $fileName);
    }

    public static function clean($string)
    {
        if (!$string) {
            return "";
        }
        $string = str_replace(' ', '-', $string); // Replaces all spaces with hyphens.
        return preg_replace('/[^A-Za-z0-9\-]/', '', $string); // Removes special chars.
    }
}