JEMBOT MAWOT Bypass Shell

Current Path : /home/cinepatreb/billetterie/modules/selltickets/
Upload File :
Current File : /home/cinepatreb/billetterie/modules/selltickets/selltickets.php

<?php
/**
 * Sell Tickets module for Prestashop by Avellana Digital
 *
 * @author    Avellana Digital SL
 * @copyright Copyright (c) 2019 Avellana Digital - www.avellanadigital.com
 * @license   Commercial license
 * @version    4.2.3
 */

if (!defined('_CAN_LOAD_FILES_')) {
    exit;
}

if (!defined('_PS_VERSION_')) {
    exit;
}


include 'lib/qr/qrlib.php';

class SellTickets extends Module
{
    public function __construct()
    {
        $this->displayName = 'Sell Tickets';
        $this->description = $this->l('Create and manage tickets for events');
        $this->name = 'selltickets';
        $this->tab = 'merchandizing';
        $this->version = '4.2.3';
        $this->author = 'Avellana Digital SL';
        $this->module_key = '87d89e75038f816c201359ad63d9174b';
        $this->context = Context::getContext();
        $this->bootstrap = true;
        $this->isps17 = (version_compare(_PS_VERSION_, '1.7.0') >= 0);
        
        $this->ps_versions_compliancy = array('min' => '1.6', 'max' => _PS_VERSION_);

        parent::__construct();
    }

    public function install()
    {
        return (
            parent::install()
            && $this->registerHook('actionOrderStatusPostUpdate') && $this->registerHook('actionCartSave')
            && $this->registerHook('customerAccount') && $this->registerHook('displayorderDetail')
            && $this->registerHook('displayHeader') && $this->registerHook('displayShoppingCartFooter')
            && $this->registerHook('displayCheckoutSummaryTop') && $this->registerHook('actionAdminControllerSetMedia')
            && $this->registerHook('displayProductActions')
            && $this->installDb()            
            && Configuration::updateValue($this->name.'_order_state', _PS_OS_PAYMENT_.','._PS_OS_PREPARATION_)
            && Configuration::updateValue($this->name.'_appkey', Tools::passwdGen(10))
            && Configuration::updateValue($this->name.'_token_ajax', Tools::passwdGen(32))
            && Configuration::updateValue($this->name.'_token_ajax_fr', Tools::passwdGen(32))
            && Configuration::updateValue($this->name.'_keygmaps', '')
            && Configuration::updateValue($this->name.'_show_map', 0)
            && Configuration::updateValue($this->name.'_overrides', 0)
            && Configuration::updateValue($this->name.'_limit_seat', 300)
            && Configuration::updateValue($this->name.'_attr_date', 0)
            && @chmod(_PS_MODULE_DIR_.$this->name.'/l/', 0777) && @chmod(_PS_MODULE_DIR_.$this->name.'/l/bar/', 0777)
        );
    }

    public function uninstall()
    {
        return (
            parent::uninstall() && $this->uninstallDb()
            && Configuration::deleteByName($this->name.'_order_state')
            && Configuration::deleteByName($this->name.'_appkey')
            && Configuration::deleteByName($this->name.'_token_ajax')
            && Configuration::deleteByName($this->name.'_token_ajax_fr')
            && Configuration::deleteByName($this->name.'_keygmaps')
            && Configuration::deleteByName($this->name.'_show_map')
            && Configuration::deleteByName($this->name.'_overrides')
            && Configuration::deleteByName($this->name.'_limit_seat')
            && Configuration::deleteByName($this->name.'_attr_date')
            && $this->deleteQrImg(null, true));
    }

    public function installDb()
    {
        Db::getInstance()->Execute('
            CREATE TABLE IF NOT EXISTS `'._DB_PREFIX_.$this->name.'` (
              `id_ticket` int(11) NOT NULL AUTO_INCREMENT,
              `id_product` int(11) UNSIGNED NOT NULL,
              `location` varchar(255) DEFAULT NULL,
              `lat` varchar(255) DEFAULT NULL,
              `long` varchar(255) DEFAULT NULL,
              `seats` tinyint(1) NOT NULL DEFAULT 0,
              `nominal` tinyint(1) NOT NULL DEFAULT 1,
              `bankwire` tinyint(1) NOT NULL DEFAULT 1,
              `date_add` datetime NOT NULL,
              PRIMARY KEY (`id_ticket`),
              UNIQUE KEY `id_product` (`id_product`)
            ) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;');

        Db::getInstance()->Execute('
            CREATE TABLE IF NOT EXISTS `'._DB_PREFIX_.$this->name.'_lang` (
              `id_ticket_lang` int(11) NOT NULL AUTO_INCREMENT,
              `id_ticket` int(11) NOT NULL,
              `name` varchar(255) NOT NULL,
              `date` text NOT NULL,
              `hour` text DEFAULT NULL,
              `conditions` text DEFAULT NULL,
              `venue` varchar(255) DEFAULT NULL,
              `id_lang` int(11) NOT NULL,
              PRIMARY KEY (`id_ticket_lang`),
              UNIQUE KEY `id_ticket` (`id_ticket`,`id_lang`)
            ) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;');

        Db::getInstance()->Execute('
            CREATE TABLE IF NOT EXISTS `'._DB_PREFIX_.$this->name.'_customer_tickets` (
              `id_customer_ticket` int(11) NOT NULL AUTO_INCREMENT,
              `id_cart` int(11) NOT NULL,
              `id_product` int(11) NOT NULL,
              `id_product_attribute` int(11) DEFAULT 0,
              `numticket` int(11) NOT NULL,
              `customer_name` varchar(255) NOT NULL,
              `customer_firstname` varchar(255) NOT NULL,
              `customer_nif` varchar(255) DEFAULT NULL,
              `customer_phone` varchar(32) DEFAULT NULL,
              `validated` tinyint(1) NOT NULL DEFAULT 0,
              `date_validated` datetime NOT NULL,
              PRIMARY KEY (`id_customer_ticket`),
              KEY `id_cart` (`id_cart`,`id_product`,`id_product_attribute`)
            ) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;');

        Db::getInstance()->Execute('
            CREATE TABLE IF NOT EXISTS `'._DB_PREFIX_.$this->name.'_orders` (
              `id_ticket_order` int(11) NOT NULL AUTO_INCREMENT,
              `id_order` int(11) NOT NULL,
              `id_ticket` int(11) NOT NULL,
              `id_product` int(11) NOT NULL,
              `id_product_attribute` int(11) DEFAULT 0,
              `date_add` datetime NOT NULL,
              PRIMARY KEY (`id_ticket_order`),
              UNIQUE KEY `id_order` (`id_order`,`id_product`,`id_product_attribute`)
            ) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;');

        Db::getInstance()->Execute('
            CREATE TABLE IF NOT EXISTS `'._DB_PREFIX_.$this->name.'_seats` (
              `id_ticket_seats` int(11) NOT NULL AUTO_INCREMENT,
              `seat_row` int(11) UNSIGNED NOT NULL,
              `seat_col` int(11) UNSIGNED NOT NULL,
              `ignore_attributes` tinyint(1) DEFAULT 0,
              `seat_available` text DEFAULT NULL,
              PRIMARY KEY (`id_ticket_seats`)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;');

        Db::getInstance()->Execute('
            CREATE TABLE IF NOT EXISTS `'._DB_PREFIX_.$this->name.'_seats_cart` (
              `id_selltickets_seats_cart` int(11) NOT NULL AUTO_INCREMENT,
              `id_ticket_seats` int(11) NOT NULL,
              `id_cart` int(11) UNSIGNED NOT NULL,
              `id_product` int(11) UNSIGNED NOT NULL,
              `id_product_attribute` int(11) UNSIGNED NOT NULL DEFAULT 0,
              `seat` text DEFAULT NULL,
              `date_upd` datetime NOT NULL,
              PRIMARY KEY (`id_selltickets_seats_cart`),
              UNIQUE KEY `id_cart` (`id_cart`,`id_product`,`id_product_attribute`,`id_ticket_seats`)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;');

        Db::getInstance()->Execute('
            CREATE TABLE IF NOT EXISTS `'._DB_PREFIX_.$this->name.'_seats_num` (
              `id_selltickets_seats_num` int(11) NOT NULL AUTO_INCREMENT,
              `id_ticket_seats` int(11) NOT NULL,
              `id_seat` int(11) UNSIGNED NOT NULL,
              `seat_num` varchar(32) DEFAULT NULL,
              `id_product_attribute` int(11) DEFAULT 0,
              PRIMARY KEY (`id_selltickets_seats_num`)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;');

        Db::getInstance()->Execute('
            CREATE TABLE IF NOT EXISTS `'._DB_PREFIX_.$this->name.'_seats_order` (
              `id_seats_order` int(11) NOT NULL AUTO_INCREMENT,
              `id_order` int(11) NOT NULL,
              `id_ticket_seats` int(11) NOT NULL,
              `seat` text NOT NULL,
              PRIMARY KEY (`id_seats_order`)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;');

        Db::getInstance()->Execute('
            CREATE TABLE IF NOT EXISTS `'._DB_PREFIX_.$this->name.'_seats_tickets` (
              `id` int(11) NOT NULL AUTO_INCREMENT,
              `id_ticket` int(11) NOT NULL,
              `id_ticket_seats` int(11) NOT NULL,
              `parent` tinyint(1) NOT NULL DEFAULT 0,
              PRIMARY KEY (`id`),
              UNIQUE KEY `id_ticket` (`id_ticket`,`id_ticket_seats`)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;');

        Db::getInstance()->Execute('
            CREATE TABLE IF NOT EXISTS `'._DB_PREFIX_.$this->name.'_shop` (
              `id_selltickets_shop` int(11) NOT NULL AUTO_INCREMENT,
              `id_ticket` int(11) UNSIGNED NOT NULL,
              `id_shop` int(11) UNSIGNED NOT NULL DEFAULT 0,
              PRIMARY KEY (`id_selltickets_shop`),
              UNIQUE KEY `id_ticket` (`id_ticket`,`id_shop`)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;');

        return true;
    }

    public function uninstallDb()
    {
        Db::getInstance()->Execute('DROP TABLE IF EXISTS `'._DB_PREFIX_.$this->name.'`;');
        Db::getInstance()->Execute('DROP TABLE IF EXISTS `'._DB_PREFIX_.$this->name.'_lang`;');
        Db::getInstance()->Execute('DROP TABLE IF EXISTS `'._DB_PREFIX_.$this->name.'_orders`;');
        Db::getInstance()->Execute('DROP TABLE IF EXISTS `'._DB_PREFIX_.$this->name.'_customer_tickets`;');
        Db::getInstance()->Execute('DROP TABLE IF EXISTS `'._DB_PREFIX_.$this->name.'_seats`;');
        Db::getInstance()->Execute('DROP TABLE IF EXISTS `'._DB_PREFIX_.$this->name.'_seats_cart`;');
        Db::getInstance()->Execute('DROP TABLE IF EXISTS `'._DB_PREFIX_.$this->name.'_seats_num`;');
        Db::getInstance()->Execute('DROP TABLE IF EXISTS `'._DB_PREFIX_.$this->name.'_seats_tickets`;');
        Db::getInstance()->Execute('DROP TABLE IF EXISTS `'._DB_PREFIX_.$this->name.'_shop`;');
        Db::getInstance()->Execute('DROP TABLE IF EXISTS `'._DB_PREFIX_.$this->name.'_seats_order`;');

        return true;
    }    

    public function hookActionCartSave($params)
    {
        if ($params['cart']) {
            $cart = $params['cart'];
        } else {
            $cart = @new Cart((int)$this->context->cart->id);
        }

        $this->getCorrectInfoCustomer((int)$cart->id);
    }

    public function hookactionOrderStatusPostUpdate($params)
    {
        $status = $params['newOrderStatus'];

        if (!Validate::isLoadedObject($status)) {
            return false;
        }

        $order = new Order((int)$params['id_order']);

        if (!$order || !Validate::isLoadedObject($order)) {
            return false;
        }

        $customer = new Customer($order->id_customer);

        if ($this->getOrderStatesOk($status->id)) {
            $tickets = $this->getTickets();
            //$products_order = $order->getProducts();
            $products_order = $order->getProductsDetail();
            
            //PROPOSTA PELS PACKS
            foreach($products_order as $key => $product) {
                if(Pack::isPack($product['product_id'])) {
                    unset($products_order[$key]);
                    $pack_products = Pack::getItems($product['product_id'], Configuration::get('PS_LANG_DEFAULT', null, null, $order->id_shop));
                    foreach ($pack_products as $pack_product) {                     
                        $products_order[] = array(
                            'id_order' => $order->id,
                            'product_id' => $pack_product->id,
                            'product_attribute_id' => $pack_product->id_pack_product_attribute,
                            'product_quantity' => $pack_product->pack_quantity * $product['product_quantity']
                        );
                    }                    
                }
            }

            // Purguem una possible entrada comprada existent a la base de dades
            $this->delSeatsOrder($params['id_order']);

            if (!empty($tickets)) {
                foreach ($products_order as $product) {
                    $assoc_seats = array();
                    $seatcart = array();
                    $delete_seats = array();
                    $seats_aux = $this->getSeatsFromOrder(
                        $params['id_order']
                    );

                    // Purguem una possible entrada comprada existent a la base de dades
                    $this->delTicketOrder(
                        $params['id_order'],
                        $product['product_id'],
                        $product['product_attribute_id'],
                        false
                    );

                    $ticket = $this->getTicketByProduct((int)$product['product_id']);

                    if ($ticket) {
                        $is_nominal = $this->getTicketIsNominalByIdProduct((int)$product['product_id']);
                        if ($ticket['seats']) {
                            $assoc_seats_aux = $this->getAssocSeatsByTicket($ticket['id_ticket']);
                            if ($assoc_seats_aux) {
                                foreach ($assoc_seats_aux as $assoc) {
                                    $assoc_seats[] = (int)$assoc['id_ticket_seats'];
                                }
                            } else {
                                $assoc_seats = array();
                            }

                            if ($assoc_seats) {
                                foreach ($assoc_seats as $id_ticket_seats) {
                                    $seatcart[$id_ticket_seats] = $this->getSeatCart(
                                        $order->id_cart,
                                        (int)$product['product_id'],
                                        (int)$product['product_attribute_id'],
                                        (int)$id_ticket_seats
                                    );

                                    $delete_seats[] = (int)$id_ticket_seats;

/*                                    $this->delSeatsCustomer(
                                        $order->id_cart,
                                        (int)$product['product_id'],
                                        (int)$product['product_attribute_id'],
                                        (int)$id_ticket_seats,
                                    );*/
                                }

                                if (count($delete_seats) > 0) {
                                    $this->delSeatsCustomer(
                                        $order->id_cart,
                                        (int)$product['product_id'],
                                        (int)$product['product_attribute_id'],
                                        (int)$delete_seats // id_ticket_seats
                                    );
                                }
                            } else {
                                $seatcart = array();
                            }
                            
                            if (count($seatcart) == 0) {
                                foreach ($seats_aux as $seat) {
                                    $seatcart[$seat['id_ticket_seat']] = $seat['seat'];
                                }
                            }
                        } else {
                            $seatcart = array();
                        }

                        $this->addTicketOrder(
                            $product['id_order'],
                            $ticket['id_ticket'],
                            $product['product_id'],
                            $product['product_attribute_id'],
                            $seatcart
                        );

                        $ticket_lang = $this->getTicketLangInfo((int)$ticket['id_ticket'], (int)$order->id_lang);

                        // Afegim la referència de l'entrada comprada
                        $product_aux = new Product((int)$product['product_id']);
                        $ticket_nom = ($ticket_lang['name'] ?
                          $ticket_lang['name'] : $product_aux->name[(int)$order->id_lang]
                        );

                        $ticket_attributes = '';
                        if ((int)$product['product_attribute_id'] != 0) {
                            $ticket_attributes = $this->getAttributesFromProduct(
                                $product['product_attribute_id'],
                                $order->id_lang
                            );
                            $ticket_attributes = implode(', ', $ticket_attributes);
                        }

                        $ticket_filename = $ticket_nom.($ticket_attributes != '' ? ' - '.$ticket_attributes : '');
                        $qty = $product['product_quantity'];

                        // Generem el codi QR personalitzat
                        $filename = $this->getFilenameTicketByOrder(
                            $order->id,
                            $product['product_id'],
                            $product['product_attribute_id'],
                            (int)$order->id_lang
                        ).'-'.$this->getQrName(
                            $customer->id,
                            $customer->firstname,
                            $customer->lastname,
                            $order->id,
                            $product['product_id'],
                            $product['product_attribute_id']
                        );

                        $ticket_ref_aux = array();

                        for ($x = 1; $x <= $qty; $x++) {
                            if (!$is_nominal) {
                                $customer_info = array();
                                $customer_info['name'] = '-';
                                $customer_info['firstname'] = '-';
                                $customer_info['phone'] = '-';
                                $this->saveCustomerInfo(
                                    $x,
                                    $customer_info,
                                    $product['product_id'],
                                    $product['product_attribute_id'],
                                    $order->id_cart
                                );
                            }

                            $num = str_pad($x, 2, 0, STR_PAD_LEFT);
                            $bar_content = $order->reference.$order->id.$product['product_id']
                            .$product['product_attribute_id'].$num;
                            $ticket_ref_aux[$x] = $bar_content;

                            try {
                                QRcode::png(
                                    $bar_content,
                                    _PS_MODULE_DIR_.$this->name.'/l/'.str_replace(
                                        $this->getFilenameTicketByOrder(
                                            $order->id,
                                            $product['product_id'],
                                            $product['product_attribute_id'],
                                            (int)$order->id_lang
                                        )
                                        .'-',
                                        '',
                                        $filename
                                    )
                                    .'_'.$x.'.png',
                                    'L',
                                    8,
                                    2
                                );

                                include_once 'lib/barcode/BarcodeBase.php';
                                include_once 'lib/barcode/Code128.php';
                                $barcode = new Code128();

                                $barcode->setData($bar_content);
                                $barcode->setDimensions(600, 90);
                                $barcode->draw();
                                $barcode_b64 = $barcode->base64();
                                $databarcode = $barcode->decbase64($barcode_b64);

                                file_put_contents(
                                    _PS_MODULE_DIR_.$this->name.'/l/bar/'.str_replace(
                                        $this->getFilenameTicketByOrder(
                                            $order->id,
                                            $product['product_id'],
                                            $product['product_attribute_id'],
                                            (int)$order->id_lang
                                        )
                                        .'-',
                                        '',
                                        $filename
                                    )
                                    .'_'.$x.'.png',
                                    $databarcode
                                );
                            } catch (Exception $e) {
                                die($e->getMessage());
                            }
                        }

                        $html_fields = array();
                        $html_cust = array();

                        if ($ticket['location'] || $ticket_lang['venue']) {
                            $html_fields['location'] = ($ticket_lang['venue'] ? $ticket_lang['venue'] : '')
                            .($ticket['location'] ? ' '.$ticket['location'] : '');
                        } else {
                            $html_fields['location'] = false;
                        }

                        if ($ticket['lat'] && $ticket['long']) {
                            $html_fields['coords'] = $ticket['lat'].' - '.$ticket['long'];
                        } else {
                            $html_fields['coords'] = false;
                        }

                        if ($ticket_lang['date']) {
                            $html_fields['date'] = $ticket_lang['date'];
                        } else {
                            $html_fields['date'] = false;
                        }

                        if ($ticket_lang['hour']) {
                            $html_fields['hour'] = $ticket_lang['hour'];
                        } else {
                            $html_fields['hour'] = false;
                        }

                        if ($ticket_lang['conditions']) {
                            $html_fields['conditions'] = $ticket_lang['conditions'];
                        } else {
                            $html_fields['conditions'] = false;
                        }

                        if ($ticket['seats']) {
                            if (count($seatcart) > 0) {
                                foreach ($seatcart as $seat) {
                                    $seats = explode(',', $seat);
                                }
                            }
                        } else {
                            $seats = false;
                        }

                        $cust_inf_all = $this->getTicketInfoCustomer(
                            (int)$order->id_cart,
                            0,
                            (int)$product['product_id'],
                            (int)$product['product_attribute_id'],
                            true
                        );

                        if ($cust_inf_all) {
                            $x = 1;
                            foreach ($cust_inf_all as $inf) {
                                $html_cust[$x]['product'] = $ticket_nom.($ticket_attributes != '' ?
                                    ' - '.$ticket_attributes : '');
                                $html_cust[$x]['ref'] = (isset($ticket_ref_aux[$x]) ? $ticket_ref_aux[$x] : '');
                                $html_cust[$x]['customer'] = ($is_nominal ?
                                    $inf['customer_name'].' '.$inf['customer_firstname'] : false
                                );
                                $html_cust[$x]['phone'] = ($is_nominal ? $inf['customer_phone'] : false);

                                if ($ticket['seats']) {
                                    $html_cust[$x]['seat'] = $this->getRealNumberSeat(
                                        (int)$ticket['id_ticket'],
                                        $seats[($x-1)]
                                    );
                                } else {
                                    $html_cust[$x]['seat'] = false;
                                }

                                $x++;
                            }
                        }

                        $GLOBALS['id_product'] = $product['product_id'];
                        $GLOBALS['id_product_attribute'] = $product['product_attribute_id'];

                        // Crearem el fitxer PDF amb l'entrada i l'adjuntem al correu que enviarem
                        include_once(_PS_MODULE_DIR_.'selltickets/classes/pdf/HTMLTemplateTicket.php');

                        $pdf = new PDF($order, 'Ticket', $this->context->smarty);
                        
                        $nomarxiu = Tools::str2url($ticket_filename);
                        $nomarxiu = (Tools::strlen($nomarxiu) >= 75 ? Tools::substr($nomarxiu, 0, 75) : $nomarxiu);

                        $file_attachement = array();

                        $file_attachement['content'] = $pdf->render(false);
                        $file_attachement['name'] = $nomarxiu.'-'.$this->getQrName(
                            $customer->id,
                            $customer->firstname,
                            $customer->lastname,
                            $order->id,
                            $product['product_id'],
                            $product['product_attribute_id']
                        ).'.pdf';
                        $file_attachement['mime'] = 'application/pdf';

                        // Resum de l'entrada al correu enviat
                        $data = array(
                            '{customer}' => $customer->firstname.' '.$customer->lastname,
                            '{ticket_customer}' => $customer->firstname.' '.$customer->lastname
                            .' ('.$customer->email.')',
                            '{order_reference}' => $order->reference,
                            '{order_id}' => $order->id,
                            '{ticket_name}' => $ticket_nom,
                            '{ticket_qty}' => $qty,
                            '{customer_info}' => $this->getTplMailTicket('mail_customers', 'customer', $html_cust),
                            '{fields_info}' => $this->getTplMailTicket('mail_fields', 'fields', $html_fields)
                        );

                        $id_lang = $order->id_lang;
                        $exists_mail_template = false;
                        $mail_iso = Language::getIsoById((int)$id_lang);

                        if (file_exists(dirname(__FILE__).'/mails/'.$mail_iso.'/'.$this->name.'-ticket.txt') &&
                            file_exists(dirname(__FILE__).'/mails/'.$mail_iso.'/'.$this->name.'-ticket.html')) {
                            $exists_mail_template = true;
                        }

                        if (!$exists_mail_template) {
                            $id_lang = Language::getIdByIso('en');
                        }

                        // Enviem el correu al client que ha adquirit l'entrada
                        Mail::Send(
                            (int)$id_lang,
                            $this->name.'-ticket',
                            $this->l('Your ticket'),
                            $data,
                            $customer->email,
                            $customer->firstname.' '.$customer->lastname,
                            null,
                            null,
                            $file_attachement,
                            null,
                            dirname(__FILE__).'/mails/'
                        );
                    } // process ticket
                } // foreach
            } else {
                $this->deleteTicketInfoCustomer((int)$order->id_cart);
            }

            return true;
        }
        return false;
    }

    public function hookActionAdminControllerSetMedia()
    {
        if (Module::isInstalled($this->name) && Module::isEnabled($this->name)) {
            if ($this->isps17) {
                if (Configuration::get($this->name.'_overrides')) {
                    if (isset($this->context->controller->controller_name)
                        && $this->context->controller->controller_name == 'AdminProducts') {
                        $this->context->controller->addJS($this->_path.'views/js/form.js');
                    }
                }
            }
        }
    }

    protected function getTplMailTicket($tpl_name, $var, $data)
    {
        $this->context->smarty->assign($var, $data);

        if (file_exists(_PS_THEME_DIR_.'modules/'.$this->name.'/views/templates/front/'.$tpl_name.'.tpl')) {
            return $this->context->smarty->fetch(_PS_THEME_DIR_.
                'modules/'.$this->name.'/views/templates/front/'.$tpl_name.'.tpl');
        }

        return $this->context->smarty->fetch(_PS_MODULE_DIR_.$this->name.'/views/templates/front/'.$tpl_name.'.tpl');
    }

    public function hookdisplayHeader($params)
    {
        if ($this->isps17) {
            $this->context->controller->addJquery();
            $this->context->controller->addCSS(
                __PS_BASE_URI__.'modules/'.$this->name.'/views/css/'.$this->name.'-17.css'
            );
            if (isset($this->context->controller->php_self)) {
                if ($this->context->controller->php_self == 'order' || 
                        ($this->context->controller->php_self == 'product' && (int)Configuration::get($this->name.'_show_map') !== 0 )) {
                    $this->context->controller->addJS($this->_path.'views/js/selltickets-17.js');
                }
            }
        } else {
            $this->context->controller->addCSS(__PS_BASE_URI__.'modules/'.$this->name.'/views/css/'.$this->name.'.css');
        }
    }

    public function hookdisplayCheckoutSummaryTop($params)
    {
        if ($this->isps17) {
            return $this->formCustomerTickets($params);
        }
    }

    public function hookdisplayShoppingCartFooter($params)
    {
        if (!$this->isps17) {
            return $this->formCustomerTickets($params);
        }
    }
    
    public function hookdisplayProductActions($params)
    {
        if ($this->isps17 && (int)Configuration::get($this->name.'_show_map') !== 0) {
            $ticket = $this->getTicketByProduct($params['product']->id_product); 
            if ($ticket) {        
                $assoc_seat = $this->getAssocSeatsByTicket($ticket['id_ticket']);
                $aux_attribute = $params['product']->id_product_attribute;
                if ($this->ignoreProductAttribute($ticket['id_ticket'])) {
                    $params['product']->id_product_attribute = 0;
                }

                $this->context->smarty->assign(array(
                    'product' => $params['product'],
                    'assoc_seat' => $assoc_seat[0]['id_ticket_seats'],
                    'aux_attribute' => $aux_attribute,
                    'total_tickets_nominal' => (int)0,
                    'total_tickets_seats' => (int)1,
                    'add_to_cart_url' => Context::getContext()->link->getAddToCartURL(
                                    $params['product']->id_product,
                                    $params['product']->id_product_attribute
                                ),
                    'ajax_token_front' => Configuration::get($this->name.'_token_ajax_fr')

                ));

                return $this->display(__FILE__, 'views/templates/hook/product-seat-17.tpl');        
            }
        }
    }       

    public function formCustomerTickets($params)
    {
        if ($this->isps17) {
            $products = $params['cart']->getProducts();
        } else {
            $products = $params['products'];
        }

        $gettickets = $this->getTickets();
        $tickets = array();
        $tickets_seats = array();
        $total_tickets_nominal = 0;
        $total_seats = 0;

        foreach ($products as $k => $prod) {
            foreach ($gettickets as $ticket) {
                if ($prod['id_product'] == $ticket['id_product']) {
                    if ((int)$prod['is_virtual'] == 1 && (int)$prod['active'] == 1) {
                        if ($ticket['nominal']) {
                            $total_tickets_nominal++;
                        }
                        
                        $aux_attribute = $prod['id_product_attribute'];
                        if ($this->ignoreProductAttribute($ticket['id_ticket'])) {
                            $prod['id_product_attribute'] = 0;
                        }

                        $tickets[$k]['id_ticket'] = $ticket['id_ticket'];
                        $tickets[$k]['nominal'] = $ticket['nominal'];
                        $tickets[$k]['name'] = $prod['name'];
                        $tickets[$k]['attributes'] = ($prod['id_product_attribute'] != 0 ?
                            ' '.$prod['attributes'] : false);
                        $tickets[$k]['num'] = $prod['quantity'];
                        $tickets[$k]['id_product'] = $prod['id_product'];
                        $tickets[$k]['id_product_attribute'] = $prod['id_product_attribute'];
                        $tickets[$k]['id_aux_product_attribute'] = $aux_attribute;
                                                
                        if ($ticket['seats']) {
                            $assoc_seats = $this->getAssocSeatsByTicket($ticket['id_ticket']);
                            if ($assoc_seats) {
                                foreach ($assoc_seats as $assoc) {
                                    $tickets[$k]['assoc_seats'][] = (int)$assoc['id_ticket_seats'];
                                }
                            } else {
                                $tickets[$k]['assoc_seats'] = array();
                            }

                            $seat_attr = $this->getSeatsByProductAttribute((int)$assoc['id_ticket_seats'], $prod['id_product_attribute']);
                            if ($seat_attr) {
                                $total_seats++;
                                $tickets_seats[$prod['id_product']][$prod['id_product_attribute']] = true;
                            } else {
                                $tickets_seats[$prod['id_product']][$prod['id_product_attribute']] = false;
                            }
                        } else {
                            $tickets_seats[$prod['id_product']][$prod['id_product_attribute']] = false;
                        }

                        $info_customer = $this->getTicketInfoCustomer(
                            (int)$this->context->cookie->id_cart,
                            0,
                            (int)$prod['id_product'],
                            (int)$prod['id_product_attribute'],
                            true
                        );

                        if ($info_customer) {
                            foreach ($info_customer as $i) {
                                $tickets[$k]['info'][$i['numticket']]['customer_name'] = $i['customer_name'];
                                $tickets[$k]['info'][$i['numticket']]['customer_firstname'] = $i['customer_firstname'];
                                $tickets[$k]['info'][$i['numticket']]['customer_phone'] = $i['customer_phone'];
                            }
                        }
                    }
                }
            }
        }

        $this->context->smarty->assign(array(
            'total_tickets_nominal' => (int)$total_tickets_nominal,
            'total_tickets_seats' => (int)$total_seats,
            'is_product_seat' => $tickets_seats,
            'tickets_customer' => $tickets,
            'ajax_token_front' => Configuration::get($this->name.'_token_ajax_fr')
        ));

        if ($this->isps17) {
            return $this->fetch('module:selltickets/views/templates/hook/shopping-cart-17.tpl');
        } else {
            return $this->display(__FILE__, 'views/templates/hook/shopping-cart.tpl');
        }
    }

    public function hookCustomerAccount($params)
    {
        if ($this->isps17) {
            return $this->display(__FILE__, 'views/templates/hook/my-account-17.tpl');
        } else {
            return $this->display(__FILE__, 'views/templates/hook/my-account.tpl');
        }
    }

    public function hookDisplayOrderDetail($params)
    {
        $order = $params['order'];
        $customer = new Customer($order->id_customer);
        $product_detail = $order->getProductsDetail();
        $ticket_info = array();

        foreach ($product_detail as $k => $prod_det) {
            $exists_real = $this->getTicketInfoNumComplete(
                (int)$order->id_cart,
                $prod_det['product_id'],
                $prod_det['product_attribute_id']
            );

            if ((int)$exists_real > 0) {
                $ticket = $this->getTicketByOrder(
                    $order->id,
                    $prod_det['product_id'],
                    $prod_det['product_attribute_id']
                );

                if ($prod_det['product_id'] == $ticket['id_product']
                    && $prod_det['product_attribute_id'] == $ticket['id_product_attribute']) {
                    $ticket_lang = $this->getTicketLangInfo((int)$ticket['id_ticket'], (int)$order->id_lang);
                    $product = new Product((int)$prod_det['product_id']);
                    $ticket_nom = ($ticket_lang['name'] ? $ticket_lang['name'] : $product->name[(int)$order->id_lang]);

                    $ticket_attributes = '';
                    if ((int)$prod_det['product_attribute_id'] != 0) {
                        $ticket_attributes = $this->getAttributesFromProduct(
                            $prod_det['product_attribute_id'],
                            $order->id_lang
                        );
                        $ticket_attributes = implode(', ', $ticket_attributes);
                    }

                    $ticket_info[$k]['filename'] = $this->getQrName(
                        $customer->id,
                        $customer->firstname,
                        $customer->lastname,
                        $order->id,
                        $prod_det['product_id'],
                        $prod_det['product_attribute_id']
                    );
                    $ticket_info[$k]['ticket_name'] = $ticket_nom.($ticket_attributes != '' ?
                        ' - '.$ticket_attributes : '');
                    $ticket_info[$k]['order_id'] = $order->id;
                    $ticket_info[$k]['id_product'] = $prod_det['product_id'];
                    $ticket_info[$k]['id_product_attribute'] = $prod_det['product_attribute_id'];
                    $ticket_info[$k]['qty'] = (int)$prod_det['product_quantity'];
                }
            }
        }

        $this->context->smarty->assign(array(
            'base' => Tools::getHttpHost(true).__PS_BASE_URI__,
            'ticket_info' => $ticket_info
        ));

        if ($this->isps17) {
            return $this->display(__FILE__, 'views/templates/hook/order-detail-17.tpl');
        } else {
            return $this->display(__FILE__, 'views/templates/hook/order-detail.tpl');
        }
    }
    
    public static function getAttributesResume($id_product, $id_lang, $attribute_value_separator = ' - ', $attribute_separator = ', ')
    {
        if (!Combination::isFeatureActive()) {
            return array();
        }

        $combinations = Db::getInstance()->executeS('SELECT pa.*, product_attribute_shop.*
                FROM `' . _DB_PREFIX_ . 'product_attribute` pa
                ' . Shop::addSqlAssociation('product_attribute', 'pa') . '
                WHERE pa.`id_product` = ' . (int) $id_product . '
                GROUP BY pa.`id_product_attribute`');

        if (!$combinations) {
            return false;
        }

        $product_attributes = array();
        foreach ($combinations as $combination) {
            $product_attributes[] = (int) $combination['id_product_attribute'];
        }

        $lang = Db::getInstance()->executeS('SELECT pac.id_product_attribute, GROUP_CONCAT(agl.`name`, \'' . pSQL($attribute_value_separator) . '\',al.`name` ORDER BY agl.`id_attribute_group` SEPARATOR \'' . pSQL($attribute_separator) . '\') as attribute_designation
                FROM `' . _DB_PREFIX_ . 'product_attribute_combination` pac
                LEFT JOIN `' . _DB_PREFIX_ . 'attribute` a ON a.`id_attribute` = pac.`id_attribute`
                LEFT JOIN `' . _DB_PREFIX_ . 'attribute_group` ag ON ag.`id_attribute_group` = a.`id_attribute_group`
                LEFT JOIN `' . _DB_PREFIX_ . 'attribute_lang` al ON (a.`id_attribute` = al.`id_attribute` AND al.`id_lang` = ' . (int) $id_lang . ')
                LEFT JOIN `' . _DB_PREFIX_ . 'attribute_group_lang` agl ON (ag.`id_attribute_group` = agl.`id_attribute_group` AND agl.`id_lang` = ' . (int) $id_lang . ')
                WHERE pac.id_product_attribute IN (' . implode(',', $product_attributes) . ')
                GROUP BY pac.id_product_attribute');

        foreach ($lang as $row) {
            foreach ($combinations as $k =>  $combination) {
            	    if((int)$row['id_product_attribute'] == (int) $combination['id_product_attribute']) {
		            $combinations[$k]['attribute_designation'] = $row['attribute_designation'];
	            }
	     }
        }

        //Get quantity of each variations
        foreach ($combinations as $key => $row) {
            $cache_key = $row['id_product'] . '_' . $row['id_product_attribute'] . '_quantity';

            if (!Cache::isStored($cache_key)) {
                $result = StockAvailable::getQuantityAvailableByProduct($row['id_product'], $row['id_product_attribute']);
                Cache::store(
                    $cache_key,
                    $result
                );
                $combinations[$key]['quantity'] = $result;
            } else {
                $combinations[$key]['quantity'] = Cache::retrieve($cache_key);
            }
        }

        return $combinations;
    }

    public function getContent()
    {
        if ($this->isps17) {
            if (!$this->isRegisteredInHook('actionAdminControllerSetMedia')) {
                $this->registerHook('actionAdminControllerSetMedia');
            }
        }

        if (!Configuration::get($this->name.'_appkey')) {
            Configuration::updateValue($this->name.'_appkey', Tools::passwdGen(10));
        }

        if (!Configuration::get($this->name.'_keygmaps')) {
            Configuration::updateValue($this->name.'_keygmaps', '');
        }

        $id_shop = Shop::getContextShopID();
        if (is_null($id_shop)) {
            $id_shop = false; // Totes les botigues
        }

        $languages = Language::getLanguages(true, $id_shop);
        $link = new Link();
        $token = Tools::getValue('token');
        $url = $this->context->link->getAdminLink('AdminModules', false).'&configure='.$this->name.'&token='.$token;
        $url_customer = $this->context->link->getAdminLink('AdminCustomers', true).'&viewcustomer';
        $url_product = $this->context->link->getAdminLink('AdminProducts', true).'&updateproduct';
        $lang = ($this->context->cookie->id_lang ?
            $this->context->cookie->id_lang : Configuration::get('PS_LANG_DEFAULT'));
        $products = Product::getProducts((int)$lang, 0, 0, 'name', 'ASC');
        $error = false;
        $result = false;
        $perms = false;
        $warning_overrides = false;
        $from_overrides = array();
        $to_overrides = array();
        $products_notavail = array();

        $this->addsHead();

        // neteja productes ja associats
        if ($products) {
            $tickets = $this->getTickets();
            foreach ($products as $product) {
                foreach ($tickets as $ticket) {
                    if ($product['id_product'] == $ticket['id_product']) {
                        $products_notavail[] = $product['id_product'];
                    }
                }
            }
        }

        if (Tools::isSubmit('submitOrderStatesTicket')) {
            $states_array = Tools::getValue('order_states');

            if (!$states_array) {
                $result = $this->l('You must select almost one state');
                $error = true;
            } else {
                Configuration::updateValue($this->name.'_order_state', implode(',', $states_array));
            }

            if (Tools::getValue('generatekey')) {
                Configuration::updateValue($this->name.'_appkey', Tools::passwdGen(10));
            }

            Configuration::updateValue($this->name.'_attr_date', Tools::getValue('attribute_date'));
            Configuration::updateValue($this->name.'_keygmaps', Tools::getValue('keygmaps'));
            Configuration::updateValue($this->name.'_show_map', Tools::getValue('show_map')); 
            Configuration::updateValue($this->name.'_limit_seat', Tools::getValue('limit_seat'));
        } elseif (Tools::isSubmit('submitTicket')) {
            $name = Tools::getValue('name');
            $date = Tools::getValue('date');
            $hour = Tools::getValue('hour');
            $id_product = (int)Tools::getValue('id_product');
            $cond = Tools::getValue('conditions');
            $venue = Tools::getValue('venue');
            $location = Tools::getValue('location');
            $lat = Tools::getValue('lat');
            $long = Tools::getValue('long');
            $nominal = Tools::getValue('nominal');
            $seat = Tools::getValue('seats');
            $seat_op = array();

            if ((int)$seat) {
                if (!Tools::getValue('selected_seatmaps')) {
                    $seat_op['rows'] = Tools::getValue('seat_row');
                    $seat_op['cols'] = Tools::getValue('seat_col');
                    $seat_op['avail'] = Tools::getValue('seat_distribution');
                    $seat_op['numbers'] = Tools::getValue('seatnum');
                    $seat_op['isassoc'] = false;
                } else {
                    $seat_op['isassoc'] = true;
                    $seat_op['assoc'] = Tools::getValue('selected_seatmaps');
                }
            }

            $edit = false;

            if (Tools::getValue('edicio')) {
                $edit = (int)Tools::getValue('edicio');
            }

            if ($this->addTicket(
                $id_product,
                $name,
                $date,
                $hour,
                $cond,
                $venue,
                $location,
                $lat,
                $long,
                $edit,
                $nominal,
                $seat,
                $seat_op
            )
            ) {
                $this->updateVirtualProduct($id_product);

                $result = $this->l('Ticket successfully updated');
                $error = false;
            } else {
                $result = $this->l('Error creating the ticket');
                $error = true;
            }
        } elseif (Tools::isSubmit('enableTicketsSelect')) {
            $tickets_array_sel = Tools::getValue('ticketBox');

            if (count($tickets_array_sel) > 0) {
                foreach ($tickets_array_sel as $id_ticket_del) {
                    $id_ticket = (int)$id_ticket_del;
                    $id_product = $this->getIdProductByTicket($id_ticket);

                    $product = new Product((int)$id_product['id_product']);
                    $product->active = 1;

                    if ($product->save()) {
                        $result = $this->l('Ticket enabled successfully');
                        $error = false;
                    } else {
                        $result = $this->l('Error enabling ticket');
                        $error = true;
                    }
                }
            } else {
                $result = $this->l('You must select almost one ticket for enable');
                $error = true;
            }
        } elseif (Tools::isSubmit('disableTicketsSelect')) {
            $tickets_array_sel = Tools::getValue('ticketBox');

            if (count($tickets_array_sel) > 0) {
                foreach ($tickets_array_sel as $id_ticket_del) {
                    $id_ticket = (int)$id_ticket_del;
                    $id_product = $this->getIdProductByTicket($id_ticket);

                    $product = new Product((int)$id_product['id_product']);
                    $product->active = 0;

                    if ($product->save()) {
                        $result = $this->l('Ticket disabled successfully');
                        $error = false;
                    } else {
                        $result = $this->l('Error disabling ticket');
                        $error = true;
                    }
                }
            } else {
                $result = $this->l('You must select almost one ticket for disable');
                $error = true;
            }
        } elseif (Tools::isSubmit('deleteTicketsSelect')) {
            $tickets_array_sel = Tools::getValue('ticketBox');

            if (count($tickets_array_sel) > 0) {
                foreach ($tickets_array_sel as $id_ticket_del) {
                    // Elimina Informació Ticket i tickets comprats relacionats
                    $id_ticket = (int)$id_ticket_del;
                    $id_product = $this->getIdProductByTicket($id_ticket);
                    $ticketorders = $this->getTicketOrdersByIdTicket($id_ticket);

                    if ($this->delTicket($id_ticket)) {
                        $this->updateVirtualProduct((int)$id_product['id_product'], 0);
                        // Converteix el producte en article normal

                        // Elimina els tickets comprats
                        foreach ($ticketorders as $ticketorder) {
                            $this->delTicketOrder($ticketorder['id_order'], $id_product['id_product']);

                            $order = new Order($ticketorder['id_order']);
                            $this->deleteTicketInfoCustomer($order->id_cart, $id_product['id_product']);

                            $customer = new Customer((int)$order->id_customer);
                            $qr = $this->getQrName(
                                $customer->id,
                                $customer->firstname,
                                $customer->lastname,
                                $ticketorder['id_order'],
                                $id_product['id_product'],
                                $ticketorder['id_product_attribute']
                            );

                            $this->deleteQrImg($qr, false);
                        }

                        $result = $this->l('Ticket deleted successfully');
                        $error = false;
                    } else {
                        $result = $this->l('Error deleting ticket');
                        $error = true;
                    }
                }
            } else {
                $result = $this->l('You must select almost one ticket for delete');
                $error = true;
            }
        } elseif (Tools::getValue('del_id_ticket')) {
            // Elimina Informació Ticket i tickets comprats relacionats
            $id_ticket = (int)Tools::getValue('del_id_ticket');
            $id_product = $this->getIdProductByTicket($id_ticket);
            $ticketorders = $this->getTicketOrdersByIdTicket($id_ticket);

            if ($this->delTicket($id_ticket)) {
                $this->updateVirtualProduct((int)$id_product['id_product'], 0);
                // Converteix el producte en article normal

                // Elimina els tickets comprats
                foreach ($ticketorders as $ticketorder) {
                    $this->delTicketOrder(
                        $ticketorder['id_order'],
                        $id_product['id_product'],
                        $ticketorder['id_product_attribute']
                    );

                    $order = new Order($ticketorder['id_order']);
                    $this->deleteTicketInfoCustomer(
                        $order->id_cart,
                        $id_product['id_product'],
                        $ticketorder['id_product_attribute']
                    );

                    $customer = new Customer((int)$order->id_customer);
                    $qr = $this->getQrName(
                        $customer->id,
                        $customer->firstname,
                        $customer->lastname,
                        $ticketorder['id_order'],
                        $id_product['id_product'],
                        $ticketorder['id_product_attribute']
                    );

                    $this->deleteQrImg($qr, false);
                }

                $result = $this->l('Ticket deleted successfully');
                $error = false;
            } else {
                $result = $this->l('Error deleting ticket');
                $error = true;
            }
        } elseif (Tools::getValue('export_tickets')) {
            // Exporta dades de Tickets comprats
            $id_ticket = (int)Tools::getValue('export_tickets');
            $this->exportTicketsOrders($id_ticket);
        } elseif (Tools::getValue('del_order')) {
            // Elimina Ticket comprat en comanda
            $infos_del_order = explode('-', Tools::getValue('del_order'));

            $id_order = $infos_del_order[0];
            $id_product = $infos_del_order[1];
            $id_product_attribute = $infos_del_order[2];

            if (Validate::isInt($id_order) && Validate::isInt($id_product) && Validate::isInt($id_product_attribute)) {
                $order = new Order((int)$id_order);
                $this->deleteTicketInfoCustomer($order->id_cart, $id_product, $id_product_attribute);

                if ($this->delTicketOrder($id_order, $id_product, $id_product_attribute)) {
                    $result = $this->l('Ticket order deleted successfully');
                    $error = false;
                } else {
                    $result = $this->l('Error deleting ticket order');
                    $error = true;
                }
            }
        } elseif (!$this->isps17 && Tools::getValue('ticket_bankwire')) {
            $ticket_bankwire = explode('_', Tools::getValue('ticket_bankwire'));

            $optionb = $ticket_bankwire[0];
            $ticketidb = $ticket_bankwire[1];
            // id ticket a canviar

            Db::getInstance()->Execute('UPDATE `'._DB_PREFIX_.$this->name.'` SET bankwire = '.(int)$optionb.'
                WHERE `id_ticket` = '.(int)$ticketidb);
        } elseif (Tools::getValue('edit')) {
            $edit = Tools::getValue('edit');
            $edit_tickets = $this->getTicket((int)$edit, false);
            $ed_seats_op = false;
            $ed_seats_numbers = false;
            $ed_seat_assoc = false;
            $ed_parent_seat = array();

            if ($edit_tickets) {
                foreach ($languages as $language) {
                    $ticket_lang = $this->getTicketLangInfo((int)$edit, $language['id_lang']);
                    $edit_tickets['name'][$language['id_lang']] = $ticket_lang['name'];
                    $edit_tickets['date'][$language['id_lang']] = $ticket_lang['date'];
                    $edit_tickets['hour'][$language['id_lang']] = $ticket_lang['hour'];
                    $edit_tickets['conditions'][$language['id_lang']] = $ticket_lang['conditions'];
                    $edit_tickets['venue'][$language['id_lang']] = $ticket_lang['venue'];
                }

                if ((int)$edit_tickets['seats']) {
                    $ed_seats_op_result = $this->getSeats((int)$edit);
                    if (count($ed_seats_op_result) > 0) {
                        $ed_seats_op = $ed_seats_op_result[0];
                        $ed_seats_numbers = $this->getNumberSeatsByTicket((int)$edit);
                        $ed_seat_assoc = $this->getAssocSeatsByTicket((int)$edit);
                    }

                    foreach ($ed_seat_assoc as $k => $assocseatmap) {
                        $infoseatmap = $this->getSeatMapIdByIdSeat($assocseatmap['id_ticket_seats'], false, 1);
                        $name_ticket_map = '';
                        $ed_parent_seat = array();
                        if ($infoseatmap) {
                            //$ticket_info = $this->getTicket((int)$infoseatmap['id_ticket'], false);
                            $ticket_lang_seat = $this->getTicketLangInfo(
                                (int)$infoseatmap['id_ticket'],
                                (int)$lang
                            );
                            $product_id_ticket = $this->getIdProductByTicket((int)$infoseatmap['id_ticket']);

                            if (isset($ticket_lang_seat['name']) && $ticket_lang_seat['name'] != '') {
                                $name_ticket_map = $ticket_lang_seat['name'];
                            } else {
                                $product_ticket = new Product((int)$product_id_ticket['id_product']);
                                $name_ticket_map = $product_ticket->name[(int)$lang];
                            }

                            $ed_seat_assoc[$k]['assocmap']['ticket_name'] = $name_ticket_map;
                            $ed_seat_assoc[$k]['assocmap']['id_ticket'] = (int)$infoseatmap['id_ticket'];
                            $ed_seat_assoc[$k]['assocmap']['id_product'] = (int)$product_id_ticket['id_product'];
                        } else {
                            $ed_seat_assoc[$k]['assocmap'] = false;
                        }
                    }
                }

                $this->context->smarty->assign(array(
                    'ed_nom' => $edit_tickets['name'],
                    'ed_date' => $edit_tickets['date'],
                    'ed_hour' => $edit_tickets['hour'],
                    'ed_id_product' => $edit_tickets['id_product'],
                    'ed_conditions' => $edit_tickets['conditions'],
                    'ed_venue' => $edit_tickets['venue'],
                    'ed_location' => $edit_tickets['location'],
                    'ed_lat' => $edit_tickets['lat'],
                    'ed_long' => $edit_tickets['long'],
                    'ed_nominal' => $edit_tickets['nominal'],
                    'ed_seats' => $edit_tickets['seats'],
                    'ed_seats_op' => $ed_seats_op,
                    'ed_seats_numbers' => $ed_seats_numbers,
                    'ed_seat_assoc' => $ed_seat_assoc,
                    'ed_parent_seat' => $ed_parent_seat,
                    'ed_id_ticket' => $edit
                ));
            } else {
                $result = $this->l('Error getting Ticket info');
                $error = true;
            }
        } elseif ($this->isps17 && Tools::getValue('overrides')
            && (int)Configuration::get($this->name.'_overrides') == 0) {
            Configuration::updateValue($this->name.'_overrides', 1);
            $result = $this->l('Now you can create virtual products with combinations of attributes.');
            $error = false;
        }

/* ########################## PAGINATION & FILTERS ########################## */

        $fields_filter = array('id_ticket', 'name');
        $filter = array();
        foreach ($fields_filter as $field) {
            $value_key = $this->name.'Filter_'.$field;
            $value = Context::getContext()->cookie->{$value_key};
            if (!$value && Tools::getIsset($value_key)) {
                $value = Tools::getValue($value_key);
                $this->context->cookie->{$value_key} = $value;
            } else {
                $this->context->cookie->{$value_key} = '';
            }

            $filter[$field] = $value;
        }

        $has_value = false;

        foreach ($filter as $val) {
            if (isset($val) && $val !== false && $val !== '') {
                if (trim($val) == '') {
                    continue;
                }

                $has_value = true;
                break;
            }
        }

        $inactive_tickets = Tools::getValue('innactive');

        $total_tickets = count($this->getTickets(true, false, false, $filter, $inactive_tickets));

        $_pagination = array(20, 50, 100, 300, 1000);
        $_default_pagination = 20;
        $pagination = $_default_pagination;

        if (in_array((int)Tools::getValue($this->name.'_pagination'), $_pagination)) {
            $pagination = (int)Tools::getValue($this->name.'_pagination');
        } elseif (isset($this->context->cookie->{$this->name.'_pagination'})
            && $this->context->cookie->{$this->name.'_pagination'}) {
            $pagination = $this->context->cookie->{$this->name.'_pagination'};
        }

        $total_pages = max(1, ceil($total_tickets / $pagination));
        $page = (int)Tools::getValue('submitFilter'.$this->name);

        if (!$page) {
            $page = 1;
        }

        if ($page > $total_pages) {
            $page = $total_pages;
        }

        $selected_pagination = Tools::getValue(
            $this->name.'_pagination',
            isset($this->context->cookie->{$this->name.'_pagination'}) ?
            $this->context->cookie->{$this->name.'_pagination'} : $_default_pagination
        );

        $this->context->cookie->{$this->name.'_pagination'} = $selected_pagination;

/* ########################## /PAGINATION & FILTERS ########################## */

        $aux_tickets = $this->getTickets(true, $page, $pagination, $filter, $inactive_tickets);        

        $tk = array();
        $status_ticket = false;
        $custm_inf = array();

        foreach ($aux_tickets as $k => $ticket) {
            $product = new Product($ticket['id_product']);

            if (($product->active == 1 && !Tools::getValue('innactive') || ($product->active == 0
                && Tools::getValue('innactive') == 1))) {
                $tk[$k] = $ticket;

                foreach ($languages as $language) {
                    $ticket_lang = $this->getTicketLangInfo((int)$ticket['id_ticket'], $language['id_lang']);
                    $tk[$k]['name'][$language['id_lang']] = $ticket_lang['name'];
                    $tk[$k]['date'][$language['id_lang']] = $ticket_lang['date'];
                    $tk[$k]['hour'][$language['id_lang']] = $ticket_lang['hour'];
                    $tk[$k]['conditions'][$language['id_lang']] = $ticket_lang['conditions'];
                    $tk[$k]['venue'][$language['id_lang']] = $ticket_lang['venue'];
                }

                $tk[$k]['product'] = $product->name[$lang];
                $tk[$k]['prod_link'] = $link->getProductLink(
                    $product,
                    null,
                    null,
                    null,
                    $lang,
                    (!$id_shop ? null : $id_shop)
                );
                $tk[$k]['ord'] = array();
                $tickets_orders = $this->getTicket($ticket['id_ticket'], true);
                $total = 0;
                //$last_id_order = 0;

                if (is_array($tickets_orders) && count($tickets_orders) > 0) {
                    foreach ($tickets_orders as $z => $ticketorder) {
                        $order = new Order((int)$ticketorder['id_order']);
                        $customer = new Customer((int)$order->id_customer);
                        $order_state = new OrderState((int)$order->current_state);
                        $product_detail = $order->getProductsDetail();
                        
                        foreach($product_detail as $key => $prod_det) {
                            if(Pack::isPack($prod_det['product_id'])) {
                                unset($product_detail[$key]);
                                $pack_products = Pack::getItems($prod_det['product_id'], Configuration::get('PS_LANG_DEFAULT', null, null, $order->id_shop));
                                foreach ($pack_products as $pack_product) {                     
                                    $product_detail[] = array(
                                        'id_order' => $order->id,
                                        'product_id' => $pack_product->id,
                                        'product_attribute_id' => $pack_product->id_pack_product_attribute,
                                        'product_quantity' => $pack_product->pack_quantity * $prod_det['product_quantity']
                                    );
                                }                    
                            }
                        }

                        // Veure si la comanda on s'ha adquirit l'entrada és correcte
                        $status_ticket = $this->getOrderStatesOk($order_state->id);
                        $qty = 0;

                        foreach ($product_detail as $prod_det) {
                            //
                            if ($prod_det['product_id'] == $ticketorder['id_product']
                                && $prod_det['product_attribute_id'] == $ticketorder['id_product_attribute']) {
                                if($this->ignoreProductAttribute($ticket['id_ticket'])) {
                                    $prod_det['product_attribute_id'] = 0;
                                }
                                $exists_real = $this->getTicketInfoNumComplete(
                                    (int)$order->id_cart,
                                    $prod_det['product_id'],
                                    $prod_det['product_attribute_id']
                                );
                                if ((int)$exists_real > 0) {
                                    $qty = $prod_det['product_quantity'];                                    
                                    $customer_info = $this->getTicketInfoCustomer(
                                        (int)$order->id_cart,
                                        0,
                                        (int)$prod_det['product_id'],
                                        (int)$prod_det['product_attribute_id'],
                                        true
                                    );
                                    $n = 1;
                                    $assoc_seats = array();
                                    $seatcart = array();
                                    $optseats = false;
                                    $seats = array();

                                    $assoc_seats_aux = $this->getAssocSeatsByTicket($ticket['id_ticket']);
                                    if ($assoc_seats_aux) {
                                        foreach ($assoc_seats_aux as $assoc) {
                                            $assoc_seats[] = (int)$assoc['id_ticket_seats'];
                                        }
                                    } else {
                                        $assoc_seats = array();
                                    }

                                    if (count($assoc_seats) > 0) {
                                        foreach ($assoc_seats as $id_ticket_seats) {
                                            $seatcart[$id_ticket_seats] = explode(
                                                ',',
                                                $this->getSeatsByOrderAndAssocSeat(
                                                    (int)$id_ticket_seats,
                                                    $order->id
                                                )
                                            );
                                        }

                                        $seats = $seatcart;
                                        $seat_attr = $this->getSeatsByProductAttribute(
                                            (int)$id_ticket_seats,
                                            (int)$prod_det['product_attribute_id']
                                        );
                                        if ($seat_attr) {
                                            $optseats = true;
                                        } else {
                                            $optseats = false;
                                            $tk[$k]['ord'][$z]['cus'][$n]['seat'] = false;
                                        }
                                    } else {
                                        $seats = array();
                                        $optseats = false;
                                        $tk[$k]['ord'][$z]['cus'][$n]['seat'] = false;
                                    }


                                    foreach ($customer_info as $c) {
                                        $tk[$k]['ord'][$z]['cus'][$n]['name'] = $c['customer_name'];
                                        $tk[$k]['ord'][$z]['cus'][$n]['firstname'] = $c['customer_firstname'];
                                        $tk[$k]['ord'][$z]['cus'][$n]['phone'] = $c['customer_phone'];
                                        $tk[$k]['ord'][$z]['cus'][$n]['validated'] = $c['validated'];
                                        $tk[$k]['ord'][$z]['cus'][$n]['numticket'] = $c['numticket'];
                                        $tk[$k]['ord'][$z]['cus'][$n]['id_customer_ticket'] = $c['id_customer_ticket'];

                                        $ref_ticket = $this->getReferenceTicket(
                                            $order->reference,
                                            $order->id,
                                            $prod_det['product_id'],
                                            $prod_det['product_attribute_id'],
                                            $n
                                        );
                                        $tk[$k]['ord'][$z]['cus'][$n]['reference_ticket'] = $ref_ticket;

                                        if ($optseats) {
                                            foreach ($seats as $id_t_seat => $seat) {
                                                $realnum = $this->getRealNumberSeat(
                                                    (int)$id_t_seat,
                                                    $seat[($n-1)]
                                                );
                                                $tk[$k]['ord'][$z]['cus'][$n]['seat'][$id_t_seat] = $realnum;
                                            }
                                        } else {
                                            $tk[$k]['ord'][$z]['cus'][$n]['seat'] = false;
                                            //$tk[$k]['ord'][$z]['cus'][$n]['nameseatmap'] = false;
                                        }

                                        $n++;
                                    }

                                   // $ticket_nom = ($ticket['name'] ? $ticket['name'] : $product->name[$lang]);
                                    $ticket_nom = ($tk[$k]['name'][$lang] ?
                                      $tk[$k]['name'][$lang] : $product->name[$lang]);

                                    $ticket_attributes = '';
                                    if ((int)$prod_det['product_attribute_id'] != 0) {
                                        $ticket_attributes = $this->getAttributesFromProduct(
                                            $prod_det['product_attribute_id'],
                                            $lang
                                        );
                                        $ticket_attributes = implode(', ', $ticket_attributes);
                                    }

                                    $tk[$k]['ord'][$z]['id_ticket_order'] = $ticketorder['id_ticket_order'];
                                    $tk[$k]['ord'][$z]['customer'] = $customer->firstname.' '.$customer->lastname;
                                    $tk[$k]['ord'][$z]['id_customer'] = $customer->id;
                                    $tk[$k]['ord'][$z]['email'] = $customer->email;
                                    $tk[$k]['ord'][$z]['id_order'] = $order->id;
                                    $tk[$k]['ord'][$z]['id_cart'] = $order->id_cart;
                                    $tk[$k]['ord'][$z]['id_product'] = $ticket['id_product'];
                                    $tk[$k]['ord'][$z]['id_product_attribute'] = $ticketorder['id_product_attribute'];
                                    $tk[$k]['ord'][$z]['name'] = $ticket_nom;
                                    $tk[$k]['ord'][$z]['attributes'] = $ticket_attributes;
                                    $tk[$k]['ord'][$z]['reference'] = $order->reference;
                                    $tk[$k]['ord'][$z]['qty'] = $qty;
                                    $tk[$k]['ord'][$z]['qr'] = $this->getQrName(
                                        $customer->id,
                                        $customer->firstname,
                                        $customer->lastname,
                                        $order->id,
                                        $ticket['id_product'],
                                        $ticketorder['id_product_attribute']
                                    );
                                    $tk[$k]['ord'][$z]['ok'] = $status_ticket;

                                    if ($status_ticket) {
                                        $total += $qty;
                                    }
                                }
                            }
                        }
                    }
                }
                
                if (method_exists($product, 'hasCombinations')) {
                    if($product->hasCombinations()) {
                        $tk[$k]['product_attributes'] = $product->getAttributesResume($lang);
                    }
                }
                else {
                    $attributes = Product::getAttributesInformationsByProduct($product->id);
                    if(!empty($attributes)) {
                        $tk[$k]['product_attributes'] = $product->getAttributesResume($lang);
                    }
                }

                $tk[$k]['total_sold'] = $total;
            }
        }

        if (Tools::substr(decoct(fileperms(_PS_MODULE_DIR_.$this->name.'/l/')), 2) != 777
            && Tools::substr(decoct(fileperms(_PS_MODULE_DIR_.$this->name.'/l/bar/')), 2) != 777) {
            $perms = $this->l('You need to change file permissions at folder');
            $perms .= ' '.$this->l('modules/selltickets/l/ and modules/selltickets/l/bar/');
        }

        if ((int)Tools::getValue('down_ticket')) {
            $this->getTicketPdfById(Tools::getValue('down_ticket'));
            exit;
        }

        $ticket_seats_map = $this->getSeats();
        if ($ticket_seats_map) {
            foreach ($ticket_seats_map as $k => $ticketseat) {
                $infoseatmap = $this->getSeatMapIdByIdSeat($ticketseat['id_ticket_seats'], false, 1);
                $name_ticket_map = '';
                if ($infoseatmap) {
                    //$ticket_info = $this->getTicket((int)$infoseatmap['id_ticket'], false);
                    $ticket_lang_seat = $this->getTicketLangInfo((int)$infoseatmap['id_ticket'], (int)$lang);
                    $product_id_ticket = $this->getIdProductByTicket((int)$infoseatmap['id_ticket']);

                    if (isset($ticket_lang_seat['name']) && $ticket_lang_seat['name'] != '') {
                        $name_ticket_map = $ticket_lang_seat['name'];
                    } else {
                        $product_ticket = new Product((int)$product_id_ticket['id_product']);
                        $name_ticket_map = $product_ticket->name[(int)$lang];
                    }
                }

                $ticket_seats_map[$k]['parent_ticket_name'] = $name_ticket_map;
                $ticket_seats_map[$k]['parent_id_ticket'] = (int)$infoseatmap['id_ticket'];
                $ticket_seats_map[$k]['parent_id_product'] = (int)$product_id_ticket['id_product'];
            }
        }

        $this->context->smarty->assign(array(
            'products' => $products,
            'products_not_available' => $products_notavail,
            'ticket_seats_map' => $ticket_seats_map,
            'tickets' => $tk,
            'customer_info' => $custm_inf,
            'result' => $result,
            'key_gmaps' => Configuration::get($this->name.'_keygmaps'),
            'limit_seat' => Configuration::get($this->name.'_limit_seat'),
            'show_map' => (int)Configuration::get($this->name.'_show_map'),
            'apikey' => Configuration::get($this->name.'_appkey'),
            'ave' => Tools::getHttpHost(true).__PS_BASE_URI__.$this->name,
            'st_error' => $error,
            'perms' => $perms,
            'overrides' => Configuration::get($this->name.'_overrides'),
            'from_overrides' => (!$this->isps17 && $warning_overrides ? $from_overrides : ''),
            'to_overrides' => (!$this->isps17 && $warning_overrides ? $to_overrides : ''),
            'warning_overrides' => (!$this->isps17 ? $warning_overrides : ''),
            'innactive' => Tools::getValue('innactive'),
            'base' => Tools::getHttpHost(true).__PS_BASE_URI__,
            'ajax_token_admin' => Configuration::get($this->name.'_token_ajax'),
            'url_base' => $url,
            'url_customer' => $url_customer,
            'url_product' => $url_product,
            'order_states' => OrderState::getOrderStates((int)$lang),
            'order_sel_states' => explode(',', Configuration::get($this->name.'_order_state')),
            'page' => $page,
            'total_pages' => $total_pages,
            'selected_pagination' => $selected_pagination,
            'pagination' => $_pagination,
            'list_total' => $total_tickets,
            'filters_has_value' => $has_value,
            'filter' => $filter,
            'linkobj' => $this->context->link,
            'selected_lang_iso' => $this->context->language->iso_code,
            'languages' => $languages,
            'lang_id' => $lang,
            'attributes' => AttributeGroup::getAttributesGroups($lang),
            'selected_attribute' => Configuration::get($this->name.'_attr_date')
        ));

        if ($this->isps17) {
            return $this->display(__FILE__, 'views/templates/admin/'.$this->name.'-17.tpl');
        } else {
            return $this->display(__FILE__, 'views/templates/admin/'.$this->name.'.tpl');
        }
    }

    public function delSeats($id_ticket)
    {
        $id_ticket_seats = Db::getInstance()->getValue('SELECT `id_ticket_seats` FROM `'._DB_PREFIX_.$this->name
            .'_seats_tickets`
            WHERE `id_ticket` = '.(int)$id_ticket.';
        ');

        if ($id_ticket_seats) {
            if (Db::getInstance()->Execute('
                DELETE FROM `'._DB_PREFIX_.$this->name.'_seats_tickets` WHERE `id_ticket` = '.(int)$id_ticket.'
                AND `id_ticket_seats`;')
            ) {
                $number_assoc_seats = Db::getInstance()->getValue('SELECT COUNT(*) FROM `'._DB_PREFIX_.$this->name
                    .'_seats_tickets`
                    WHERE `id_ticket_seats` = '.(int)$id_ticket_seats.';
                ');

                if ((int)$number_assoc_seats <= 0) {
                    if (Db::getInstance()->Execute('DELETE FROM `'._DB_PREFIX_.$this->name.'_seats`
                        WHERE `id_ticket_seats` = '.(int)$id_ticket_seats.';')) {
                        Db::getInstance()->Execute('DELETE FROM `'._DB_PREFIX_.$this->name.'_seats_num`
                            WHERE `id_ticket_seats` = '.(int)$id_ticket_seats.';');
                    }
                }
            }
        }
    }

    public function getSeatsFromOrder($id_order)
    {
        return Db::getInstance()->getRow('SELECT `id_ticket_seats`, `seat`
          FROM `'._DB_PREFIX_.$this->name.'_seats_order`
            WHERE `id_order` = '.(int)$id_order.';');
    }

    public function setAssocSeats($id_ticket, $id_ticket_seats, $parent = 0)
    {
        if (!Db::getInstance()->getRow('SELECT * FROM `'._DB_PREFIX_.$this->name.'_seats_tickets`
            WHERE `id_ticket` = '.(int)$id_ticket.' AND `id_ticket_seats` = '.(int)$id_ticket_seats.';')) {
            return Db::getInstance()->Execute('
                INSERT INTO `'._DB_PREFIX_.$this->name.'_seats_tickets` (`id_ticket`, `id_ticket_seats`, `parent`)
                VALUES ('.(int)$id_ticket.','.(int)$id_ticket_seats.', '.(int)$parent.')');
        }
    }

    public function getAssocSeatsByTicket($id_ticket)
    {
        return Db::getInstance()->ExecuteS('
            SELECT * FROM `'._DB_PREFIX_.$this->name.'_seats_tickets` WHERE `id_ticket` = '.(int)$id_ticket.';');
    }

    public function setSeats($id_ticket, $seat)
    {
        $ignore_attributes = (int)Tools::getValue('ignore_attributes');
                
        if ($seat['isassoc']) {
            $selected_seatmaps = explode(',', rtrim($seat['assoc'], ','));
            foreach ($selected_seatmaps as $seatmap) {
                if ($seatmap != '' && (int)$seatmap > 0) {
                    $this->setAssocSeats((int)$id_ticket, (int)$seatmap);
                }
            }
            return true;
        } else {
            $seatsids = explode(',', $seat['avail']);
            $collect_attribute = array();
            $str_avail = '';

            foreach ($seatsids as $seatid) {
                $seatinf = explode('_', $seatid);
                if($ignore_attributes == 0) {
                    $collect_attribute[$seatinf[1]] = $seatinf[0];  // 0 = id_product_attribute // 1 = id_seat.
                }
                else {
                    $collect_attribute[$seatinf[1]] = 0;  // 0 = id_product_attribute // 1 = id_seat.
                }
                $str_avail .= $seatinf[1].',';
            }

            $str_avail = rtrim($str_avail, ',');

            if (Db::getInstance()->Execute('
                INSERT INTO `'._DB_PREFIX_.$this->name.'_seats` (`seat_row`, `seat_col`, `seat_available`, `ignore_attributes`)
                VALUES ('.(int)$seat['rows'].','.(int)$seat['cols'].',
                    \''.pSQL($str_avail).'\', '.$ignore_attributes.')')) {
                $id_ticket_seats = Db::getInstance()->Insert_ID();
                if ($id_ticket_seats) {
                    if ($this->setAssocSeats($id_ticket, $id_ticket_seats, 1)) {
                        foreach ($seat['numbers'] as $id => $num) {
                            Db::getInstance()->Execute('
                            INSERT INTO `'._DB_PREFIX_.$this->name.'_seats_num`
                            (`id_ticket_seats`, `id_seat`, `seat_num`, `id_product_attribute`)
                            VALUES ('.(int)$id_ticket_seats.','.(int)$id.',
                              \''.pSQL($num).'\','.(int)$collect_attribute[$id].')');
                        }
                        return true;
                    } else {
                        return false;
                    }
                } else {
                    return false;
                }
            } else {
                return false;
            }
        }
    }

    public function getSeats($id_ticket = false)
    {
        if ($id_ticket) {
            $id_ticket_seats = $this->getSeatMapIdByTicket($id_ticket);
        } else {
            $id_ticket_seats = false;
        }

        return (Db::getInstance()->ExecuteS('
            SELECT * FROM `'._DB_PREFIX_.$this->name.'_seats`'.(!$id_ticket_seats ? '' : ' WHERE `id_ticket_seats` = '
                .(int)$id_ticket_seats).';')
        );
    }

    public function getSeatsByIdSeat($id)
    {
        return (Db::getInstance()->ExecuteS('
            SELECT * FROM `'._DB_PREFIX_.$this->name.'_seats` WHERE `id_ticket_seats` = '.(int)$id.';')
        );
    }

    public function getSeatsByProductAttribute($id_ticket_seats, $id_product_attribute)
    {
        return (Db::getInstance()->ExecuteS('
            SELECT * FROM `'._DB_PREFIX_.$this->name.'_seats_num`
            WHERE `id_ticket_seats`= '.(int)$id_ticket_seats.' AND `id_product_attribute` = '.(int)$id_product_attribute.';')
        );
    }

    public function getSeatMapIdByIdSeat($id, $all = false, $parent = 0)
    {
        return (Db::getInstance()->getRow('
            SELECT * FROM `'._DB_PREFIX_.$this->name.'_seats_tickets` WHERE `id_ticket_seats` = '
            .(int)$id.(!$all ? ' AND `parent` = '.(int)$parent : '').';')
        );
    }

    public function getSeatMapIdByTicket($id_ticket)
    {
        return (Db::getInstance()->getValue('
            SELECT `id_ticket_seats` FROM `'._DB_PREFIX_.$this->name.'_seats_tickets`
            WHERE `id_ticket` = '.(int)$id_ticket.';')
        );
    }

    public function getRealNumberSeat($id_ticket_seats, $id_seat)
    {
       // $id_ticket_seats = $this->getSeatMapIdByTicket($id_ticket);

        return (Db::getInstance()->getValue('
            SELECT `seat_num` FROM `'._DB_PREFIX_.$this->name.'_seats_num`
            WHERE `id_ticket_seats` = '.(int)$id_ticket_seats.' AND `id_seat` = '.(int)$id_seat.';')
        );
    }

    public function getNumberSeatsBySeatMap($id_ticket_seats)
    {
        $seats = Db::getInstance()->ExecuteS('
            SELECT `id_seat`, `seat_num` FROM `'._DB_PREFIX_.$this->name.'_seats_num`
            WHERE `id_ticket_seats` = '.(int)$id_ticket_seats.';');

        $seats_arr = array();

        foreach ($seats as $seat) {
            $seats_arr[$seat['id_seat']] = $seat['seat_num'];
        }

        return $seats_arr;
    }

    public function getNumberSeatsByTicket($id_ticket)
    {
        $id_ticket_seats = $this->getSeatMapIdByTicket($id_ticket);
        return $this->getNumberSeatsBySeatMap($id_ticket_seats);
    }

    public function getSecondsSeatCustomer($id_cart)
    {
        if (!$id_cart) {
            $id_cart = (int)$this->context->cookie->id_cart;
        }

        if ($id_cart) {
            $products_cart = $this->getProductsCart((int)$id_cart);
            $tickets = $this->getTickets();
            $seat_info = array();
            $assoc_seats = array();

            if ($tickets && count($products_cart) > 0) {
                foreach ($products_cart as $k => $prd) {
                    foreach ($tickets as $ticket) {
                        $assoc_seats = array();
                        if ($prd['id_product'] == $ticket['id_product']) {
                            if ($ticket['seats']) {
                                $assoc_seats_aux = $this->getAssocSeatsByTicket($ticket['id_ticket']);

                                if ($assoc_seats_aux) {
                                    foreach ($assoc_seats_aux as $assoc) {
                                        $assoc_seats[] = (int)$assoc['id_ticket_seats'];
                                    }
                                } else {
                                    $assoc_seats = array();
                                }

                                if ($assoc_seats) {
                                    foreach ($assoc_seats as $z => $id_ticket_seats) {
                                        $seatcart = $this->getSeatCart(
                                            $id_cart,
                                            $prd['id_product'],
                                            $prd['id_product_attribute'],
                                            $id_ticket_seats
                                        );
                                        if ($seatcart) {
                                            $seconds_passed = $this->scanOwnSeatTime(
                                                $id_cart,
                                                $prd['id_product'],
                                                $prd['id_product_attribute'],
                                                $id_ticket_seats,
                                                true
                                            );
                                            $seat_info[$k][$z]['id_product'] = $prd['id_product'];
                                            $seat_info[$k][$z]['id_product_attribute'] = $prd['id_product_attribute'];
                                            $seat_info[$k][$z]['id_ticket_seats'] = $id_ticket_seats;
                                            $seat_info[$k][$z]['seconds'] = ($seconds_passed ? $seconds_passed : 0);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                if (count($seat_info) > 0) {
                    return $seat_info;
                } else {
                    return false;
                }
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

    public function getInfoSeats($id_cart, $id_product, $id_product_attribute, $id_ticket_seats)
    {
        $ticket = $this->getTicketByProduct((int)$id_product);
        if ($ticket['seats']) {
            $this->scanAllSeatTimeOut();
           // $seats = $this->getSeats((int)$ticket['id_ticket']);
            $seats = $this->getSeatsByIdSeat((int)$id_ticket_seats);

            $assoc_seats_aux = $this->getAssocSeatsByTicket($ticket['id_ticket']);
            $assoc_seats = array();
            if ($assoc_seats_aux) {
                foreach ($assoc_seats_aux as $assoc) {
                    $assoc_seats[] = (int)$assoc['id_ticket_seats'];
                }
            }
            
            $data_seats = array();
            $seat_arr = false;

            if (count($seats) > 0) {
                $seat_arr = $seats[0];
            }

            if ($seat_arr) {
                if (!$id_cart) {
                    $id_cart = (int)$this->context->cookie->id_cart;
                }                              

                $quantity = $this->getQtyProductCart((int)$id_cart, (int)$id_product, (int)$id_product_attribute);
                $data_seats['col'] = (int)$seat_arr['seat_col'];
                $data_seats['row'] = (int)$seat_arr['seat_row'];
                $data_seats['qty'] = (int)$quantity;
                $data_seats['qty_assoc'] = count($assoc_seats);
                $data_seats['available_total'] = json_decode('['.$seat_arr['seat_available'].']', true);

                if($this->ignoreProductAttribute($ticket['id_ticket'])) {
                    $id_product_attribute = 0;
                }
                
                $seatcartselected = $this->getSeatCartSelected($id_ticket_seats);
                $seatorderselected = $this->getSeatOrders($id_ticket_seats);
                $seatsforthisattribute = $this->getSeatsByProductAttribute($id_ticket_seats, $id_product_attribute);

                $seatsselecteds_aux = '';
                $seatsattravailabl_aux = '';
                foreach ($seatorderselected as $seat_sel) {
		    if($seat_sel['seat'] && $seat_sel['seat'] != '') {
                    	$seatsselecteds_aux .= $seat_sel['seat'].',';
		    }
                }

                foreach ($seatcartselected as $seat_sel) {
		    if($seat_sel['seat'] && $seat_sel['seat'] != '') {
                        $seatsselecteds_aux .= $seat_sel['seat'].',';
		    }
                }

                foreach ($seatsforthisattribute as $seat_sel) {
                    $seatsattravailabl_aux .= $seat_sel['id_seat'].',';
                }

                $data_seats['notavailable'] = json_decode('['.trim($seatsselecteds_aux, ',').']', true);
                $data_seats['available'] = json_decode('['.trim($seatsattravailabl_aux, ',').']', true);

                $seatcart = $this->getSeatCart($id_cart, $id_product, $id_product_attribute, $id_ticket_seats);
                if ($seatcart) {
                    $seatselected = explode(',', $seatcart);
                    $seatselected = count($seatselected);
                } else {
                    $seatselected = 0;
                }

                $data_seats['select'] = json_decode('['.$seatcart.']', true);
                $data_seats['selectqty'] = ($seatselected ? $seatselected : 0);

                $data_seats['numbers'] = $this->getNumberSeatsBySeatMap((int)$id_ticket_seats);

                return $data_seats;
            } else {
                return false;
            }
        }
    }

    public function isAllSeatsSelected($seats, $id_cart, $id_product, $id_product_attribute)
    {
        $ticket = $this->getTicketByProduct((int)$id_product);
        if ($ticket['seats']) {
            if (!$id_cart) {
                $id_cart = (int)$this->context->cookie->id_cart;
            }

            /*$assoc_seats_aux = $this->getAssocSeatsByTicket($ticket['id_ticket']);
            $assoc_seats = array();
            if ($assoc_seats_aux) {
                foreach ($assoc_seats_aux as $assoc) {
                    $assoc_seats[] = (int)$assoc['id_ticket_seats'];
                }
            }*/

            $quantity = $this->getQtyProductCart((int)$id_cart, (int)$id_product, (int)$id_product_attribute);
            //$quantity = count($assoc_seats)*$quantity;

            if ($seats) {
                $seatselected = explode(',', $seats);
                $seatselected = count($seatselected);
            } else {
                $seatselected = 0;
            }

            if ($quantity == $seatselected) {
                return true;
            } else {
                return false;
            }
        }
    }

    public function getSeatsByOrderAndAssocSeat($id_ticket_seats, $id_order)
    {
        return Db::getInstance()->getValue('SELECT `seat` FROM `'._DB_PREFIX_.$this->name.'_seats_order`
            WHERE `id_ticket_seats` = '.(int)$id_ticket_seats.' AND `id_order` = '.(int)$id_order.';');
    }

    public function getSeatOrders($id_ticket_seats)
    {
        return Db::getInstance()->ExecuteS('SELECT `seat` FROM `'._DB_PREFIX_.$this->name.'_seats_order`
            WHERE `id_ticket_seats` = '.(int)$id_ticket_seats.';');
    }

    public function isSeatAvailable($seat, $id_product, $id_product_attribute, $id_ticket_seats)
    {
        $seats = explode(',', $seat);
        foreach ($seats as $numseat) {
            $viewseats = Db::getInstance()->getValue('SELECT COUNT(*) FROM `'._DB_PREFIX_.$this->name.'_seats_cart`
                WHERE `seat` IN ('.(int)$numseat.')
                AND `id_product` = '.(int)$id_product.'
                AND `id_product_attribute` = '.(int)$id_product_attribute.'
                AND `id_ticket_seats` = '.(int)$id_ticket_seats.';
            ');
            
            if ((int)$viewseats > 0) {
                return false;
            }
        }

        return true;
    }

    public function getSeatCartSelected($id_ticket_seats)
    {
        return Db::getInstance()->ExecuteS('SELECT `seat` FROM `'._DB_PREFIX_.$this->name.'_seats_cart`
            WHERE `id_ticket_seats` = '.(int)$id_ticket_seats.';');
    }

    public function getSeatCart($id_cart, $id_product, $id_product_attribute, $id_ticket_seats)
    {
        return Db::getInstance()->getValue('SELECT `seat` FROM `'._DB_PREFIX_.$this->name.'_seats_cart`
            WHERE `id_cart` = '.(int)$id_cart.'
            AND `id_product` = '.(int)$id_product.'
            AND `id_product_attribute` = '.(int)$id_product_attribute.'
            AND `id_ticket_seats` = '.(int)$id_ticket_seats.';
        ');
    }

    public function scanOwnSeatTime($id_cart, $id_product, $id_product_attribute, $id_ticket_seats, $returntime = false)
    {
        $date = Db::getInstance()->getValue('SELECT `date_upd` FROM `'._DB_PREFIX_.$this->name.'_seats_cart`
            WHERE `id_cart` = '.(int)$id_cart.'
            AND `id_product` = '.(int)$id_product.'
            AND `id_product_attribute` = '.(int)$id_product_attribute.'
            AND `id_ticket_seats` = '.(int)$id_ticket_seats.';
        ');

        if ($date) {
            $start = date_create($date);
            $end = date_create();
            $time = date_diff($start, $end);
            $limit_time = (int)Configuration::get('selltickets_limit_seat');

            if ($time->i >= ($limit_time/60)) {
                $this->delSeatsCustomer($id_cart, $id_product, $id_product_attribute, $id_ticket_seats);
            } else {
                if ($returntime) {
                    return ($limit_time - (($time->i * 60) + $time->s));
                }
            }
        }
    }

    public function scanAllSeatTimeOut()
    {
        $seatscart = Db::getInstance()->ExecuteS('SELECT * FROM `'._DB_PREFIX_.$this->name.'_seats_cart`;');
        if ($seatscart) {
            foreach ($seatscart as $seat) {
                $start = date_create($seat['date_upd']);
                $end = date_create();
                $time = date_diff($start, $end);
                $limit_time = (int)Configuration::get('selltickets_limit_seat');

                if ($time->i >= ($limit_time/60)) {
                    $this->delSeatsCustomer(
                        $seat['id_cart'],
                        $seat['id_product'],
                        $seat['id_product_attribute'],
                        $seat['id_ticket_seats']
                    );
                }
            }
        }
    }

    public function delSeatsCustomer($id_cart, $id_product, $id_product_attribute, $id_ticket_seats)
    {
        return Db::getInstance()->Execute('DELETE FROM `'._DB_PREFIX_.$this->name.'_seats_cart`
            WHERE `id_cart` = '.(int)$id_cart.'
            AND `id_product` = '.(int)$id_product.'
            AND `id_product_attribute` = '.(int)$id_product_attribute.'
            AND `id_ticket_seats` = '.(int)$id_ticket_seats.';
        ');
    }

    public function saveSeatsCustomer($seats, $id_cart, $id_product, $id_product_attribute, $id_ticket_seats)
    {
        if (!$id_cart) {
            $id_cart = $this->context->cookie->id_cart;
        }

        $info_seats = $this->getSeatCart(
            (int)$id_cart,
            (int)$id_product,
            (int)$id_product_attribute,
            (int)$id_ticket_seats
        );

        if (!$info_seats) {
            $seat_available = $this->isSeatAvailable(
                $seats,
                (int)$id_product,
                (int)$id_product_attribute,
                (int)$id_ticket_seats
            );

            if (!$seat_available) {
                return false;
            }

            return Db::getInstance()->Execute('
                INSERT INTO `'._DB_PREFIX_.$this->name.'_seats_cart`
                (`id_cart`, `id_ticket_seats`, `id_product`, `id_product_attribute`, `seat`, `date_upd`)
                VALUES (
                    '.(int)$id_cart.','.(int)$id_ticket_seats.','.(int)$id_product.',
                    '.(int)$id_product_attribute.', \''.pSQL($seats).'\', "'.date('Y-m-d H:i:s').'"
                )');
        } else {
            return Db::getInstance()->Execute('UPDATE `'._DB_PREFIX_.$this->name.'_seats_cart`
                SET `seat` = \''.pSQL($seats).'\'
                WHERE `id_product` = '.(int)$id_product.'
                AND `id_product_attribute` = '.(int)$id_product_attribute.'
                AND `id_ticket_seats` = '.(int)$id_ticket_seats.'
                AND `id_cart` = '.(int)$id_cart);
        }

        return false;
    }

    public function addTicket(
        $id_product,
        $name = array(),
        $date = array(),
        $hour = array(),
        $conditions = array(),
        $venue = array(),
        $location = null,
        $lat = null,
        $long = null,
        $edit = false,
        $nominal = 1,
        $seats = 0,
        $seat_op = array()
    ) {
        $id_shop = Shop::getContextShopID();
        if (is_null($id_shop)) {
            $id_shop = false; // Totes les botigues
        }

        $languages = Language::getLanguages(true, $id_shop);

        if ($edit) {
            if (!$id_product) {
                return false;
            } else {
                if ($conditions) {
                    $conditions = str_replace("\n", '<br>', $conditions);
                }

                if (Db::getInstance()->Execute('
                    UPDATE `'._DB_PREFIX_.$this->name.'`
                    SET `id_product` = '.(int)$id_product.',
                    `location` = \''.pSQL($location).'\',
                    `lat` = \''.pSQL($lat).'\',
                    `long` = \''.pSQL($long).'\',
                    `nominal` = \''.(int)$nominal.'\',
                    `seats` = '.(int)$seats.'
                    WHERE  `id_ticket` = '.(int)$edit.';')
                ) {
                    if ($languages) {
                        foreach ($languages as $lang) {
                            Db::getInstance()->Execute('
                              UPDATE `'._DB_PREFIX_.$this->name.'_lang`
                              SET `name` = \''.pSQL($name[$lang['id_lang']]).'\',
                              `date` = \''.pSQL($date[$lang['id_lang']]).'\',
                              `hour` = \''.pSQL($hour[$lang['id_lang']]).'\',
                              `conditions` = \''.pSQL($conditions[$lang['id_lang']]).'\',
                              `venue` = \''.pSQL($venue[$lang['id_lang']]).'\'
                              WHERE `id_ticket` = '.(int)$edit.'
                              AND `id_lang` = '.(int)$lang['id_lang'].';');
                        }
                    }
                    if (!(int)$seats) {
                        $this->delSeats($edit);
                        return true;
                    } else {
                        return true;
                    }
                } else {
                    return false;
                }
            }
        } else {
            $is_created = $this->getTicketByProduct($id_product);

            if (!is_array($is_created)) {
                if (!$id_product) {
                    return false;
                } else {
                    if (Db::getInstance()->Execute('
                        INSERT INTO `'._DB_PREFIX_.$this->name.'` (`id_product`, `location`, `lat`, 
                          `long`, `nominal`, `seats`, `date_add`)
                        VALUES (
                          '.(int)$id_product.',
                          \''.pSQL($location).'\',
                          \''.pSQL($lat).'\',
                          \''.pSQL($long).'\',
                          \''.(int)$nominal.'\',
                          '.(int)$seats.',
                          "'.date('Y-m-d H:i:s').'"
                        );')) {
                        $id_ticket_last = Db::getInstance()->Insert_ID();

                        if ($id_ticket_last) {
                            if ($languages) {
                                foreach ($languages as $lang) {
                                    if ($conditions[$lang['id_lang']]) {
                                        $conditions[$lang['id_lang']] = str_replace(
                                            "\n",
                                            '<br>',
                                            $conditions[$lang['id_lang']]
                                        );
                                    }
                                    Db::getInstance()->Execute('
                                    INSERT INTO `'._DB_PREFIX_.$this->name.'_lang` (`id_ticket`, `name`, `date`,
                                      `hour`, `conditions`, `venue`, `id_lang`)
                                    VALUES (
                                    '.(int)$id_ticket_last.',
                                    \''.pSQL($name[$lang['id_lang']]).'\',
                                    \''.pSQL($date[$lang['id_lang']]).'\',
                                    \''.pSQL($hour[$lang['id_lang']]).'\',
                                    \''.pSQL($conditions[$lang['id_lang']]).'\',
                                    \''.pSQL($venue[$lang['id_lang']]).'\',
                                    '.$lang['id_lang'].');');
                                }
                            }
                            Db::getInstance()->Execute('
                                INSERT INTO `'._DB_PREFIX_.$this->name.'_shop` (`id_ticket`, `id_shop`)
                                VALUES ('.(int)$id_ticket_last.','.(!$id_shop ? 0 : (int)$id_shop).');');

                            if ((int)$seats) {
                                if ($this->setSeats($id_ticket_last, $seat_op)) {
                                    return true;
                                } else {
                                    return false;
                                }
                            } else {
                                return true;
                            }
                        } else {
                            return false;
                        }
                    } else {
                        return false;
                    }
                }
            } else {
                return false;
            }
        }
    }

    private function delTicket($id_ticket)
    {
        if (Db::getInstance()->Execute('DELETE FROM `'._DB_PREFIX_.$this->name.'`
            WHERE `id_ticket` = '.(int)$id_ticket)) {
            Db::getInstance()->Execute('DELETE FROM `'._DB_PREFIX_.$this->name.'_lang`
                WHERE `id_ticket` = '.(int)$id_ticket);
            Db::getInstance()->Execute('DELETE FROM `'._DB_PREFIX_.$this->name.'_orders`
                WHERE `id_ticket` = '.(int)$id_ticket);
            Db::getInstance()->Execute('DELETE FROM `'._DB_PREFIX_.$this->name.'_shop`
                WHERE `id_ticket` = '.(int)$id_ticket);
            $this->delSeats((int)$id_ticket);
        } else {
            return false;
        }

        return true;
    }

    private function addTicketOrder($id_order, $id_ticket, $id_product, $id_product_attribute = 0, $seats = array())
    {
        if (!$id_order || !$id_ticket || !$id_product) {
            return false;
        } else {
            if (Db::getInstance()->Execute('
                INSERT INTO `'._DB_PREFIX_.$this->name.'_orders` (
                    `id_order`, `id_ticket`, `id_product`,
                    `id_product_attribute`, `date_add`)
                VALUES (
                    '.(int)$id_order.',
                    '.(int)$id_ticket.',
                    '.(int)$id_product.',
                    '.(int)$id_product_attribute.',
                    "'.date('Y-m-d H:i:s').'"
                );
            ')) {
                if (count($seats) > 0) {
                    foreach ($seats as $id_ticket_seats => $seat) {
                        Db::getInstance()->Execute('
                            INSERT INTO `'._DB_PREFIX_.$this->name.'_seats_order` (
                                `id_order`, `id_ticket_seats`, `seat`)
                            VALUES (
                                '.(int)$id_order.',
                                '.(int)$id_ticket_seats.',
                                \''.pSQL($seat).'\'
                            );
                        ');
                    }
                    return true;
                } else {
                    return true;
                }
            }
        }
    }

    private function delSeatsOrder($id_order)
    {        
        Db::getInstance()->Execute('DELETE FROM `'._DB_PREFIX_.$this->name.'_seats_order`
                WHERE `id_order` = '.(int)$id_order.';');
    }
    
    private function delTicketOrder($id_order, $id_product = false, $id_product_attribute = null, $del_seats_order = true)
    {
        if($del_seats_order) {
            Db::getInstance()->Execute('DELETE FROM `'._DB_PREFIX_.$this->name.'_seats_order`
                WHERE `id_order` = '.(int)$id_order.';');
        }

        return Db::getInstance()->Execute('DELETE FROM `'._DB_PREFIX_.$this->name.'_orders`
            WHERE `id_order` = '.(int)$id_order.
            ($id_product ? ' AND `id_product` = '.(int)$id_product.($id_product_attribute != null ?
                ' AND `id_product_attribute` = '.(int)$id_product_attribute : '') : ''));
    }

    public function getReferenceTicket($order_ref, $id_order, $id_product, $id_product_attribute, $num)
    {
        $num_formatted = str_pad($num, 2, 0, STR_PAD_LEFT);
        $ref_ticket = $order_ref.$id_order.$id_product.$id_product_attribute.$num_formatted;

        return $ref_ticket;
    }

    public function saveCustomerInfo(
        $numticket,
        $customer_info,
        $id_product,
        $id_product_attribute = 0,
        $id_cart = false
    ) {
        if (!$id_cart) {
            $id_cart = $this->context->cookie->id_cart;
        }

        $info_customer = $this->getTicketInfoCustomer(
            (int)$id_cart,
            $numticket,
            $id_product,
            $id_product_attribute
        );

        if (!$info_customer) {
            return Db::getInstance()->Execute('
                INSERT INTO `'._DB_PREFIX_.$this->name.'_customer_tickets`
                (`id_cart`, `id_product`, `id_product_attribute`, `numticket`,
                    `customer_name`, `customer_firstname`, `customer_phone`)
                VALUES ('.(int)$id_cart.','.(int)$id_product.', '.(int)$id_product_attribute.',
                '.(int)$numticket.',\''.pSQL($customer_info['name']).'\',\''.pSQL($customer_info['firstname']).'\'
                ,\''.pSQL($customer_info['phone']).'\')');
        } else {
            return Db::getInstance()->Execute('UPDATE `'._DB_PREFIX_.$this->name.'_customer_tickets`
                SET `customer_name` = \''.pSQL($customer_info['name']).'\',
                `customer_firstname` = \''.pSQL($customer_info['firstname']).'\',
                `customer_phone` = \''.pSQL($customer_info['phone']).'\' 
                WHERE `id_product` = '.(int)$id_product.'
                AND `id_product_attribute` = '.(int)$id_product_attribute.'
                AND `id_cart` = '.(int)$id_cart.'
                AND `numticket` = '.(int)$numticket);
        }

        return false;
    }

    public function saveCustomerInfoFromBo($customer_info)
    {
        return Db::getInstance()->Execute('UPDATE `'._DB_PREFIX_.$this->name.'_customer_tickets`
                SET `customer_name` = \''.pSQL($customer_info['name']).'\',
                `customer_firstname` = \''.pSQL($customer_info['firstname']).'\',
                `customer_phone` = \''.pSQL($customer_info['phone']).'\' 
                WHERE `id_customer_ticket` = '.pSQL($customer_info['id_customer_ticket']));
    }

    public function getCustomerTicketProductExists($customer_info, $id_product, $id_product_attribute = 0)
    {
        return Db::getInstance()->getValue('SELECT COUNT(*) FROM `'._DB_PREFIX_.$this->name.'_customer_tickets`
            WHERE `id_cart` = '.(int)$this->context->cookie->id_cart.'
            AND `id_product` = '.(int)$id_product.'
            AND `id_product_attribute` = '.(int)$id_product_attribute.'
            AND `customer_name` = \''.pSQL($customer_info['name']).'\' 
            AND `customer_firstname` = \''.pSQL($customer_info['firstname']).'\'');
    }

    public function getTicketIsNominalByIdProduct($id_product)
    {
        return Db::getInstance()->getValue('SELECT `nominal` FROM `'._DB_PREFIX_.$this->name.'`
            WHERE `id_product` = '.(int)$id_product.';');
    }

    public function getTicketInfoCustomer($id_cart, $numticket, $id_product, $id_product_attribute = 0, $all = false)
    {
        return Db::getInstance()->ExecuteS('SELECT * FROM `'._DB_PREFIX_.$this->name.'_customer_tickets`
            WHERE `id_cart` = '.(int)$id_cart.' AND `id_product` = '.(int)$id_product.'
            AND `id_product_attribute` = '.(int)$id_product_attribute
            .($all ?'' : ' AND `numticket` = '.(int)$numticket.' '));
    }

    public function getTicketInfoCustomerLite($id_cart, $id_product, $id_product_attribute = null)
    {
        return Db::getInstance()->ExecuteS('SELECT * FROM `'._DB_PREFIX_.$this->name.'_customer_tickets`
            WHERE `id_cart` = '.(int)$id_cart.' AND `id_product` = '.(int)$id_product.
            ($id_product_attribute != null ? ' AND `id_product_attribute` = '.(int)$id_product_attribute : ''));
    }

    public function deleteTicketInfoCustomer($id_cart, $id_product = false, $id_product_attribute = null, $rest = false)
    {
        return Db::getInstance()->Execute('DELETE FROM `'._DB_PREFIX_.$this->name.'_customer_tickets`
            WHERE `id_cart` = '.(int)$id_cart.($id_product ? ' AND `id_product` = '.(int)$id_product.
            ($id_product_attribute != null ? ' AND `id_product_attribute` = '.(int)$id_product_attribute : '') : '').
            (!$rest ? '' : ' AND `numticket` > '.$rest));
    }

    public function getTicketInfoNumComplete($id_cart, $id_product, $id_product_attribute = null)
    {
        return Db::getInstance()->getValue('SELECT COUNT(*) FROM `'._DB_PREFIX_.$this->name.'_customer_tickets`
            WHERE `id_cart` = '.(int)$id_cart.' AND `id_product` = '.(int)$id_product.
            ($id_product_attribute != null ? ' AND `id_product_attribute` = '.(int)$id_product_attribute : ''));
    }

    public function getTicketInfoCustomerById($id_customer_ticket)
    {
        return Db::getInstance()->getRow('SELECT * FROM `'._DB_PREFIX_.$this->name.'_customer_tickets`
            WHERE `id_customer_ticket` = '.(int)$id_customer_ticket);
    }
    
    public function getProductsCart($id_cart)
    {
        return Db::getInstance()->ExecuteS('SELECT * FROM `'._DB_PREFIX_.'cart_product`
            WHERE `id_cart` = '.(int)$id_cart);
    }
    
    public function getAllTicketsSeat($id_cart) {
        return Db::getInstance()->executeS('SELECT * FROM `'._DB_PREFIX_.$this->name.'_seats_cart`
            WHERE `id_cart` = '.(int)$id_cart);
    }
    
    public function getProductQuantity($id_cart, $idProduct, $idProductAttribute = 0, $idCustomization = 0, $idAddressDelivery = 0)
    {
        $productIsPack = Pack::isPack($idProduct);
        $defaultPackStockType = Configuration::get('PS_PACK_STOCK_TYPE');
        $packStockTypesAllowed = [
            Pack::STOCK_TYPE_PRODUCTS_ONLY,
            Pack::STOCK_TYPE_PACK_BOTH,
        ];
        $packStockTypesDefaultSupported = (int) in_array($defaultPackStockType, $packStockTypesAllowed);
        $firstUnionSql = 'SELECT cp.`quantity` as first_level_quantity, 0 as pack_quantity
          FROM `' . _DB_PREFIX_ . 'cart_product` cp';
        $secondUnionSql = 'SELECT 0 as first_level_quantity, cp.`quantity` * p.`quantity` as pack_quantity
          FROM `' . _DB_PREFIX_ . 'cart_product` cp' .
            ' JOIN `' . _DB_PREFIX_ . 'pack` p ON cp.`id_product` = p.`id_product_pack`' .
            ' JOIN `' . _DB_PREFIX_ . 'product` pr ON p.`id_product_pack` = pr.`id_product`';

        if ($idCustomization) {
            $customizationJoin = '
                LEFT JOIN `' . _DB_PREFIX_ . 'customization` c ON (
                    c.`id_product` = cp.`id_product`
                    AND c.`id_product_attribute` = cp.`id_product_attribute`
                )';
            $firstUnionSql .= $customizationJoin;
            $secondUnionSql .= $customizationJoin;
        }
        $commonWhere = '
            WHERE cp.`id_product_attribute` = ' . (int) $idProductAttribute . '
            AND cp.`id_customization` = ' . (int) $idCustomization . '
            AND cp.`id_cart` = ' . (int) $id_cart;

        if ($idCustomization) {
            $commonWhere .= ' AND c.`id_customization` = ' . (int) $idCustomization;
        }
        $firstUnionSql .= $commonWhere;
        $firstUnionSql .= ' AND cp.`id_product` = ' . (int) $idProduct;
        $secondUnionSql .= $commonWhere;
        $secondUnionSql .= ' AND p.`id_product_item` = ' . (int) $idProduct;
        $secondUnionSql .= ' AND (pr.`pack_stock_type` IN (' . implode(',', $packStockTypesAllowed) . ') OR (
            pr.`pack_stock_type` = ' . Pack::STOCK_TYPE_DEFAULT . '
            AND ' . $packStockTypesDefaultSupported . ' = 1
        ))';
        $parentSql = 'SELECT
            COALESCE(SUM(first_level_quantity) + SUM(pack_quantity), 0) as deep_quantity,
            COALESCE(SUM(first_level_quantity), 0) as quantity
          FROM (' . $firstUnionSql . ' UNION ' . $secondUnionSql . ') as q';

        return Db::getInstance()->getRow($parentSql);
    }

    public function getQtyProductCart($id_cart, $id_product, $id_product_attribute)
    {
        return Db::getInstance()->getValue('SELECT `quantity` FROM `'._DB_PREFIX_.'cart_product`
            WHERE `id_cart` = '.(int)$id_cart.'
            AND `id_product` = '.(int)$id_product.'
            AND `id_product_attribute` = '.(int)$id_product_attribute.';
        ');
    }
    
    public function ignoreProductAttribute ($id_ticket) {
        $id_ticket_seats = Db::getInstance()->getValue('SELECT `id_ticket_seats` FROM `'._DB_PREFIX_.'selltickets_seats_tickets`
            WHERE `id_ticket` = '.(int)$id_ticket);

        if(!$id_ticket_seats)
            return false;
        
        return (int)Db::getInstance()->getValue('SELECT `ignore_attributes` FROM `'._DB_PREFIX_.'selltickets_seats`
            WHERE `id_ticket_seats` = '.(int)$id_ticket);
    }

    public function getCorrectInfoCustomer($id_cart = false)
    {
        if (!$id_cart) {
            $id_cart = (int)$this->context->cookie->id_cart;
        }

        if ($id_cart) {
            $products_cart = $this->getProductsCart((int)$id_cart);
            $cart_tickets_seat = $this->getAllTicketsSeat((int)$id_cart);
            $tickets = $this->getTickets();
            $qty_ticket = 0;
            $qty_seats = 0;
            $count_tickets = 0;
            $seatsqty = 0;
            $seats = false;
            $continue_info = false;
            $products_tickets = array();
            $products_tickets_seat = array();
            
            if ($tickets && $cart_tickets_seat && count($cart_tickets_seat) > 0) {
                foreach($cart_tickets_seat as $ticket_seat) {
                    $qty = $this->getProductQuantity($ticket_seat['id_cart'], $ticket_seat['id_product'], $ticket_seat['id_product_attribute']);
                    $qty_selected = count(explode(",",$ticket_seat['seat']));
                    if((int)$qty["quantity"] == 0 || (int)$qty_selected != (int)$qty["quantity"]) {                    
                        $this->delSeatsCustomer(
                            $ticket_seat['id_cart'],
                            $ticket_seat['id_product'],
                            $ticket_seat['id_product_attribute'],
                            $ticket_seat['id_ticket_seats']
                        );
                    }
                }
            }

            if ($tickets && count($products_cart) > 0) {                
                foreach ($products_cart as $k => $product) {
                    foreach ($tickets as $ticket) {
                        if ($product['id_product'] == $ticket['id_product']) {
                            
                            $aux_product_attribute = $product['id_product_attribute'];
                            if($this->ignoreProductAttribute($ticket['id_ticket'])) {
                                $product['id_product_attribute'] = 0;
                            }
                            
                            if ($ticket['nominal']) {
                                $qty_ticket += $product['quantity'];
                                $products_tickets[$k]['id_product'] = $product['id_product'];
                                $products_tickets[$k]['id_product_attribute'] = $product['id_product_attribute'];
                                $products_tickets[$k]['qty'] = $product['quantity'];
                            }

                            if ($ticket['seats']) {
                                $seats = true;
                                $products_tickets_seat[$k]['id_product'] = $product['id_product'];
                                $products_tickets_seat[$k]['id_product_attribute'] = $product['id_product_attribute'];
                                $products_tickets_seat[$k]['qty'] = $product['quantity'];
                                $assoc_seats = $this->getAssocSeatsByTicket($ticket['id_ticket']);
                                if ($assoc_seats) {
                                    foreach ($assoc_seats as $assoc) {
                                        $products_tickets_seat[$k]['assoc_seats'][] = (int)$assoc['id_ticket_seats'];
                                    }
                                } else {
                                    $products_tickets_seat[$k]['assoc_seats'] = array();
                                }

                                $seat_attr = $this->getSeatsByProductAttribute((int)$assoc['id_ticket_seats'], $product['id_product_attribute']);
                                if ($seat_attr) {
                                    $qty_seats += $product['quantity']*count($products_tickets_seat[$k]['assoc_seats']);
                                }
                            }

                            $count_tickets++;
                        }
                    }
                }

                if ($count_tickets > 0) {
                    $result_ticketcustomer = 0;
                    $result_seats = 0;

                    foreach ($products_tickets as $info_customer) {

                        $qty_complete_prod = $this->getTicketInfoNumComplete(
                            (int)$id_cart,
                            (int)$info_customer['id_product'],
                            (int)$info_customer['id_product_attribute']
                        );
                        
                        if ((int)$qty_complete_prod > (int)$info_customer['qty']) {
                            // eliminem restes de entrades que s'han afegit i
                            // després s'han eliminat, pujada - baixada de cistella
                            $this->deleteTicketInfoCustomer(
                                (int)$id_cart,
                                (int)$info_customer['id_product'],
                                (int)$info_customer['id_product_attribute'],
                                (int)$info_customer['qty']
                            );
                            $qty_complete_prod = $this->getTicketInfoNumComplete(
                                (int)$id_cart,
                                (int)$info_customer['id_product'],
                                (int)$info_customer['id_product_attribute']
                            );
                        }

                        $result_ticketcustomer += $qty_complete_prod;
                    }

                    foreach ($products_tickets_seat as $info_seat) {
                        if($this->ignoreProductAttribute($ticket['id_ticket'])) {
                            $info_seat['id_product_attribute'] = $aux_product_attribute;
                        }
                        
                        if ($seats) {
                            foreach ($info_seat['assoc_seats'] as $assoc_seats) {
                                $seatcart = $this->getSeatCart(
                                    (int)$id_cart,
                                    (int)$info_seat['id_product'],
                                    (int)$info_seat['id_product_attribute'],
                                    (int)$assoc_seats
                                );

                                if ($seatcart) {
                                    $seatsqty = explode(',', $seatcart);
                                    $seatsqty = count($seatsqty);
                                    $result_seats += $seatsqty;
                                } else {
                                    $result_seats += 0;
                                }
                            }
                        }
                    }
                    
                    if ($seats) {
                        if ($qty_seats == $result_seats) {
                            $continue_info = true;
                        } else {
                            $continue_info = false;
                        }
                    } else {
                        $continue_info = true;
                    }

                    if ($continue_info) {
                        if ($qty_ticket == $result_ticketcustomer) {
                            return true;
                        } else {
                            return false;
                        }
                    } else {
                        return false;
                    }
                }
            } else {
                $this->deleteTicketInfoCustomer((int)$id_cart);
            }
        }
    }

    public function getOrderStatesOk($id_order_state)
    {
        $states = explode(',', Configuration::get($this->name.'_order_state'));

        if (in_array($id_order_state, $states)) {
            return true;
        } else {
            return false;
        }
    }

    public function getTicketOrdersByIdTicket($id_ticket, $id_lang = null)
    {
        return Db::getInstance()->ExecuteS('SELECT ao.*'.($id_lang == null ? '' : ', a.`name`').'
          FROM `'._DB_PREFIX_.$this->name.'_orders` ao
            '.($id_lang == null ?
              '' : 'LEFT JOIN `'._DB_PREFIX_.$this->name.'_lang` a ON (a.`id_ticket` = ao.`id_ticket`)').'
            WHERE ao.`id_ticket` = '.(int)$id_ticket.($id_lang == null ? '' : ' AND a.`id_lang` = '.(int)$id_lang));
    }

    public function getTicket($id, $orders = false)
    {
        $id_shop = Shop::getContextShopID();
        if (is_null($id_shop)) {
            $id_shop = false; // Totes les botigues
        }

        if ($orders) {
            return Db::getInstance()->ExecuteS('SELECT * FROM `'._DB_PREFIX_.$this->name.'_orders` s
                WHERE s.`id_ticket` = '.(int)$id);
        } else {
            return Db::getInstance()->getRow('SELECT * FROM `'._DB_PREFIX_.$this->name.'` s
                '.(!$id_shop ? '' : 'LEFT JOIN `'._DB_PREFIX_.$this->name.'_shop` sh
                    ON (s.`id_ticket` = sh.`id_ticket`)').'
                WHERE s.`id_ticket` = '.(int)$id.(!$id_shop ? '' : ' AND sh.`id_shop` IN (0, '.(int)$id_shop.')'));
        }
    }

    public function getTicketLangInfo($id_ticket, $id_lang)
    {
        return Db::getInstance()->getRow('SELECT `name`, `date`, `hour`, `conditions`, `venue`
          FROM `'._DB_PREFIX_.$this->name.'_lang`
            WHERE `id_ticket` = '.(int)$id_ticket.' AND `id_lang` = '.(int)$id_lang.';');
    }

    public function getTicketByOrder($id_order, $id_product, $id_product_attribute = 0)
    {
        $id_shop = Shop::getContextShopID();
        if (is_null($id_shop)) {
            $id_shop = false; // Totes les botigues
        }

        $order = new Order((int)$id_order);
        $order_state = new OrderState((int)$order->current_state);
        
        if ($this->getOrderStatesOk($order_state->id)) {
            return Db::getInstance()->getRow('SELECT a.*, ao.* FROM `'._DB_PREFIX_.$this->name.'_orders` ao
                LEFT JOIN `'._DB_PREFIX_.$this->name.'` a ON (a.`id_ticket` = ao.`id_ticket`)
                '.(!$id_shop ? '' : 'LEFT JOIN `'._DB_PREFIX_.$this->name.'_shop` sh
                    ON (a.`id_ticket` = sh.`id_ticket`)').'
                WHERE ao.`id_order` = '.(int)$id_order.' AND ao.`id_product` = '.(int)$id_product.'
                AND ao.`id_product_attribute` = '.(int)$id_product_attribute
                .(!$id_shop ? '' : ' AND sh.`id_shop` IN (0, '.(int)$id_shop.')'));
        } else {
            return false;
        }
    }

    public function getTicketsByOrder($id_order)
    {
        $id_shop = Shop::getContextShopID();
        if (is_null($id_shop)) {
            $id_shop = false; // Totes les botigues
        }

        $order = new Order((int)$id_order);
        $order_state = new OrderState((int)$order->current_state);
        
        if ($this->getOrderStatesOk($order_state->id)) {
            return Db::getInstance()->ExecuteS('SELECT a.* FROM `'._DB_PREFIX_.$this->name.'_orders` ao
                LEFT JOIN `'._DB_PREFIX_.$this->name.'` a ON (a.`id_ticket` = ao.`id_ticket`)
                '.(!$id_shop ? '' : 'LEFT JOIN `'._DB_PREFIX_.$this->name.'_shop` sh
                    ON (a.`id_ticket` = sh.`id_ticket`)').'
                WHERE ao.`id_order` = '.(int)$id_order
                .(!$id_shop ? '' : ' AND sh.`id_shop` IN (0, '.(int)$id_shop.')'));
        } else {
            return false;
        }
    }

    public function getTicketByProduct($id_product)
    {
        $id_shop = Shop::getContextShopID();
        if (is_null($id_shop)) {
            $id_shop = false; // Totes les botigues
        }

        return Db::getInstance()->getRow('SELECT s.* FROM `'._DB_PREFIX_.$this->name.'` s
            '.(!$id_shop ? '' : 'LEFT JOIN `'._DB_PREFIX_.$this->name.'_shop` sh
                ON (s.`id_ticket` = sh.`id_ticket`)').'
            WHERE s.`id_product` = '.(int)$id_product.(!$id_shop ? '' : ' AND sh.`id_shop` IN (0, '.(int)$id_shop.')'));
    }
    
    public function getTicketsByProduct($id_product)
    {
        $id_shop = Shop::getContextShopID();
        if (is_null($id_shop)) {
            $id_shop = false; // Totes les botigues
        }
        
        $sql = 'SELECT s.* FROM `'._DB_PREFIX_.$this->name.'` s';
        if ($id_shop) {
            $sql .= ' LEFT JOIN `'._DB_PREFIX_.$this->name.'_shop` sh ON (s.`id_ticket` = sh.`id_ticket`)';
        }
        
        $sql .= ' WHERE p.`active` = 1 AND id_product = '.(int)$id_product;
        if ($id_shop) {
            $sql .= ' AND sh.`id_shop` IN (0, '.(int)$id_shop.')';
        }
        
        return Db::getInstance()->ExecuteS($sql);
    }

    public function getTickets($backoffice = false, $p = false, $n = false, $filter = null, $inactive = false)
    {
        $id_shop = Shop::getContextShopID();
        if (is_null($id_shop)) {
            $id_shop = false; // Totes les botigues
        }

        $sql = 'SELECT s.* FROM `'._DB_PREFIX_.$this->name.'` s';
        if ($id_shop) {
            $sql .= ' LEFT JOIN `'._DB_PREFIX_.$this->name.'_shop` sh ON (s.`id_ticket` = sh.`id_ticket`)';
        }

        if ($backoffice) {
            $sql .= ' LEFT JOIN `'._DB_PREFIX_.'product` p ON (s.`id_product` = p.`id_product`)';

            if ($filter != null) {
                $sql_filters = '';
                $lang_filter = false;
                $i = 0;

                foreach ($filter as $key => $value) {
                    if (isset($value) && $value != '' && $value != ' ') {
                        if ($key == 'id_ticket' && Validate::isInt($value)) {
                            $sql_filters .= ($i > 0 ? ' AND ' : '').'s.`id_ticket` = '.$value;
                        }

                        if ($key == 'name' && Validate::isName($value)) {
                            $lang_filter = true;
                            /*$sql_filters .= ($i > 0 ? ' AND ' : '').'(s.`name` LIKE "%'.$value.'%"
                                OR (pl.`name` LIKE "%'.$value.'%"
                                    AND pl.`id_lang` = '.Configuration::get('PS_LANG_DEFAULT').'))';*/
                            $sql_filters .= ($i > 0 ? ' AND ' : '').'(pl.`name` LIKE "%'.$value.'%"
                                    AND pl.`id_lang` = '.Configuration::get('PS_LANG_DEFAULT').')';
                        }

                        $i++;
                    }
                }                
                
                if ($i > 0) {
                    if ($lang_filter) {
                        $sql .= ' LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON (s.`id_product` = pl.`id_product`)';
                    }
                    
                    $sql .= ' WHERE '.$sql_filters.($inactive ? ' AND p.`active` = 0' : ' AND p.`active` = 1');
                    if ($id_shop) {
                        $sql .= ' AND sh.`id_shop` IN (0, '.(int)$id_shop.')';
                    }
                } else {
                    $sql .= ($inactive ? ' WHERE p.`active` = 0' : ' WHERE p.`active` = 1');
                    if ($id_shop) {
                        $sql .= ' AND sh.`id_shop` IN (0, '.(int)$id_shop.')';
                    }
                }
            } else {
                $sql .= ($inactive ? ' WHERE p.`active` = 0' : ' WHERE p.`active` = 1');
                if ($id_shop) {
                    $sql .= ' AND sh.`id_shop` IN (0, '.(int)$id_shop.')';
                }
            }

            $sql .= ' ORDER BY s.`id_ticket` DESC ';
            $sql .= ($p ? ' LIMIT '.(((int)$p - 1) * (int)$n).','.(int)$n : '');
        }        

        return Db::getInstance()->ExecuteS($sql);
    }

    public function getIdProductByTicket($id_ticket)
    {
        $id_shop = Shop::getContextShopID();
        if (is_null($id_shop)) {
            $id_shop = false; // Totes les botigues
        }

        return Db::getInstance()->getRow('SELECT s.`id_product` FROM `'._DB_PREFIX_.$this->name.'` s
            '.(!$id_shop ? '' : 'LEFT JOIN `'._DB_PREFIX_.$this->name.'_shop` sh
                ON (s.`id_ticket` = sh.`id_ticket`)').'
            WHERE s.`id_ticket` = '.(int)$id_ticket.(!$id_shop ? '' : ' AND sh.`id_shop` IN (0, '.(int)$id_shop.')'));
    }

    public function getFilenameTicketByOrder($id_order, $id_product, $id_product_attribute, $id_lang)
    {
        $ticket = $this->getTicketByOrder((int)$id_order, (int)$id_product, (int)$id_product_attribute);

        if (isset($ticket['name']) && $ticket['name'] != '') {
            $name_ticket = $ticket['name'];
        } else {
            $product = new Product((int)$id_product);
            $name_ticket = $product->name[(int)$id_lang];
        }

        $filename = Tools::str2url($name_ticket);
        $filename = (Tools::strlen($filename) >= 75 ? Tools::substr($filename, 0, 75) : $filename);

        return $filename;
    }

    public function getQrName($id_customer, $name, $lastname, $id_order, $id_product, $id_product_attribute)
    {
        return md5($id_customer.$name.$lastname.$id_order.$id_product.$id_product_attribute);
    }

    private function deleteQrImg($filename = null, $all = false)
    {
        if ($all) {
            $path = dirname(__FILE__).'/l/*.png';
            $qr_imgs = glob($path);

            if (is_array($qr_imgs)) {
                foreach (@$qr_imgs as $qr) {
                    @unlink($qr);
                }
            }

            $pathbar = dirname(__FILE__).'/l/bar/*.png';
            $bar_imgs = glob($pathbar);

            if (is_array($bar_imgs)) {
                foreach (@$bar_imgs as $barimg) {
                    @unlink($barimg);
                }
            }
        } else {
            $qr_img = dirname(__FILE__).'/l/'.$filename.'.png';
            $bar_img = dirname(__FILE__).'/l/bar/'.$filename.'.png';

            @unlink($qr_img);
            @unlink($bar_img);
        }

        return true;
    }

    public function getFieldsCsv()
    {
        return array(
            $this->l('REF. TICKET'),
            $this->l('PRODUCT NAME'),
            $this->l('SEAT'),
            $this->l('ID ORDER'),
            $this->l('QUANTITY'),
            $this->l('CUSTOMER'),
            $this->l('PHONE'),
            $this->l('PURCHASED BY'),
            $this->l('E-MAIL')
        );
    }

    public function getAttributesFromProduct($id_product_attribute, $id_lang)
    {
        $result = Db::getInstance()->ExecuteS('
            SELECT CONCAT( agl.`name` , \': \', al.`name` ) AS `attributes`
                FROM `'._DB_PREFIX_.'product_attribute_combination` pac
                JOIN `'._DB_PREFIX_.'attribute` a ON (pac.`id_attribute` = a.`id_attribute`)
                JOIN `'._DB_PREFIX_.'attribute_group_lang` agl ON (a.`id_attribute_group` = agl.`id_attribute_group`
                    AND agl.`id_lang` = '.(int)$id_lang.')
                JOIN `'._DB_PREFIX_.'attribute_lang` al ON (pac.`id_attribute` = al.`id_attribute`
                    AND al.`id_lang` = '.(int)$id_lang.')
            WHERE pac.`id_product_attribute` = '.(int)$id_product_attribute);
        
        $attributes = array();

        if ($result) {
            foreach ($result as $attr) {
                $attributes[] = $attr['attributes'];
            }
        }

        return $attributes;
    }

    public function updateVirtualProduct($id_product, $bool = 1)
    {
        Db::getInstance()->update('product', array(
            'is_virtual' => (int)$bool,
        ), 'id_product = '.(int)$id_product);
    }

    public function addsHead()
    {
        $this->context->controller->addJquery();
        $this->context->controller->addJqueryUI('ui.selectable');
        if ($this->isps17) {
            $this->context->controller->addCSS(
                __PS_BASE_URI__.'modules/'.$this->name.'/views/css/'.$this->name.'-17.css'
            );
        } else {
            $this->context->controller->addCSS(__PS_BASE_URI__.'modules/'.$this->name.'/views/css/'.$this->name.'.css');
        }

        $this->context->controller->addJS($this->_path.'views/js/selltickets-admin.js');
    }

    public function getMsgAjax($num)
    {
        if ($num == 0) {
            $msg = $this->l('Data saved successfully');
        } elseif ($num == 1) {
            $msg = $this->l('Error: Cannot save data');
        } elseif ($num == 2) {
            $msg = $this->l('Error: Check data from ticket are correct');
        } elseif ($num == 3) {
            $msg = $this->l('has already a ticket for this product');
        } elseif ($num == 4) {
            $msg = $this->l('Your seats have been reserved. You have 5min for finish your purchase.');
        } elseif ($num == 5) {
            $msg = $this->l('Cannot reserve your seats. Maybe someone have been more faster!');
        } elseif ($num == 6) {
            $msg = $this->l('You must select your seats before saving');
        } else {
            $msg = $this->l('Unexpected error');
        }

        return $msg;
    }

    public function getTicketPdfById($infos)
    {
        $info = explode('-', $infos);
        $id_order = $info[0];
        $id_product = $info[1];
        $id_product_attribute = $info[2];

        if (Validate::isInt($id_order) && Validate::isInt($id_product) && Validate::isInt($id_product_attribute)) {
            $order = new Order($id_order);
            $customer = new Customer($order->id_customer);

            $filename = $this->getQrName(
                $customer->id,
                $customer->firstname,
                $customer->lastname,
                $order->id,
                $id_product,
                $id_product_attribute
            );
            $ticketorder_exists = $this->getTicketByOrder($id_order, $id_product, $id_product_attribute);
            
            if ($filename && (int)$order->id_customer == (int)$customer->id
                && (is_array($ticketorder_exists) && count($ticketorder_exists) != 0)) {
                $GLOBALS['id_product'] = $id_product;
                $GLOBALS['id_product_attribute'] = $id_product_attribute;

                include_once(_PS_MODULE_DIR_.'selltickets/classes/pdf/HTMLTemplateTicket.php');

                $pdf = new PDF($order, 'Ticket', Context::getContext()->smarty);
                $pdf->render(true);
            }
        }
    }

    public function validateTicketFromBo($id_customer_ticket)
    {
        $ticket_info_customer = $this->getTicketInfoCustomerById($id_customer_ticket);
        $info_result = 0;

        if ((int)$ticket_info_customer['validated'] == 0) {
            if ($this->setValidationTicket($id_customer_ticket, true, 1)) {
                $info_result = 1;
            }
        } else {
            if ($this->setValidationTicket($id_customer_ticket, true, 0)) {
                $info_result = 0;
            }
        }

        return $info_result;
    }

    public function setValidationTicket($id, $backoffice = false, $validation = 1)
    {
        return Db::getInstance()->Execute('UPDATE `'._DB_PREFIX_.$this->name.'_customer_tickets`
            SET validated = '.($backoffice ? $validation : '1').', `date_validated` = "'.date('Y-m-d H:i:s').'" WHERE `id_customer_ticket` = '.(int)$id);
    }

    public function validateTicket($scanned)
    {
        $result = array();
        $result['info']['ticket_event'] = '-';
        $result['info']['ticket_customer'] = '-';
        $result['info']['ticket_dni'] = '-';
        $result['info']['ticket_email'] = '-';
        $result['info']['ticket_reference'] = '-';
        $result['status'] = 'ko';

        if (Validate::isCleanHtml($scanned)) {
            $order_reference = preg_replace('/[^A-Z]/', '', $scanned);
            //$order_reference = substr($scanned, 0, 6);
            $order_info = Order::getByReference($order_reference);

            $order = $order_info[0];
            $id_order = $order->id;
            $id_customer = $order->id_customer;
            $id_cart = $order->id_cart;

            $order_state = new OrderState((int)$order->current_state);
            $status_ticket = $this->getOrderStatesOk($order_state->id);

            if ($order->id && $status_ticket) {
                $products_order = $order->getProductsDetail();
                $tickets_created = $this->getTickets();
                $info_prod = array();
                
                foreach($products_order as $key => $product) {
                    if(Pack::isPack($product['product_id'])) {
                        unset($products_order[$key]);
                        $pack_products = Pack::getItems($product['product_id'], Configuration::get('PS_LANG_DEFAULT', null, null, $this->order->id_shop));
                        foreach ($pack_products as $pack_product) {                     
                            $products_order[] = array(
                                'id_order' => $this->order->id,
                                'product_id' => $pack_product->id,
                                'product_attribute_id' => $pack_product->id_pack_product_attribute,
                                'product_quantity' => $pack_product->pack_quantity * $product['product_quantity'],
                                'unit_price_tax_incl' => $pack_product->getPrice()
                            );
                        }                    
                    }
                }

                if ($tickets_created) {
                    foreach ($products_order as $product) {
                        foreach ($tickets_created as $k => $ticket) {
                            if ($product['product_id'] == $ticket['id_product']) {
                                $info_prod[$k]['id_product'] = $product['product_id'];
                                $info_prod[$k]['id_product_attribute'] = $product['product_attribute_id'];

                                $product_aux = new Product((int)$product['product_id']);
                                $ticket_nom = ($ticket['name'] ?
                                    $ticket['name'] : $product_aux->name[(int)$order->id_lang]);

                                $ticket_attributes = '';
                                if ((int)$product['product_attribute_id'] != 0) {
                                    $ticket_attributes = $this->getAttributesFromProduct(
                                        $product['product_attribute_id'],
                                        $order->id_lang
                                    );
                                    $ticket_attributes = implode(', ', $ticket_attributes);
                                }

                                $info_prod[$k]['product_name'] = $ticket_nom
                                .($ticket_attributes != '' ? ' - '.$ticket_attributes : '');
                            }
                        }

                        if (count($info_prod) > 0) {
                            foreach ($info_prod as $inf) {
                                /*$ticket = $this->getTicketByOrder(
                                    (int)$id_order,
                                    (int)$inf['id_product'],
                                    (int)$inf['id_product_attribute']
                                );*/
                                //$ticket = $ticket_info;

                                $ticket_customers = $this->getTicketInfoCustomerLite(
                                    (int)$id_cart,
                                    (int)$inf['id_product'],
                                    (int)$inf['id_product_attribute']
                                );

                                foreach ($ticket_customers as $ticket_customer) {
                                    $num_ticket = str_pad($ticket_customer['numticket'], 2, 0, STR_PAD_LEFT);
                                    $aux_reference = $order->reference.$id_order.$inf['id_product']
                                    .$inf['id_product_attribute'].$num_ticket;

                                    if ($aux_reference == $scanned) {
                                        $customer = new Customer($id_customer);
                                        $result['info']['ticket_event'] = $inf['product_name'];
                                        $result['info']['ticket_customer'] = $ticket_customer['customer_name']
                                        .' '.$ticket_customer['customer_firstname'];
                                        $result['info']['ticket_dni'] = ($ticket_customer['customer_phone'] ?
                                            $ticket_customer['customer_phone'] : '');
                                        $result['info']['ticket_email'] = $customer->email;
                                        $result['info']['ticket_reference'] = $scanned;

                                        if ($ticket_customer['validated'] == 1) {    // JA ESTAVA VALIDAT
                                            $result['status'] = 'ko';
                                        } else {
                                            if ($this->setValidationTicket($ticket_customer['id_customer_ticket'])) {
                                                $result['status'] = 'ok';
                                            } else {
                                                $result['status'] = 'ko';
                                            }
                                        }

                                        return $result;
                                    }
                                    //}
                                }
                            }

                            $result['status'] == 'ko';
                        } else {
                            $result['status'] == 'ko';
                        }
                    }

                    $result['status'] == 'ko';
                } else {
                    $result['status'] == 'ko';
                }
            } else {
                $result['status'] == 'ko';
            }
        } else {
            $result['status'] == 'ko';
        }

        return $result;
    }
}

xxxxx1.0, XXX xxxx