<?php

define('INI_CHAR', '{'); // Caracter de inicio
define('END_CHAR', '}'); // Caracter de fin

/**
 * CN_TABLE engulfs most of the services required for data mainuplation by other
 * classes
 *
 * @author narange
 */
class CN_TABLE {

    /**
     * Gets all records of a table
     *
     * @param Doctrine_Table $table_name The name of the table to query
     * @return Doctrine_Collection|array
     */
    public static function getAll($table_name) {
        //Obtener todas las filas de una tabla/vista
        $table = Doctrine_Core::getTable($table_name);
        return $table->findAll();
    }

    /**
     * Gets all records of a table
     *
     * @param Doctrine_Table $table_name The name of the table to query
     * @param boolean $limit_results
     * @param array $criteria
     * @return Doctrine_Collection|array
     */
    public static function getAllWithCriteria($table_name, $limit_results, $criteria) {
        //Obtener todas las filas de una tabla/vista
        $table = Doctrine_Core::getTable($table_name);
    }

    /**
     * crea el sql de consulta para los parametros de entrada
     * devuelve las filas de la base de datos
     *
     * @param array $table_names
     * @param array $table_join_ids
     * @param array $fields
     * @param int $tot_num_records
     * @param array $field_conditions
     * @param array $field_or_conditions
     * @param string $query_qualifier
     * @param array $fields_orderBy
     * @param string $sortBy
     * @return array
     */
    public static function getAllWithFriendFields($table_names, $table_join_ids, $fields, &$tot_num_records, $field_conditions = null, $field_or_conditions = null, $query_qualifier = null, $summatory = null, $sum_res = null, $fields_orderBy = null, $sortBy = null) {

        //se instancia la clase del manejo del log
        $logger = sfContext::getInstance()->getLogger();
        $logger->info("Obtener consulta");


        //valida si viene los datos de ordenamiento
        if (!is_null($fields_orderBy) && is_null($sortBy)) {

            $has_coma = false;
            foreach ($fields_orderBy as $value) {
                if ($has_coma) {
                    $sortBy.=' , ';
                }
//                if (!is_null($sortBy)) {
//                    $sortBy.=' , ';
//                }
                $sortBy.=$value;
                $has_coma = true;
            }
        }

        //variable para el sql
        $sql = "";
        //array de alias (tab) para las tablas
        $tids = array();
        for ($i = 0; $i < count($table_names); $i++) {
            $tids[$table_names[$i]] = 'tab' . $i;
        }

        //se anexa  total de columnas
        $sql_count = 'SELECT COUNT(*) AS num_filas';
        $qq = $query_qualifier != null ? $query_qualifier : '';
        $logger->info("*** Cualificador: " . $query_qualifier);
        $sql .= "SELECT *
            FROM (SELECT row_.*, ROWNUM rownum_
            FROM ( ";

        $sql_body = "SELECT $qq ";

        //recorre cada alias y anexa las variables de las tablas al sql
        foreach ($tids as $tab_name => $alias) {
            if (array_key_exists($tab_name, $fields)) {
                foreach ($fields[$tab_name] as $fname => $falias) {
                    $fexpres = ''; // The expression that will hold the fields
//                    $logger->info("[CN_TABLE] Nombres de campos de tabla. " . $fname);
                    $concats = explode(',', $fname);
                    $i = 0;
                    foreach ($concats as $concat) {

                        //si posee letras el valor
                        if (preg_match('/[A-z_]/', $concat)) {
                            //si es una fecha
                            if (strpos($concat, 'fecha') === false) {
                                $fexpres .= "$alias.$concat";
                            } else {

                                /*
                                 * Si es fecha_log
                                 */
                                if ($concat == 'fecha_log'
                                        || $concat == 'fecha_facturacion'
                                        || $concat == 'fecha_estado') {
                                    //cambiar el formato a la fecha
                                    $fexpres .= "to_char($alias.$concat, 'YYYY-MM-DD HH:MI AM')";
                                } else {
                                    //cambiar el formato a la fecha
                                    $fexpres .= "to_char($alias.$concat, 'YYYY-MM-DD')";
                                }
                            }
                        } else {
                            //si posee espacios colocar entre comillas
                            if (preg_match("/ /", $concat)) {

                                $fexpres .= "'$concat'";
                            } else {

                                $fexpres .= "$concat";
                            }
                        }
//                        if ($i < count($concats) - 1) {
//                            $fexpres.= '||';
//                            $i++;
//                        }
                    }

                    $sql_body.=" $fexpres as $falias,";
                }
            }
        }
        $sql_body = substr($sql_body, 0, -1);

        $sql.=$sql_body;

        if (!is_null($query_qualifier)) {
            $sql_count.=" FROM ( " . $sql_body . " ";
        }

        //anexar tabla principal al sql
        $main_tab_name = $table_names[0];
        $sql_from = " FROM $main_tab_name $tids[$main_tab_name]";

        //recorre cada alias y anexa los join de las tablas al sql
        foreach ($table_join_ids as $tab_name => $join_ids) {

            $rel_val = explode(',', $tab_name);
            $tab = $rel_val[0];
            if (count($join_ids) == 0) {
                $sql_from.=", $tab $tids[$tab]";
            } else {
                $jtype = count($rel_val) > 1 ? $rel_val[1] : '';

                $sql_from.=" $jtype JOIN $tab $tids[$tab] ON";
                $j = 0;
                //join de tablas con sus alias
                foreach ($join_ids as $id_name => $rel_name) {

                    //validar si los alias son diferentes en las tablas
                    if (!preg_match("/-/", $id_name)) {//valida si esta la coma
                        $sql_from.=" $tids[$rel_name].$id_name = $tids[$tab].$id_name";
                    } else {
                        $id_name_alias = explode('-', $id_name); //divide el string en un array
                        $sql_from.=" $tids[$rel_name].$id_name_alias[0] = $tids[$tab].$id_name_alias[1]";
                    }

                    //si hay mas parametros de join
                    if ($j < count($join_ids) - 1) {
                        $sql_from.= ' AND';
                        $j++;
                    }
                }
            }
        }

        $sql.=$sql_from;
        $sql_count.=$sql_from;

        //filtros para la consulta
        $where = '';
        if (!is_null($field_or_conditions) || !is_null($field_conditions)) {
            $where.=' WHERE ';
        }

        $appendAnd = '';
        $condNorm = '';
        $condCount = '';

        //filtros de condicion or
        if (!is_null($field_or_conditions)) {
            $condOr = CN_TABLE::extractSQLConditions($field_or_conditions, 'OR', $tids, false);
            if (trim($condOr) != '') {
                $condNorm.=' (' . $condOr . ')';
                $condCount.=' (' . $condOr . ')';
                $appendAnd .= ' AND ';
            }
        }

        //filtros de condicion and
        if (!is_null($field_conditions)) {

            //validar si hubo parametros de filtro
            $filtro = CN_TABLE::extractSQLConditions($field_conditions, 'AND', $tids, true, $sortBy);
            $logger->info("+-------------------------" . $filtro);

            //debe ser diferente de null, vacio
            //tab indica que hay mas filtros 
            if (preg_match("/tab/", $filtro)) {
                $condNorm.=$appendAnd . $filtro;
            } else {
                $condNorm.= $filtro;
            }

            //validar si hubo parametros de filtro
            $filtro = CN_TABLE::extractSQLConditions($field_conditions, 'AND', $tids, false);
            //debe ser diferente de null, vacio
            //tab indica que hay mas filtros 
            if (preg_match("/tab/", $filtro)) {
                $condCount.=$appendAnd . $filtro;
            } else {
                $condCount.= $filtro;
            }
        }

        if ($condNorm != '') {

//            $sql.= $where == '' ? ') row_ )' : $where . $condNorm;

            if ($where == '') {
                //$fields_orderBy= null, $sortBy=null
                //agregar ordenamiento
                if (!is_null($sortBy)) {
                    $sql.= ' ORDER BY ' . $sortBy;
                }
                $sql.= ' ) row_ )';
            } else {

                $sql.= $where . $condNorm;
            }
        } else {
            //$fields_orderBy= null, $sortBy=null
            //agregar ordenamiento
            if (!is_null($sortBy)) {
                $sql.= ' ORDER BY ' . $sortBy;
            }
            $sql.= ' )  row_ )';
        }

        if ($condCount != '') {
            $sql_count.= $where . $condCount;
        }

        if (!is_null($query_qualifier)) {
            $sql_count.=" ) ";
        }

        //ejecutar el sql
        $count_records = CN_TABLE::executeSQL($sql_count);
        //validar si hay registros
        if (!is_null($count_records)) {
            //contar numero de registros
            $tot_num_records = $count_records[0]['num_filas'];
        }

        return CN_TABLE::executeSQL($sql);
    }

    /**
     * extraer el sql con las condiciones de la consulta
     *
     * @param array $field_conditions
     * @param string $connector
     * @param array $tids the table ids
     * @return string the resulting sql
     */
    public static function extractSQLConditions($field_conditions, $connector, $tids, $with_rows, $sortBy = null) {

        $sql = '';
        $append_row_start = '';

//      $append_row_end = $with_rows ? ' ) row_ )' : '';
        if ($with_rows) {
            //$fields_orderBy= null, $sortBy=null
            //validar campos de ordenamiento
            if (!is_null($sortBy)) {
                $order = ' ORDER BY ' . $sortBy;
            } else {
                $order = '';
            }
            $append_row_end = $order . ' ) row_ )';
        } else {

            $append_row_end = '';
        }

        $i = 0;

        //seleccionar el tipo de filtro en sql
        foreach ($field_conditions as $tab_name => $conditions) {
            $j = 0;
            foreach ($conditions as $id_name => $expres) {
                $id_names = explode(',', $id_name);
                $id_name = $id_names[0];
                $row_type = count($id_names) > 1 ? $id_names[1] : null;
                $k = 0;
                foreach ($expres as $type => $params) {
                    if ($id_name == 'rownum' && !$with_rows) {
                        $sql = substr($sql, 0, -4);
                        $k++;
                    } else if ($id_name == 'rownum') {
                        if ($row_type == 'start')
                            $append_row_start = " WHERE rownum_ $type $params[0] ";
                        if ($row_type == 'end') {

                            if (!is_null($sortBy)) {
                                $order = ' ORDER BY ' . $sortBy;
                            } else {
                                $order = '';
                            }

                            $append_row_end = $order . " ) row_ WHERE ROWNUM $type $params[0]) ";
                        }

                        $sql = substr($sql, 0, -4);
                        $k++;
                    } else {
                        $poner_comillas = false;
                        if ($id_name == 'condition') {
                            $field_names = array();
                            for ($i = 1; $i < count($id_names); $i++) {
                                $field_names[] = $id_names[$i];
                            }
                            // primer parámetro
                            $param1 = explode(',', $params[0]);
                            $full_field_name = "$tids[$tab_name].$param1[1]";
                            //segundo parámetro
                            $param2 = explode(',', $params[1]);
                            $params[0] = "$tids[$tab_name].$param2[1]";
                        } else {
                            /*
                             * si biene un dato que puede tener varios tipos de filtros
                             * extraer el numero 2 que representa dos posibilidades
                             * solo funciona para 2 tipos de filtro y si no se van agregar los dos
                             */
                            if (substr($id_name, -1, 1) == '2') {
                                $id_name = substr($id_name, 0, -1);
                            }


                            $poner_comillas = true;
                            $full_field_name = "$tids[$tab_name].$id_name";
                        }
                        /*
                         * manejo de identificador de filtro sql
                         */
                        switch ($type) {
                            //si es likeall colocar % al inicio y al final
                            case 'LIKEALLPLUS':
                                $full_express = implode('', $params);
                                $full_express = strtolower($full_express);
                                $sql.=" ( LOWER($full_field_name) LIKE '%$full_express' ";

                                //si posee espacios el parametro
                                //se busca por cada uno
                                if (preg_match("/ /", $params[0])) {

                                    //parte el parametro por espacios
                                    $caracteres = preg_split('/ /', $params[0], -1, PREG_SPLIT_NO_EMPTY);

                                    //valida que hay particion por espacios
                                    if (!is_null($caracteres)) {

                                        $sql.=" or ( ";

                                        //para imprimir el parametro de conexion and
                                        $varias = false;
                                        //recorre el parametro dividido en espacios
                                        foreach ($caracteres as $value) {
                                            if ($varias) {
                                                $sql.=" and ";
                                            }

                                            //crea sql para cada valor
                                            $sql.=" LOWER($full_field_name) LIKE '%$value%' ";


                                            $varias = true;
                                        }


                                        $sql.=" ) ";
                                    }
                                }

                                $sql.=" ) ";
                                break;
                            //si es likeall colocar % al inicio y al final
                            case 'LIKEALL':
                                $full_express = implode('', $params);
                                $full_express = strtolower($full_express);
                                $sql.=" ( LOWER($full_field_name) LIKE '%$full_express' ) ";
                                break;
                            //si es like colocar % al final
                            case 'LIKE':
                                $full_express = implode('', $params);
                                $full_express = strtolower($full_express);
                                $sql.=" LOWER($full_field_name) $type '$full_express'";
                                break;
                            //si es: IS NOT NULL o IS NULL
                            case 'IS':
                                $sql.=" $full_field_name $type $params ";
                                break;
                            //si es: NULL
                            case 'NULL':
                                $sql.=" $full_field_name IS $params[0] ";
                                break;
                             //si es: IN
                            case 'IN':
                                /* la lista debe venir eg 1,2,3 para numerico o '1','2','3' para string */
                                $sql .= " $full_field_name $type ($params[0])";
                                break;
                            //si es between variables entre and
                            case 'BETWEEN':
                                if ($poner_comillas) {
                                    $params[0] = "'$params[0]'";
                                    $params[1] = "'$params[1]'";
                                }
                                $sql.=" $full_field_name $type $params[0] AND $params[1]";
                                break;
                            /*
                             * si es between variables entre and
                             * prueba para fecha
                             * colocar la conversion de  formato fecha
                             * para no tener en cuenta la hora
                             */
                            case 'BETWEENFECHA':
                                if ($poner_comillas) {
                                    $params[0] = "'$params[0]'";
                                    $params[1] = "'$params[1]'";
                                }
//                                $sql.="  to_char($full_field_name, 'YYYY-MM-DD') BETWEEN $params[0] AND $params[1]";
                                $sql.="  $full_field_name BETWEEN to_date($params[0], 'YYYY-MM-DD') AND to_date($params[1], 'YYYY-MM-DD') ";
                                break;
                            default:
                                if ($poner_comillas) {
                                    $params[0] = "'$params[0]'";
                                }
                                $sql.=" $full_field_name $type $params[0]";
                                break;
                        }

                        if ($k < count($expres) - 1) {
                            $sql.= " $connector";
                            $k++;
                        }
                    }
                }
                if ($j < count($conditions) - 1) {
                    $sql.= " $connector";
                    $j++;
                }
            }
            if ($i < count($field_conditions) - 1) {
                $sql.= trim($sql) != '' ? " $connector" : '';
                $i++;
            }
        }
        $sql.=$append_row_end . $append_row_start;
        return $sql;
    }

    /**
     * obtener la sumatoria de una consulta
     *
     * @param array $table_names
     * @param array $table_join_ids
     * @param array $summatory_data
     * @return array
     */
    public static function getSum($table_names, $table_join_ids, $fields, $summatory_data, $field_conditions = null, $field_or_conditions = null, $query_qualifier = null) {
        $tids = array();
        for ($i = 0; $i < count($table_names); $i++) {
            $tids[$table_names[$i]] = 'tab' . $i;
        }
        // sum supper clause
        //sql de sum
        $sql = " SELECT ";
        //variables a realizar la sumatorio
        foreach ($tids as $tab_name => $alias) {
            if (array_key_exists($tab_name, $summatory_data)) {
                if (array_key_exists('count', $summatory_data[$tab_name])) {
                    $sql.=" count(*) as " . $summatory_data[$tab_name]['count'] . ", ";
                }
                foreach ($summatory_data[$tab_name]['fields'] as $fname) {
                    /*
                     * Validar que no posea case o demas operaciones - Modifico 20120514
                     */
                    if (!preg_match("/#/", $fname)) {//valida si esta la coma
                        $sql.=" SUM($fname) AS $fname,";
                    } else {
                        $fname_array = explode('#', $fname); //divide el string en un array

                        $sql.=" SUM($fname_array[0]) AS $fname_array[1],";
                    }
                }
                if (array_key_exists('labels', $summatory_data[$tab_name])) {
                    foreach ($summatory_data[$tab_name]['labels'] as $label) {
                        $labelValues = explode(',', $label);
                        $labelField = $labelValues[0];
                        $labelDisplay = count($labelValues) > 1 ? $labelValues[1] : '';
                        $sql.=" '$labelDisplay' AS $labelField,";
                    }
                }
            }
        }

        $sql = substr($sql, 0, -1);

        // Include query qualifier in an inner clause
        $qq = $query_qualifier != null ? $query_qualifier : '';
        //adjuntar sql pra la sumatoria
        $sql.= " FROM ( SELECT $qq  ";
        foreach ($tids as $tab_name => $alias) {
            if (array_key_exists($tab_name, $fields)) {
                foreach ($fields[$tab_name] as $fname => $falias) {
                    $fexpres = ''; // The expression that will hold the fields
                    $concats = explode(',', $fname);
                    $i = 0;
                    foreach ($concats as $concat) {
                        if (preg_match('/[A-z_]/', $concat)) {
                            //validar si es fecha
                            if (strpos($concat, 'fecha') === false)
                                $fexpres .= "$alias.$concat";
                            else
                            //cambiar el formato de fecha
                                $fexpres .= "to_char($alias.$concat, 'YYYY-MM-DD')";
                        }
                        else {
                            //si posee un espacio
                            if (preg_match("/ /", $concat)) {

                                $fexpres .= "'$concat'";
                            } else {

                                $fexpres .= "$concat";
                            }
                        }
//                        if ($i < count($concats) - 1) {
//                            $fexpres.= '||';
//                            $i++;
//                        }
                    }

                    $sql.=" $fexpres as $falias,";
                }
            }
        }

        $sql = substr($sql, 0, -1);

        // From clause
        $main_tab_name = $table_names[0];
        //tabla principal
        $sql_from = " FROM $main_tab_name $tids[$main_tab_name]";

        //tablas de join
        //recorre cada alias y anexa los join de las tablas al sql
        foreach ($table_join_ids as $tab_name => $join_ids) {

            $rel_val = explode(',', $tab_name);
            $tab = $rel_val[0];
            if (count($join_ids) == 0) {
                $sql_from.=", $tab $tids[$tab]";
            } else {
                $jtype = count($rel_val) > 1 ? $rel_val[1] : '';

                $sql_from.=" $jtype JOIN $tab $tids[$tab] ON";
                $j = 0;
                //join de tablas con sus alias
                foreach ($join_ids as $id_name => $rel_name) {

                    //validar si los alias son diferentes en las tablas
                    if (!preg_match("/-/", $id_name)) {//valida si esta la coma
                        $sql_from.=" $tids[$rel_name].$id_name = $tids[$tab].$id_name";
                    } else {
                        $id_name_alias = explode('-', $id_name); //divide el string en un array

                        /*
                         * Si las variables son por request - Modifico 20120514
                         */
                        if ($id_name_alias[1] == 'request') {

                            $valor = $request[$rel_name];

                            $sql_from.=" $tids[$tab].$id_name_alias[0] = '$valor'";
                        } else {

                            $sql_from.=" $tids[$rel_name].$id_name_alias[0] = $tids[$tab].$id_name_alias[1]";
                        }
                    }

                    //si hay mas parametros de join
                    if ($j < count($join_ids) - 1) {
                        $sql_from.= ' AND';
                        $j++;
                    }
                }
            }
        }

        //antes 20111122
//        foreach ($table_join_ids as $tab_name => $join_ids) {
//
//            //divide la variable por coma (,)
//            $rel_val = explode(',', $tab_name);
//            $tab = $rel_val[0];
//            $jtype = count($rel_val) > 1 ? $rel_val[1] : '';
//
//            $sql_from.=" $jtype JOIN $tab $tids[$tab] ON";
//            $j = 0;
//            foreach ($join_ids as $id_name => $rel_name) {
//                $sql_from.=" $tids[$rel_name].$id_name = $tids[$tab].$id_name";
//                if ($j < count($join_ids) - 1) {
//                    $sql_from.= ' AND';
//                    $j++;
//                }
//            }
//        }

        $sql.=$sql_from;

        //filtros para la consulta
        $where = '';
        if (!is_null($field_or_conditions) || !is_null($field_conditions)) {
            $where.=' WHERE ';
        }

        $appendAnd = '';
        //filtros de condicion or
        if (!is_null($field_or_conditions)) {
            $where.='(' . CN_TABLE::extractSQLConditions($field_or_conditions, 'OR', $tids, false) . ')';
            $appendAnd .= ' AND ';
        }
        //filtros de condicion and
        if (!is_null($field_conditions)) {
            $where.=$appendAnd . CN_TABLE::extractSQLConditions($field_conditions, 'AND', $tids, false);
        }

        $sql.=$where;

        //recorre los valores y construye parte del sql
        foreach ($tids as $tab_name => $alias) {
            if (array_key_exists($tab_name, $summatory_data)) {
                foreach ($summatory_data[$tab_name] as $data_id => $data_val) {
                    $id = explode(',', $data_id);
                    $name = $id[0];
                    if ($name == 'condition') {
                        $sql.= $where != '' ? ' AND ' : ' WHERE ';
                        $where = $where != '' ? $where : ' WHERE ';
                        foreach ($data_val as $cond_val) {
                            if ($cond_val != 'field') {
                                $sql.=$cond_val;
                            } else {
                                $sql.="$alias.$id[1]";
                            }
                        }
                    }
                }
            }
        }
        $sql.= ' ) ';

        //ejecutar el sql
        return CN_TABLE::executeSQL($sql);
    }
    
    /**
     * Metodo de envio de correos
     * 
     * @param type $report_params
     * @param type $datos_usuario
     * @param type $subject
     * @param type $currentUri
     * @param type $ruta
     * @param type $adjunto
     * @param type $progress_key
     */
    public static function envioCorreo($report_params, $datos_usuario, $subject, $currentUri, $ruta, $adjunto, $progress_key, $array_adjuntos,$body) {

        /**
         * Clase de log
         */
        $logger = sfContext::getInstance()->getLogger();
        $logger->info('Metodo Envio de Correo.');

        /**
         * ipServidorCorreo
         */
       //$ipServidorCorreo = $report_params["ipServidorCorreo"];
         $logger->info('*** Variables configuración ***');
        $i = 1;
        $ipServidorCorreo = sfConfig::get('app_ipServidorCorreo');
        $email_envio = sfConfig::get('app_correoEnvio');
        //$SMTPSecure = sfConfig::get('app_SMTPSecure');
        //$SMTPAuth = sfConfig::get('app_SMTPAuth');
        //$port = sfConfig::get('app_port');
        //$username = sfConfig::get('app_username');
        //$password = sfConfig::get('app_password');

        /**
         * ipServidorCorreo
         */
        //$ipServidorCorreo = $report_params["ipServidorCorreo"];
        $logger->info('IP SERVIDOR de Correo:'.$ipServidorCorreo);
        $logger->info('EMAIL ENVIO:'.$email_envio);

        
        
        /**
         * Variables
         */
        $i = 0;

        
        
        
        /**
         * PHPMailer
         */
        // Instanciar PHPMailer una primera Vez
        $mail = new PHPMailer(); // defaults to using php "mail()"


        /*
         * Sofhouse
         */
        $mail->IsSMTP(); // telling the class to use SMTP
        $mail->SMTPSecure = "ssl";
        $mail->SetFrom($email_envio, 'Sofhouse');
        $mail->AddReplyTo($email_envio, 'Sofhouse');
        $mail->SMTPAuth = true;
        $ipServidorCorreo = "192.168.2.1";
        $mail->Host = $ipServidorCorreo;      // SMTP server
        $mail->Port = 465;                    // set the SMTP port for the GMAIL server
        $mail->Username = "alexia.velasquez";              // SMTP account username
        $mail->Password = "51s4em@s";           // SMTP account password        
        /*
         * INCI
         */
//        $mail->IsSMTP(); // telling the class to use SMTP
//        $mail->SMTPSecure = "ssl";
//        $mail->Host = $ipServidorCorreo;      // SMTP server
        //$mail->SMTPDebug  = 2;                     // enables SMTP debug information (for testing)
        // 1 = errors and messages
        // 2 = messages only
//        $mail->SMTPAuth = true;                  // enable SMTP authentication
//        $mail->Port = 465;                    // set the SMTP port for the GMAIL server
//        $mail->Username = "inci";              // SMTP account username
//        $mail->Password = "Sistemas";           // SMTP account password
//        $mail->SetFrom($report_params["email_envio"], utf8_decode('Contratación Sofhouse'));
//        //$mail->AddReplyTo($report_params["email_envio"], utf8_decode('Nómina INCI'));
//        $mail->AddAddress($report_params["email_envio"], utf8_decode('Contratación Sofhouse'));


        /*
         * ANM
         */
//            $mail->IsSMTP(); // telling the class to use SMTP
//            $mail->SMTPSecure = "tls";
//            $mail->Host = $ipServidorCorreo;      // SMTP server
//            //$mail->SMTPDebug  = 2;                     // enables SMTP debug information (for testing)
//            // 1 = errors and messages
//            // 2 = messages only
//            $mail->SMTPAuth = true;                  // enable SMTP authentication
//            $mail->Port = 25;                    // set the SMTP port for the GMAIL server
//            $mail->Username = "nomina";              // SMTP account username
//            $mail->Password = "Nominaanm";           // SMTP account password
//            $mail->SetFrom($report_params["email_envio"], 'Nómina ANM');
//            $mail->AddReplyTo($report_params["email_envio"], 'Nómina ANM');

        /*
         * SGC
         */
//        $mail->IsSMTP(); // telling the class to use SMTP
//        $mail->SMTPSecure = "tls";
//        $mail->Host = $ipServidorCorreo;      // SMTP server
//            $mail->SMTPDebug  = 2;                     // enables SMTP debug information (for testing)
        // 1 = errors and messages
        // 2 = messages only
//        $mail->SMTPAuth = false;                  // enable SMTP authentication
//        $mail->Port = 587;                    // set the SMTP port for the GMAIL server
//        $mail->Username = "websafi";              // SMTP account username
//        $mail->Password = "wsaf0SGC$";           // SMTP account password
//        $mail->SetFrom($report_params["email_envio"], utf8_decode('Nomina Websafi'));
//            $mail->AddReplyTo($report_params["email_envio"], 'Nómina ANM');

        $mail->Subject = $subject;
        $logger->info('Enviando ' . count($datos_usuario) . ' - ' . $subject);

        /**
         * Recorre usuarios para envio de correo
         */
        $i_porcentaje = 1;
        $cantidad_array = count($datos_usuario);

        // Antes de inicar el proceso largo
        $brecha = 1;
        if ($cantidad_array > 100)
            $brecha = $cantidad_array - (0.99 * $cantidad_array);
        $logger->info("Valor de progress_key: " . $progress_key . " - Cantidad " . $cantidad_array);

        foreach ($datos_usuario as $value) {

            
//            // Guardar un valor en el proceso largo
//            if ($i_porcentaje % $brecha == 0) {
//                MemcacheHandler::getInstance()->set($progress_key, round(($i_porcentaje / $cantidad_array) * 100, 0));
//            }


            $logger->info("Funcionario: " . $value);
            $datos = explode(';', $value);

            //Datos del funcionario para el envio del correo
            $report_params["num_doc"] = $datos[0];
            $report_params["id_tipo_doc"] = $datos[1];
            $report_params["email"] = $datos[2];
            $report_params["email"] = "alexia.velasquez@sofhouse.net";
            $nombre_completo = $report_params["nombre_completo"] = $datos[3];

            //mensaje_extra
            if (isset($report_params["mensaje_extra"])) {
                $report_params["mensaje_extra"] = "<br/><br/>" . $datos[4];
            }

            //arrayadjuntos
            if (isset($report_params["arrayadjuntos"])) {
                $array_adjuntos = array();
                $cant_adjuntos = $report_params["arrayadjuntos"];
                for ($i = 1; $i <= $cant_adjuntos; $i++) {
                    $datos_adj = explode('+', $datos[3 + $i]);
                    $key_datos = $datos_adj[1];
                    $array_adjuntos[$key_datos] = str_replace("+", "/", $datos[3 + $i]);
                }
            }



            /*
             * Operacion con el archivo
             */
            if (true) {

                /*
                 * $mail->AddReplyTo($report_params["email"], $report_params["username"]);
                 */

                // Agregar El correo
                // Agregar el Attachment
                // Cambiar el body
                $address = $report_params["email"];
                $mail->AddAddress($address, $report_params["num_doc"]);

                /**
                 * Reemplazo de caracteres
                 */
                $subject = str_replace("ó", "&oacute;", $subject);
                $report_params["mensaje_extra"] = str_replace("ó", "&oacute;", $report_params["mensaje_extra"]);
                $report_params["mensaje_extra"] = str_replace(",", "<br/>", $report_params["mensaje_extra"]);
                $report_params["mensaje_extra"] = str_replace("null", " ", $report_params["mensaje_extra"]);

                
                //$mail->AltBody = "This is the body in plain text for non-HTML mail clients"; // optional, comment out and test

                $body = str_replace("á", "&aacute;", $body);
                $body = str_replace("é", "&eacute;", $body);
                $body = str_replace("í", "&iacute;", $body);
                $body = str_replace("ó", "&oacute;", $body);
                $body = str_replace("ú", "&uacute;", $body);
                $body = str_replace("ñ", "&ntilde;", $body);
                $mail->MsgHTML($body);
                /**
                 * Si el envio es con adjunto de jasper
                 */
                if ($adjunto) {
//                    $mail->AddAttachment("$ruta/nivel/2- Competencias comunes.docx", "ManualNomina.pdf");      // attachment
//                    $mail->AddAttachment("images/phpmailer_mini.gif"); // attachment
                    foreach ($array_adjuntos as $key => $value) {
                        $mail->AddAttachment("$ruta/$value", $key);      // attachment                        
                    }
                }

                /*
                 *  Enviar el correo
                 */
                if (!$mail->Send()) {
//                        echo "Mailer Error: " . $mail->ErrorInfo;
                    $logger->info("Mailer Error: " . $mail->ErrorInfo . "<br/>");
                } else {
//                        echo "Message sent! ";
                    $logger->info("Correo enviado");
                }

                /*
                 * Limpiar datos del correo
                 */
                $mail->ClearAllRecipients();
                $mail->ClearAttachments();
            } else {
                header('Content-type: application/pdf');
                header('Content-Disposition: attachment; filename="ManualNomina.pdf"');
                readfile("$ruta/Comprobante$i.pdf");
            }

            //Contadores
            $i = $i + 1;
            $i_porcentaje = $i_porcentaje + 1;
//                echo 'Correo enviado por el usuario ' . $report_params["username"] . ' al funcionario ' .
//                $report_params["nombre_completo"] . ' al correo ' . $report_params["email"];
//                echo '<br/>';
        }
        $logger->info("Fin de envio de correos");
        //Actualizar el Memcache
        //MemcacheHandler::getInstance()->set($progress_key, 99);
    }
    

    /**
     * ejecuta un sql en la base de datos
     * @param string $sql
     * @param boolean $noRevisar enviar true en caso de que se quiera que la conexion no cambie las variables de numeros a booleanas, no enviar ningun parametro en caso contrario
     * @return array
     */
    public static function executeSQL($sql, $noRevisar = null) {

        //realiza la conexion a la base de datos
        $conn = Doctrine_Manager::connection();
        //ejecuta el sql y obtiene todos los resultados
        $results = $conn->execute($sql)->fetchAll();

        //inicializa variable de retorno
        $records = array();

        //recorre los resultados de la consulta 
        foreach ($results as $result) {
            $record = array();
            foreach ($result as $key => $value) {
                $key = strtolower($key);
                //cambia los datos para los campos boolean
                if ($noRevisar == null) {
                    if ($key == 'afecta_antigu'
                            || $key == 'afecta_alimen'
                            || $key == 'causa_liquidacion'
                            || $key == 'afecta_antiguedad'
                            || $key == 'afecta_alimentacion'
                            || $key == 'estado'
                            || $key == 'tiempo_liqui'
                            || $key == 'liquida_reint'
                            || $key == 'operador'
                            || $key == 'festivo'
                            || $key == 'prorroga'
                            || $key == 'aplica_descuento'
                            || $key == 'afecta_pago'
                            || $key == 'actual'
                            || $key == 'periodica'
                            || $key == 'usa_dias_calen'
                            || $key == 'activo'
                            || $key == 'aplica_certif'
                            || $key == 'suspension'
                            || $key == 'traslado'
                            || $key == 'aplica_vacac'
                            || $key == 'aplica_tiempo'
                            || $key == 'aplica_numero'
                            || $key == 'aplica_desde_hasta'
                            || $key == 'aplica_oferentes'
                            || $key == 'aplica_relacion'
                            || $key == 'aplica_adjudicatario'
                            || $key == 'aplica_formulario'
                            || $key == 'campo_fijo'
                            || $key == 'obligatorio'
                            || $key == 'interventoria'
                            || $key == 'timbre'
                            || $key == 'liquidado'
                            || $key == 'terminacion'
                            || $key == 'liquidacion'
                            || $key == 'alerta'
                            || $key == 'documento'
                            || $key == 'carta_aceptacion'
                            || $key == 'unilateral'
                            || $key == 'mutuo_acuerdo'
                            || $key == 'sgr'
                            || $key == 'aplica_aprobacion'
                            || $key == 'aplica_proceso'
                            || $key == 'opcional'
                    ){
                        $value = $value == 1 ? true : false;
                    }                   
                    
                    
                }
                //$value = str_replace("&quot;", "'", $value);
                $record[strtolower($key)] = $value;

//                echo $key . " - " . $value . " * ";
            }
            $records[] = $record;
        }
        //retorna el resultado con los cambios pertinentes
        return $records;
    }

    /**
     * adjunta una fila en la base
     *
     * @param <type> $table_name
     * @param array $values
     * @param <type> $id_name
     * @param <type> $id_names
     * @param <type> $field_names
     * @param <type> $has_id_cia
     * @param <type> $has_activo
     * @param string $check_exists
     * @param <type> $has_vigencia
     * @param <type> $other_tab_uq_fields
     * @return Doctrine_Record
     */
    public static function addRow($table_name, array $values, $id_name, $id_names, $field_names, $has_id_cia, $has_activo, $check_exists, $has_vigencia, $other_tab_uq_fields, $has_secuencia = true) {



        /*
         * Variables globales del proyecto
         */
        $tabla_seg = sfConfig::get('app_tablaSeg');
        $tabla_vig_seg = sfConfig::get('app_tablaVigSeg');



        //se instancia la clase del manejo del log
        $logger = sfContext::getInstance()->getLogger();
        $other_tab_vals = array();

        /*
         * recorrer los campos y colocar null(vacio)
         */
        if (!is_null($field_names)) {
            foreach ($field_names as $field_names_value) {
                //si no esta el valor
                if (isset($values[$field_names_value])) {
//                $values[$field_names_value] = null;
                    $logger->info("--+--" . $field_names_value);
                } else {
                    $values[$field_names_value] = null;
                    $logger->info("--*--" . $field_names_value);
                }
            }
        }


        // Populate values with dependent data
        if (!is_null($other_tab_uq_fields)) {

            //recorre las variables para la consulta en otras tablas
            foreach ($other_tab_uq_fields as $fname => $tab_props) {

                //divide la variable
                $fnames = explode(",", $fname);

//                if ($fnames || $fnames < 1) {
//                    $fnameArray = $fnames;
//                } else {
//                    $fnameArray = array($fname);
//                }

                $logger->info("*********************************************1-" . $fname);
                //recorre los campos para la combinacion de ids de otros campos, tabla y
                foreach ($tab_props as $tab_name => $fields) {
                    $key_found = true;
                    //recorre todos los campos para verificar si biene datos y no son nulos
                    foreach ($fnames as $fname) {
                        $logger->info($values[$fname] . "*********************************************2-" . $fname);
                        $key_found = $key_found &&
                                array_key_exists($fname, $values) &&
                                $values[$fname] != null &&
                                $values[$fname] != 'null';

                        if ($values[$fname] != 'null') {

                            $logger->info("*********************************************entro" . $fname);
                        } else {
                            $logger->info("*********************************************no entro" . $fname);
                        }

                        $logger->info("*********************************************variables-" . $values[$fname]);
                        $logger->info("*********************************************3-" . $key_found);
                    }
//                    $key_found = true; //corregir por que no entra la parte de arriba
                    //valida para la busqueda del id
                    if ($key_found) {



                        $logger->info("*********************************************4-");
                        $record = CN_TABLE::getByIdNames($tab_name, $fnames, $values); //obtiene el id para la tabla y campos requeridos diferentes
                        //valida si hay resultado
                        if (!is_null($record)) {
                            //recorre los campos y anexa el valor del record
                            foreach ($fields as $field) {

                                $values[$field] = $record[$field];
                                $logger->info("*********************************************5-" . $values[$field]);

                                $other_tab_vals[$field] = $record[$field];
                                $logger->info("*********************************************6-" . $other_tab_vals[$field]);
                            }
                        } else {


                            /*
                             * recorre los campos y anexa el valor del record - 20111014
                             * Si los datos no se encuentras de cambian por null(vacio)
                             */
                            foreach ($fields as $field) {

                                $values[$field] = null;
//                                unset($values[$field]);
                            }
                        }
                    } else {

                        /*
                         * recorre los campos y anexa el valor del record - 20111014
                         * Si los datos no se encuentras de cambian por null(vacio)
                         */
                        foreach ($fields as $field) {

                            $values[$field] = null;
//                            unset($values[$field]);
                        }
                    }
                }
            }
        }
//        die(); 

        $existing_record = null;

        // Check if the existing one should return
        if (!is_null($check_exists)) {

            //si posee id_cia
            if ($has_id_cia) {
                $check_exists[] = 'id_cia';
            }

            //valida si hay la combinacion con las variables de los campos especificados en check_exist esta ya en la base de datos
            $existing_record = CN_TABLE::getByIdNames($table_name, $check_exists, $values);
        }

        // Create the record
        $table = Doctrine_Core::getTable($table_name); // Fetch the table type
        $record = $table->create();

        //valida si hay la combinacion con las variables de los campos especificados en check_exist
        if ($existing_record != null) {
            $logger->info("[CN_TABLE] Record exists.");
            $record = $existing_record;
        }

        //si exite y hay valores
        if ($existing_record != null && count($values) > 0) {
            $record = $existing_record; // if it existed, then apply it
            $logger->info("[CN_TABLE] Updating record.");
            foreach ($values as $key => $value) {
                if (!in_array($key, $id_names) && $key != 'id_cia' && in_array($key, $field_names)) {
                    $record[$key] = $value;
                    $logger->info("[CN_TABLE] Changing record[$key] = $value");
                }
            }
            $logger->info("[CN_TABLE] Fin Changing record.");

            $logger->info("[CN_TABLE] *** " . $id_name);
            // -- Forced update
            $values[$id_name] = $existing_record[$id_name];
            $tab_id = 'tab';
            $set_segment = '';
            $where_segment = '';
            $q = Doctrine_Query::create()->update("$table_name $tab_id");
            foreach ($values as $key => $value) {
                if (!in_array($key, $id_names) && $key != 'id_cia' && in_array($key, $field_names)) {
                    $q = $q->set("$tab_id.$key", "'$value'");
                } else if (in_array($key, $id_names)) {
                    $where_segment.=" $tab_id.$key = '$value' AND";
                }
            }
            $set_segment = substr($set_segment, 0, -1); //eliminar la ultima posicion
            $where_segment = substr($where_segment, 0, -3); //eliminar el ultimo and

            $q = $q->where($where_segment);

            //actualiza la secuencia para la tabla
            if ($has_secuencia) {
                CN_TABLE::executeSQL("SELECT " . $table_name . "_SEQ.NEXTVAL FROM DUAL"); // Invoke this or it won't work
            }

            //ejecuta el sql de adicion
//            $logger->info("[CN_TABLE] SQL ".$q);
            CN_TABLE::executeSQL($q->getSqlQuery());
            $logger->info("[CN_TABLE] Fin updating record.");
        }

        // Check if the id_name comes in
        $seqId = null;
        if ($existing_record == null && !is_null($id_name) && $has_secuencia) {
            $logger->info("[CN_TABLE] Check seq the $tabla_seg and $tabla_vig_seg.");
            if ($has_id_cia && !$has_vigencia) {// is it a company id?
                // Get the sequence for that company and table
                $seq = CN_TABLE::getByIds($tabla_seg, array(
                            'id_cia' => $values['id_cia'],
                            'nom_entidad' => $table_name)
                );
                // if it doesn't exist, create it
                if (is_null($seq)) {
                    $seq = CN_TABLE::addRow($tabla_seg, array(
                                'id_cia' => $values['id_cia'],
                                'nom_entidad' => $table_name,
                                'seq' => 0), null, null, null, false, false, null, false, null);
                }

                $seq->seq++; // increment the sequence
                $seq->save(); // persist it
                $seqId = $seq->seq; // assign it to the id
            } else if ($has_id_cia && $has_vigencia) { // if not, is it a vigencia sequence??
                //verificar si es con id o no
                if (!isset($values['id_vigencia'])) {
                    $values['id_vigencia'] = $values['vigencia'];
                }

                // Get the sequence for that company and table
                $seq = CN_TABLE::getByIds($tabla_vig_seg, array(
                            'id_cia' => $values['id_cia'],
                            'nom_entidad' => $table_name, 'id_vigencia' => $values['id_vigencia'])
                );

                if (is_null($seq)) { // if it doesn't exist, create it
                    $seq = CN_TABLE::addRow($tabla_vig_seg, array(
                                'id_cia' => $values['id_cia'],
                                'id_vigencia' => $values['id_vigencia'],
                                'nom_entidad' => $table_name,
                                'seq' => 0), null, null, null, false, false, null, false, null);
                }
                $seq->seq++; // increment the sequence
                $seq->save(); // persist it
                $seqId = $seq->seq; // assign it to the id
            } else if (!$has_id_cia && $has_vigencia) {// Sino tiene id_cia, pero si vigencia
                //verificar si es con id o no
                if (!isset($values['id_vigencia'])) {
                    $values['id_vigencia'] = $values['vigencia'];
                }

                // Get the sequence for that company and table
                $seq = CN_TABLE::getByIds($tabla_vig_seg, array(
                            'nom_entidad' => $table_name, 'id_vigencia' => $values['id_vigencia'])
                );

                // if it doesn't exist, create it
                if (is_null($seq)) {
                    $seq = CN_TABLE::addRow($tabla_vig_seg, array(
                                'id_vigencia' => $values['id_vigencia'],
                                'nom_entidad' => $table_name,
                                'seq' => 0), null, null, null, false, false, null, false, null);
                }

                $seq->seq++; // increment the sequence
                $seq->save(); // persist it
                $seqId = $seq->seq; // assign it to the id
            }
        }

        /*
         * prueba para ts_im
         * funciona para no seguir la secuencia, pero aun implica que se lleve el consecutivo en la tabla de CN_TABLE_SEQ
         * se cambia valor por el que ingrese el usuario
         */
//        if ($id_name == 'id_ts_im') {
//            $seqId = $values[$id_name];
//            $logger->info("*** Cambio de id de secuencia: " . $seqId . "-" . $id_name);
//        }

        $logger->info("[CN_TABLE] Listo para guardar.");

        if (!is_null($seqId) && $existing_record == null) { // If the seqId is set
            $logger->info("[CN_TABLE] Saving! with secuence in table");
            $values[$id_name] = $seqId; // Assign it to the new record
            $record->fromArray($values); // Assign the values from the array
            $record->save(); // Save the record
        } else if ($existing_record == null) {
            $logger->info("[CN_TABLE] Saving! with secuence in db");
            $record->fromArray($values); // Assign the values from the array
            $record->save(); // Save the record
            if (is_null($seqId) && !is_null($id_name) && $has_secuencia
                    && !($has_id_cia && $has_vigencia)) {
                $logger->info("[CN_TABLE] SI Actualizar secuencia.");
                $conn = Doctrine_Manager::connection();
                $record[$id_name] = $conn->lastInsertId($table_name);
            } elseif (is_null($seqId) && !is_null($id_name) && !$has_secuencia) {

                $logger->info("[CN_TABLE] SI/NO Actualizar secuencia.");
                $conn = Doctrine_Manager::connection();
                $record[$id_name] = $conn->lastInsertId($table_name);
            } else {

                $logger->info("[CN_TABLE] NO Actualizar secuencia.");
            }
        }

//    if ($existing_record != null) {
//      foreach ($values as $key => $value) {
//        if (!in_array($key, $id_names) && $key != 'id_cia') {
//          $record[$key] = $value;
//          $logger->info("[CN_TABLE] Changing record[$key] = $value");
//        }
//      }
//      $logger->info('[CN_TABLE] Writing form existing');
//    }

        if (is_null($seqId) && !is_null($id_name) && is_null($existing_record)) {
            // if it has a name for its id
            // and no id assigned, ask for
            // it from an apparent
            // existing sequence
        }

        // poner los valores que se esperaban de la otra tabla
        if (count($other_tab_vals) > 0) {
            foreach ($other_tab_vals as $key => $value) {
                $record[$key] = $value;
            }
        }

        return $record;
    }

    /**
     * actualizar fila
     *
     * @param <type> $record
     * @param array $values
     * @return <type>
     */
    public static function updateRow($record, array $values) {
        $record->synchronizeWithArray($values);
        $record->save();
        return $record;
    }

    /**
     *
     * @param <type> $record
     * @param array $values
     * @return <type>
     */
    public static function updateRowFromContainer(Doctrine_Record $record, array $value_names, $container, $fecha_sistema) {

        //crea un array de record para la actualizacion
        foreach ($value_names as $name) {

            $record[$name] = sfAPIActions::extractIfBoolean($container[$name]);
        }

        //anexa variables de fecha sistema que lo requieran
        if ($fecha_sistema && isset($fecha_sistema)) {//agregada, arrojaba un warning - 20111118
            foreach ($fecha_sistema as $key => $value) {

                $record[$key] = $value;
            }
        }

        //guarda el record
        $record->save();
        return $record;
    }

    /**
     * obtener los nombres de los id de una tabla por los campos requeridos
     *
     * @param <type> $table_name
     * @param array $id_names
     * @param array $ids
     * @return <type>
     */
    public static function getByIdNames($table_name, array $id_names, array $ids) {
        $table = Doctrine_Core::getTable($table_name);

        $where = '';
        for ($i = 0; $i < count($id_names); $i++) {

            /*
             * Para el num_doc debe manejarse como texto - 20120309
             */
            if ($id_names[$i] == 'num_doc') {
                $id_val = '\'' . $ids[$id_names[$i]] . '\'';
            } else {
                $id_val = is_numeric($ids[$id_names[$i]]) ? $ids[$id_names[$i]] : '\'' . $ids[$id_names[$i]] . '\'';
            }

            $where.="$id_names[$i] = $id_val";
            if ($i < count($id_names) - 1)
                $where.=' AND ';
        }
        $res = null;
        $records = $table->findByDql($where);
        //Se cambia para que no valide solo con un registro, sino mas de uno - 20160620
        if (sizeof($records) >= 1) {
            $res = $records->getFirst();
        }
        return $res;
    }

    /**
     * obtener el id para los campos de una tabla
     *
     * @param <type> $table_name
     * @param array $ids
     * @return <type>
     */
    public static function getByIds($table_name, array $ids) {
        $table = Doctrine_Core::getTable($table_name);
        $where = '';
        $i = 0;
        foreach ($ids as $key => $value) {
            $where.="$key = ";
            if (is_numeric($value)) {
                $where.="$value";
            } else {
                $where.="'$value'";
            }

            if ($i < count($ids) - 1) {
                $where.=' AND ';
                $i++;
            }
        }
        $res = null;
        $records = $table->findByDql($where);
        //Se cambia para que no valide solo con un registro, sino mas de uno - 20160620
        if (sizeof($records) >= 1) {
            $res = $records->getFirst();
        }
        return $res;
    }

    /**
     *
     * @param <type> $table_name
     * @param array $id_names
     * @param array $ids
     * @return <type>
     */
    public static function getByIdFromContainer($table_name, array $id_names, $id_cont, $has_name_texto = false) {

        //se instancia la clase del manejo del log
        $logger = sfContext::getInstance()->getLogger();
        $logger->info("[CN_TABLE] Metodo obtener id.");


        $table = Doctrine_Core::getTable($table_name);

        $where = '';
        $ids = array();
        for ($i = 0; $i < count($id_names); $i++) {

            //si el id_name es texto
            if ($has_name_texto) {
                $where.="$id_names[$i] = " . "'" . $id_cont[$id_names[$i]] . "'";
            } else {
                $where.="$id_names[$i] = " . $id_cont[$id_names[$i]];
            }

            if ($i < count($id_names) - 1)
                $where.=' AND ';
        }
        $res = null;
        $logger->info("[CN_TABLE] Where: " . $where);
        $records = $table->findByDql($where);
        if (sizeof($records) == 1) {
            $res = $records->getFirst();
        }


        foreach ($records as $value) {

            $logger->info("******recorrer respuesta where: " . $value);
        }
        $logger->info("******recorrer respuesta where: " . $records->__toString());
//            $logger->info("******recorrer respuesta where: " . $res->toArray());

        return $res;
    }

    /**
     * eliminar el id para la tabla
     *
     * @param <type> $table_name
     * @param array $id_names
     * @param array $ids
     * @return <type>
     */
    public static function deleteById($table_name, array $id_names, array $ids) {
        $record = CN_TABLE::getById($table_name, $id_names, $ids);
        $success = $record->delete();

        return $success;
    }

    /**
     * eliminar una fila de la base de datos
     *
     * @param <type> $record
     * @return <type>
     */
    public static function delete($record) {
        $success = $record->delete();

        return $success;
    }

    /**
     * Metodo que registra en la tabla_log una fila para el control de logs
     *
     * @param <type> $id_tabla
     * @param <type> $id_vigencia
     * @param <type> $cen_op
     * @param <type> $id_cia
     * @param <type> $id_mae_bd
     * @param <type> $id_ope_bd
     * @param <type> $id_mae_ter
     * @param <type> $usuario
     * @param <type> $fecha_log
     * @param <type> $comando
     * @param <type> $observacion
     * @return <type>
     */
    public static function registroTableLog($id_tabla, $id_ope_bd, $id_mae_bd, $usuario, $username, $comando, $observacion) {

        $logger = sfContext::getInstance()->getLogger();
        $logger->info("[CN_TABLE] Entro registro tabla log.");

        /*
         * Variables globales del proyecto
         */
        $modulo = sfConfig::get('app_modulo');
        $usuarioERP = sfConfig::get('app_usuarioERP');
        $claveERP = sfConfig::get('app_claveERP');
        $tabla_log = sfConfig::get('app_tablaLog');




        try {
            //sentencia sql para registro log
            $sql = <<<EOD
INSERT INTO $tabla_log (ID_TABLA,ID_ANHO,ID_MAE_BD,ID_OPE_DB,ID_MAE_TER,USUARIO,FECHA_LOG,COMANDO,OBSERVACION) 
VALUES ($id_tabla, extract(year from sysdate), $id_mae_bd ,$id_ope_bd, $usuario, '$username', sysdate, '$comando', $observacion)
EOD;


            //ejecuta y obtiene el resultado del sql
            CN_TABLE::executeSQL($sql);

            //  $logger->info("[CN_TABLE] sql: " . $sql);
        } catch (Excepcion $e) {
            $logger->info("[CN_TABLE]Error al insertar el log");
        }
//        $results = CN_TABLE::executeOCI_SQL_Add($sql, $usuarioERP, $claveERP);

        /*
         * IMPRESION SQL EN EL ARCHIVO DE LOG
         */


        return $sql;
    }

    /**
     * Metodo que registra en la tabla_log una fila para el control de logs
     *
     * @param <type> $request
     * @param <type> $id_ope_bd 
      //1 - indica operacion de consultar
      //2 - indica operacion de actualizar
      //3 - indica operacion de adicionar
      //4 - indica operacion de eliminar
      //5 - indica operacion de anular
     * @param <type> $observacion
     * @return <type>
     */
    public static function registrarLog(sfWebRequest $request, $id_ope_bd, $id_mae_bd, $observacion = null) {
        $logger = sfContext::getInstance()->getLogger();
        $sql = "";
        try {



            //TODO 
            $id_tabla = 'null';
            //id del usuario
            $id_usuario = '0';
            if (isset($request['id_usuario_log'])) {
                $id_usuario = $request['id_usuario_log'];
            }
            //id del tercero del usuario
            $id_tercero = 'null';
            if (isset($request['id_tercero_log'])) {
                $id_tercero = $request['id_tercero_log'];
            }
            //comando de funcionalidad
            $cod_func = 'sin comando';
            if (isset($request['comando'])) {
                $cod_func = $request['comando'];
            }

            //id de companhia
            $id_cia = 'null';
            if (isset($request['id_cia'])) {
                $id_cia = $request['id_cia'];
            }


            //id del tercero del usuario
            $id_tercero = 'null';
            if (isset($request['id_tercero_log'])) {
                $id_tercero = $request['id_tercero_log'];
            }
            //comando de funcionalidad
            $cod_func = 'sin comando';
            if (isset($request['comando'])) {
                $cod_func = $request['comando'];
            }

            switch ($id_ope_bd) {
                case 1:
                    $operacion = "consulto";
                    break;
                case 2:
                    $operacion = "actualizo";
                    break;
                case 3:
                    $operacion = "adiciono";
                    break;
                case 4:
                    $operacion = "elimino";
                    break;
                case 5:
                    $operacion = "anulo";
                    break;
            }

            $nombreTabla = CN_TABLE::consultarNombreTablaBD($id_mae_bd);
            if (is_null($observacion)) {
                $observacion = "'Se $operacion sobre la tabla $nombreTabla desde la funcionalidad: $cod_func.'";
            } else {
                $observacion = "'Se $operacion sobre la tabla $nombreTabla desde la funcionalidad: $cod_func, $observacion'";
            }


            /*
             * registro de consulta en tabla de log $id_tabla, $id_ope_bd, $id_mae_bd, $usuario, $comando, $observacion
             */
            $sql = CN_TABLE::registroTableLog($id_tabla, $id_ope_bd, $id_mae_bd, $id_usuario, $cod_func, $observacion);
        } catch (Exception $exp) {
            $logger->info("[CN_TABLE] Error de Log " . $exp);
        }
        return $sql;
    }

    /**
     * Metodo para obtener el id de la tabla en la base de datos
     *
     * @param <type> $tabla
     * @return <type>
     */
    public static function consultarIdTablaBD($tabla) {

        $id_mae_bd = 0;

        /*
         * Variables globales del proyecto
         */
        $tabla_mae = sfConfig::get('app_tablaMae');

        //sentencia sql para registro log
        $sql = <<<EOD
select * from $tabla_mae
where DES_MAE_BD = '$tabla'
EOD;

        //ejecuta y obtiene el resultado del sql
        $record = CN_TABLE::executeSQL($sql);

        //validar que existe registro de la tabla
        if (count($record) > 0) {

            $id_mae_bd = $record[0]['id_mae_bd'];
        } else {

            //llamar al metodo para crear nuevo registro en la tabla CN_MAE_TER
            $id_mae_bd = CN_TABLE::crearTabla_MAE_BD($tabla);
        }

        return $id_mae_bd;
    }

    /**
     * Metodo para obtener el id de la tabla en la base de datos
     *
     * @param <type> $tabla
     * @return <type>
     */
    public static function consultarNombreTablaBD($tabla) {

        $id_mae_bd = 0;

        /*
         * Variables globales del proyecto
         */
        $tabla_mae = sfConfig::get('app_tablaMae');

        //sentencia sql para registro log
        $sql = <<<EOD
select * from $tabla_mae
where ID_MAE_BD = '$tabla'
EOD;

        //ejecuta y obtiene el resultado del sql
        $record = CN_TABLE::executeSQL($sql);

        //validar que existe registro de la tabla
        if (count($record) > 0) {

            $nombre = $record[0]['des_mae_bd'];
        } else {

            $nombre = "";
        }

        return $nombre;
    }

    /*
     * Crear registro de tabla en XX_MAE_BD - maestro de bade de datos
     */

    public static function crearTabla_MAE_BD($tabla) {


        $id_mae_bd = 0;

        /*
         * Variables globales del proyecto
         */
        $tabla_mae = sfConfig::get('app_tablaMae');

        //obtener id mayor +1 de la tabla
        //sentencia sql para registro log
        $sql = <<<EOD
select nvl(count(ID_MAE_BD)+1,0) as id_seq from $tabla_mae
EOD;

        //ejecuta y obtiene el resultado del sql
        $record = CN_TABLE::executeSQL($sql);

        if (count($record) > 0) {

            $id_mae_bd = $record[0]['id_seq'];
        } else {
            return $id_mae_bd;
        }

        //crear registro en la tabla
        //sentencia sql para registro log
        $sql = <<<EOD
INSERT INTO $tabla_mae VALUES ( $id_mae_bd , '$tabla' )
EOD;

        //ejecuta y obtiene el resultado del sql
        CN_TABLE::executeSQL($sql);

        return $id_mae_bd;
    }

    /**
     * Metodo que ejecuta un insert de la sentencia sql
     * conexion con la base de datos websafiERP
     *
     * @param <type> $sql
     * @param <type> $user
     * @param <type> $pass
     * @return <type>
     */
    public static function executeOCI_SQL_Add($sql, $user, $pass) {

        $logger = sfContext::getInstance()->getLogger();
//    $logger->info("Sql de insert: " . $sql);

        $exito = true;

        /*
         * Variables globales del proyecto
         */
        $modulo = sfConfig::get('app_modulo');
        $ip = sfConfig::get('app_ip');

        /*
         * Conexion a la base de datos
         */
        //base de datos websafiERP
        $conn = oci_connect($user, $pass, $ip);

        //validacion conexion
        if (!$conn) {
            $exito = false;
            $e = oci_error();
//        print htmlentities($e['message']);
            $logger->info("error conn:" . $e['message']);
//            exit;
        }

        $stid = oci_parse($conn, $sql);
        //validar errores
        if (!$stid) {
            $exito = false;
            $e = oci_error($conn);
            $logger->info("error stid:" . $e['message']);
//            exit;
        }

        $exec = oci_execute($stid);
        //validar errores
        if (!$exec) {
            $exito = false;
            $e = oci_error($stid);

            $logger->info("error exec:" . $e['message']);

//        echo htmlentities($e['message']);
//        echo "<pre>";
//        echo htmlentities($e['sqltext']);
//        printf("\n%" . ($e['offset'] + 1) . "s", "^");
//        echo "</pre>";
//            exit;
        } else {
//        echo "Registro insertado correctamente: " . $sql . "<br>";
            $logger->info("Informacion: " . "Registro insertado correctamente: " . $sql);
        }


        //cerrar la conexion en la base de datos
        oci_close($conn);

        //returna array de consulta
        return $exito;
    }

    /**
     * Metodo que ejecuta una sentencia sql y retorna la consulta en un array
     * conexion con la base de datos websafiERP
     *
     * @param <type> $sql
     * @param <type> $user
     * @param <type> $pass
     * @return <type>
     */
    public static function executeOCI_SQL_List($sql, $user, $pass) {

        $logger = sfContext::getInstance()->getLogger();
    $logger->info("Sql de insert: " . $sql);

        /*
         * Variables globales del proyecto
         */
        $modulo = sfConfig::get('app_modulo');
        $ip = sfConfig::get('app_ip');

        /*
         * Conexion a la base de datos
         */
        //base de datos  websafiERP
        $conn = oci_connect($user, $pass, $ip); //se debe verificar cambio de ip para uso fuera de la red interna
        //validacion conexion
        if (!$conn) {
            $e = oci_error();
            $logger->info($e['message']);
//            print htmlentities($e['message']);
//            exit;
        }

        $stid = oci_parse($conn, $sql);
        $exec = oci_execute($stid);

//    echo var_dump($stid);
//    print_r($stid);
//    die();

        $records = array();

        //validar ejecucion
        if ($exec && $stid) {
            while ($row = oci_fetch_array($stid, OCI_ASSOC + OCI_RETURN_NULLS)) {
//        print_r($row);
//            echo "\n" . var_dump($row) . "\n";
                $records[] = $row;
            }
        } else {
            //mensajes de error
            $logger->info("Se produjo un error");
            $e = oci_error($conn);
            $logger->info($e['message']);
//            exit;
        }

        //cerrar la conexion en la base de datos
        oci_close($conn);

        //returna array de consulta
        return $records;
    }

    /**
     * Metodo para retornar string de fecha sistema
     *
     * @return string 
     */
    public static function fechaSistema() {

        //fecha del sistema
        $anho_completo = date('Y'); //anho completo cuatro digitos
        $mes = date('m'); //mes con dos digitos
        $dia = date('d'); //dia con dos digitos
        $fecha_sistema = $anho_completo . '-' . $mes . '-' . $dia;

        return $fecha_sistema;
    }

    /**
     * Metodo para retornar el anho - mes anterior
     *
     * @return string
     */
    public static function fechaAnterior($anho, $mes) {

        //inicializar variables
        $fechaAnterior = array();
        $anho_ant = 0;
        $mes_ant = 0;

        /*
         * obtener fecha siguiente anho - mes
         */

        //valida primer periodo
        if ($mes == 1) {

            $anho_ant = $anho - 1;
            $mes_ant = 12;
        } else {

            $anho_ant = $anho;
            $mes_ant = $mes - 1;
        }

        $fechaAnterior = array(
            'id_anhos' => $anho_ant,
            'id_meses' => $mes_ant
        );


        return $fechaAnterior;
    }

    /**
     * Metodo para retornar el anho - mes siguiente
     *
     * @return string
     */
    public static function fechaSiguiente($anho, $mes) {

        //inicializar variables
        $fechaSiguinte = array();
        $anho_sig = 0;
        $mes_sig = 0;

        /*
         * obtener fecha siguiente anho - mes
         */

        //valida ultimo periodo
        if ($mes == 12) {

            $anho_sig = $anho + 1;
            $mes_sig = 1;
        } else {

            $anho_sig = $anho;
            $mes_sig = $mes + 1;
        }

        $fechaSiguinte = array(
            'id_anhos' => $anho_sig,
            'id_meses' => $mes_sig
        );


        return $fechaSiguinte;
    }

    /**
     * Metodos de aplicacion formula
     * Ejemplo: ( 2+2 > 5*8 ? 5*10 : 5 == 54 ? 1 :  +1000+1 )
     */
    public static function aplicarEval($formula) {

        $logger = sfContext::getInstance()->getLogger();
        $logger->info("[CN_TABLE] Formula: " . $formula);

        if (!is_null($formula)) {
            // Ejemplo de Eval
            $eval = eval('return (' . $formula . ');');
            if ($eval === false) {
//                $eval = false;
                $logger->info("[CN_TABLE] Formula Error Eval: " . $formula);
            }
        } else {

            $eval = false;
        }

        /*
         * Retornar resultado
         */
        return $eval;
    }

    /**
     * Reemplaza en la consulta los filtros y valores del SQL, que vienen en el record
     * Ejemplo: select raz_soc from id_cia where id_cia = $id_cia
     * $id_cia - > variable de reemplazo
     * Reemplaza $id_cia por el valor en el record
     * @param type $consulta
     * @param type $record
     */
    public static function reemplazoConsulta($consulta, $record) {

        $logger = sfContext::getInstance()->getLogger();
        $logger->info("[CN_TABLE] Consulta: " . $consulta);

        foreach ($record as $key => $value) {

            //Fecha
            if ($key == 'fecha_desde' || $key == 'fecha_hasta') {

                $consulta = str_replace('$' . $key, " to_date('" . $value . "', 'yyyy-mm-dd') ", $consulta);
            } else
            //Texto
            if ($key == 'num_doc') {

                $consulta = str_replace('$' . $key, " '" . $value . "' ", $consulta);
            }
            //Numero
            else {

                $consulta = str_replace('$' . $key, $value, $consulta);
            }

//            if ($key == 'porcentaje') {
//                $logger->info("[CN_TABLE] Consulta: " . $consulta);
//            }
        }

        return $consulta;
    }

    /**
     * Get the variables within the formula
     * Ejemplo: 'C1'
     * @param array $vars
     * @param string $formula
     */
    public static function getVarsInFormula(&$vars, $formula) {
        if ($formula != '') {
            $pos_ini = strpos($formula, INI_CHAR);
            $pos_end = strpos($formula, END_CHAR);

            if ($pos_ini !== false && $pos_end !== false) {
                $var = substr($formula, $pos_ini + 1, $pos_end - $pos_ini - 1);
                if (array_search($var, $vars) === false)
                    $vars[] = $var;

                CN_TABLE::getVarsInFormula($vars, substr($formula, $pos_end + 1));
            }
        }
    }

    /**
     * Obtener dias entre dos fechas 
     * formato yyyy-mm-dd
     * @param type $fecha_ini
     * @param type $fecha_fin
     * @param type $calendario
     * @return int
     */
    public static function diasEntreFechas($fecha_ini, $fecha_fin, $calendario = true) {

        $logger = sfContext::getInstance()->getLogger();
        $logger->info("[CN_TABLE] diasEntreFechas: " . $fecha_ini . " - " . $fecha_fin);

        $dias = 0;

        /*
         * Validar forma de calculo
         */
        if ($calendario) {

            $dias = ((strtotime($fecha_fin) - strtotime($fecha_ini)) / 86400);
        }
        //Todos los meses de 30 dias
        else {

            /*
             * Dividir fecha formato yyyy-mm-dd
             * Posicion 0 anho
             * Posicion 1 mes
             * Posicion 2 dia
             */
            $fecha_ini = explode('-', $fecha_ini);
            $fecha_fin = explode('-', $fecha_fin);

            //Para cuando el anho y mes es el mismo
            if ($fecha_ini[0] == $fecha_fin[0] && $fecha_ini[1] == $fecha_fin[1]) {

                //$logger->info($fecha_fin[2]." - " . $fecha_ini[2]);

                if ($fecha_fin[2] > 30) {
                    $fecha_fin[2] = 30;
                } elseif ($fecha_fin[1] == 2) {
                    if ($fecha_fin[2] >= 28) {
                        $fecha_fin[2] = 30;
                    }
                }

                $dias = $fecha_fin[2] - $fecha_ini[2] + 1;
            } else {

                $dias = 30 - $fecha_ini[2] + 1;

                $fecha_ini = CN_TABLE::fechaSiguiente($fecha_ini[0], $fecha_ini[1]);
//                $logger->info("[CN_TABLE] fechasCiclo: " .$fecha_ini['id_anhos'] . "-" . $fecha_ini['id_meses']);


                if ($fecha_ini['id_anhos'] > 2200) {
                    $logger->info("[CN_TABLE] Supero fecha 2200.");
                    return 0;
                    die();
                }

                //Unir fecha formato yyyy-mm-dd
                $fecha_ini = $fecha_ini['id_anhos'] . "-" . str_pad($fecha_ini['id_meses'], 2, "0", STR_PAD_LEFT) . "-0" . 1;
                $fecha_fin = $fecha_fin[0] . "-" . $fecha_fin[1] . "-" . $fecha_fin[2];

                $dias += CN_TABLE::diasEntreFechas($fecha_ini, $fecha_fin, false);
            }
        }

        $logger->info("[CN_TABLE] dias: " . $dias);
        return $dias;
    }

    /**
     * Obtener meses entre dos fechas 
     * formato yyyy-mm-dd
     * @param type $fecha_ini
     * @param type $fecha_fin
     * @param type $calendario
     * @return int
     */
    public static function mesesEntreFechas($fecha_ini, $fecha_fin, $calendario = true) {

        $logger = sfContext::getInstance()->getLogger();
        $logger->info("[CN_TABLE] mesesEntreFechas: " . $fecha_ini . " - " . $fecha_fin);

        $meses = 0;

        /*
         * Validar forma de calculo - meses de 30 dias
         */
        if ($calendario) {
            //round(($a=(($e-$s)/86400)/30),0);
            $dias = ((strtotime($fecha_fin) - strtotime($fecha_ini)) / 86400);
            $meses = round(($dias / 30), 0);
        }
        //Todos los meses de 30 dias - trabajados completos
        else {

            //Dividir fecha formato yyyy-mm-dd
            $fecha_ini = explode('-', $fecha_ini);
            $fecha_fin = explode('-', $fecha_fin);

            $anho_mes_ini = $fecha_ini[0] . str_pad($fecha_ini[1], 2, '0', STR_PAD_LEFT);
            $anho_mes_fin = $fecha_fin[0] . str_pad($fecha_fin[1], 2, '0', STR_PAD_LEFT);

            $anho_mes_ini = $anho_mes_ini * 1;
            $anho_mes_fin = $anho_mes_fin * 1;
            $logger->info("[CN_TABLE] anho_mes_ini: " . $anho_mes_ini . ' - anho_mes_fin: ' . $anho_mes_fin);

            $dia_ini = $fecha_ini[2];
            $dia_fin = $fecha_fin[2];
            $mes_fin = $fecha_fin[1];

            do {

                /*
                 * Validar mes completo
                 */
                if ($anho_mes_ini < $anho_mes_fin && $dia_ini == 1) {
                    $meses = $meses + 1;
                } elseif ($anho_mes_ini == $anho_mes_fin && $dia_ini == 1
                        && $dia_fin >= 30) {
                    $meses = $meses + 1;
                } elseif ($anho_mes_ini == $anho_mes_fin && $mes_fin == 2
                        && $dia_ini == 1 && $dia_fin >= 28) {
                    $meses = $meses + 1;
                }

                if ($anho_mes_ini > 220001) {
                    $logger->info("[CN_TABLE] Supero mes 220001.");
                    return 0;
                    die();
                }

                $fecha_ini = CN_TABLE::fechaSiguiente(substr($anho_mes_ini, 0, 4), substr($anho_mes_ini, 4, 2));
                $anho_mes_ini = $fecha_ini['id_anhos'] . str_pad($fecha_ini['id_meses'], 2, '0', STR_PAD_LEFT);
                $anho_mes_ini = $anho_mes_ini * 1;
                $dia_ini = 1;

                $logger->info("[CN_TABLE] anho_mes_ini: " . $anho_mes_ini);
            } while ($anho_mes_ini <= $anho_mes_fin);
        }

//        $logger->info("[CN_TABLE] meses: " . $meses);
        return $meses;
    }

    /**
     * Metodo para redondear hacia abajo los terminados en 5...
     * @param type $valor_calculo
     * @param type $redondeo
     * @return int
     */
    public static function redondeoValor($valor_calculo, $redondeo) {

        $logger = sfContext::getInstance()->getLogger();
        $logger->info("[CN_TABLE] Valor_calculo: " . $valor_calculo . " - Redondeo " . $redondeo);

        $valor = 0;
        $redondeo_calc = $redondeo * -1;
        
//        $logger->info( "-> " . str_pad(1, $redondeo, 0, STR_PAD_RIGHT) );
//        die();
        
        //obtener el valor a redondear
        if ($redondeo_calc >= 0) {
            $valor_redondeo = 5 * str_pad(1, $redondeo_calc, 0, STR_PAD_RIGHT);
        } else {
            $redondeo_calc = $redondeo_calc * -1;
            $valor_redondeo = 5 / str_pad(1, $redondeo_calc, 0, STR_PAD_RIGHT);
        }

        //obtener valor redondeado hacia abajo
        if (($valor_calculo + $valor_redondeo) == round($valor_calculo, $redondeo)) {
            $valor_calculo = $valor_calculo - $valor_redondeo;
        } else {
            $valor_calculo = round($valor_calculo, $redondeo);
        }

        $valor = $valor_calculo;

        return $valor;
    }
            /**
     *  @Descripción *Validador de formato de fecha YYYY-MM-DD
     * @param date $valor
     * @return boolean
     */
    public static function validarStringDateFormat($valor) {
        if (preg_match("/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/", $valor)) {
            return true;
        } else {
            return false;
        }
    }
    
    public static function validarNumeroFormat($numero){
        if(is_numeric($numero)){
            return true;
        }else{
            return false;
        }
        
        
    }
    
    
    

}

?>
