<?php

/**
 * 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
                    $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') {
                                    //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) {
                    $sql_from.=" $tids[$rel_name].$id_name = $tids[$tab].$id_name";
                    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)) {

//            $logger->info("---------------------------");
//            foreach ($field_conditions as $key => $value) {
//                $logger->info($key . " 1 --------------------------- " . $value);
//                foreach ($value as $key2 => $value2) {
//                    $logger->info($key2 . " 2 --------------------------- " . $value2);
//                }
//            }
//            die();

            $condNorm.=$appendAnd . CN_TABLE::extractSQLConditions($field_conditions, 'AND', $tids, true, $sortBy);
            $condCount.=$appendAnd . CN_TABLE::extractSQLConditions($field_conditions, 'AND', $tids, false);
        }

        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) {


        //se instancia la clase del manejo del log
        $logger = sfContext::getInstance()->getLogger();
        $logger->info("extraer el sql con las condiciones de la consulta");


        $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";
                        }
//                        $logger->info(" 1 ---------------------------------------- full_field_name: " . $full_field_name);
//                        $logger->info(" 2 ---------------------------------------- params: " . $params[0]);

                        /*
                         * 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 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) {
                    $sql.=" SUM($fname) AS $fname,";
                }
                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
        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);
    }

    /**
     * ejecuta un sql en la base de datos
     *
     * @param string $sql
     * @return array
     */
    public static function executeSQL($sql) {


        //echo "<hr><br>'Locale' disponibles:<br>";
        //system('locale -a');
        //die();
        //realiza la conexion a la base de datos
        $conn = Doctrine_Manager::connection();
//        echo $conn;
        //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 ($key == 'activo'
                        || $key == 'corriente'
                        || $key == 'usa_tercero'
                        || $key == 'usa_auxiliar'
                        || $key == 'usa_cen_cto'
                        || $key == 'usa_sub_cen_cto'
                        || $key == 'no_corriente'
                        || $key == 'estado'
                        || $key == 'obligatorio'
                        || $key == 'es_sql'
                        || $key == 'aplica_reciproca'
                        || $key == 'pcic'
                        || $key == 'pcire'
                        || $key == 'pagnp'
                        || $key == 'cubs'
                        || $key == 'ter'
                        || $key == 'ctaban'
                        || $key == 'cating'
                        || $key == 'catgas'
                        || $key == 'maq'
                        || $key == 'ecc'
                        || $key == 'ett'
                        || $key == 'ecdh'
                        || $key == 'mye'
                        || $key == 'emc'
                        || $key == 'edi'
                        || $key == 'rlc'
                        || $key == 'pdt'
                        || $key == 'trr'
                        || $key == 'inv'
                        || $key == 'pvb'
                        || $key == 'pps'
                        || $key == 'pss'
                        || $key == 'sem'
                        || $key == 'pla'
                ) {
                    $value = $value == 1 ? true : false;
                }

                //arreglo de decimales, cambio de coma por punto
//                if ($key == 'saldo_anterior'
//                        || $key == 'saldo_actual'
//                        || $key == 'debito'
//                        || $key == 'credito'
//                        || $key == 'sal_ant_deb'
//                        || $key == 'sal_ant_cre'
//                        || $key == 'mov_debito'
//                        || $key == 'mov_credito'
//                        || $key == 'sal_act_deb'
//                        || $key == 'sal_act_cre') {
//
////                    $value = str_replace(',', '.', $value);
//                }


                $record[strtolower($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, $forzar_entrada = false, $has_tipo_comprobante = false) {

        //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);
                    }

                    /*
                     * Machete
                     * variable para validar que entre en la consulta sin importar que
                     */
                    $logger->info("------------------------------------------------------------------------------1" . $forzar_entrada);
                    if ($forzar_entrada) {
                        $logger->info("------------------------------------------------------------------------------2" . $forzar_entrada);
                        $key_found = true;
                    }

//                    $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 {


                            $logger->info("*********************************************7-");

                            /*
                             * recorre los campos y anexa el valor del record - 20111014
                             * Si los datos no se encuentras se 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");
                }
            }

            // -- 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
            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 if the id_name comes in");
            if ($has_id_cia && !$has_vigencia) {// is it a company id?
                $seq = CN_TABLE::getByIds('CN_TABLE_SEQ', array('id_cia' => $values['id_cia'],
                            'nom_entidad' => $table_name)); // Get the sequence for that company and table

                if (is_null($seq)) { // if it doesn't exist, create it
                    $seq = CN_TABLE::addRow('CN_TABLE_SEQ', 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 && !$has_tipo_comprobante) { // if not, is it a vigencia sequence??
                $seq = CN_TABLE::getByIds('CN_TABLE_VIG_SEQ', array('id_cia' => $values['id_cia'],
                            'nom_entidad' => $table_name, 'id_vigencia' => $values['id_vigencia'])); // Get the sequence for that company and table

                if (is_null($seq)) { // if it doesn't exist, create it
                    $seq = CN_TABLE::addRow('CN_TABLE_VIG_SEQ', 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 && $has_tipo_comprobante) { // if not, is it a vigencia sequence??

                /*
                 * Si viene en value o other_tab_vals
                 */
                if (isset($values['id_tipo_comprobante'])) {
                    $tipo_comp = $values['id_tipo_comprobante'];
                } elseif (isset($other_tab_vals['id_tipo_comprobante'])) {
                    $tipo_comp = $other_tab_vals['id_tipo_comprobante'];
                } else {
                    $tipo_comp = '0';
                }


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

                if (is_null($seq)) { // if it doesn't exist, create it
                    $seq = CN_TABLE::addRow('CN_TABLE_TIPCOMP_SEQ', array(
                                'id_cia' => $values['id_cia'],
                                'id_vigencia' => $values['id_vigencia'],
                                'id_tipo_comprobante' => $tipo_comp,
                                '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);
//        }

        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) {
                $logger->info("[CN_TABLE] 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) {

        foreach ($value_names as $name) {

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

        $record->save();
        return $record;
    }

    /**
     * obtener los nombres de los ids 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) {

        //se instancia la clase del manejo del log
        $logger = sfContext::getInstance()->getLogger();
        /**
         * Entrada de datos 
         */
//        foreach ($id_names as $key => $value) {
//            $logger->info("[Metodo: getByIdNames] " . $value);
//        }


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

        $where = '';
        for ($i = 0; $i < count($id_names); $i++) {
            $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;
//            $logger->info("[Metodo: getByIdNames] where: " . $where);
        $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) {
        $table = Doctrine_Core::getTable($table_name);

        $where = '';
        $ids = array();
        for ($i = 0; $i < count($id_names); $i++) {
            $where.="$id_names[$i] = " . $id_cont[$id_names[$i]];
            if ($i < count($id_names) - 1)
                $where.=' AND ';
        }
        $res = null;
        $records = $table->findByDql($where);
        if (sizeof($records) == 1) {
            $res = $records->getFirst();
        }
        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
     * @param <type> $ip_address
     * @return <type>
     */
    public static function registroTableLog($id_tabla, $id_vigencia, $cen_op, $id_cia, $id_mae_bd, $id_ope_bd, $id_mae_ter, $usuario, $comando, $observacion, $ip_address = null) {

        $logger = sfContext::getInstance()->getLogger();
        $logger->info("entro registro tabla log");

        //Ip del servidor o equipode ingreso - 20190222
        if (is_null($ip_address)) {
            $ip_address = $_SERVER['REMOTE_ADDR'];
        }

        //conexion a la base de datos
        $conn = Doctrine_Manager::connection();

        //sentencia sql para registro log
        $sql = <<<EOD
INSERT INTO CN_TABLA_LOG
VALUES ( 0, $id_tabla, $id_vigencia, $cen_op, $id_cia, $id_mae_bd, $id_ope_bd, $id_mae_ter, '$usuario', SYSDATE, '$comando', $observacion, '$ip_address')
EOD;

        //ejecuta y obtiene el resultado del sql
        $results = $conn->execute($sql)->fetchAll();
//        $results = CN_TABLE::executeOCI_SQL_Add($sql, "ws_contab", "Sistemas");

        /*
         * IMPRESION SQL EN EL ARCHIVO DE LOG
         */
//       $logger->info("sql: " . $sql);

        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;

        //sentencia sql para registro log
        $sql = <<<EOD
select * from CN_MAE_BD
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;
    }

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

    public static function crearTabla_MAE_BD($tabla) {


        $id_mae_bd = 0;

        //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 CN_MAE_BD
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 CN_MAE_BD 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) {

        /*
         * variable de configuracion - app.yml
         */
        $ip = sfConfig::get('app_ip');
        $modulo = sfConfig::get('app_modulo');

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

        $exito = true;

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

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

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

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

            $logger->info("error" . $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) {

        /*
         * variable de configuracion - app.yml
         */
        $ip = sfConfig::get('app_ip');
        $modulo = sfConfig::get('app_modulo');

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

        /*
         * Conexion a la base de datos
         */
        //base de datos contabilidad websafi
        $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($conconexion);
            $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;
    }

}

?>
