<?php

/**
 * nov_deven_concepto actions.
 *
 * @package    nomina
 * @subpackage nov_deven_concepto
 * @author     Your name here
 * @version    SVN: $Id: actions.class.php 23810 2009-11-12 11:07:44Z Kris.Wallsmith $
 */
class nov_deven_conceptoActions extends sfQuery {
    /*
     * ------------VARIABLES PARA SERVICIOS DE CONSULTA - LIST
     */

    protected $table_names = array(
        'NO_NOV_CONCEPTO',
        'NO_NOV_DED_ADIC',
        'NO_CONCEP_NOMINA'
    ); //tablas para construir el sql, por medio de joins
    protected $table_join_ids = array(
        'NO_NOV_DED_ADIC' =>
        array(
            'id_nov_ded_adic-id_nov_dec_adic' => 'NO_NOV_CONCEPTO'
        ),
        'NO_CONCEP_NOMINA' =>
        array(
            'id_concep_nomina' => 'NO_NOV_CONCEPTO'
        )
    ); //si posee tablas para joins, identificar la relacion de los campos con las tablas
    protected $fields = array(
        'NO_NOV_CONCEPTO' =>
        array(
            'id_nov_concepto' => 'id_nov_concepto',
            'id_nov_ded_adic' => 'id_nov_ded_adic',
            'id_concep_nomina' => 'id_concep_nomina',
            'valor' => 'valor',
            'porcentaje' => 'porcentaje',
        ),
        'NO_NOV_DED_ADIC' =>
        array(
            'id_nov_dec_adic' => 'id_nov_dec_adic',
            'id_tipo_doc' => 'id_tipo_doc',
            'num_doc' => 'num_doc',
            'id_tipo_nov_ded_adic' => 'id_tipo_nov_ded_adic',
            'fecha_ini' => 'fecha_ini',
            'fecha_fin' => 'fecha_fin',
            'tipo_doc_sop' => 'tipo_doc_sop',
            'num_doc_sop' => 'num_doc_sop',
            'fecha_doc_sop' => 'fecha_doc_sop',
            'tipo_doc_cierre' => 'tipo_doc_cierre',
            'num_doc_cierre' => 'num_doc_cierre',
            'fecha_doc_cierre' => 'fecha_doc_cierre',
            'observaciones_cierre' => 'observaciones_cierre',
            'id_periodo' => 'id_periodo',
            'estado' => 'estado'
        ),
        'NO_CONCEP_NOMINA' =>
        array(
            'codigo' => 'codigo_concepto',
            'descripcion' => 'descripcion_concepto',
            'codigo,||, - ,||,descripcion' => 'completo_concepto'
        )
    ); //por cada tabla especificar los campos del select

    /*
     * OPCIONES DE FILTRO:
     *
     * LIKEALLPLUS- busqueda comparativa de la cadena dividida por los espacios en blanco en cualquier posición
     * LIKEALL - busqueda comparativa de la cadena en cualquier posición
     * LIKE - busqueda en la cadena que inicie por la variable de filtro
     *
     * rownum,start - rownum,end / estos campos para uso del Grid live GWT, numero fijo de filas de consulta
     */
    protected $table_field_conditions = array(
        'NO_NOV_CONCEPTO' => array(
            'id_nov_concepto,a' => array('!=' => array(-1)),
            'id_nov_concepto,b' => array('=' => array('id_nov_concepto')),
            'id_concep_nomina' => array('=' => array('id_concep_nomina')),
            'id_nov_ded_adic' => array('=' => array('id_nov_ded_adic')),
            'rownum,start' => array('>' => array('_startRow')),
            'rownum,end' => array('<=' => array('_endRow'))
        )
    ); //por cada tabla se dan los campos, opcion de filtro y variable que entra para los posibles filtros
    protected $table_field_or_conditions = array(); // filtros de condicion or
    protected $fields_orderBy = array(
        'num_doc'
    ); //campos para el ordenamiento de la consulta
//    protected $table_field_obligatory = array('id_debito'); //campos obligatorios de filtro - estan en el request

    /*
     * Variables manejo de log
     */
    //true - consulta de administracion
    protected $is_admin = true;
    //si es servicio para filtro agregar campo
//    protected $filtro = 'Area';
    //true - la tabla principal de busqueda no es una vista
    protected $is_filtro = true;


    /*
     * ------------VARIABLES PARA SERVICIOS CRUD
     */
    protected $id_name = 'id_nov_concepto'; //identificador de la tabla
    protected $id_names = array('id_nov_concepto'); //llave primaria
    protected $field_names = array('id_nov_ded_adic', 'id_concep_nomina', 'valor', 'porcentaje'); //campos de la tabla, sin la llave primaria
    protected $table_name = 'NO_NOV_CONCEPTO'; //tabla en la cual se aplican los cambios
    protected $has_activo = true; //si posee campo en la tabla de nombre activo ---- ESTADO PARA REGALIAS - CARTERA
    protected $has_vigencia = false; //si posee vigencia
    protected $has_cen_op = false; //si posee centro de operacion
    protected $has_id_cia = false; //si posee compañia
    protected $has_secuencia = false; //si posee secuencia la tabla - true si es por tabla, false - trigger
//    protected $en_mayuscula = true; // si se pone, se puede poner en mayucula con true y en minuscula con false, de lo contrario la pone tal cual la BD

    /*
     * Manejo de registro log
     */
    protected $id_unico = 'id_nov_concepto'; //identificador unico de la tabla
    //false - Registrar log para list - consultar
    protected $log_list = false;
    //false - Registrar log para add - update - remove
    protected $log_crud = false;

    /**
     * Construccion de observacion perzonalizada
     * 
     * Toda variable para tomarla del request con el formato:
     * &request-variable&
     * 
     * false - observacion por defecto
     *
     * @var string 
     */
    protected $observacion_list = false;
    protected $observacion_add = false;
    protected $observacion_update = false;
    protected $observacion_remove = false;

    // Validate
    /**
     * Ejecuta una validación previa a la ejecución de una operación tipo Add
     *
     * @param sfWebRequest $request
     * @return array 
     */
    protected function validateAdd(sfWebRequest $request) {

        //valor por defecto
        $errors = null;

        /*
         * Variables request
         */
        $id_concep_nomina = $request['id_concep_nomina'];
        $id_nov_ded_adic = $request['id_nov_ded_adic'];


        /*
         *  Validar la operación, ya sea por SQL
         */

        $sql = <<<EOD
SELECT * FROM NO_NOV_DED_ADIC WHERE ID_NOV_DEC_ADIC =$id_nov_ded_adic
EOD;

        $results = CN_TABLE::executeSQL($sql);

        $id_tipo_doc = $results[0]['id_tipo_doc'];
        $num_doc = $results[0]['num_doc'];

        $sql = <<<EOD
SELECT * FROM NO_CONCEPTO_FUNC WHERE estado=1 and actual=1 and id_concep_nomina = $id_concep_nomina and id_tipo_doc = $id_tipo_doc and num_doc = $num_doc
EOD;

        $results = CN_TABLE::executeSQL($sql);

        /*
         *  Generar errores en $errors
         */

        if (count($results) > 0) {
            $errors['mensaje'] = "El funcionario ya tiene registrado este concepto. Favor Verificar";
            $errors['servicio'] = "nov_deven_concepto";
        }

        return $errors;
    }

    /**
     * Ejecuta una validación previa a la ejecución de una operación tipo Update
     *
     * @param sfWebRequest $request
     * @return array 
     */
    protected function validateUpdate(sfWebRequest $request) {

        //valor por defecto
        $errors = null;

        /*
         *  Validar la operación, ya sea por SQL
         */

        /*
         *  Generar errores en $errors
         */

        return $errors;
    }

    /**
     * Ejecuta una validación previa a la ejecución de una operación tipo Remove
     *
     * @param sfWebRequest $request
     * @return array 
     */
    protected function validateRemove(sfWebRequest $request) {

        //valor por defecto
        $errors = null;

        /*
         *  Validar la operación, ya sea por SQL
         */

        /*
         *  Generar errores en $errors
         */

        return $errors;
    }

    /**
     * Acciones anteriores a la original
     * 
     * return sfWebRequest Changed Request with additional parameters.
     * 
     * @param type $Action ( ADD, UPDATE, REMOVE )
     * @param sfWebRequest $request
     * @return \sfWebRequest 
     */
    protected function preprocessRequest($Action, sfWebRequest $request) {

        /*
         * Se instancia la clase del manejo del log
         */
        $logger = sfContext::getInstance()->getLogger();
        $logger->info("Entro a preprocessRequest");

        /*
         * Procesar Request
         */
        //accion add
        if ($Action == "ADD" || $Action == "UPDATE") {

            /**
             * Cargar tabla constantes
             */
            $text = '$con_';
            //Constantes 
            $sql = <<<EOD
Select cons.*, '$text'|| cons.id_constante as reemplazo from no_constante cons 
EOD;
            //Ejecutar SQL
            $records = CN_TABLE::executeSQL($sql);

            //Agrega a un array todas las constantes
            foreach ($records as $value) {

//                foreach ($value as $key => $value2) {
//                    $this->logMessage($key . " - " . $value2);
//                }

                $arrayConstantes[$value['reemplazo']] = $value;
//                $this->logMessage($value['reemplazo'] . "------------------------" . $arrayConstantes[$value['reemplazo']]);
            }

            /*
             * Anexo de variables del request para reemplazo en constantes
             */
            $arrayConstantes['$WDIASV'] = '0';
            $arrayConstantes['$WDIAST'] = '0';

            //Periodo
            $id_periodo = $request['id_periodo'];
            $num_doc = $request['num_doc'];
            $id_tipo_doc = $request['id_tipo_doc'];

            //Valores del request
            $id_concep_nomina = $request['id_concep_nomina'];
            $dias_liq = 30; //Valor por defecto

            /*
             * Validar valores 
             */
            if (isset($request['valor'])) {
                $valor = $request['valor'];
            } else {
                $valor = "null";
            }

            if (isset($request['porcentaje'])) {
                $porcentaje = $request['porcentaje'];
            } else {
                $porcentaje = "null";
            }


            $sql = <<<EOD
select
1 as tag,
to_char(sysdate,'yyyy-mm-dd') as fecha_hasta,
0 as usa_dias_calen,
$dias_liq as dias_liq,
$dias_liq as num_dias,
nvl($porcentaje, 0) as porcentaje,
$num_doc as num_doc,
$id_tipo_doc as id_tipo_doc,
$id_periodo as id_periodo_ajuste,
$id_periodo as id_periodo,
$id_periodo as periodo,
$id_concep_nomina as id_concep_nomina
from dual     
EOD;
            //Ejecutar SQL
            $recordsLiq = CN_TABLE::executeSQL($sql);
            //Liquidar concepto
            $record_liq = $recordsLiq[0];

            /**
             * Calcular concepto por formula
             */
            $valor_liq = $this->liquidar($id_periodo, $num_doc, $id_tipo_doc, $id_concep_nomina, $record_liq, $arrayConstantes);

            //Validar resultado
            if ($valor_liq !== -9999) {
                $request['valor'] = $valor_liq;
            }
        }

        //accion remove
        if ($Action == "REMOVE") {
            
        }

        return $request;
    }

    /**
     * Acciones posteriores a la original
     * 
     * return sfWebRequest Changed Request with additional parameters.
     * 
     * @param type $Action ( ADD, UPDATE, REMOVE )
     * @param sfWebRequest $request
     * @return \sfWebRequest 
     */
    protected function postprocessRequest($Action, sfWebRequest $request, $list_data_post) {

        /*
         * Se instancia la clase del manejo del log
         */
        $logger = sfContext::getInstance()->getLogger();
        $logger->info("Entro a postprocessRequest - " . $list_data_post);

        /*
         * Procesar Request
         * Al registrar una novedad de Devengado adicionales el sistema 
         * registra un nuevo concepto para el funcionario para ser liquidado, 
         * si la fecha de registro es anterior al periodo actual; registra un ajuste 
         * del concepto sino tiene suma los días al concepto original. 
         * Se cambia a registrar en el concepto original y no el ajuste.
         * 
         * Se realizo el cambio para que tome el salario activo correspondiente del funcionario, 
         * y no valores parciales. Tambien se verifico que esta tomando los días de nómina (base 30 días mes).
         */
        //accion add
        if ($Action == "ADD") {

            $this->conn = Doctrine_Manager::getInstance()->getCurrentConnection();
            $this->conn->beginTransaction();

            try {


                $id_concep_nomina = $list_data_post[0]['id_concep_nomina'];
                $id_nov_ded_adic = $list_data_post[0]['id_nov_ded_adic'];
                $valor = $list_data_post[0]['valor'];
                $porcentaje = $list_data_post[0]['porcentaje'];




                $sql = <<<EOD
SELECT * FROM NO_CONCEP_NOMINA WHERE ID_CONCEP_NOMINA= $id_concep_nomina
EOD;

                $results = CN_TABLE::executeSQL($sql);

                $id_concep_ajuste = $results[0]['id_concep_ajuste'];
                $id_tipo_concepto = $results[0]['id_tipo_concepto'];


                $sql = <<<EOD
SELECT * FROM NO_PERIODO WHERE estado = 1 and activo = 1 
EOD;
                $results = CN_TABLE::executeSQL($sql);

                $id_anhos = $results[0]['id_anhos'];
                $id_meses = $results[0]['id_meses'];
                $id_periodo = $results[0]['id_periodo'];
                $id_tipo_periodo = $results[0]['id_tipo_periodo'];
                $fecha_desde = $results[0]['fecha_ini'];
                $fecha_hasta = $results[0]['fecha_fin'];

                $sql = <<<EOD
SELECT * FROM NO_TIPO_PERIODO WHERE ID_TIPO_PERIODO = $id_tipo_periodo 
EOD;
                $results = CN_TABLE::executeSQL($sql);

                $num_dias = $results[0]['no_dias_mes'];

                $sql = <<<EOD
SELECT * FROM NO_NOV_DED_ADIC WHERE ID_NOV_DEC_ADIC =$id_nov_ded_adic
EOD;

                $results = CN_TABLE::executeSQL($sql);

                $id_tipo_doc = $results[0]['id_tipo_doc'];
                $num_doc = $results[0]['num_doc'];
                $fecha_ini = $results[0]['fecha_ini'];


                /*
                 * Validar valores 
                 */
                if ($valor != "") {
                    $valor = $valor;
                } else {
                    $valor = "null";
                }

                if ($porcentaje != "") {
                    $porcentaje = $porcentaje;
                } else {
                    $porcentaje = "null";
                }


                $date1 = new DateTime($fecha_ini);
                $date2 = new DateTime($fecha_desde);


                $sql = <<<EOD
INSERT INTO NO_CONCEPTO_FUNC (ID_TIPO_DOC,NUM_DOC,ID_CONCEP_NOMINA,VALOR,PORCENTAJE,ESTADO,ACTUAL,FECHA_DESDE)
    VALUES($id_tipo_doc,$num_doc,$id_concep_nomina,$valor,$porcentaje
        ,1,1,to_date('$fecha_ini','YYYY-MM-DD HH24:MI:SS'))
EOD;
                $this->conn->execute($sql);

                //validar que sea de tipo concepto diferente a transferencia - 20140812
                if ($id_tipo_concepto != 4) {
                    if ($date1 < $date2) {

                        $sql = <<<EOD
INSERT INTO NO_CONCEPTO_PERIODO (ID_ANHOS,ID_MESES,PERIODO,ID_TIPO_DOC,NUM_DOC,ID_CONCEP_NOMINA,
    FECHA_DESDE,FECHA_HASTA,VALOR,PORCENTAJE,NUM_DIAS)
    VALUES($id_anhos,$id_meses,$id_periodo,$id_tipo_doc,$num_doc,$id_concep_nomina,
        to_date('$fecha_desde','YYYY-MM-DD HH24:MI:SS'),last_day(to_date('$fecha_hasta','YYYY-MM-DD HH24:MI:SS')),
                $valor,$porcentaje,
        $num_dias - TO_NUMBER(to_char(to_date('$fecha_desde','YYYY-MM-DD HH24:MI:SS'),'DD')) +1)
EOD;

                        $this->conn->execute($sql);

                        /**
                         * Se cambia el concepto de ajuste por un nuevo registro del concepto original - 20140918
                         */
                        $sql = <<<EOD
INSERT INTO NO_CONCEPTO_PERIODO (ID_ANHOS,ID_MESES,PERIODO,ID_TIPO_DOC,NUM_DOC,ID_CONCEP_NOMINA,
    FECHA_DESDE,FECHA_HASTA,VALOR,PORCENTAJE,NUM_DIAS)
    VALUES($id_anhos,$id_meses,$id_periodo,$id_tipo_doc,$num_doc,$id_concep_nomina,
        to_date('$fecha_ini','YYYY-MM-DD HH24:MI:SS'),last_day(to_date('$fecha_desde','YYYY-MM-DD HH24:MI:SS')),
                $valor,$porcentaje,
        $num_dias - TO_NUMBER(to_char(to_date('$fecha_ini','YYYY-MM-DD HH24:MI:SS'),'DD')) +1)
EOD;

                        $this->conn->execute($sql);

//                        if ($id_concep_ajuste) {
//                            $sql = <<<EOD
//INSERT INTO NO_CONCEPTO_PERIODO (ID_ANHOS,ID_MESES,PERIODO,ID_TIPO_DOC,NUM_DOC,ID_CONCEP_NOMINA,
//    FECHA_DESDE,FECHA_HASTA,VALOR,NUM_DIAS)
//    VALUES($id_anhos,$id_meses,$id_periodo,$id_tipo_doc,$num_doc,$id_concep_ajuste,
//        to_date('$fecha_ini','YYYY-MM-DD HH24:MI:SS'),last_day(to_date('$fecha_desde','YYYY-MM-DD HH24:MI:SS')-1),
//                $valor,
//        $num_dias - TO_NUMBER(to_char(to_date('$fecha_ini','YYYY-MM-DD HH24:MI:SS'),'DD')) +1)
//EOD;
//
//                            $this->conn->execute($sql);
//                        } else {
//                            $sql = <<<EOD
//update NO_CONCEPTO_PERIODO set FECHA_DESDE = to_date('$fecha_ini','YYYY-MM-DD HH24:MI:SS'), 
//        NUM_DIAS =  NUM_DIAS + ( $num_dias - TO_NUMBER(to_char(to_date('$fecha_ini','YYYY-MM-DD HH24:MI:SS'),'DD')) +1 )                           
//    where id_concep_nomina = $id_concep_nomina and periodo = $id_periodo 
//        and id_tipo_doc = $id_tipo_doc and num_doc = $num_doc
//EOD;
//
//                            $this->conn->execute($sql);
//                        }
                    } else {

                        $sql = <<<EOD
INSERT INTO NO_CONCEPTO_PERIODO (ID_ANHOS,ID_MESES,PERIODO,ID_TIPO_DOC,NUM_DOC,ID_CONCEP_NOMINA,
    FECHA_DESDE,FECHA_HASTA,VALOR,PORCENTAJE,NUM_DIAS)
    VALUES($id_anhos,$id_meses,$id_periodo,$id_tipo_doc,$num_doc,$id_concep_nomina,
        to_date('$fecha_ini','YYYY-MM-DD HH24:MI:SS'),last_day(to_date('$id_anhos-$id_meses-01','YYYY-MM-DD')),
                $valor,$porcentaje,
        $num_dias - TO_NUMBER(to_char(to_date('$fecha_ini','YYYY-MM-DD HH24:MI:SS'),'DD')) +1)
EOD;
                        $this->conn->execute($sql);
                    }
                }

                //COMMIT DE TODAS LAS TRANSACCIONES
                $this->conn->commit();
            } catch (Exception $e) {

                //ROLLBACK DE TODAS LAS TRANSACCIONES EN CASO DE QUE OCURRA ALGUN ERROR
                $this->conn->rollback();
            }
        }

        //accion update
        if ($Action == "UPDATE") {

            $this->conn = Doctrine_Manager::getInstance()->getCurrentConnection();
            $this->conn->beginTransaction();

            try {

                $id_concep_nomina = $list_data_post[0]['id_concep_nomina'];
                $id_nov_ded_adic = $list_data_post[0]['id_nov_ded_adic'];
                $valor = $list_data_post[0]['valor'];
                $porcentaje = $list_data_post[0]['porcentaje'];

                $sql = <<<EOD
SELECT * FROM NO_CONCEP_NOMINA WHERE ID_CONCEP_NOMINA = $id_concep_nomina
EOD;

                $results = CN_TABLE::executeSQL($sql);

                $id_concep_ajuste = $results[0]['id_concep_ajuste'];
                $id_tipo_concepto = $results[0]['id_tipo_concepto'];



                $sql = <<<EOD
SELECT * FROM NO_PERIODO WHERE estado = 1 and activo = 1 
EOD;
                $results = CN_TABLE::executeSQL($sql);

                $id_anhos = $results[0]['id_anhos'];
                $id_meses = $results[0]['id_meses'];
                $id_periodo = $results[0]['id_periodo'];
                $id_tipo_periodo = $results[0]['id_tipo_periodo'];

                $sql = <<<EOD
SELECT * FROM NO_TIPO_PERIODO WHERE ID_TIPO_PERIODO = $id_tipo_periodo 
EOD;
                $results = CN_TABLE::executeSQL($sql);

                $num_dias = $results[0]['no_dias_mes'];

                $sql = <<<EOD
SELECT * FROM NO_NOV_DED_ADIC WHERE ID_NOV_DEC_ADIC =$id_nov_ded_adic
EOD;

                $results = CN_TABLE::executeSQL($sql);

                $id_tipo_doc = $results[0]['id_tipo_doc'];
                $num_doc = $results[0]['num_doc'];
                $fecha_ini = $results[0]['fecha_ini'];


                /*
                 * Validar valores 
                 */
                if ($valor != "") {
                    $valor = $valor;
                } else {
                    $valor = "null";
                }

                if ($porcentaje != "") {
                    $porcentaje = $porcentaje;
                } else {
                    $porcentaje = "null";
                }


                $sql = "update NO_CONCEPTO_FUNC tab0 set tab0.valor = $valor, tab0.porcentaje = $porcentaje
            where tab0.id_concep_nomina = $id_concep_nomina and tab0.id_tipo_doc = $id_tipo_doc 
                and tab0.num_doc = $num_doc";

                $this->conn->execute($sql);


                $sql = "update NO_CONCEPTO_PERIODO tab0 set tab0.valor = $valor, tab0.porcentaje = $porcentaje
            where tab0.id_concep_nomina = $id_concep_nomina and tab0.periodo = $id_periodo 
                and tab0.id_tipo_doc = $id_tipo_doc and tab0.num_doc = $num_doc";

                $this->conn->execute($sql);

                /**
                 * Se cambia el concepto de ajuste por un nuevo registro del concepto original - 20140918
                 */
//                if ($id_concep_ajuste != null && $id_concep_ajuste != '') {
//
//                    $sql = "update NO_CONCEPTO_PERIODO tab0 set tab0.valor = $valor 
//            where tab0.id_concep_nomina = $id_concep_ajuste and tab0.periodo = $id_periodo 
//                and tab0.id_tipo_doc = $id_tipo_doc and tab0.num_doc = $num_doc";
//
//                    $this->conn->execute($sql);
//                }
                //COMMIT DE TODAS LAS TRANSACCIONES
                $this->conn->commit();
            } catch (Exception $e) {

                //ROLLBACK DE TODAS LAS TRANSACCIONES EN CASO DE QUE OCURRA ALGUN ERROR
                $this->conn->rollback();
            }
        }

        //accion remove
        if ($Action == "REMOVE") {
            
        }

        return $request;
    }

    /**
     * Procesa la liquidacion para el periodo, funcionario y concepto nomina
     * @param type $id_periodo
     * @param type $num_doc
     * @param type $id_tipo_doc
     * @param type $id_concep_nomina
     * @param type $record_liq
     * @param type $arrayConstantes
     */
    private function liquidar($id_periodo, $num_doc, $id_tipo_doc, $id_concep_nomina, $record_liq, $arrayConstantes) {
        $this->logMessage("[nov_deven_concepto] Liquidar: periodo " . $id_periodo .
                " - funcionario " . $num_doc . " - concepto nomina " . $id_concep_nomina);

        /**
         * Varibles
         */
        $arrayParametros = array();
        $valor_liquidado = 0;
        $num_dias = $record_liq['num_dias'];

        /*
         * Valor Base y porcentaje
         */
        $porcentaje = 'null';
        $valor_base = 'null';

        /*
         *  Cargar fórmulas por concepto
         */
        //Sql
        $sql = <<<EOD
Select * from no_formula WHERE id_concep_nomina = $id_concep_nomina 
EOD;
        //Ejecutar SQL
        $records = CN_TABLE::executeSQL($sql);

        /*
         * Valida si posee formula el concepto
         */
        if (count($records) > 0) {
            $this->logMessage("[nov_deven_concepto] Entro a calcular Formula.");

            foreach ($records as $value) {

                $formula = $value['formula'];
                $this->logMessage("[nov_deven_concepto] Formula Inicial: " . $formula);


                /*
                 *  Buscar las constantes, variables, fórmulas(parametros) y agrupaciones que use la fórmula
                 */
                //Reemplazo de constantes            
                $formula = $this->reemplazoConstante($formula, $arrayConstantes);
                $this->logMessage("[nov_deven_concepto] Formula Constante: " . $formula);

                /*
                 * 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
                 * Reemplaza $id_cia por el valor en el record
                 */
                $formula = CN_TABLE::reemplazoConsulta($formula, $record_liq);
                $this->logMessage("[nov_deven_concepto] Formula consulta los filtros: " . $formula);

                /*
                 * Cambio en la formula de A por (C1+C2)
                 */
                $vars = array();

                CN_TABLE::getVarsInFormula($vars, $formula);

//        var_dump($vars);

                foreach ($vars as $var) {
                    if (substr($var, 0, 1) == 'A') {
                        /*
                         * Cambio de A1 por relacion con los conceptos C1
                         * Ejemplo: 'A1' => '0'
                         */
                        $agrup = $this->reemplazoAgrupacion(substr($var, 1));
                        $this->logMessage("[nov_deven_concepto] Agrupacion: " . $agrup);

                        $formula = str_replace('{' . $var . '}', $agrup, $formula);
                    }
                }
                $this->logMessage("[nov_deven_concepto] Formula parametrosFormula y reemplazoAgrupacion: " . $formula);


                /*
                 * Parser de la formula para obtener parametros(variables)
                 * Ejemplo: 'A1' => '0',
                 * 'C1' => '0'
                 */
                $arrayParametros = $this->parametrosFormula($formula);


                /*
                 * Obtener resultados de los parametros(variables)
                 * Ejemplo: $arrayParametros = array(
                 * 'C1' => '0',
                 * 'C2' => '0'
                 * );
                 */
                $arrayParametros2 = $this->resultadoParametros($arrayParametros, $record_liq);


                /*
                 * Reemplazo de parametros(variables) a la formula
                 * Ejemplo: $arrayParametros = array(
                 * 'C1' => '1100',
                 * 'C2' => '55'
                 * );
                 */
                $formula = $this->reemplazoParametros($formula, $arrayParametros2);
                $this->logMessage("[nov_deven_concepto] Formula Final: " . $formula);


                /*
                 * Ejecutar fórmula
                 * Ejemplo: ( 0 == 0 ? {C1} * $porcentaje : false )
                 * Retorna false  si no cumple con la condicion
                 */
                $formula = str_replace('{', ' ', $formula);
                $formula = str_replace('}', ' ', $formula);
                $result = CN_TABLE::aplicarEval($formula);


                /*
                 * No cumple con la condicion
                 */
                if ($result === false) {
                    $this->logMessage("[nov_deven_concepto] Formula No cumple con la condicion: " . $formula);
                    $result = 0;
                }


                /*
                 * Acumulan resultados de liquidacion
                 */
                if ($result !== -9999) // Validar al cumplir condicion -9999 - no cumplue con la condicion de la formula
                    $valor_liquidado += $result;

                /*
                 * Si es por porcentaje
                 */
                if ($record_liq['porcentaje'] != '' || $record_liq['porcentaje'] != null) {
                    /*
                     * Tipo de formula
                     * V - Valor base 
                     * R - Valor restado 
                     * F - Valor de la fórmula (Uso normal)
                     */
                    if ($value['cod_tipo'] == 'V') {
                        $this->logMessage("[nov_deven_concepto] Formula CodTipo: " . $value['cod_tipo']);

                        /*
                         * Valor Base y porcentaje
                         */
                        $porcentaje = $record_liq['porcentaje'];
                        $valor_base = ($result * 100) / $record_liq['porcentaje'];
                    }
                }
            }
        } else {

            /*
             * La liquidación se hacer por 2 espacios temporales:
             *
             * - Mensual
             * En cuyo caso, todos los meses tienen una duración de 30 días
             * - Por días calendario
             * En cuyo caso se hace por la cantidad de días especificada en no_concepto_periodo.num_dias
             * 
             * Esta especificación, si se hace mensual o usando los días, lo especifica la variable no_concep_nomina.dias_calendario
             * 
             * Si se hace una interrupción en un concepto, digamos algún cargo temporal, debe liquidarse el valor del concepto asÍ: 
             * Ejemplo: $valor = ($valor_liquidado_concepto_mes/30)*$num_dias
             */

            /*
             * Si es por porcentaje y diferente de 0
             */
            if (($record_liq['porcentaje'] != '' || $record_liq['porcentaje'] != null) && $record_liq['porcentaje'] != 0) {
                $this->logMessage("[nov_deven_concepto] Calcular porcentaje - " . $record_liq['porcentaje']);


                //Toma el salario completo para la liquidacion - 20140917
                //Sql
                $sql = <<<EOD
select 
no_concepto_periodo.valor as valor_liquidado,
no_concepto_periodo.* from no_concepto_periodo
where id_concep_nomina = (select id_concep_basica from no_param_concep where id_param_concep = 1)
and periodo = $id_periodo
and id_tipo_doc = $id_tipo_doc
and num_doc = '$num_doc' 
and rownum = 1 
EOD;
                //Ejecutar SQL
                $records = CN_TABLE::executeSQL($sql);

                if (count($records) <= 0) {
                    $records[0]['valor_liquidado'] = 0;
                }

                //Resultado del calculo de porcentaje
                $result = ($records[0]['valor_liquidado'] * $record_liq['porcentaje']) / 100;

                /*
                 * Valor Base y porcentaje
                 */
                $porcentaje = $record_liq['porcentaje'];
                $valor_base = $records[0]['valor_liquidado'];
            } else {
                $this->logMessage("[nov_deven_concepto] Calcular valor - " . $record_liq['valor']);

                if (!is_null($record_liq['num_dias'])) {

                    /*
                     * usa_dias_calen
                     */
                    if ($record_liq['usa_dias_calen'] == 0) { //Mensual
                        $num_dias = 30;
                        $num_dias = $record_liq['num_dias']; // ? Revisar
                    } else { //Por días calendario
                        $num_dias = $record_liq['num_dias'];
                    }

                    $result = ($record_liq['valor'] / 30) * $num_dias;
                } else {
                    $num_dias = 'null';
                    $result = $record_liq['valor'];
                }
            }

            $valor_liquidado += $result;
        }

        /*
         * Valida creacion de registro
         */
        if ($valor_liquidado > 0) {

            $this->logMessage("[nov_deven_concepto] El valor liquidado es: " . $valor_liquidado);

            return $valor_liquidado;
        } else {

            $this->logMessage("[nov_deven_concepto] El valor_liquidado es menor a cero.");
            return -9999;
        }
    }

    /**
     * Reemplaza en la formula las constantes por valores de la tabla NO_CONSTANTE
     * Ejemplo: $con_1
     * @param type $formula
     * @param type $arrayConstantes
     */
    private function reemplazoConstante($formula, $arrayConstantes) {

        /*
         * Recorrer array de Constantes
         */
        foreach ($arrayConstantes as $key => $value) {

            //$formula = str_replace($key, $value['valor'], $formula);
            $formula = str_replace($key, $value, $formula);
        }

        return $formula;
    }

    /**
     * Reemplaza los parametros(variables) a la formula
     * Ejemplo: $key: {C1} / $value: valor - 2+5
     * @param type $formula
     * @param type $arrayParametros
     */
    private function reemplazoParametros($formula, $arrayParametros) {

        /*
         * Recorrer array de Parametros
         */
        foreach ($arrayParametros as $key => $value) {

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

        return $formula;
    }

    /**
     * Obtener resultados de los parametros(variables)
     * Ejemplo: 'C1' => '0'
     * @param type $arrayParametros
     * @param type $record_liq
     */
    private function resultadoParametros($arrayParametros, $record_liq) {

        /*
         * Recorrer array de Parametros
         */
        foreach ($arrayParametros as $key => $value) {

            //Sacar caracter y numero(id_concep_nomina) para consulta
            $caracter = substr($key, 0, 1);
            $id_concep_nomina = substr($key, 1);
            $this->logMessage("[nov_deven_concepto] Caracter: " . $caracter . ", numero: " . $id_concep_nomina);

            /*
             * Obtener consulta por caracter
             */
            //Sql
            $sql = <<<EOD
select * from NO_CONSULTA where caracter = '$caracter' 
EOD;
            //Ejecutar SQL
            $record = CN_TABLE::executeSQL($sql);

            //Validar registros SQL
            if (count($record) > 0) {

                $consulta = $record[0]['consulta'];

                //Reemplazo de id_concep_nomina
                $consulta = str_replace('$id_concep_nomina', $id_concep_nomina, $consulta);

                /*
                 * 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
                 * Reemplaza $id_cia por el valor en el record
                 */
                $consulta = CN_TABLE::reemplazoConsulta($consulta, $record_liq);

                /*
                 * Ejecutar SQL de consulta
                 */
                //Sql
                $sql = <<<EOD
$consulta  
EOD;
                //Ejecutar SQL
                $record = CN_TABLE::executeSQL($sql);

                //Validar registros SQL
                if (count($record) > 0) {
                    $valor = $record[0]['valor'];
                } else {
                    $valor = 0;
                }
            } else {
                $valor = 0;
            }

            $arrayParametros[$key] = $valor;

            $this->logMessage("[nov_deven_concepto] Valor por Caracter: " . $valor);
        }
        return $arrayParametros;
    }

    /**
     * Parser de la formula para obtener parametros(variables)
     * Ejemplo: 'C1' => '0'
     * @param type $formula
     * @param type $arrayParametros
     */
    private function parametrosFormula($formula) {

        $vars = array();

        CN_TABLE::getVarsInFormula($vars, $formula);

        foreach ($vars as $var) {
            $arrayParametros[$var] = 0;
        }

//        var_dump($arrayParametros);
//        exit();
//        $arrayParametros = array(
//            'C1' => '0',
//            'C2' => '0',
//            'T1' => '0',
//            'A1' => '0'
//        );

        return $arrayParametros;
    }

    /**
     * Reemplaza las agrupaciones por los parametros(variables)
     * Ejemplo: A1 -> (+C1-C2-T1)
     * @param type $id_agrup_var
     */
    private function reemplazoAgrupacion($id_agrup_var) {

        $agrup = '( ';

        /*
         * Ejecutar SQL de agrupciones
         */
        //Sql
        $sql = <<<EOD
select 
agru.*,
agru.tipo_valor as caracter
from
no_agrup_deta agru
where agru.id_agrup_concepto = $id_agrup_var  
EOD;
        //Ejecutar SQL
        $records = CN_TABLE::executeSQL($sql);

        /*
         * Recorrer registros 
         */
        foreach ($records as $value) {

            $operador = ($value['operador'] == 1 ? '+' : '-');

            //Concatenar todas las agrupaciones
            $agrup .= $operador . '{' . $value['caracter'] . $value['id_concep_nomina'] . '}';
        }

        $agrup .= ' )';

        return $agrup;
    }

}
