Claude este módulo de PrestaShop de afiliados genera códigos de descuentos para los embajadores y resulta que el cupón que genera para ellos mismos para que sus siguidores lo puedan utilizar solo una vez, resulta que ellos los embajadores tambien lo pueden utilizar cuando ellos no tendria que poder utilizar sino nuevos clientes <?php
/**
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade PrestaShop to newer
 * versions in the future.If you wish to customize PrestaShop for your
 * needs please refer to http://www.prestashop.com for more information.
 * We offer the best and most useful modules PrestaShop and modifications for your online store.
 *
 * @author    knowband.com <<PRESIDIO_ANONYMIZED_EMAIL_ADDRESS>>
 * @copyright 2018 knowband
 * @license   see file: LICENSE.txt
 * @category  PrestaShop Module
 */

//changes by vishal
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\BirthdayType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\Email;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\Type;
use PrestaShop\PrestaShop\Adapter\Category\CategoryDataProvider;
use PrestaShop\PrestaShop\Core\Domain\Customer\ValueObject\FirstName;
use PrestaShop\PrestaShop\Core\Domain\Customer\ValueObject\LastName;
use PrestaShop\PrestaShop\Core\Domain\Customer\ValueObject\Password;
use PrestaShopBundle\Form\Admin\Type\Material\MaterialChoiceTableType;
use PrestaShopBundle\Form\Admin\Type\SwitchType;
use PrestaShopBundle\Form\Admin\Type\CategoryChoiceTreeType;
use PrestaShopBundle\Form\Admin\Type\ChoiceCategoriesTreeType;
use PrestaShopBundle\Translation\TranslatorAwareTrait;
use PrestaShop\PrestaShop\Adapter\Order\OrderPresenter;

//changes end

if (!defined('_PS_VERSION_')) {
    exit;
}
require_once(_PS_MODULE_DIR_ . 'kbaffiliates/classes/KbAffiliateCustomers.php');
require_once(_PS_MODULE_DIR_ . 'kbaffiliates/classes/KbReferrals.php');
require_once(_PS_MODULE_DIR_ . 'kbaffiliates/classes/KbCommission.php');
require_once(_PS_MODULE_DIR_ . 'kbaffiliates/classes/KbVouchers.php');
require_once(_PS_MODULE_DIR_ . 'kbaffiliates/classes/KbRedeemedCommission.php');

class KbAffiliates extends Module
{

    const PARENT_TAB_CLASS = 'AdminKbAffiliates';
    const SELL_CLASS_NAME = 'SELL';

    public function __construct()
    {
        $this->name = 'kbaffiliates';
        $this->tabClassName = "KbAffiliates";
        $this->tab = 'front_office_features';
        $this->version = '1.1.0';
        $this->author = 'Knowband';
        $this->need_instance = 0;
        $this->module_key = '58dfc1a0a5d4d2976c9884d0dabb4030';
        $this->author_address = '0x2C366b113bd378672D4Ee91B75dC727E857A54A6';
        $this->ps_versions_compliancy = array(
            'min' => '1.7',
            'max' => _PS_VERSION_);
        $this->bootstrap = true;

        parent::__construct();

        $this->displayName = $this->l('Knowband Affiliates System');
        $this->description = $this->l('Increases the traffic and sales of the store with the help of registered customers');

        $this->confirmUninstall = $this->l('Are you sure you want to uninstall?');
    }
     /*
     * Install module
     */

    public function install()
    {

        if (Shop::isFeatureActive()) {
            Shop::setContext(Shop::CONTEXT_ALL);
        }
        if (!parent::install()
            || !$this->registerHook('displayBackOfficeHeader')
            || !$this->registerHook('displayAdminCustomersForm')
            || !$this->registerHook('displayHeader')
            || !$this->registerHook('actionCustomerAccountAdd')
            || !$this->registerHook('displayCustomerAccount')
            || !$this->registerHook('displayOrderConfirmation')
            || !$this->registerHook('displayMyAccountBlock')
            || !$this->registerHook('displayCustomerAccountForm')
            || !$this->registerHook('actionExportGDPRData')
            || !$this->registerHook('actionDeleteGDPRCustomer')
            ) {
            return false;
        }
        
        //changes by vishal
        if (version_compare(_PS_VERSION_, '1.7.6.0', '>=')) {
            if (!$this->registerHook('actionAfterCreateCustomerFormHandler')
                || !$this->registerHook('actionAfterUpdateCustomerFormHandler')
                || !$this->registerHook('actionCustomerFormBuilderModifier')
                ) {
                return false;
            }
        }
        //change end
        /** Start: Changes done by tarun gupta on 4th june 2019
         * to add columns in table affiliate customer for multiple commission feature**/
        //Create SQL Tables

        /**
         * Start Changes to fix the issue of adding tables in DB in single query.
         * Using multiple queries instead of single query.
         * NAAug2023 Query
         * @date 28-08-2023
         * @modifier Nikhil Aggarwal
         */
        $createTableSQL = "CREATE TABLE IF NOT EXISTS `" . _DB_PREFIX_ . "affiliate_customers` (
                            `id_affiliate_customer` int(11) NOT null AUTO_INCREMENT,
                            `id_customer` int(11) NOT null,
                            `status` int(1) NOT null,
                            `referral_code` varchar(11) NOT null,
                            `referral_rate` float NOT null,
                            `referral_rate_user_registration` float NOT null,
                            `id_cart_rules` text,
                            `total_commission_earned` float NOT null DEFAULT '0',
                            `total_commission_redeemed` float NOT null DEFAULT '0',
                            `hits_count` int(11) NOT null DEFAULT '0',
                            `use_global_rate` int(1) NOT null DEFAULT '1',
                            `use_global_voucher` int(1) NOT null DEFAULT '1',
                            `date_from` Date DEFAULT null,
                            `date_until` Date DEFAULT null,
                            `enable_disable_multiple_commission` int(1) NOT null,
                            `use_global_orders_count` int(1) NOT null DEFAULT '1',
                            `disable_commission_after` int(1) NOT null DEFAULT '0',
                            PRIMARY KEY (`id_affiliate_customer`)
                          ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;";
                          if (!Db::getInstance()->execute($createTableSQL)) {
                                $this->custom_errors[] = $this->l('Error while installing database.');
                                return false;
                          }
                
        $createTableSQL = "CREATE TABLE IF NOT EXISTS `" . _DB_PREFIX_ . "affiliate_commission`( `id_affiliate_commission` int(11) NOT null AUTO_INCREMENT, `id_affiliate_referrals` int(11) NOT null, `id_affiliate_customer` int(11) NOT null, `commission_value` float NOT null,
                        `currency_id` int(2) NOT null,
                        `order_placed` TEXT NOT null,
                        `user_registered` int(11) NOT null,
                        `date_added` Date DEFAULT null,
                        PRIMARY KEY (`id_affiliate_commission`)
                        ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;";
        if (!Db::getInstance()->execute($createTableSQL)) {
                                $this->custom_errors[] = $this->l('Error while installing database.');
                                return false;
                          }
        $createTableSQL = "CREATE TABLE IF NOT EXISTS `" . _DB_PREFIX_ . "affiliate_referrals` (
                        `id_affiliate_referrals` int(11) NOT null AUTO_INCREMENT,
                        `referred_by` int(11) NOT null,
                        `id_customer` int(11) NOT null,
                        `referral_type` text NOT null,
                        `status` text NOT null,
                        `date_added` Date DEFAULT null,
                        PRIMARY KEY (`id_affiliate_referrals`)
                        ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;";
        if (!Db::getInstance()->execute($createTableSQL)) {
            $this->custom_errors[] = $this->l('Error while installing database.');
            return false;
        }
                          
        $createTableSQL = "CREATE TABLE IF NOT EXISTS `" . _DB_PREFIX_ . "voucher_configuration` (
                        `id_affiliate_voucher_configuration` int(11) NOT null AUTO_INCREMENT,
                        `id_affiliate_voucher_customer` int(11) NOT null,
                        `voucher_type` varchar(10) NOT null,
                        `voucher_value` varchar(11) NOT null,
                        `voucher_quantity` int(11) NOT null,
                        `voucher_quantity_per_user` int(11) NOT null,
                        PRIMARY KEY (`id_affiliate_voucher_configuration`)
                        ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;";
        if (!Db::getInstance()->execute($createTableSQL)) {
            $this->custom_errors[] = $this->l('Error while installing database.');
            return false;
        }
        $createTableSQL = "CREATE TABLE IF NOT EXISTS `" . _DB_PREFIX_ . "affiliate_payout_requests` (
                        `id_affiliate_payout_request` int(11) NOT null AUTO_INCREMENT,
                        `id_affiliate_customer` int(11) NOT null,
                        `payout_value` float NOT null,
                        `currency` int(2) NOT null,
                        `status` int(1) NOT null,
                        `date_requested` Date DEFAULT null,
                        PRIMARY KEY (`id_affiliate_payout_request`)
                        ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;";
        if (!Db::getInstance()->execute($createTableSQL)) {
            $this->custom_errors[] = $this->l('Error while installing database.');
            return false;
        }
        $createTableSQL = "CREATE TABLE IF NOT EXISTS `" . _DB_PREFIX_ . "affiliate_redeemed_commission` (
                        `id_affiliate_redeemed_commission` int(11) NOT null AUTO_INCREMENT,
                        `id_affiliate_customer` int(11) NOT null,
                        `redeemed_type` varchar(10) NOT null,
                        `val` float NOT null,
                        `currency` int(2) DEFAULT null,
                        `date_added` Date DEFAULT null,
                        PRIMARY KEY (`id_affiliate_redeemed_commission`)
                        ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;";
        if (!Db::getInstance()->execute($createTableSQL)) {
            $this->custom_errors[] = $this->l('Error while installing database.');
            return false;
        }
        $createTableSQL = "CREATE TABLE IF NOT EXISTS `" . _DB_PREFIX_ . "affiliate_vouchers` (
                        `id_affiliate_voucher` int(11) NOT null AUTO_INCREMENT,
                        `id_affiliate_customer` int(11) NOT null,
                        `code` varchar(10) NOT null,
                        `type` varchar(10) NOT null,
                        `value` int(11) NOT null,
                        `currency` varchar(10) NOT null,
                        `date_expiry` Date NOT null,
                        PRIMARY KEY (`id_affiliate_voucher`)
                        ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;";
        if (!Db::getInstance()->execute($createTableSQL)) {
            $this->custom_errors[] = $this->l('Error while installing database.');
            return false;
        }
        $createTableSQL = "CREATE TABLE IF NOT EXISTS `" . _DB_PREFIX_ . "kb_affiliate_email_content` (
                        `id_template` int(10) NOT NULL auto_increment,
                        `id_lang` int(10) NOT NULL,
                        `id_shop` int(11) NOT NULL DEFAULT '0',                        
                        `template_name` varchar(255) NOT NULL,
                        `text_content` text NOT NULL,
                        `body` text NOT NULL,
                        `date_added` DATETIME NULL,
                        `date_updated` DATETIME NULL,
                        PRIMARY KEY (`id_template`),
                        INDEX (`id_lang`)
                        ) ENGINE = InnoDB";
        if (!Db::getInstance()->execute($createTableSQL)) {
            $this->custom_errors[] = $this->l('Error while installing database.');
            return false;
        }
        // Changes end by Nikhil
        /** End: Changes done by tarun gupta on 4th june 2019
         * to add columns in table affiliate customer for multiple commission feature**/
        
        if (!Db::getInstance()->execute($createTableSQL)) {
            $this->custom_errors[] = $this->l('Error while installing database.');
            return false;
        }
        /** Start: Changes done by tarun gupta on 4th june 2019
         * to add columns in table affiliate customer for multiple commission feature**/
        
        $select_datatype = 'SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA="'._DB_NAME_.'" AND TABLE_NAME="'._DB_PREFIX_.'affiliate_customers" AND column_name="enable_disable_multiple_commission"';
        $data_type = Db::getInstance()->getValue($select_datatype);
        if (empty($data_type)) {
            Db::getInstance()->execute('ALTER TABLE '._DB_PREFIX_.'affiliate_customers ADD COLUMN `enable_disable_multiple_commission` INT(1) NOT NULL DEFAULT "0" AFTER `date_until`');
            Db::getInstance()->execute('ALTER TABLE '._DB_PREFIX_.'affiliate_customers ADD COLUMN `use_global_orders_count` INT(1) NOT NULL DEFAULT "1" AFTER `enable_disable_multiple_commission`');
            Db::getInstance()->execute('ALTER TABLE '._DB_PREFIX_.'affiliate_customers ADD COLUMN `disable_commission_after` INT(1) NOT NULL DEFAULT "0" AFTER `use_global_orders_count`');
        }
        /** End: Changes done by tarun gupta on 4th june 2019
         * to add columns in table affiliate customer for multiple commission feature**/
        $referral_template = $this->getDefaultEmail();
        $this->insertEmailDefaultData($referral_template);
        
        $this->installKbTabs();

        return true;
    }
    /*
     * Uninstall Module
     */
    
    public function uninstall()
    {
        $query = "DROP TABLE IF EXISTS " . _DB_PREFIX_ . "kb_affiliate_email_content";
//        $results1 = Db::getInstance()->execute($sql);
        $results2 = Db::getInstance()->execute($query);
        if (!parent::uninstall()
            || !$this->unregisterHook('displayBackOfficeHeader')
            || !$this->unregisterHook('displayAdminCustomersForm')
            || !$this->unregisterHook('displayHeader')
            || !$this->unregisterHook('actionCustomerAccountAdd')
            || !$this->unregisterHook('displayCustomerAccount')
            || !$this->unregisterHook('displayOrderConfirmation')
            || !$this->unregisterHook('displayMyAccountBlock')
            || !$this->unregisterHook('displayCustomerAccountForm')
            || !$this->unregisterHook('actionExportGDPRData')
            || !$this->unregisterHook('actionDeleteGDPRCustomer')
        ) {
            return false;
        }
        //change by vishal
        if (version_compare(_PS_VERSION_, '1.7.6.0', '>=')) {
            if (!$this->unregisterHook('actionAfterCreateCustomerFormHandler')
                || !$this->unregisterHook('actionAfterUpdateCustomerFormHandler')
                || !$this->unregisterHook('actionCustomerFormBuilderModifier')
                ) {
                return false;
            }
        }
        //changes end

        $this->unInstallKbTabs();

        return true;
    }
    
    public function saveEmailTemplate($lang_id, $email_body, $email_templates_name)
    {
        try {
            $text_data=strip_tags($email_body);
            Db::getInstance()->insert('kb_affiliate_email_content', array(
                        'id_template' => '',
                        'id_lang' => (int)$lang_id,
                        'id_shop' => 0,
                        'template_name' =>  pSQL($email_templates_name),
                        'text_content' => pSQL($text_data),
                        'body' => pSQL(Tools::htmlentitiesUTF8($email_body)),
                        'date_added' => pSQL(date("Y-m-d H:i:s")),
                        'date_updated' => pSQL(date("Y-m-d H:i:s")),
                    ));
            return true;
        } catch (Exception $ex) {
            return false;
        }
    }
    
    public function getDefaultEmail()
    {
        $template_html = array();
        $template_html['name'] = 'Referral';
        $template_html['body'] = $this->context->smarty->fetch(_PS_MODULE_DIR_ . 'kbaffiliates/views/templates/admin/defaultEmail.tpl');
        $template_html['text_content'] = '';
        $template_html['template_lang'] = 1;
        return $template_html;
    }
   
    public function insertEmailDefaultData($template_data)
    {
        foreach (Language::getLanguages(false) as $lang) {
            $this->saveEmailTemplate($lang['id_lang'], $template_data['body'], $template_data['name']);
        }
        return true;
    }
    
    
    /*
     * Function to delete the customer data from this module for the GDPR compliant plugin.
     */
    public function hookActionDeleteGDPRCustomer($customer)
    {
        if (!empty($customer['email']) && Validate::isEmail($customer['email'])) {
            if (Module::isInstalled($this->name)) {
                /**
                 * Start Changes for PS8 and PHP8 Compatibility - Using json_decode
                 * NAAug2023 json_decode
                 * @date 29-08-2023
                 * @author Nikhil Aggarwal
                 */
                $config = json_decode(Configuration::get('kb_affiliates_basic_settings', null, null, $this->context->shop->id));
                // Changes end by Nikhil
                if ($config->enable && $config->GDPR_compatibility_status) {
                    $existing_customer = Db::getInstance()->executeS('SELECT id_customer from ' . _DB_PREFIX_ . 'customer where email="' . pSQL($customer['email']) . '"');
                    if (!empty($existing_customer)) {
                        foreach ($existing_customer as $existing_cust) {
                            $id_customer = $existing_cust['id_customer'];
                            if (!empty($id_customer)) {
                                $data = Db::getInstance()->getRow('SELECT * FROM '._DB_PREFIX_.'affiliate_customers where id_customer="'.(int) $id_customer.'"');
                                if (isset($data['id_affiliate_customer']) && !empty($data['id_affiliate_customer'])) {
                                    Db::getInstance()->execute('Delete FROM ' . _DB_PREFIX_ . 'affiliate_customers WHERE id_affiliate_customer =' . (int) $data['id_affiliate_customer']);
                                    Db::getInstance()->execute('Delete FROM ' . _DB_PREFIX_ . 'affiliate_commission WHERE id_affiliate_customer =' . (int) $data['id_affiliate_customer']);
                                    Db::getInstance()->execute('Delete FROM ' . _DB_PREFIX_ . 'affiliate_payout_requests WHERE id_affiliate_customer =' . (int) $data['id_affiliate_customer']);
                                    Db::getInstance()->execute('Delete FROM ' . _DB_PREFIX_ . 'affiliate_redeemed_commission WHERE id_affiliate_customer =' . (int) $data['id_affiliate_customer']);
                                    Db::getInstance()->execute('Delete FROM ' . _DB_PREFIX_ . 'affiliate_vouchers WHERE id_affiliate_customer =' . (int) $data['id_affiliate_customer']);
                                    Db::getInstance()->execute('Delete FROM ' . _DB_PREFIX_ . 'affiliate_referrals WHERE referred_by =' . (int) $data['id_affiliate_customer']);
                                    Db::getInstance()->execute('Delete FROM ' . _DB_PREFIX_ . 'voucher_configuration WHERE id_affiliate_voucher_customer =' . (int) $data['id_affiliate_customer']);
                                } else {
                                    Db::getInstance()->execute('Delete FROM ' . _DB_PREFIX_ . 'affiliate_commission WHERE id_customer =' . (int) $id_customer);
                                    Db::getInstance()->execute('Delete FROM ' . _DB_PREFIX_ . 'affiliate_referrals WHERE id_customer =' . (int) $id_customer);
                                }
                            }
                        }
                        return json_encode(true);
                    }
                }
                return json_encode($this->l('Affiliate Module: No user found with this email.'));
            }
        }
    }
    /*
     * Function to export the customer data from this module for the GDPR compliant plugin.
    */
    public function hookActionExportGDPRData($customer)
    {
        if (!empty($customer['email']) && Validate::isEmail($customer['email'])) {
            if (Module::isInstalled($this->name)) {
                /**
                 * Start Changes for PS8 and PHP8 Compatibility - Using json_decode
                 * NAAug2023 json_decode
                 * @date 29-08-2023
                 * @author Nikhil Aggarwal
                 */
                $config = json_decode(Configuration::get('kb_affiliates_basic_settings', null, null, $this->context->shop->id));
                // Changes end by Nikhil
                if ($config->enable && $config->GDPR_compatibility_status) {
                    $existing_customer = Db::getInstance()->executeS('SELECT id_customer from ' . _DB_PREFIX_ . 'customer where email="' . pSQL($customer['email']) . '"');
                    $gdpr_data = array();
                    if (!empty($existing_customer)) {
                        foreach ($existing_customer as $key => $existing_cust) {
                            $order_content = array();
                            $id_customer = $existing_cust['id_customer'];
                            if (!empty($id_customer)) {
                                $data = Db::getInstance()->getRow('SELECT * FROM '._DB_PREFIX_.'affiliate_customers where id_customer="'.(int) $id_customer.'"');
                                if (isset($data['id_affiliate_customer']) && !empty($data['id_affiliate_customer'])) {
                                    $result = Db::getInstance()->executeS("SELECT * FROM ". _DB_PREFIX_ . "affiliate_customers where id_affiliate_customer =".(int) $data['id_affiliate_customer']);

                                    if (!empty($result)) {
                                        if ($result[0]['status'] == 1) {
                                            $result[0]['status'] = $this->l('Enabled');
                                        } else {
                                            $result[0]['status'] = $this->l('Disabled');
                                        }
                                    }

                                    $affiliate_commission_obj = new KbCommission();
                                    $affiliate_redeemed_obj = new KbRedeemedCommission();

                                    $total_com_datas = $affiliate_commission_obj->getComUsingAffiliateId((int) $data['id_affiliate_customer']);
                                    $total_com = 0;

                                    if (count($total_com_datas) != 0) {
                                        foreach ($total_com_datas as $total_com_data) {
                                            if ($this->context->currency->id != $total_com_data['currency_id']) {
                                                $currency_com = new Currency((int) $total_com_data['currency_id']);
                                                $currency_to = new Currency((int) $this->context->currency->id);
                                                $total_com = $total_com + Tools::convertPriceFull($total_com_data['commission_value'], $currency_com, $currency_to);
                                            } else {
                                                $total_com = $total_com + $total_com_data['commission_value'];
                                            }
                                        }
                                    }
                                    $total_earned = Tools::math_round($total_com, 2);

                                    $total_redeemed_com = 0;

                                    $redeemed_data = $affiliate_redeemed_obj->getRedmedComUsingAffiliateId((int) $data['id_affiliate_customer']);
                                    if (count($redeemed_data) != 0) {
                                        foreach ($redeemed_data as $redeemed) {
                                            if ($this->context->currency->id != (int) $redeemed['currency']) {
                                                $currency_com = new Currency((int) $redeemed['currency']);
                                                $currency_to = new Currency((int) $this->context->currency->id);
                                                $total_redeemed_com = $total_redeemed_com + Tools::convertPriceFull($redeemed['val'], $currency_com, $currency_to);
                                            } else {
                                                $total_redeemed_com = $total_redeemed_com + $redeemed['val'];
                                            }
                                        }
                                    }

                                    $total_redeemed = Tools::math_round($total_redeemed_com, 2);
                                    
                                    $pending_data = Db::getInstance()->executeS('SELECT * FROM '._DB_PREFIX_.'affiliate_commission as A INNER JOIN '._DB_PREFIX_.'affiliate_referrals as B on (A.id_affiliate_referrals = B.id_affiliate_referrals) where A.id_affiliate_customer="'.(int) $data['id_affiliate_customer'].'" and B.status="pending"');
                                    $pending_com = 0;

                                    if (count($pending_data) != 0) {
                                        foreach ($pending_data as $pending) {
                                            if ($this->context->currency->id != $pending['currency_id']) {
                                                $currency_com = new Currency((int) $pending['currency_id']);
                                                $currency_to = new Currency((int) $this->context->currency->id);
                                                $pending_com = $pending_com + Tools::convertPriceFull($pending['commission_value'], $currency_com, $currency_to);
                                            } else {
                                                $pending_com = $pending_com + $pending['commission_value'];
                                            }
                                        }
                                    }
                                    $payable_data = Db::getInstance()->executeS('SELECT * FROM '._DB_PREFIX_.'affiliate_payout_requests where status=0 AND id_affiliate_customer='.(int) $data['id_affiliate_customer']);

                                    $payable_com = 0;

                                    if (count($payable_data) != 0) {
                                        foreach ($payable_data as $payable) {
                                            if ($this->context->currency->id != $payable['currency']) {
                                                $currency_com = new Currency((int) $payable['currency']);
                                                $currency_to = new Currency((int) $this->context->currency->id);
                                                $payable_com = $payable_com + Tools::convertPriceFull($payable['payout_value'], $currency_com, $currency_to);
                                            } else {
                                                $payable_com = $payable_com + $payable['payout_value'];
                                            }
                                        }
                                    }

                                    $affiliate_content = array(
                                        $this->l('Status') => $result[0]['status'],
                                        $this->l('Referral Code') => $result[0]['referral_code'],
                                        $this->l('Cart Rules Assigned') => $result[0]['id_cart_rules'],
                                        $this->l('Hits Count') => $result[0]['hits_count'],
                                        $this->l('Total Commission') => Tools::displayPrice($total_earned),
                                        $this->l('Commission Redeemed') => Tools::displayPrice($total_redeemed),
                                        $this->l('Pending Commission') => Tools::displayPrice($pending_com),
                                        $this->l('Payable Commission') => Tools::displayPrice($payable_com),
                                    );

                                    $gdpr_data[] = $affiliate_content;
                                }
                            }
                        }
                    }
                    
                    if (!empty($gdpr_data) && count($gdpr_data) > 0) {
                          return json_encode($gdpr_data);
                    }
                    
                    return json_encode($this->l('Affiliate: No user found with this email.'));
                }
            }
        }
    }
    //Function definition to install module tabs
    public function installKbTabs()
    {
        $parentTab = new Tab();
        $parentTab->name = array();
        foreach (Language::getLanguages(true) as $lang) {
            $parentTab->name[$lang['id_lang']] = $this->l('Knowband Affiliates');
        }

        $parentTab->class_name = self::PARENT_TAB_CLASS;
        $parentTab->module = $this->name;
        $parentTab->active = 1;
        $parentTab->id_parent = Tab::getIdFromClassName(self::SELL_CLASS_NAME);
        $parentTab->add();
        $id_parent_tab = (int) Tab::getIdFromClassName(self::PARENT_TAB_CLASS);
        $admin_menus = $this->adminSubMenus();

        foreach ($admin_menus as $menu) {
            $tab = new Tab();
            foreach (Language::getLanguages(true) as $lang) {
                $tab->name[$lang['id_lang']] = $this->l($menu['name']);
            }

            $tab->class_name = $menu['class_name'];
            $tab->module = $this->name;
            $tab->active = $menu['active'];
            $tab->id_parent = $id_parent_tab;
            $tab->add($this->id);
        }
        return true;
    }
    
    public function unInstallKbTabs()
    {
        $parentTab = new Tab(Tab::getIdFromClassName(self::PARENT_TAB_CLASS));
        $parentTab->delete();

        $admin_menus = $this->adminSubMenus();

        foreach ($admin_menus as $menu) {
            $sql = 'SELECT id_tab FROM `' . _DB_PREFIX_ . 'tab` Where class_name = "' . pSQL($menu['class_name']) . '" 
                AND module = "' . pSQL($this->name) . '"';
            $id_tab = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
            $tab = new Tab($id_tab);
            $tab->delete();
        }
        return true;
    }
    
    // function getContent()
    // {
    //     $this->installKbTabs();
    // }

    //Function definition to get submenus list
    public function adminSubMenus()
    {
        $subMenu = array(
            array(
                'class_name' => 'AdminKbBasicConfiguration',
                'name' => $this->l('Basic Configuration'),
                'active' => 1,
            ),
            array(
                'class_name' => 'AdminKbAffiliateCustomers',
                'name' => $this->l('Affiliate Customers'),
                'active' => 1,
            ),
            array(
                'class_name' => 'AdminKbReferrals',
                'name' => $this->l('Referrals Listing'),
                'active' => 1,
            ),
            array(
                'class_name' => 'AdminKbCommission',
                'name' => $this->l('Commission Listing'),
                'active' => 1,
            ),
            array(
                'class_name' => 'AdminKbSubCommissions',
                'name' => $this->l('Sub Commissions'),
                'active' => 0,
            ),
            array(
                'class_name' => 'AdminKbPayOutRequests',
                'name' => $this->l('Pay Out Requests'),
                'active' => 1,
            ),
        );

        return $subMenu;
    }

    // Added this function to add the icon of the menus in back office
    public function hookDisplayBackOfficeHeader()
    {
        $this->context->controller->addCSS($this->_path . 'views/css/admin_menu.css');
        /*Start: Changes done by tarun gupta on 14th june 2019
        to fix UI of commission listing while edit*/
        
        if ($this->context->controller->controller_name == 'AdminKbCommission') {
            $this->context->controller->addCSS($this->_path . 'views/css/admin_affiliate_menu.css');
        }
        /*End: Changes done by tarun gupta on 14th june 2019
        to fix UI of commission listing while edit*/
    }
    
    //Renders the footer link in the bottom menu of the page
    public function hookDisplayMyAccountBlock()
    {
        $config = Configuration::get('kb_affiliates_basic_settings', false, null, $this->context->shop->id);
        /**
         * Start Changes for PS8 and PHP8 Compatibility - Using json_decode
         * NAAug2023 json_decode
         * @date 29-08-2023
         * @author Nikhil Aggarwal
         */
        $config = json_decode($config, true);
        // Changes end by Nikhil
        $customer = new Customer((int) $this->context->customer->id);
        $customer_group = false;
        if (isset($config['kb_customer_groups']) && count($config['kb_customer_groups']) > 0) {
            foreach ($config['kb_customer_groups'] as $val) {
                if ($customer->id_default_group == $val) {
                    $customer_group = true;
                    break;
                }
            }
        } else {
            $customer_group = true;
        }
        
        if ($config['enable'] == 1 && $config['enable_registration'] == 1 && $customer_group == true) {
            $this->context->smarty->assign('link_to_register', $this->context->link->getModuleLink(
                $this->name,
                'Register',
                array(),
                (bool)Configuration::get('PS_SSL_ENABLED')
            ));

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

    //Renders the field to enter the registration code
    public function hookDisplayCustomerAccountForm()
    {
        $config = Configuration::get('kb_affiliates_basic_settings', false, null, $this->context->shop->id);
        /**
         * Start Changes for PS8 and PHP8 Compatibility - Using json_decode
         * NAAug2023 json_decode
         * @date 29-08-2023
         * @author Nikhil Aggarwal
         */
        $config = json_decode($config, true);
        // Changes end by Nikhil
        $flag = false;
        /* Start: changes done by tarun gupta on 3rd-jun-2019 for check referal system method is enable or not*/
        
        if (isset($config['referral_systems']) && count($config['referral_systems']) > 0) {
            foreach ($config['referral_systems'] as $con) {
                if ($con == 'code') {
                    $flag = true;
                }
            }
        }
        /* End: changes done by tarun gupta on 3rd-jun-2019 for check referal system method is enable or not*/
        
        if ($config['enable'] == 1 && $flag) {
            return $this->context->smarty->fetch(_PS_MODULE_DIR_.$this->name.'/views/templates/hook/code_field.tpl');
        }
    }

    // Renders the form for the affiliate customers
    public function hookDisplayAdminCustomersForm($param)
    {
        $config = Configuration::get('kb_affiliates_basic_settings', false, null, $this->context->shop->id);
        /**
         * Start Changes for PS8 and PHP8 Compatibility - Using json_decode
         * NAAug2023 json_decode
         * @date 29-08-2023
         * @author Nikhil Aggarwal
         */
        $config = json_decode($config, true);
        // Changes end by Nikhil
        if ($config['enable'] == 1) {
            unset($param);
            $this->context->controller->addJS($this->_path . 'views/js/admin/affiliate_form.js');
            $this->context->controller->addJS($this->_path . 'views/js/velovalidation.js');
            return $this->renderSellerSettingForm();
        }
    }
    
    // Creates the cookie in case the code is present in the link or the voucher added in the cart is of an affilaite customer
    public function hookDisplayHeader()
    {
        $config = Configuration::get('kb_affiliates_basic_settings', false, null, $this->context->shop->id);
        /**
         * Start Changes for PS8 and PHP8 Compatibility - Using json_decode
         * NAAug2023 json_decode
         * @date 29-08-2023
         * @author Nikhil Aggarwal
         */
        $config = json_decode($config, true);
        // Changes end by Nikhil
        if ($config['enable'] != 1) {
            return false;
        }
        $flag = false;
        $referral_code = Tools::getValue('referral_code');
        if (!empty($referral_code)) {
            if ((bool) $this->context->customer->isLogged()) {
                $id_customer = $this->context->customer->id;
                /**
                 * Start Changes to fix the static call to function issue
                 * NAAug2023 static
                 * @date 29-08-2023
                 * @author Nikhil Aggarwal
                 */
                $KbReferrals = new KbReferrals();
                $referral_existence = $KbReferrals->checkReferralExistenceByCustomerId($id_customer);
                // Changes end by Nikhil
                if ($referral_existence == 0) {
                    $flag = true;
                } else {
                    return;
                }
            }
            foreach ($config['referral_systems'] as $con) {
                if ($con == 'link' || $con == 'social' || $con == 'mail') {
                    $flag = true;
                }
            }

            if (!$flag) {
                return;
            }
            
            $cookie = new Cookie('referrer');
            if ($cookie->__isset('referrer') && $cookie->__get('referrer') == $referral_code) {
                return false;
            }
            
            $affiliate_obj = new KbAffiliateCustomers();
            $data = $affiliate_obj->getAffiliateCustomerByCode($referral_code);
            
            if (isset($data['id_affiliate_customer'])) {
                $affiliate_obj = new KbAffiliateCustomers($data['id_affiliate_customer']);
            }
        } else {
            if (isset($config['referral_systems'])) {
                foreach ($config['referral_systems'] as $con) {
                    if ($con == 'voucher') {
                        $flag = true;
                    }
                }
            }
            
            if (!$flag) {
                return;
            }

            $cart_obj = new Cart($this->context->cart->id);
            $cart_rules = $cart_obj->getCartRules();
            $count = 0;

            foreach ($cart_rules as $key => $val) {
                if ($cart_rules[$key]['description'] == 'AFFILIATE' && $count == 0) {
                    $count = 1;
                    $data_affiliate = Db::getInstance()->getRow('SELECT * FROM '._DB_PREFIX_.'affiliate_customers where id_cart_rules LIKE "%'.pSQL($cart_rules[$key]['code']).'%"');
                    /**
                     * Start Changes to fix the Trying to access array offset on value of type bool error
                     * Adding is_array condition
                     * NASep2023 cart_rule_offset_issue
                     * @date 04-09-2023
                     * @modifier Nikhil Aggarwal
                     */
                    if(is_array($data_affiliate) && count($data_affiliate) > 0) {
                        $id_affiliate_customer = $data_affiliate['id_affiliate_customer'];
                    }
                    // Changes end by Nikhil
                }
            }
            if (isset($id_affiliate_customer)) {
                $affiliate_obj = new KbAffiliateCustomers((int) $id_affiliate_customer);
                $referral_code = $affiliate_obj->referral_code;
            }
        }
        if (isset($affiliate_obj)) {
            if ($affiliate_obj->status == 1) {
                //do nothing
            } else {
                return false;
            }
            
            if (!empty($affiliate_obj->date_until) == '0000-00-00' || $affiliate_obj->date_until >= date('Y-m-d')) {
                //do nothing
            } else {
                return false;
            }

            $affiliate_obj->hits_count = $affiliate_obj->hits_count+1;
            
            if ($affiliate_obj->date_from == '0000-00-00') {
                $affiliate_obj->date_from = null;
            } else {
                $affiliate_obj->date_from = $affiliate_obj->date_from;
            }

            if ($affiliate_obj->date_until == '0000-00-00') {
                $affiliate_obj->date_until = null;
            } else {
                $affiliate_obj->date_until = $affiliate_obj->date_until;
            }

            $affiliate_obj->save();
            if ($config['enable'] == 1 && $config['enable_permenent_referral'] == 0) {
                $time_out = time() + 86400*$config['referral_time_out'];
                $cookie = new Cookie('referrer', '', $time_out);
                $cookie->__set('referrer', $referral_code);
            } else if ($config['enable'] == 1 && $config['enable_permenent_referral'] == 1) {
                $time_out = time() + 86400*999;
                $cookie = new Cookie('referrer', '', $time_out);
                $cookie->__set('referrer', $referral_code);
            }
        }
    }

    // Function for showing the module front link in the `My Account` section
    public function hookDisplayCustomerAccount()
    {
        $config = Configuration::get('kb_affiliates_basic_settings', false, null, $this->context->shop->id);
        /**
         * Start Changes for PS8 and PHP8 Compatibility - Using json_decode
         * NAAug2023 json_decode
         * @date 29-08-2023
         * @author Nikhil Aggarwal
         */
        $config = json_decode($config, true);
        // Changes end by Nikhil
        $customer = new Customer((int) $this->context->customer->id);
        $customer_group = false;
        if (isset($config['kb_customer_groups']) && count($config['kb_customer_groups']) > 0) {
            foreach ($config['kb_customer_groups'] as $val) {
                if ($customer->id_default_group == $val) {
                    $customer_group = true;
                    break;
                }
            }
        } else {
            $customer_group = true;
        }
        /**
         * Start Changes to fix the issue of affiliate account tab not visible when registration is off and custom is already an affiliate
         * NASep2023 affiliate_registration
         * Removed  && $config['enable_registration'] == 1 condition from below if block
         * Added the condition in the else block by changing it to else if($config['enable_registration'] == 1)
         * @date 04-09-2023
         * @modifier Nikhil Aggarwal
         */
        if ($config['enable'] == 1 && $customer_group == true) {
            $sql = "SELECT id_affiliate_customer,status FROM "._DB_PREFIX_."affiliate_customers where id_customer=". (int) $this->context->customer->id;
            $result = DB::getInstance()->getRow($sql);
            if (isset($result['id_affiliate_customer'])) {
                $this->context->smarty->assign('front_url', $this->context->link->getModuleLink(
                    $this->name,
                    'Dashboard',
                    array(),
                    (bool)Configuration::get('PS_SSL_ENABLED')
                ));
                $this->context->smarty->assign('status', $result['status']);
                $this->context->smarty->assign('registered', 1);
                return $this->context->smarty->fetch(_PS_MODULE_DIR_.$this->name.'/views/templates/hook/front_myaccount_link.tpl');
            } else if($config['enable_registration'] == 1){
                $this->context->smarty->assign('front_url', $this->context->link->getModuleLink(
                    $this->name,
                    'Dashboard',
                    array('register' => 1),
                    (bool)Configuration::get('PS_SSL_ENABLED')
                ));
                $this->context->smarty->assign('registered', 0);
                return $this->context->smarty->fetch(_PS_MODULE_DIR_.$this->name.'/views/templates/hook/front_myaccount_link.tpl');
            }
            // Changes end by Nikhil
            
        }
    }

    //Add referral if there is a cookie set for referral code, this code will only work when the user registers on the store
    public function hookActionCustomerAccountAdd($param)
    {
        if ($param['newCustomer']->is_guest == 1) {
            return false;
        }

        $config = Configuration::get('kb_affiliates_basic_settings', false, null, $this->context->shop->id);
        /**
         * Start Changes for PS8 and PHP8 Compatibility - Using json_decode
         * NAAug2023 json_decode
         * @date 29-08-2023
         * @author Nikhil Aggarwal
         */
        $config = json_decode($config, true);
        // Changes end by Nikhil
        if (Tools::getIsset('referral_code') && !empty(Tools::getValue('referral_code'))) {
            $referral_code = Tools::getValue('referral_code');
            $affiliate_customer_obj = new KbAffiliateCustomers();
            $data = $affiliate_customer_obj->getAffiliateCustomerByCode(Tools::getValue('referral_code'));
            if (isset($data)) {
                if ($data['status'] == 1) {
                    //do nothing
                } else {
                    return false;
                }

                if ($data['date_until'] == '0000-00-00' || $data['date_until'] >= date('Y-m-d')) {
                    //do nothing
                } else {
                    return false;
                }

                if ($config['enable'] == 1 && $config['enable_permenent_referral'] == 0) {
                    $time_out = time() + 86400*$config['referral_time_out'];
                    $cookie = new Cookie('referrer', '', $time_out);
                    $cookie->__set('referrer', $referral_code);
                } else if ($config['enable'] == 1 && $config['enable_permenent_referral'] == 1) {
                    $time_out = time() + 86400*999;
                    $cookie = new Cookie('referrer', '', $time_out);
                    $cookie->__set('referrer', $referral_code);
                }
            }
        }
        $flag = false;
        if (isset($config['referral_count'])) {
            foreach ($config['referral_count'] as $key => $val) {
                if ($val == 'user_registration') {
                    $flag = true;
                }
            }
        } else {
            return;
        }

        $cookie = new Cookie('referrer');
        if ($config['enable'] == 1 && $flag) {
            if (($cookie->__isset('referrer') && !empty($cookie->__get('referrer'))) || Tools::getIsset('referral_code') && !empty(Tools::getValue('referral_code'))) {
                $affiliate_customer_obj = new KbAffiliateCustomers();
                if ($cookie->__isset('referrer') && !empty($cookie->__get('referrer'))) {
                    $data = $affiliate_customer_obj->getAffiliateCustomerByCode($cookie->__get('referrer'));
                } else {
                    $data = $affiliate_customer_obj->getAffiliateCustomerByCode(Tools::getValue('referral_code'));
                }
                if ($data['date_until'] == '0000-00-00' || $data['date_until'] >= date('Y-m-d')) {
                    //do nothing
                } else {
                    return false;
                }
                if (isset($data['id_affiliate_customer']) && $data['status'] == 1) {
                    //Add data in the referrals table
                    $referral_obj = new KbReferrals();
                    $referral_obj->referred_by = $data['id_affiliate_customer'];
                    $referral_obj->id_customer = $param['newCustomer']->id;
                    $referral_obj->referral_type = 'User Registration';
                    $referral_obj->status = $config['referral_default_status'];
                    $referral_obj->date_added = date("Y-m-d");
                    $referral_obj->save();

                    //Add data in the commission table
                    $commission_obj = new KbCommission();
                    $commission_obj->id_affiliate_referrals = Db::getInstance()->Insert_ID();
                    $commission_obj->id_affiliate_customer = $data['id_affiliate_customer'];

                    if ($data['use_global_rate'] == 1) {
                        $commission_obj->commission_value = $config['referral_rate_user_registration'];
                    } else {
                        $commission_obj->commission_value = $data['referral_rate_user_registration'];
                    }

                    $commission_obj->currency_id = $this->context->currency->id;
                    $commission_obj->order_placed = '';
                    $commission_obj->user_registered = $param['newCustomer']->id;
                    $commission_obj->date_added = date("Y-m-d");
                    $commission_obj->save();

                    $affiliate_customer_code_obj = new KbAffiliateCustomers($data['id_affiliate_customer']);
                    $affiliate_customer_code_obj->total_commission_earned = $affiliate_customer_code_obj->total_commission_earned + $commission_obj->commission_value;

                    if ($affiliate_customer_code_obj->date_from == '0000-00-00') {
                        $affiliate_customer_code_obj->date_from = null;
                    } else {
                        $affiliate_customer_code_obj->date_from = $affiliate_customer_code_obj->date_from;
                    }

                    if ($affiliate_customer_code_obj->date_until == '0000-00-00') {
                        $affiliate_customer_code_obj->date_until = null;
                    } else {
                        $affiliate_customer_code_obj->date_until = $affiliate_customer_code_obj->date_until;
                    }
                    $affiliate_customer_code_obj->save();
                }
                $cookie->__unset('referrer');
            }
        }
    }

    //Add referral when order is placed
    public function hookDisplayOrderConfirmation($param)
    {
        $config = Configuration::get('kb_affiliates_basic_settings', false, null, $this->context->shop->id);
        /**
         * Start Changes for PS8 and PHP8 Compatibility - Using json_decode
         * NAAug2023 json_decode
         * @date 29-08-2023
         * @author Nikhil Aggarwal
         */
        $config = json_decode($config, true);
        // Changes end by Nikhil
        $flag = false;
        if (isset($config['referral_count'])) {
            foreach ($config['referral_count'] as $key => $val) {
                if ($val == 'order_placed') {
                    $flag = true;
                }
            }
        } else {
            return;
        }
        $cookie = new Cookie('referrer');
        
        if ($config['enable'] == 1 && $flag) {
            if ($cookie->__isset('referrer') && !empty($cookie->__get('referrer'))) {
                
                /** Start : changes done by Tarun gupta on 4th june 2019
                 * to add a feature multiple commission**/
                if ((bool) $this->context->customer->isLogged()) {
                    $id_customer = $this->context->customer->id;
                    /**
                     * Start Changes to fix the static call to function issue
                     * NAAug2023 static
                     * @date 29-08-2023
                     * @author Nikhil Aggarwal
                     */
                    $KbReferrals = new KbReferrals();
                    $referral_existence = $KbReferrals->checkReferralExistenceByCustomerId($id_customer);
                    // Changes end by Nikhil

                    if ($referral_existence == 0) {
                    } else {
                        /**
                         * Start Changes to fix the static call to function issue
                         * NAAug2023 static
                         * @date 29-08-2023
                         * @author Nikhil Aggarwal
                         */
                        $KbReferrals = new KbReferrals();
                        $referrer_id = $KbReferrals->getReferrerIdByCustomerId($id_customer);
                        // Changes end by Nikhil
                        $referrer_customer_obj = new KbAffiliateCustomers($referrer_id);
                        
                        $referral_code = $referrer_customer_obj->referral_code;
                        $cookie->__unset('referrer');
                        $cookie = new Cookie('referrer');
                        $cookie->__set('referrer', $referral_code);
                        
                        if ($referrer_customer_obj->enable_disable_multiple_commission == 1) {
                            if ($referrer_customer_obj->use_global_orders_count == 1) {
                                $count = $config['disable_commission_after'];
                            } else {
                                $count = $referrer_customer_obj->disable_commission_after;
                            }
                            /**
                             * Start Changes to fix the static call to function issue
                             * NAAug2023 static
                             * @date 29-08-2023
                             * @author Nikhil Aggarwal
                             */
                            $referral_count = $KbReferrals->getReferralCountByReferrerId($referrer_id, $id_customer);
                            // Changes end by Nikhil
                            if ($count > $referral_count || $count == 0) {
                            } else {
                                return false;
                            }
                        } else {
                            return false;
                        }
                    }
                }
                /** End : changes done by Tarun gupta on 4th june 2019
                 * to add a feature multiple commission**/
                
                $affiliate_customer_obj = new KbAffiliateCustomers();
                $data = $affiliate_customer_obj->getAffiliateCustomerByCode($cookie->__get('referrer'));
                if ($data['date_until'] == '0000-00-00' || $data['date_until'] >= date('Y-m-d')) {
                    //do nothing
                } else {
                    return false;
                }
                $order_reference_obj = new Order((int) Tools::getValue('id_order'));
                $order_reference = $order_reference_obj->reference;
                /**
                 * Start Changes to fix the static call to function issue
                 * NAAug2023 static
                 * @date 29-08-2023
                 * @author Nikhil Aggarwal
                 */
                $KbCommission = new KbCommission();
                $referral_existence = $KbCommission->checkOrderReferenceExistence($order_reference);
                // Changes end by Nikhil
                if ($referral_existence == 0) {
                    if (isset($data['id_affiliate_customer']) && $data['status'] == 1) {
                        //Add data in the referrals table
                        $referral_obj = new KbReferrals();
                        $referral_obj->referred_by = $data['id_affiliate_customer'];
                        $referral_obj->id_customer = $this->context->customer->id;
                        $referral_obj->referral_type = 'Order Placed';
                        $referral_obj->status = $config['referral_default_status'];
                        $referral_obj->date_added = date("Y-m-d");

                        $referral_obj->save();

                        //Add data in the commission table
                        $commission_obj = new KbCommission();
                        $commission_obj->id_affiliate_referrals = Db::getInstance()->Insert_ID();
                        $commission_obj->id_affiliate_customer = $data['id_affiliate_customer'];

                        $order_obj = new Order((int) Tools::getValue('id_order'));

                        if ($data['use_global_rate'] == 1) {
                            $commission_obj->commission_value = ($order_obj->total_paid * $config['referral_rate']) / 100;
                        } else {
                            $commission_obj->commission_value = ($order_obj->total_paid * $data['referral_rate']) / 100;
                        }

                        $commission_obj->currency_id = $this->context->currency->id;
                        $commission_obj->order_placed = $order_obj->reference;
                        $commission_obj->user_registered = 0;
                        $commission_obj->date_added = date("Y-m-d");
                        $commission_obj->save();

                        $affiliate_customer_code_obj = new KbAffiliateCustomers($data['id_affiliate_customer']);
                        $affiliate_customer_code_obj->total_commission_earned = $affiliate_customer_code_obj->total_commission_earned + $commission_obj->commission_value;

                        if ($affiliate_customer_code_obj->date_from == '0000-00-00') {
                            $affiliate_customer_code_obj->date_from = null;
                        } else {
                            $affiliate_customer_code_obj->date_from = $affiliate_customer_code_obj->date_from;
                        }

                        if ($affiliate_customer_code_obj->date_until == '0000-00-00') {
                            $affiliate_customer_code_obj->date_until = null;
                        } else {
                            $affiliate_customer_code_obj->date_until = $affiliate_customer_code_obj->date_until;
                        }

                        $affiliate_customer_code_obj->save();
                    }
                    $cookie->__unset('referrer');
                    /** Start : changes done by Tarun gupta on 4th june 2019
                     * to add a feature multiple commission**/
                } else {
                    $cookie = new Cookie('referrer');
                    $cookie->__unset('referrer');
                    return false;
                }
            } else {
                if ((bool) $this->context->customer->isLogged()) {
                    $count = -1;
                    $id_customer = $this->context->customer->id;
                    /**
                     * Start Changes to fix the static call to function issue
                     * NAAug2023 static
                     * @date 29-08-2023
                     * @author Nikhil Aggarwal
                     */
                    $KbReferrals = new KbReferrals();
                    $referrer_id = $KbReferrals->getReferrerIdByCustomerId($id_customer);
                    // Changes end by Nikhil
                    $referrer_customer_obj = new KbAffiliateCustomers($referrer_id);
                    $referral_code = $referrer_customer_obj->referral_code;
                    $cookie->__set('referrer', $referral_code);
                    if ($referrer_customer_obj->enable_disable_multiple_commission == 1) {
                        if ($referrer_customer_obj->use_global_orders_count == 1) {
                            $count = $config['disable_commission_after'];
                        } else {
                            $count = $referrer_customer_obj->disable_commission_after;
                        }
                    }
                    /**
                     * Start Changes to fix the static call to function issue
                     * NAAug2023 static
                     * @date 29-08-2023
                     * @author Nikhil Aggarwal
                     */
                    $referral_count = $KbReferrals->getReferralCountByReferrerId($referrer_id, $id_customer);
                    // Changes end by Nikhil
                    if ($count > $referral_count || $count == 0) {
                    } else {
                        return false;
                    }
                    $affiliate_customer_obj = new KbAffiliateCustomers();
                    $data = $affiliate_customer_obj->getAffiliateCustomerByCode($cookie->__get('referrer'));
                    if ($data['date_until'] == '0000-00-00' || $data['date_until'] >= date('Y-m-d')) {
                        //do nothing
                    } else {
                        return false;
                    }
                    $order_reference_obj = new Order((int) Tools::getValue('id_order'));
                    $order_reference = $order_reference_obj->reference;
                    /**
                     * Start Changes to fix the static call to function issue
                     * NAAug2023 static
                     * @date 29-08-2023
                     * @author Nikhil Aggarwal
                     */
                    $KbCommission = new KbCommission();
                    $referral_existence = $KbCommission->checkOrderReferenceExistence($order_reference);
                    // Changes end by Nikhil
                    if ($referral_existence == 0) {
                        if (isset($data['id_affiliate_customer']) && $data['status'] == 1) {
                            //Add data in the referrals table
                            $referral_obj = new KbReferrals();
                            $referral_obj->referred_by = $data['id_affiliate_customer'];
                            $referral_obj->id_customer = $this->context->customer->id;
                            $referral_obj->referral_type = 'Order Placed';
                            $referral_obj->status = $config['referral_default_status'];
                            $referral_obj->date_added = date("Y-m-d");

                            $referral_obj->save();

                            //Add data in the commission table
                            $commission_obj = new KbCommission();
                            $commission_obj->id_affiliate_referrals = Db::getInstance()->Insert_ID();
                            $commission_obj->id_affiliate_customer = $data['id_affiliate_customer'];

                            $order_obj = new Order((int) Tools::getValue('id_order'));

                            if ($data['use_global_rate'] == 1) {
                                $commission_obj->commission_value = ($order_obj->total_paid * $config['referral_rate']) / 100;
                            } else {
                                $commission_obj->commission_value = ($order_obj->total_paid * $data['referral_rate']) / 100;
                            }

                            $commission_obj->currency_id = $this->context->currency->id;
                            $commission_obj->order_placed = $order_obj->reference;
                            $commission_obj->user_registered = 0;
                            $commission_obj->date_added = date("Y-m-d");
                            $commission_obj->save();

                            $affiliate_customer_code_obj = new KbAffiliateCustomers($data['id_affiliate_customer']);
                            $affiliate_customer_code_obj->total_commission_earned = $affiliate_customer_code_obj->total_commission_earned + $commission_obj->commission_value;

                            if ($affiliate_customer_code_obj->date_from == '0000-00-00') {
                                $affiliate_customer_code_obj->date_from = null;
                            } else {
                                $affiliate_customer_code_obj->date_from = $affiliate_customer_code_obj->date_from;
                            }

                            if ($affiliate_customer_code_obj->date_until == '0000-00-00') {
                                $affiliate_customer_code_obj->date_until = null;
                            } else {
                                $affiliate_customer_code_obj->date_until = $affiliate_customer_code_obj->date_until;
                            }

                            $affiliate_customer_code_obj->save();
                            $cookie->__unset('referrer');
                        }
                    } else {
                        $cookie = new Cookie('referrer');
                        $cookie->__unset('referrer');
                        return false;
                    }
                }
            }
            
            /** End : changes done by Tarun gupta on 4th june 2019
            * to add a feature multiple commission**/
        }
    }
    
    //Renders form in the admins customer panel
    protected function renderSellerSettingForm()
    {
        $helper      = new HelperForm();
        $id_customer = (int) Tools::getValue('id_customer');
        $id_affiliate_customer = (int) Tools::getValue('id_affiliate_customer');
        $options_vouchers = array();

        $options_vouchers[] = array(
            'id' => 'fixed',
            'name' => $this->l('Fixed')
        );

        $options_vouchers[] = array(
            'id' => 'percentage',
            'name' => $this->l('Percentage')
        );

        $fields_form = array(
            'form' => array(
                'legend' => array(
                    'title' => $this->l('Affiliate Customer Form'),
                    'icon' => 'icon-cog'
                ),
                'input' => array(
                    array(
                        'type' => 'switch',
                        'label' => $this->l('Status'),
                        'name' => 'status',
                        'values' => array(
                            array(
                                'value' => 1
                            ),
                            array(
                                'value' => 0
                            )
                        ),
                    ),
                    array(
                        'type' => 'hidden',
                        'name' => 'id_affiliate_customer',
                    ),
                    array(
                        'type' => 'text',
                        'label' => $this->l('Affiliate From'),
                        'name' => 'date_from',
                        'readonly' => true,
                        'col' => 3,
                    ),
                    array(
                        'type' => 'date',
                        'label' => $this->l('Affiliate Until'),
                        'name' => 'date_until',
                    ),
                    array(
                        'type' => 'switch',
                        'label' => $this->l('Use global referral rates'),
                        'hint' => $this->l('If this field is enabled then the referral rate for seller will be the global referral rate entered'),
                        'name' => 'use_global_rate',
                        'values' => array(
                            array(
                                'value' => 1
                            ),
                            array(
                                'value' => 0
                            )
                        ),
                    ),
                    array(
                        'type' => 'text',
                        'label' => $this->l('Referral rate for order placed'),
                        'name' => 'referral_rate',
                        'col' => 1,
                        'suffix' => '%',
                    ),
                    array(
                        'type' => 'text',
                        'label' => $this->l('Referral rate for user registration'),
                        'name' => 'referral_rate_user_registration',
                        'col' => 1,
                    ),
                    /** Start : changes done by tarun gupta on 3rd-jun-2019
             *  To get id customer and to affiliate customer through admin*/
                    
                    array(
                        'type' => 'hidden',
//                        'label' => $this->l('Referral rate for user registration'),
                        'name' => 'id_customer',
                        'col' => 1,
                        
                    ),
            /** End : changes done by tarun gupta on 3rd-jun-2019
             *  To get id customer and to affiliate customer through admin*/
            /****/
            /** Start: changes done by tarun gupta on 4th june 2019
            * to add a feature for multiple commission**/
                    array(
                        'type' => 'switch',
                        'label' => $this->l('Enable disable multiple commission'),
                        'name' => 'enable_disable_multiple_commission',
                        'hint' => $this->l('Enable disable multiple commission feature for the affilaite customers'),
                        'values' => array(
                            array(
                                'value' => 1
                            ),
                            array(
                                'value' => 0
                            )
                        ),
                    ),
                    array(
                        'type' => 'switch',
                        'label' => $this->l('Use global Commission Validity'),
                        'hint' => $this->l('If this field is enabled then the number of orders will be the global number of orders entered'),
                        'name' => 'use_global_orders_count',
                        'values' => array(
                            array(
                                'value' => 1
                            ),
                            array(
                                'value' => 0
                            )
                        ),
                    ),
                    array(
                        'type' => 'text',
                        'label' => $this->l('Disable Commission After'),
                        'name' => 'disable_commission_after',
                        'col' => 3,
                        'suffix' => 'orders',
                    ),
            /** End: changes done by tarun gupta on 4th june 2019
            * to add a feature for multiple commission**/
                    array(
                        'type' => 'switch',
                        'label' => $this->l('Use global voucher configuration'),
                        'name' => 'enable_global_voucher',
                        'hint' => $this->l('If this will be enabled then a voucher will be generated according to the global configuration'),
                        'values' => array(
                            array(
                                'value' => 1
                            ),
                            array(
                                'value' => 0
                            )
                        ),
                    ),
                    array(
                        'type' => 'select',
                        'label' => $this->l('Voucher type'),
                        'name' => 'voucher_type',
                        'options' => array(
                            'query' => $options_vouchers,
                            'id' => 'id',
                            'name' => 'name',
                        ),
                    ),
                    array(
                        'type' => 'text',
                        'label' => $this->l('Voucher value'),
                        'name' => 'voucher_val',
                        'col' => 3,
                        'desc' => $this->l('Please note that the voucher currency will be according to the currenct currency available'),
                    ),
                    array(
                        'type' => 'text',
                        'label' => $this->l('Voucher quantity'),
                        'name' => 'voucher_quan',
                        'col' => 1,
                    ),
//                    array(
//                        'type' => 'text',
//                        'label' => $this->l('Voucher quantity per user'),
//                        'name' => 'voucher_quan_per',
//                        'col' => 1,
//                    ),
                    /** Start: Changes done by tarun gupta on 3rd june 2019
                     * to add a field to enter a custom voucher code**/
                    
                    array(
                       'type' => 'text',
                       'label' => $this->l('Coupon Code'),
                       'name' => 'voucher_code',
                       'col' => 4,
                       'desc' => $this->l('First enter the coupon code here & then click on the Generate button. If you want it to generate the code randomly then leave it blank.'),
                   ),
                    /** End: Changes done by tarun gupta on 3rd june 2019
                     * to add a field to enter a custom voucher code**/
                    
                    array(
                        'type' => 'textarea',
                        'label' => $this->l('Vouchers'),
                        'name' => 'vouchers',
                        'col' => 5,
                        'desc' => $this->l('If you want to remove the voucher then just disable it from the back office, it will not be shown to the affiliate customer also'),
                        'readonly' => true
                    ),
                ),
                'submit' => array(
                    'title' => $this->l('Save'),
                    'class' => 'btn btn-default pull-right form_kb_affiliate_customer'
                ),
            )
        );

        $languages = Language::getLanguages();
        foreach ($languages as $k => $language) {
            $languages[$k]['is_default'] = ((int) ($language['id_lang'] == $this->context->language->id));
        }
        
        $helper = new HelperForm();
        $helper->show_toolbar = false;
        $lang = new Language((int) Configuration::get('PS_LANG_DEFAULT'));
        $language = Language::getLanguages(false);
        $helper->default_form_language = $lang->id;
        $helper->languages = $languages;
        $helper->submit_action = 'kb_affiliate_customer_settings';
        $helper->token = Tools::getAdminTokenLite('AdminKbAffiliateCustomers');
        $helper->currentIndex = $this->context->link->getAdminLink('AdminKbAffiliateCustomers', true);

        $affliate_obj = new KbAffiliateCustomers($id_affiliate_customer);
        $voucher_data = new KbVouchers();
        $data = $voucher_data->getVoucherConfiguration((int) $id_affiliate_customer);
        $helper->fields_value['status'] = $affliate_obj->status;
        if ($affliate_obj->date_from == '0000-00-00') {
            $helper->fields_value['date_from'] = null;
        } else {
            $helper->fields_value['date_from'] = $affliate_obj->date_from;
        }
        if ($affliate_obj->date_until == '0000-00-00') {
            $helper->fields_value['date_until'] = null;
        } else {
            $helper->fields_value['date_until'] = $affliate_obj->date_until;
        }
        
        $helper->fields_value['use_global_rate'] = $affliate_obj->use_global_rate;
        $helper->fields_value['enable_global_voucher'] = $affliate_obj->use_global_voucher;
        $helper->fields_value['voucher_type'] = $data['voucher_type'];
        $helper->fields_value['voucher_val'] = $data['voucher_value'];
        $helper->fields_value['voucher_quan'] = $data['voucher_quantity'];
//        $helper->fields_value['voucher_quan_per'] = $data['voucher_quantity_per_user'];
        $helper->fields_value['referral_rate'] = $affliate_obj->referral_rate;
        $helper->fields_value['referral_rate_user_registration'] = $affliate_obj->referral_rate_user_registration;
        $helper->fields_value['vouchers'] = $affliate_obj->id_cart_rules;
        $helper->fields_value['id_affiliate_customer'] = $id_affiliate_customer;
        $helper->fields_value['voucher_code'] = '';
        /** Start : changes done by tarun gupta on 3rd-jun-2019
             *  To get customer id and to affiliate user through admin*/
        
        $helper->fields_value['id_customer'] = (int) Tools::getValue('id_customer');
        /** End : changes done by tarun gupta on 3rd-jun-2019
             *  To get customer id and to affiliate user through admin*/
        
        /** Start: changes done by tarun gupta on 4th june 2019
            * to add a feature for multiple commission**/
                    
        $helper->fields_value['enable_disable_multiple_commission'] = $affliate_obj->enable_disable_multiple_commission;
        $helper->fields_value['use_global_orders_count'] = $affliate_obj->use_global_orders_count;
        $helper->fields_value['disable_commission_after'] = $affliate_obj->disable_commission_after;
        /** End: changes done by tarun gupta on 4th june 2019
        * to add a feature for multiple commission**/
        $kb_form_contents = $helper->generateForm(array($fields_form));
        
        $this->context->smarty->assign(
            array(
                'kb_form_contents' => $kb_form_contents,
                'kb_affiliate_customer_link' => 'index.php?controller=AdminKbAffiliateCustomers&token='.$helper->token,
                'id_affiliate_customer' => $id_affiliate_customer,
                'token_affiliate' => Tools::getAdminTokenLite('AdminKbAffiliateCustomers'),
            )
        );

        $helper = new HelperView();
        $helper->module = $this;
        $helper->token = Tools::getAdminTokenLite('AdminModules');
        $helper->current = AdminController::$currentIndex . '&configure=' . $this->name;
        $helper->show_toolbar = false;
        $helper->toolbar_scroll = true;
        $helper->override_folder = 'helpers/';
        $helper->base_folder = 'view/';
        $helper->base_tpl = 'view_custom.tpl';

        $view = $helper->generateView();

        return $this->display(__FILE__, 'views/templates/admin/affiliate_form.tpl').$view;
    }
    //changes by vishal
    public function hookActionAfterCreateCustomerFormHandler(array $params)
    {
        $id_customer = $params['id'];
        $customerFormData = $params['form_data'];
        $this->registerAffiliate($id_customer, $customerFormData);
    }

    public function hookActionCustomerFormBuilderModifier(array $params)
    {
        $formBuilder = $params['form_builder'];
        $id_customer = $params['id'];
        $config = Configuration::get('kb_affiliates_basic_settings', false, null, $this->context->shop->id);
        /**
         * Start Changes for PS8 and PHP8 Compatibility - Using json_decode
         * NAAug2023 json_decode
         * @date 29-08-2023
         * @author Nikhil Aggarwal
         */
        $config = json_decode($config, true);
        // Changes end by Nikhil
        if ($config['enable'] == 1) {
            if (isset($id_customer)) {
                $sql = "SELECT * FROM " . _DB_PREFIX_ . "affiliate_customers where id_customer=" . (int) $id_customer;
                $result = DB::getInstance()->getRow($sql);
                /**
                 * Start Changes to fix the error of Trying to access array offset on value of type bool on customer page 
                 * Adding is_array condition
                 * NASep admin_customer_is_array
                 * @date 04-09-2023
                 * @modifier Nikhil Aggarwal
                 */
                if (is_array($result) && count($result) > 1) {
                    return;
                    // Changes end by Nikhil
                } else {
                    $formBuilder->add('register_as_affiliate', SwitchType::class, [
                        'label' => $this->l('Register as Affiliate'),
                        'required' => false,
                    ]);
                    $params['data']['register_as_affiliate'] = false;
                }
            } else {
                $formBuilder->add('register_as_affiliate', SwitchType::class, [
                    'label' => $this->l('Register as Affiliate'),
                    'required' => false,
                ]);
                $params['data']['register_as_affiliate'] = false;
            }
            $formBuilder->setData($params['data']);
        }
    }

    public function hookActionAfterUpdateCustomerFormHandler(array $params)
    {
        $id_customer = $params['id'];
        $customerFormData = $params['form_data'];
        $this->registerAffiliate($id_customer, $customerFormData);
    }

    public function registerAffiliate($id_customer, $customerFormData = array())
    {
        if (isset($customerFormData['register_as_affiliate']) && (int) $customerFormData['register_as_affiliate'] == 1) {
            $sql = "SELECT * FROM " . _DB_PREFIX_ . "affiliate_customers where id_customer=" . (int) $id_customer;
            $result = DB::getInstance()->getRow($sql);

            if (isset($result['id_affiliate_customer'])) {
                return;
            }

            $config = Configuration::get('kb_affiliates_basic_settings', false, null, $this->context->shop->id);
            /**
             * Start Changes for PS8 and PHP8 Compatibility - Using json_decode
             * NAAug2023 json_decode
             * @date 29-08-2023
             * @author Nikhil Aggarwal
             */
            $config = json_decode($config, true);
            // Changes end by Nikhil
            $affiliate_customer_obj = new KbAffiliateCustomers();
            $affiliate_customer_obj->id_customer = $id_customer;
            $affiliate_customer_obj->status = 0;
            $affiliate_customer_obj->referral_rate = $config['referral_rate'];
            $affiliate_customer_obj->referral_rate_user_registration = $config['referral_rate_user_registration'];
            $affiliate_customer_obj->referral_code = $this->randomNumber(10);
            $affiliate_customer_obj->use_global_rate = 1;
            $affiliate_customer_obj->use_global_voucher = 1;
            /*             * Start: Changes done by tarun gupta on 4th june 2019
             * to add a feature multiple commission from user end* */

            $affiliate_customer_obj->enable_disable_multiple_commission = $config['enable_disable_multiple_commission'];
            $affiliate_customer_obj->use_global_orders_count = 1;
            $affiliate_customer_obj->disable_commission_after = $config['disable_commission_after'];
            /*             * End: Changes done by tarun gupta on 4th june 2019
             * to add a feature multiple commission from user end* */

            $affiliate_customer_obj->date_from = date("Y-m-d");

            if ($config['enable_generate_voucher'] == 1) {
                $affiliate_customer_obj->id_cart_rules = $this->getVoucher($config);
            }

            if ($config['enable_disable_affiliate_after'] == 1) {
                if ($config['disable_affiliate_after'] == 0) {
                    $affiliate_customer_obj->date_until = date("Y-m-d", strtotime("+365 days"));
                } else {
                    $affiliate_customer_obj->date_until = date("Y-m-d", strtotime("+" . $config['disable_affiliate_after'] . " days"));
                }
            } else {
                $affiliate_customer_obj->date_until = null;
            }

            if ($affiliate_customer_obj->save()) {
                $affiliate_customer_voucher_obj = new KbVouchers();
                $affiliate_customer_voucher_obj->id_affiliate_voucher_customer = Db::getInstance()->Insert_ID();
                $affiliate_customer_voucher_obj->voucher_type = 'fixed';
                $affiliate_customer_voucher_obj->voucher_value = 0;
                $affiliate_customer_voucher_obj->voucher_quantity = 0;
                $affiliate_customer_voucher_obj->voucher_quantity_per_user = 0;
                $affiliate_customer_voucher_obj->save();

                $new_customer = new Customer($id_customer);
                $shop = Shop::getShop($new_customer->id_shop);
                if ($this->checkSecureUrl()) {
                    $base_url = 'https://' . $shop['domain_ssl'];
                } else {
                    $base_url = 'http://' . $shop['domain'];
                }

                Mail::Send(
                    $new_customer->id_lang,
                    'registration_admin',
                    $this->l('A new affiliate has registered on your store'),
                    array(
                        '{affiliate_name}' => $customerFormData['first_name'] . ' ' . $customerFormData['last_name'],
                        '{affiliate_id}' => $customerFormData['email'],
                        '{shop_url_link}' => $base_url,
                        '{shop_name}' => $shop['name'],
                    ),
                    Configuration::get('PS_SHOP_EMAIL'),
                    null,
                    null,
                    null,
                    null,
                    null,
                    _PS_MODULE_DIR_ . 'kbaffiliates/mails/',
                    false,
                    $new_customer->id_shop
                );
            }
        }
    }

    //Generate randome number to save it as the referral code for the affiliate customers
    public function randomNumber($size)
    {
        $alpha_key = '';
        $keys = range('A', 'Z');

        for ($i = 0; $i < 2; $i++) {
            $alpha_key .= $keys[array_rand($keys)];
        }

        $length = $size - 2;

        $key = '';
        $keys = range(0, 9);

        for ($i = 0; $i < $length; $i++) {
            $key .= $keys[array_rand($keys)];
        }

        return $alpha_key . $key;
    }

    public function getVoucher($data)
    {
        $code = $this->randomNumber(8);

        if ($data['voucher_type'] == 'fixed') {
            $minimum_amount = $data['voucher_val'];
            $percent_reduction = 0;
            $fixed_reduction = $data['voucher_val'];
        } else {
            $minimum_amount = 0;
            $percent_reduction = $data['voucher_val'];
            $fixed_reduction = 0;
        }

        $sql = 'INSERT INTO ' . _DB_PREFIX_ . 'cart_rule  SET
                            date_from = "' . pSQL(date('Y-m-d H:i:s', time())) . '",
                            date_to = 
                            "' . pSQL(date('Y-m-d H:i:s', strtotime('365 days'))) . '",
                            description = "AFFILIATE",
                            quantity = ' . (int) $data['voucher_quan'] . ', quantity_per_user = 1, priority = 1,
                            partial_use = 0,
                            code = "' . pSQL($code) . '",'
                . 'minimum_amount = ' . (int) $minimum_amount . ',
                            minimum_amount_tax = 0, 
                            minimum_amount_currency = 0, minimum_amount_shipping = 0,
                            country_restriction = 0, carrier_restriction = 0, group_restriction = 0,
                            cart_rule_restriction = 0, 
                            product_restriction = 0, shop_restriction = 0, 
                            free_shipping = 0,
                            reduction_percent = ' . (int) $percent_reduction . ''
                . ', reduction_amount = ' . (int) $fixed_reduction . ', 
                            reduction_tax = 1, reduction_currency = ' . (int) $this->context->currency->id . ', 
                            reduction_product = 0, gift_product = 0, gift_product_attribute = 0,
                            highlight = 0, active = 1, 
                            date_add = "' . pSQL(date('Y-m-d H:i:s', time())) . '", date_upd = '
                . '"' . pSQL(date('Y-m-d H:i:s', time())) . '"';
        Db::getInstance()->execute($sql);

        $cart_rule_id = Db::getInstance()->Insert_ID();

        Db::getInstance()->execute(
            'INSERT INTO ' . _DB_PREFIX_ . 'cart_rule_shop
            set id_cart_rule = ' . (int) $cart_rule_id . ','
            . 'id_shop = ' . (int) $this->context->shop->id
        );

        /**
         * Fixes to add voucher for all the available languages as it was being saved blank for other languages. So we have added the same to all the languages availble on store
         * @modifier Pragya Maurya
         * @date 20-03-2024
         * PMMar2024 voucher-lang-fixes
         */
        $languages = Language::getLanguages(false);
        foreach ($languages as $lang) {
            Db::getInstance()->execute(
                'INSERT INTO ' . _DB_PREFIX_ . 'cart_rule_lang
                set id_cart_rule = ' . (int) $cart_rule_id . ','
                . 'id_lang = ' . (int) $lang['id_lang'] . ', 
                name = "AFFILIATE"'
            );
        }
        //Ends here

        return $code;
    }

    private function checkSecureUrl()
    {
        $custom_ssl_var = 0;
        if (isset($_SERVER['HTTPS'])) {
            if ($_SERVER['HTTPS'] == 'on') {
                $custom_ssl_var = 1;
            }
        } elseif (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') {
            $custom_ssl_var = 1;
        }
        if ((bool) Configuration::get('PS_SSL_ENABLED') && $custom_ssl_var == 1) {
            return true;
        } else {
            return false;
        }
    }
    //changes end
}" y dentro del modulo en esta carpeta  modules/kbaffiliates/override/classes hay el CartRule.php que esta asi "<?php
/**
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade PrestaShop to newer
 * versions in the future.If you wish to customize PrestaShop for your
 * needs please refer to http://www.prestashop.com for more information.
 * We offer the best and most useful modules PrestaShop and modifications for your online store.
 *
 * @author    knowband.com <<PRESIDIO_ANONYMIZED_EMAIL_ADDRESS>>
 * @copyright 2018 knowband
 * @license   see file: LICENSE.txt
 * @category  PrestaShop Module
 */
if (!defined('_PS_VERSION_')) {
    exit;
}
class CartRule extends CartRuleCore
{
    public function checkReferralExistenceByCustomerId($id_customer)
    {
        $count_exist = 0;
        $count_exist = Db::getInstance()->getValue('SELECT count(*) FROM '._DB_PREFIX_.'affiliate_referrals where id_customer= '. (int) $id_customer);
        return $count_exist;
    }
    
    /**
     * Check if this CartRule can be applied.
     *
     * @param Context $context Context instance
     * @param bool $alreadyInCart Check if the voucher is already on the cart
     * @param bool $display_error Display error
     * @param bool $check_carrier
     * @param bool $useOrderPrices
     *
     * @return bool|mixed|string
     */
    /**
     * Start Changes to make the checkValidity() override compatible with latest versions
     * NAAug2023 checkValidity
     * @date 28-08-2023
     * @modifier Nikhil Aggarwal
     */
    public function checkValidity(Context $context, $alreadyInCart = false, $display_error = true, $check_carrier = true, $useOrderPrices = false)
    {
        if (!CartRule::isFeatureActive()) {
            return false;
        }
        $cart = $context->cart;

        // All these checks are necessary when you add the cart rule the first time, so when it's not in cart yet
        // However when it's in the cart and you are checking if the cart rule is still valid (when performing auto remove)
        // these rules are outdated For example:
        //  - the cart rule can now be disabled but it was at the time it was applied, so it doesn't need to be removed
        //  - the current date is not in the range any more but it was at the time
        //  - the quantity is now zero but it was not when it was added
        if (!$alreadyInCart) {
            if (!$this->active) {
                return (!$display_error) ? false : $this->trans('Este cupón está desactivado', [], 'Shop.Notifications.Error');
            }
            if (!$this->quantity) {
                return (!$display_error) ? false : $this->trans('Este cupón ya ha sido utilizado', [], 'Shop.Notifications.Error');
            }
            if (strtotime($this->date_from) > time()) {
                return (!$display_error) ? false : $this->trans('Este cupón aún no es válido', [], 'Shop.Notifications.Error');
            }
            if (strtotime($this->date_to) < time()) {
                return (!$display_error) ? false : $this->trans('Este cupón ha caducado', [], 'Shop.Notifications.Error');
            }
        }

        /** start : changes done by tarun gupta on 4th june 2019
         * to check the applied voucher is belongs to the first referrer or not**/
        
        if ($this->description == 'AFFILIATE') {
            if ((bool) Context::getContext()->customer->isLogged()) {
                $id_customer = Context::getContext()->customer->id;
                $referral_existence = $this->checkReferralExistenceByCustomerId((int) $id_customer);
                if ($referral_existence == 0) {
                } else {
                    //changes by tarun to resolve the inapropriate message problem reported by shubham
                    return (!$display_error) ? false : $this->trans('Oops, parece que ya has usado este cupón.', array(), 'Shop.Notifications.Error');
                    //changes over
                }
            }
        }
        /** End : changes done by tarun gupta on 4th june 2019
         * to check the applied voucher is belongs to the first referrer or not**/
        /**
         * Start Changes to fix the issue of sql injection
         * Using int in the query
         * NASep2023 pSQL
         * @date 28-09-2023
         * @modifier Nikhil Aggarwal
         */
        if ($cart->id_customer) {
            $quantityUsed = Db::getInstance()->getValue('
			SELECT count(*)
			FROM `' . _DB_PREFIX_ . 'orders` o
			LEFT JOIN `' . _DB_PREFIX_ . 'order_cart_rule` ocr ON o.`id_order` = ocr.`id_order`
			WHERE o.`id_customer` = ' . (int)$cart->id_customer . '
			AND ocr.`deleted` = 0
			AND ocr.`id_cart_rule` = ' . (int) $this->id . '
			AND ' . (int) Configuration::get('PS_OS_ERROR') . ' != o.`current_state`
			');
            if ($alreadyInCart) {
                // Sometimes a cart rule is already in a cart, but the cart is not yet attached to an order (when logging
                // in for example), these cart rules are not taken into account by the query above:
                // so we count cart rules that are already linked to the current cart but not attached to an order yet.

                $quantityUsed += (int) Db::getInstance()->getValue('
                    SELECT count(*)
                    FROM `' . _DB_PREFIX_ . 'cart_cart_rule` ccr
                    INNER JOIN `' . _DB_PREFIX_ . 'cart` c ON c.id_cart = ccr.id_cart
                    LEFT JOIN `' . _DB_PREFIX_ . 'orders` o ON o.id_cart = c.id_cart
                    WHERE c.id_customer = ' . (int)$cart->id_customer . ' AND c.id_cart = ' . (int)$cart->id . ' AND ccr.id_cart_rule = ' . (int)$this->id . ' AND o.id_order IS NULL
                ');
                // Changes end by Nikhil
            } else {
                // When checking the cart rules present in that cart the request result is accurate
                // When we check if using the cart rule one more time is valid then we increment this value
                ++$quantityUsed;
            }
            if ($quantityUsed > $this->quantity_per_user) {
                return (!$display_error) ? false : $this->trans('Ya no puede utilizar este cupón (límite de uso alcanzado)', [], 'Shop.Notifications.Error');
            }
        }

        // Get an intersection of the customer groups and the cart rule groups (if the customer is not logged in, the default group is Visitors)
        if ($this->group_restriction) {
            $id_cart_rule = (int) Db::getInstance()->getValue('
			SELECT crg.id_cart_rule
			FROM ' . _DB_PREFIX_ . 'cart_rule_group crg
			WHERE crg.id_cart_rule = ' . (int) $this->id . '
			AND crg.id_group ' . ((int)$cart->id_customer ? 'IN (SELECT cg.id_group FROM ' . _DB_PREFIX_ . 'customer_group cg WHERE cg.id_customer = ' . (int) $cart->id_customer . ')' : '= ' . (int) Configuration::get('PS_UNIDENTIFIED_GROUP')));
            if (!$id_cart_rule) {
                return (!$display_error) ? false : $this->trans('No puede utilizar este cupón', [], 'Shop.Notifications.Error');
            }
        }

        // Check if the customer delivery address is usable with the cart rule
        if ($this->country_restriction) {
            if (!$cart->id_address_delivery) {
                return (!$display_error) ? false : $this->trans('Debe elegir una dirección de entrega antes de aplicar este cupón a su pedido', [], 'Shop.Notifications.Error');
            }
            $id_cart_rule = (int) Db::getInstance()->getValue('
			SELECT crc.id_cart_rule
			FROM ' . _DB_PREFIX_ . 'cart_rule_country crc
			WHERE crc.id_cart_rule = ' . (int) $this->id . '
			AND crc.id_country = (SELECT a.id_country FROM ' . _DB_PREFIX_ . 'address a WHERE a.id_address = ' . (int) $cart->id_address_delivery . ' LIMIT 1)');
            if (!$id_cart_rule) {
                return (!$display_error) ? false : $this->trans('No puede utilizar este cupón en su país de entrega', [], 'Shop.Notifications.Error');
            }
        }

        // Check if the carrier chosen by the customer is usable with the cart rule
        if ($this->carrier_restriction && $check_carrier) {
            if (!$cart->id_carrier) {
                return (!$display_error) ? false : $this->trans('Debe elegir un transportista antes de aplicar este cupón a su pedido', [], 'Shop.Notifications.Error');
            }
            $id_cart_rule = (int) Db::getInstance()->getValue('
			SELECT crc.id_cart_rule
			FROM ' . _DB_PREFIX_ . 'cart_rule_carrier crc
			INNER JOIN ' . _DB_PREFIX_ . 'carrier c ON (c.id_reference = crc.id_carrier AND c.deleted = 0)
			WHERE crc.id_cart_rule = ' . (int) $this->id . '
			AND c.id_carrier = ' . (int) $cart->id_carrier);
            if (!$id_cart_rule) {
                return (!$display_error) ? false : $this->trans('No puede utilizar este cupón con este transportista', [], 'Shop.Notifications.Error');
            }
        }

        if ($this->reduction_exclude_special) {
            $products = $cart->getProducts();
            $is_ok = false;
            foreach ($products as $product) {
                if (!$product['reduction_applies']) {
                    $is_ok = true;

                    break;
                }
            }
            if (!$is_ok) {
                return (!$display_error) ? false : $this->trans('No puede utilizar este cupón en productos en oferta', [], 'Shop.Notifications.Error');
            }
        }

        // Check if the cart rules appliy to the shop browsed by the customer
        if ($this->shop_restriction && $context->shop->id && Shop::isFeatureActive()) {
            $id_cart_rule = (int) Db::getInstance()->getValue('
			SELECT crs.id_cart_rule
			FROM ' . _DB_PREFIX_ . 'cart_rule_shop crs
			WHERE crs.id_cart_rule = ' . (int) $this->id . '
			AND crs.id_shop = ' . (int) $context->shop->id);
            if (!$id_cart_rule) {
                return (!$display_error) ? false : $this->trans('No puede utilizar este cupón', [], 'Shop.Notifications.Error');
            }
        }

        // Check if the products chosen by the customer are usable with the cart rule
        if ($this->product_restriction) {
            $r = $this->checkProductRestrictionsFromCart($context->cart, false, $display_error, $alreadyInCart);
            if ($r !== false && $display_error) {
                return $r;
            } elseif (!$r && !$display_error) {
                return false;
            }
        }

        // Check if the cart rule is only usable by a specific customer, and if the current customer is the right one
        if ($this->id_customer && $cart->id_customer != $this->id_customer) {
            if (!Context::getContext()->customer->isLogged()) {
                return (!$display_error) ? false : ($this->trans('No puede utilizar este cupón', [], 'Shop.Notifications.Error') . ' - ' . $this->trans('Primero inicie sesión', [], 'Shop.Notifications.Error'));
            }

            return (!$display_error) ? false : $this->trans('No puede utilizar este cupón', [], 'Shop.Notifications.Error');
        }

        if ($this->minimum_amount && $check_carrier) {
            // Minimum amount is converted to the contextual currency
            $minimum_amount = $this->minimum_amount;
            if ($this->minimum_amount_currency != Context::getContext()->currency->id) {
                $minimum_amount = Tools::convertPriceFull($minimum_amount, new Currency($this->minimum_amount_currency), Context::getContext()->currency);
            }

            $cartTotal = $cart->getOrderTotal(
                $this->minimum_amount_tax,
                Cart::ONLY_PRODUCTS,
                null,
                null,
                false,
                $useOrderPrices
            );
            if ($this->minimum_amount_shipping) {
                $cartTotal += $cart->getOrderTotal(
                    $this->minimum_amount_tax,
                    Cart::ONLY_SHIPPING,
                    null,
                    null,
                    false,
                    $useOrderPrices
                );
            }
            $products = $cart->getProducts();
            $cart_rules = $cart->getCartRules(CartRule::FILTER_ACTION_ALL, false);

            foreach ($cart_rules as $cart_rule) {
                if ($cart_rule['gift_product']) {
                    foreach ($products as $key => &$product) {
                        if (empty($product['is_gift']) && $product['id_product'] == $cart_rule['gift_product'] && $product['id_product_attribute'] == $cart_rule['gift_product_attribute']) {
                            $cartTotal = Tools::ps_round($cartTotal - $product[$this->minimum_amount_tax ? 'price_wt' : 'price'], (int) $context->currency->decimals * Context::getContext()->getComputingPrecision());
                        }
                    }
                }
            }

            if ($cartTotal < $minimum_amount) {
                return (!$display_error) ? false : $this->trans('El importe mínimo para beneficiarse de este cupón es de %s.', [Tools::getContextLocale($context)->formatPrice($minimum_amount, $context->currency->iso_code)], 'Shop.Notifications.Error');
            }
        }

        /* This loop checks:
          - if the voucher is already in the cart
          - if a non compatible voucher is in the cart
          - if there are products in the cart (gifts excluded)
          Important note: this MUST be the last check, because if the tested cart rule has priority over a non combinable one in the cart, we will switch them
         */
        $nb_products = Cart::getNbProducts($cart->id);
        $otherCartRules = [];
        if ($check_carrier) {
            $otherCartRules = $cart->getCartRules(CartRule::FILTER_ACTION_ALL, false);
        }
        if (count($otherCartRules)) {
            foreach ($otherCartRules as $otherCartRule) {
                if ($otherCartRule['id_cart_rule'] == $this->id && !$alreadyInCart) {
                    return (!$display_error) ? false : $this->trans('Este cupón ya está en su cesta', [], 'Shop.Notifications.Error');
                }
                $giftProductQuantity = $cart->getProductQuantity($otherCartRule['gift_product'], $otherCartRule['gift_product_attribute']);

                if ($otherCartRule['gift_product'] && !empty($giftProductQuantity['quantity'])) {
                    --$nb_products;
                }

                if ($this->cart_rule_restriction && $otherCartRule['cart_rule_restriction'] && $otherCartRule['id_cart_rule'] != $this->id) {
                    $combinable = Db::getInstance()->getValue('
					SELECT id_cart_rule_1
					FROM ' . _DB_PREFIX_ . 'cart_rule_combination
					WHERE (id_cart_rule_1 = ' . (int) $this->id . ' AND id_cart_rule_2 = ' . (int) $otherCartRule['id_cart_rule'] . ')
					OR (id_cart_rule_2 = ' . (int) $this->id . ' AND id_cart_rule_1 = ' . (int) $otherCartRule['id_cart_rule'] . ')');
                    if (!$combinable) {
                        $cart_rule = new CartRule((int) $otherCartRule['id_cart_rule'], $cart->id_lang);
                        // The cart rules are not combinable and the cart rule currently in the cart has priority over the one tested
                        if ($cart_rule->priority <= $this->priority) {
                            return (!$display_error) ? false : $this->trans('Este cupón no se puede combinar con otro cupón que ya esté en su cesta: %s', [$cart_rule->name], 'Shop.Notifications.Error');
                        } else {
                            // But if the cart rule that is tested has priority over the one in the cart, we remove the one in the cart and keep this new one
                            $cart->removeCartRule($cart_rule->id);
                        }
                    }
                }
            }
        }

        if (!$nb_products) {
            return (!$display_error) ? false : $this->trans('La cesta está vacía', [], 'Shop.Notifications.Error');
        }

        // Check if order cart rule was removed from back office
        $removed_order_cartRule_id = (int) Db::getInstance()->getValue('
			SELECT ocr.`id_order_cart_rule`
			FROM `' . _DB_PREFIX_ . 'order_cart_rule` ocr
			LEFT JOIN `' . _DB_PREFIX_ . 'orders` o ON ocr.`id_order` = o.`id_order`
			WHERE ocr.`id_cart_rule` = ' . (int) $this->id . '
			AND ocr.`deleted` = 1
			AND o.`id_cart` = ' . (int)$cart->id);
        if ($removed_order_cartRule_id) {
            return (!$display_error) ? false : $this->trans('No puede utilizar este cupón porque se ha eliminado manualmente.', [], 'Shop.Notifications.Error');
        }

        if (!$display_error) {
            return true;
        }
    }
}