<?php

/**
 * liquidacion_agrupacion actions.
 *
 * @package    nomina
 * @subpackage liquidacion_agrupacion
 * @author     Your name here
 * @version    SVN: $Id: actions.class.php 23810 2009-11-12 11:07:44Z Kris.Wallsmith $
 */
class liquidacion_agrupacionActions extends sfActions {

    /**
     * Liquidacion Agrupación
     *
     * @param sfRequest $request A request object
     */
    public function executeList(sfWebRequest $request) {

        //Revisar que sea post
        //$this->forward404Unless($request->isMethod('post'));
        //Guardar los parametros del request en el log
        $this->logMessage("---BEGIN Logging request");
        foreach ($request->getPostParameters() as $key => $value) {
            $this->logMessage("request[$key] = $value");
        }
        $this->logMessage("--------------------------------------------------* Ip: " . $_SERVER['REMOTE_ADDR']);
        foreach ($request->getGetParameters() as $key => $value) {
            $this->logMessage("request[$key] = $value");
        }
        $this->logMessage("---END Logging request");


        /**
         * Abrir nueva conexion con la Base de Datos
         */
        $this->conn = Doctrine_Manager::getInstance()->getCurrentConnection();
        $this->conn->beginTransaction();

        /**
         * Para el proceso de prima de navidad 
         * Se realiza por la funcionalidad Conceptos Generales Devengados
         * El filtro de Fecha Corte representa el periodo par la toma de asignacion basica -> ultimo dia de noviembre
         * El rango de fechas es el tiempo con el cual se calculan los dias propocionales -> 1 de enero hasta el 31 de diciembre
         * Los dias pueden varias por licencias no remuneradas o la fecha de ingreso de la persona -20131129
         */
        /*
         * Formato de fecha
         */
        //Sql
        $sql = <<<EOD
ALTER SESSION SET NLS_DATE_FORMAT = "YYYY-MM-DD" 
EOD;
        //Ejecutar SQL
        CN_TABLE::executeSQL($sql);
        $arrayConstantes = array();

        try {

            //Obtenemos la entidad
            $array = sfYaml::load(dirname(__FILE__) . '/../../../../api/config/app-gwt.yml');
            $int = 0;
            foreach ($array as $routeName => $routeData) {
                //echo $routeName . "\n";
                if ('entidad_cliente' == $routeName) {
                    foreach ($routeData as $key => $value) {
                        //echo $value . "\n";
                        if ($key == 'value') {
                            $entidadCliente = $value;
                        }
                    }
                }
                $int++;
            }


            /**
             * Consultar salario minimo
             */
            $salario_minimo = 550000;
            //Sql
            $sql = <<<EOD
(select nvl(valor_mensual, 0) as valor_mensual from no_smdlv where vigencia = extract(year from sysdate))  
EOD;
            //Ejecutar SQL
            $record_smlv = CN_TABLE::executeSQL($sql);

            if (count($record_smlv) > 0) {
                //No se debe redondear - 20130802
//                $salario_minimo = round($record_smlv[0]['valor_mensual'], -3);
                $salario_minimo = round($record_smlv[0]['valor_mensual']);
            }


            /*
             * Obtener consultas glodal
             */
            //Sql
            $sql = <<<EOD
select * from NO_CONSULTA 
EOD;
            //Ejecutar SQL
            $record_consul = CN_TABLE::executeSQL($sql);
            $record_consulta = array();

            if (count($record_consul) > 0) {
                foreach ($record_consul as $key => $value) {
                    $record_consulta[$value['caracter']] = $value;

//                    $this->logMessage("Caracter - " . $value['caracter']);
                }
            }
//            $this->logMessage("Consulta - " . $record_consulta['M']['consulta']);
//            die();



            /**
             * 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[''] = '';

            /**
             * Variables de filtro
             */
            //id_periodo
            $id_periodo_nuevo = $id_periodo = $request['id_periodo_filtro'];
            $progress_key = $request['progress_key'] . $request['username'];


            $sql = <<<EOD
SELECT ID_TIPO_PERIODO, NO_DIAS_MES FROM NO_TIPO_PERIODO WHERE PERIODICA = 1
EOD;
            $records = CN_TABLE::executeSQL($sql);

            //TRAIGO EL NUMERO DE DIAS PARAMETRIZADO PARA EL TIPO DE PERIODO
            $num_dias = $records[0]['no_dias_mes'];

            /*
             * Periodo valor max_ded_noley
             */
            //Sql
            $sql = <<<EOD
select * from NO_PERIODO where id_periodo = $id_periodo 
EOD;
            //Ejecutar SQL
            $rec = CN_TABLE::executeSQL($sql);

            $max_ded_noley = $rec[0]['max_ded_noley'];
            $id_anhos = $rec[0]['id_anhos'];
            $id_meses = $rec[0]['id_meses'];

            //fecha_corte
            $fecha_corte = $request['fecha_corte'];


            /*
             * Tomar periodo mensual de la fecha de corte
             */
            //Sql
            $sql = <<<EOD
select * from no_periodo
where id_tipo_periodo = 1
and to_date('$fecha_corte','YYYY-mm-dd') between fecha_ini and fecha_fin
and rownum = 1  
EOD;
            //Ejecutar SQL
            $rec = CN_TABLE::executeSQL($sql);

            $id_periodo_fecha_corte = $rec[0]['id_periodo'];



            //fecha_ini
            $fecha_ini = $request['fecha_ini'];

            //fecha_fin
            $fecha_fin = $request['fecha_fin'];

            //id_agrup_concepto
            $id_agrup_concepto = $request['id_agrup_concepto'];

            //Funcionario num_doc
            $num_doc = null;
            $whereFuncionarioNumDoc = "";
            if (isset($request['num_doc'])) {
                $num_doc = $request['num_doc'];
                $whereFuncionarioNumDoc = " AND tab0.num_doc = '" . $request['num_doc'] . "'";
            }
            //Funcionario id_tipo_doc 
            $id_tipo_doc = null;
            $whereFuncionarioTipoDoc = "";
            if (isset($request['id_tipo_doc'])) {
                $id_tipo_doc = $request['id_tipo_doc'];
                $whereFuncionarioTipoDoc = " AND tab0.id_tipo_doc = " . $request['id_tipo_doc'];
            }

            //Variable para mantener la suma de la logica N
            $valor_sumatoria_logica_n = 0;

            /*
             *  Borrar datos anteriores Periodo-Funcionario
             */
            //Sql
            $sql = <<<EOD
DELETE FROM NO_LIQUIDA_NOMINA tab0 WHERE tab0.id_periodo = $id_periodo
$whereFuncionarioNumDoc $whereFuncionarioTipoDoc 
EOD;
            //Ejecutar SQL
            CN_TABLE::executeSQL($sql);

            //Sql
            $sql = <<<EOD
DELETE FROM NO_CONCEPTO_PERIODO tab0 WHERE tab0.periodo = $id_periodo
$whereFuncionarioNumDoc $whereFuncionarioTipoDoc 
EOD;
            //Ejecutar SQL
            CN_TABLE::executeSQL($sql);



            /*
             * Tomar valores de NO_AJUSTE_NOMINA
             */
            //Sql
            $sql = <<<EOD
Insert into NO_LIQUIDA_NOMINA (ID_TIPO_DOC,NUM_DOC,ID_CONCEP_NOMINA,ID_PERIODO,VALOR_LIQUIDADO,FECHA_DESDE,FECHA_HASTA,NUM_DIAS) 

select 
tab0.id_tipo_doc,
tab0.num_doc,
tab0.id_concep_nomina,
tab0.id_periodo,
tab0.valor_ajuste,
 to_date( '01/' || per.id_meses || '/' || per.id_anhos, 'dd/mm/yyyy')  as fecha_desde,
TRUNC(LAST_DAY( to_date(per.id_meses || '/' || per.id_anhos, 'mm/yyyy')  )) as fecha_hasta,
tab0.num_dias
                    
from no_ajuste_nomina tab0
join no_periodo per
on per.id_periodo = tab0.id_periodo 
                    
WHERE 
tab0.aplicar_liq_concep = 0                     
and tab0.id_periodo = $id_periodo 
$whereFuncionarioNumDoc $whereFuncionarioTipoDoc 
EOD;
            //Ejecutar SQL
            CN_TABLE::executeSQL($sql);



            /*
             * Traer funcionarios activos para el periodo
             * Validacion personas retiradas - 20141201
             * Tag_retro para cuando es retroactivo, para retencion tiene encuenta todo el mes con lo del retroactivo - 20150610
             * Se agrega fecha de corte, que se usa en la consulta E - 20150625
             * Incidente #6468 <-> Se agrega valor_bonif - 20170613
             * En la validacion de fecha de corte, verifica con si misma - 20170704
             * Personas con novedad en comision otra entidad id -> 8,no le calcula - 20191212
             * Se cambia que tome fecha ini para los campos-consulta H
              per.id_anhos as vig_ini,
              1 as per_ini, - 20210617::LAVILA
             * Incidente #37081, para el inci si se liquida para las personas con comision otra entidad id -> 8
              //SGC-1, ANM-2, SGR-3, CYC-4, COL-5, INCI-6, LOCAL-7 - 20151026
             */
            //Sql
            $sql = <<<EOD
select 
$salario_minimo as salario_minimo,
1 as tag, 
1 as tg_retro,  
nvl((select valor_uvt from ts_uvt where vigencia = (select no_periodo.id_anhos from no_periodo where id_periodo = $id_periodo)) , 1) as valor_uvt, 
nvl((select valor_fijo from no_concep_ab where id_concep_nomina in (select no_param_concep.id_concep_bonif from no_param_concep where no_param_concep.id_param_concep = 1)) , 1) as valor_bonif,                    
extract(YEAR FROM TO_DATE('$fecha_ini','yyyy-mm-dd')) as vig_ini,
extract(MONTH FROM TO_DATE('$fecha_ini','yyyy-mm-dd')) as per_ini,  
extract(YEAR FROM TO_DATE('$fecha_fin','yyyy-mm-dd')) as vig_fin,
extract(MONTH FROM TO_DATE('$fecha_fin','yyyy-mm-dd')) as per_fin,  
tab0.*,
nombra.id_nombramiento,
nombra.fecha_nombra,
                    
--Se agrega para solicitud de continuidad - 20170602
case when nombra.solucion_continuidad = 0 then nombra.fecha_ingreso 
    else (
        nvl((
          select max(nom_ult.fecha_ingreso) as fecha_ingreso from no_nombramiento nom_ult 
          where tab0.id_tipo_doc = nom_ult.id_tipo_doc
          and tab0.num_doc = nom_ult.num_doc
          and nom_ult.estado = 0
          and nom_ult.id_nombramiento != nombra.id_nombramiento
        ),nombra.fecha_ingreso)
    )
    end as fecha_ingreso,
                    
nvl(nombra.fecha_termina, TO_DATE('$fecha_fin','yyyy-mm-dd')) as fecha_termina,
nvl(nombra.fecha_retiro, TO_DATE('$fecha_fin','yyyy-mm-dd')) as fecha_retiro,
to_date('$fecha_corte','YYYY-mm-dd') as fecha_corte,
case when 7 >= per.id_meses
then per.id_anhos - 1 else per.id_anhos end as anho_ini
from no_estado_func_v tab0

join no_nombramiento_v nombra
on tab0.id_tipo_doc = nombra.id_tipo_doc
and tab0.num_doc = nombra.num_doc

join no_periodo per
on per.id_periodo = tab0.periodo

WHERE tab0.periodo = $id_periodo
$whereFuncionarioNumDoc $whereFuncionarioTipoDoc 
and to_date('$fecha_corte','YYYY-mm-dd') <= nvl(nombra.fecha_termina, TO_DATE('$fecha_corte','yyyy-mm-dd')+1)
and tab0.num_doc not in (
    select 

    nov.num_doc 

    from no_novedad_personal nov

    where 
    nov.estado = 1
    and nov.id_novedad = 8
    and (
        (select fecha_ini from no_periodo where id_periodo = $id_periodo) between nov.fecha_inicial and nov.fecha_terminacion
        or    
        (select fecha_fin from no_periodo where id_periodo = $id_periodo) between nov.fecha_inicial and nov.fecha_terminacion
    )
    and $entidadCliente != 6                    
) 
                    
order by
tab0.id_anhos,
tab0.id_meses,
tab0.id_tipo_doc,
tab0.num_doc 
EOD;
            //Ejecutar SQL
            $records = CN_TABLE::executeSQL($sql);

            //Cantidad de funcionarios
            $cant_ter = count($records);

            //Validar si hay funcionarios para liquidación
            if ($cant_ter > 0) {
                $this->logMessage("[Liquidación Agrupación] Validar si hay funcionarios para liquidación.");

                /*
                 * Obtener concep_periodo por agrupacion - Orden a liquidar
                 */
                $sql = <<<EOD
select 
* 
from no_agrup_deta
where id_agrup_concepto = $id_agrup_concepto
order by 
orden,
id_agrup_deta 
EOD;
                //Ejecutar SQL
                $records_agrup = CN_TABLE::executeSQL($sql);

                //Cantidad de conceptos
                $cant_con = count($records_agrup);


                $this->conn->commit();


                /*
                 * Memcache liquidados
                 */
                $i = 1;
                $nom_conceptos_a_procesar = $cant_ter * $cant_con;

                // Antes de inicar el proceso largo
                $brecha = 1;
                if ($nom_conceptos_a_procesar > 100)
                    $brecha = $nom_conceptos_a_procesar - (0.99 * $nom_conceptos_a_procesar);

                $this->logMessage("[Liquidación] nom_conceptos_a_procesar: " . $nom_conceptos_a_procesar);

                /*
                 * Log liquidacion.log registros uno a uno - Funcionarios
                 */
                $logPath = sfConfig::get('sf_log_dir') . '/liquidacion.log';
                $custom_logger = new sfFileLogger(new sfEventDispatcher(), array('file' => $logPath));


                /*
                 * Por funcionario 
                 */
                foreach ($records as $value) {


                    /**
                     * Abrir nueva conexion con la Base de Datos
                     */
                    $this->conn = Doctrine_Manager::getInstance()->getCurrentConnection();
                    $this->conn->beginTransaction();

                    //Variable para mantener la suma de la logica N - para cada funcionario 
                    $valor_sumatoria_logica_n = 0;

                    /*
                     * Datos por record
                     */
                    $num_doc = $value['num_doc'];
                    $id_tipo_doc = $value['id_tipo_doc'];
                    $fecha_ingreso = $value['fecha_ingreso'];
                    $fecha_termina = $value['fecha_termina'];
                    $fecha_retiro = $value['fecha_retiro'];
                    $vig_ini = $value['vig_ini'];
                    $per_ini = $value['per_ini'];
                    $vig_fin = $value['vig_fin'];
                    $per_fin = $value['per_fin'];

                    // Termina procesamiento de concepto
                    $custom_logger->info("Procesado $i de $nom_conceptos_a_procesar conceptos. Documento: " . $num_doc . "\n");


                    /*
                     * Calcular los meses a liquidar - 20130614
                     */
//                    $meses_liq = 0;
                    $meses_liq = $this->mesesLiquidar($id_periodo, $num_doc, $id_tipo_doc, $fecha_ingreso, $fecha_termina, $value, $fecha_ini, $fecha_fin);
                    $this->logMessage("[Liquidación Definitiva] Meses de Liquidación: " . $meses_liq);
                    if ($meses_liq < 0) {
                        $meses_liq = 0;
                    }

                    /*
                     * Calcular los dias a liquidar (ausencias no afectan antiguedad)
                     * Dias de otra entidad por certificado - 20130703
                     */
                    $array_dias = $this->diasLiquidar($id_periodo, $num_doc, $id_tipo_doc, $fecha_ini, $fecha_fin, $fecha_ingreso, $fecha_termina, $value);

                    $dias_liq = $array_dias['dias_calc'];
                    $dias_otra_ent = $array_dias['dias_otra_entidad'];
                    $dias_ausenc = $array_dias['dias_ausenc'];
                    $this->logMessage("[Liquidación Agrupación] Dias de Liquidación: " . $dias_liq);
                    $this->logMessage("[Liquidación Agrupación] Dias de ausencia: " . $dias_ausenc);


                    /**
                     * Recorrer Agrupaciones
                     */
                    foreach ($records_agrup as $value_agrup) {


                        /*
                         * Variables agrup_concep
                         */
                        $id_concep_nomina = $value_agrup['id_concep_nomina'];
                        $caracter = $value_agrup['tipo_valor'];


                        /*
                         * Crear concepto_periodo - 20130614
                         * 
                         * O : Otros conceptos liquidados, con esta letra se identifica el concepto 
                         * que se desea liquidar ya que este concepto no esta en concepto funcionario, 
                         * solo indica cual es el concepto de devengado a liquidar para todos 
                         * los funcionarios activos. 
                         * 
                         * C: Concepto según tabla (Concepto funcionario) en esta letra esta 
                         * la retención en la fuente 
                         * 
                         * N: Son los deducidos de no ley que se deben tener en 
                         * cuenta para aplicar en caso de que exista para cada funcionario.
                         */
                        if ($caracter == 'C') {

                            /*
                             * CREO LOS REGISTRO DE DEVENGADOS Y DEDUCIDOS DE LEY EN NO_CONCEPTO_PERIODO 
                             * Dias de nov solo del rango de fechas del filtro y validar que no de negativo los dias - 20150612
                             */
                            $sql = <<<EOD
INSERT INTO NO_CONCEPTO_PERIODO (
ID_ANHOS,
ID_MESES,
PERIODO,
ID_TIPO_DOC,
NUM_DOC,
ID_CONCEP_NOMINA,
VALOR,
PORCENTAJE,
FECHA_DESDE,
FECHA_HASTA,
NUM_DIAS
)

SELECT 

ID_ANHOS,ID_MESES,PERIODO,
ID_TIPO_DOC,NUM_DOC,
ID_CONCEP_NOMINA,VALOR,PORCENTAJE,FECHA_DESDE,

case when fecha_hasta is null then last_day(to_date('01/$id_meses/$id_anhos','DD/MM/YYYY')) else FECHA_HASTA end as FECHA_HASTA,
--FECHA_HASTA,

(case when fecha_hasta is not null 
then (fecha_hasta-fecha_desde)
else (select perv.no_dias_mes from no_periodo_v perv where perv.id_periodo = $id_periodo_nuevo) 
end) - 
(case when dias > 30 then 30 else case when dias > 0 and aplica_vacac =1 then dias else 0 end end) 
as NUM_DIAS 

FROM(

    select  
    (select id_anhos from no_periodo where id_periodo = $id_periodo_nuevo) AS ID_ANHOS,
    (select id_meses from no_periodo where id_periodo = $id_periodo_nuevo) AS ID_MESES,
    $id_periodo_nuevo AS PERIODO,
    tab0.id_tipo_doc,tab0.num_doc,
    tab0.id_concep_nomina,
    tab0.valor,tab0.porcentaje,
    tab1.aplica_vacac,
    
    to_date('01/$id_meses/$id_anhos','DD/MM/YYYY') AS FECHA_DESDE,
        
    /*
    case when tab0.fecha_hasta IS NULL then last_day(to_date('01/$id_meses/$id_anhos','DD/MM/YYYY'))
    when extract(month from tab0.fecha_hasta) = $id_meses then tab0.fecha_hasta
    
    else last_day(to_date('01/$id_meses/$id_anhos','DD/MM/YYYY'))
    
    end AS FECHA_HASTA
    */
    case when extract(month from tab0.fecha_hasta) = 6 then tab0.fecha_hasta
    else null
    end AS FECHA_HASTA,  
    
    (
    
    select 
    nvl(sum(dias),0) AS DIAS    
    from
    (
    
        select 
        num_doc,
        nvl(sum(dias_rango_mes(novkar.fecha_ini,novkar.fecha_fin,
        (select id_meses from no_periodo where id_periodo =  $id_periodo_nuevo ))),0) as dias 
        from no_novedad_kardex novkar
        left join no_tip_nov_ka tipnov
        on tipnov.id_tip_nov_ka = novkar.id_tip_nov_ka
        where tipnov.afecta_antigu = 1
        and (
               novkar.fecha_ini between to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo where id_periodo = $id_periodo_nuevo) ,'dd/mm/yyyy')
               and trunc(last_day( to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo where id_periodo = $id_periodo_nuevo) ,'dd/mm/yyyy') )) 
               or
               novkar.fecha_fin between to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo where id_periodo = $id_periodo_nuevo) ,'dd/mm/yyyy')
               and TRUNC(LAST_DAY( TO_DATE('01/'|| (select LPAD(ID_MESES,2,'0') ||'/'||ID_ANHOS from NO_PERIODO where ID_PERIODO = $id_periodo_nuevo) ,'dd/mm/yyyy') )) 
        
               or       
        
               to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo where id_periodo = $id_periodo_nuevo) ,'dd/mm/yyyy') between novkar.fecha_ini and novkar.fecha_fin
               or
               trunc(last_day( to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo where id_periodo = $id_periodo_nuevo) ,'dd/mm/yyyy') )) between novkar.fecha_ini and novkar.fecha_fin
        )
        group by num_doc 
        
        union 
        
        select 
        num_doc,
        nvl(sum(DIAS_RANGO_MES_SIN_TREINTAYUNO(novvac.fecha_ini,novvac.fecha_fin,
        (select id_meses from no_periodo where id_periodo =  $id_periodo_nuevo))),0) as dias        
        from no_novedad_vac novvac
        left join no_tipo_nov_vac tipnov on tipnov.id_tipo_nov_vac = novvac.id_tipo_nov_vac
        where tipnov.tiempo_liqui = 1
        and (
               novvac.fecha_ini between to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo where id_periodo = $id_periodo_nuevo) ,'dd/mm/yyyy')
               and trunc(last_day( to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo where id_periodo = $id_periodo_nuevo) ,'dd/mm/yyyy') )) 
               or
               novvac.fecha_fin between to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo where id_periodo = $id_periodo_nuevo) ,'dd/mm/yyyy')
               and TRUNC(LAST_DAY( TO_DATE('01/'|| (select LPAD(ID_MESES,2,'0') ||'/'||ID_ANHOS from NO_PERIODO where ID_PERIODO = $id_periodo_nuevo) ,'dd/mm/yyyy') )) 
        
               or       
        
               to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo where id_periodo = $id_periodo_nuevo) ,'dd/mm/yyyy') between novvac.fecha_ini and novvac.fecha_fin
               or
               trunc(last_day( to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo where id_periodo = $id_periodo_nuevo) ,'dd/mm/yyyy') )) between novvac.fecha_ini and novvac.fecha_fin
        )
        group by num_doc
        
    )tab3 where tab0.num_doc = tab3.num_doc) as dias
    
    from no_concepto_func tab0
    
    LEFT JOIN no_concep_nomina tab1 
    ON tab1.id_concep_nomina = tab0.id_concep_nomina 
    
    where 
    tab0.estado = 1 and tab0.actual = 1 
    and tab1.id_tipo_concepto != 4
    and tab0.id_concep_nomina = $id_concep_nomina
    AND tab0.num_doc = '$num_doc'
    AND tab0.id_tipo_doc = $id_tipo_doc
    and exists (select est.num_doc from no_estado_func_v est where est.num_doc = tab0.num_doc and est.periodo = $id_periodo_nuevo)

    
    union

    select     
    (select id_anhos from no_periodo where id_periodo = $id_periodo_nuevo) AS ID_ANHOS,
    (select id_meses from no_periodo where id_periodo = $id_periodo_nuevo) AS ID_MESES,
    $id_periodo_nuevo AS PERIODO,
    tab0.id_tipo_doc,
    tab0.num_doc,
    tab0.id_concep_nomina,
    tab0.valor,
    tab0.porcentaje,
    0 as aplica_vacac,
    tab0.fecha_desde,
    null AS FECHA_HASTA,   
    (
    
    select 
    nvl(sum(dias),0) AS DIAS    
    from
    (
    
        select 
        num_doc,
        nvl(sum(dias_rango_mes(novkar.fecha_ini,novkar.fecha_fin,
        (select id_meses from no_periodo where id_periodo =  $id_periodo_nuevo ))),0) as dias 
        from no_novedad_kardex novkar
        left join no_tip_nov_ka tipnov
        on tipnov.id_tip_nov_ka = novkar.id_tip_nov_ka
        where tipnov.afecta_antigu = 1
        and (
               novkar.fecha_ini between to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo where id_periodo = $id_periodo_nuevo) ,'dd/mm/yyyy')
               and trunc(last_day( to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo where id_periodo = $id_periodo_nuevo) ,'dd/mm/yyyy') )) 
               or
               novkar.fecha_fin between to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo where id_periodo = $id_periodo_nuevo) ,'dd/mm/yyyy')
               and TRUNC(LAST_DAY( TO_DATE('01/'|| (select LPAD(ID_MESES,2,'0') ||'/'||ID_ANHOS from NO_PERIODO where ID_PERIODO = $id_periodo_nuevo) ,'dd/mm/yyyy') )) 
        
               or       
        
               to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo where id_periodo = $id_periodo_nuevo) ,'dd/mm/yyyy') between novkar.fecha_ini and novkar.fecha_fin
               or
               trunc(last_day( to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo where id_periodo = $id_periodo_nuevo) ,'dd/mm/yyyy') )) between novkar.fecha_ini and novkar.fecha_fin
        )
        group by num_doc 
        
        union 
        
        select 
        num_doc,
        nvl(sum(DIAS_RANGO_MES_SIN_TREINTAYUNO(novvac.fecha_ini,novvac.fecha_fin,
        (select id_meses from no_periodo where id_periodo =  $id_periodo_nuevo))),0) as dias        
        from no_novedad_vac novvac
        left join no_tipo_nov_vac tipnov on tipnov.id_tipo_nov_vac = novvac.id_tipo_nov_vac
        where tipnov.tiempo_liqui = 1
        and (
               novvac.fecha_ini between to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo where id_periodo = $id_periodo_nuevo) ,'dd/mm/yyyy')
               and trunc(last_day( to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo where id_periodo = $id_periodo_nuevo) ,'dd/mm/yyyy') )) 
               or
               novvac.fecha_fin between to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo where id_periodo = $id_periodo_nuevo) ,'dd/mm/yyyy')
               and TRUNC(LAST_DAY( TO_DATE('01/'|| (select LPAD(ID_MESES,2,'0') ||'/'||ID_ANHOS from NO_PERIODO where ID_PERIODO = $id_periodo_nuevo) ,'dd/mm/yyyy') )) 
        
               or       
        
               to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo where id_periodo = $id_periodo_nuevo) ,'dd/mm/yyyy') between novvac.fecha_ini and novvac.fecha_fin
               or
               trunc(last_day( to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo where id_periodo = $id_periodo_nuevo) ,'dd/mm/yyyy') )) between novvac.fecha_ini and novvac.fecha_fin
        )
        group by num_doc
        
    )tab3 where tab0.num_doc = tab3.num_doc) as num_dias
    
    from(
        select distinct 
        rownum id_concepto_periodo,
        per.id_anhos as id_anhos,
        per.id_meses as id_meses,
        per.id_periodo as periodo,
        aut.id_tipo_doc,
        aut.num_doc,
        param.id_concep_rete as id_concep_nomina,
        per.fecha_ini as fecha_desde,
        per.fecha_fin as fecha_hasta,
        null as valor,
        1 as porcentaje,
        30 as num_dias,
        per.id_periodo as id_periodo_ajuste,
        per.id_tipo_periodo,
        aut.id_tipo_proced_rete

        from no_novedad_proced_rete aut

        left join no_nombramiento_v nom
        on nom.num_doc = aut.num_doc and nom.id_tipo_doc = aut.id_tipo_doc

        left join no_periodo per
        on per.id_periodo = $id_periodo_nuevo

        left join no_param_concep param
        on param.id_param_concep = 1

        where
        aut.estado = 1                
        and aut.id_tipo_proced_rete = 1
        or (
            aut.estado = 0 and nom.fecha_termina between (select no_periodo.fecha_ini from no_periodo where id_periodo = $id_periodo_nuevo )  
                and (select no_periodo.fecha_fin from no_periodo where id_periodo = $id_periodo_nuevo ) 
        ) 
    )tab0
    where
    tab0.id_tipo_periodo in ( 3,4 ) 
    and tab0.id_tipo_proced_rete = 1 
    and tab0.periodo = $id_periodo_nuevo
    and tab0.NUM_DOC in ($num_doc ) 
    and tab0.id_concep_nomina = (select id_concep_rete from no_param_concep where id_param_concep = 1)
)    
EOD;

                            $this->conn->execute($sql);
                        } elseif ($caracter == 'O') {

                            $num_dias = $dias_liq;

                            /*
                             * Variables globales del proyecto - 20130702
                             */
                            $cambioMesPorDias = sfConfig::get('app_cambioMesPorDias');
                            //Si aplica cambio de mes por dias
                            if ($cambioMesPorDias) {
                                //Colocar en dias la cantidad de meses - 20130618
                                if ($id_concep_nomina == 16) {
                                    $num_dias = $meses_liq;
                                }
                            }

                            $sql = <<<EOD
INSERT INTO NO_CONCEPTO_PERIODO (ID_ANHOS,ID_MESES,PERIODO,ID_TIPO_DOC,NUM_DOC,ID_CONCEP_NOMINA,FECHA_DESDE,FECHA_HASTA,PORCENTAJE,NUM_DIAS)
    VALUES($id_anhos,$id_meses,$id_periodo_nuevo,$id_tipo_doc,$num_doc,$id_concep_nomina,
        to_date('01/$id_meses/$id_anhos','DD/MM/YYYY'),last_day(to_date('01/$id_meses/$id_anhos','DD/MM/YYYY')),
            0, $num_dias )
EOD;
                            $this->conn->execute($sql);
                        } elseif ($caracter == 'N') {

                            /*
                             * CREO LOS REGISTRO DE DEDUCIDOS DE NO LEY EN NO_CONCEPTO_PERIODO
                             * Se agrega filtro de periodo para no tomar otros meses - 20211123::LAVILA
                             */
                            $sql = <<<EOD
INSERT INTO NO_CONCEPTO_PERIODO (
ID_ANHOS,
ID_MESES,
PERIODO,
ID_TIPO_DOC,
NUM_DOC,
ID_CONCEP_NOMINA,
VALOR,
PORCENTAJE,
FECHA_DESDE,
FECHA_HASTA,
NUM_DIAS
)

SELECT ID_ANHOS,ID_MESES,PERIODO,ID_TIPO_DOC,NUM_DOC,ID_CONCEP_NOMINA,VALOR,PORCENTAJE,FECHA_DESDE,
 /*   
case when fecha_hasta is null 
then last_day(to_date('01/$id_meses/$id_anhos','DD/MM/YYYY'))
else FECHA_HASTA end as FECHA_HASTA,
 */
FECHA_HASTA,
/*
case when fecha_hasta is not null 
then (fecha_hasta-fecha_desde)
else (select perv.no_dias_mes from no_periodo_v perv where perv.id_periodo = $id_periodo_nuevo) 
end as NUM_DIAS
*/
$num_dias AS NUM_DIAS

FROM(

    select  
    (select id_anhos from no_periodo where id_periodo = $id_periodo_nuevo) AS ID_ANHOS,(select id_meses from no_periodo where id_periodo = $id_periodo_nuevo) AS ID_MESES
    ,$id_periodo_nuevo AS PERIODO,tab0.id_tipo_doc,tab0.num_doc,tab0.id_concep_nomina,tab0.valor_cuota AS VALOR,tab0.porcentaje_cuota AS PORCENTAJE,

       to_date('01/$id_meses/$id_anhos','DD/MM/YYYY') AS FECHA_DESDE,
    last_day(to_date('01/$id_meses/$id_anhos','DD/MM/YYYY')) AS FECHA_HASTA                      
        /*
    case when tab0.fecha_hasta IS NULL then last_day(to_date('01/$id_meses/$id_anhos','DD/MM/YYYY'))
    when extract(month from tab0.fecha_hasta) = $id_meses then tab0.fecha_hasta

    else last_day(to_date('01/$id_meses/$id_anhos','DD/MM/YYYY'))

        end AS FECHA_HASTA

    case when extract(month from tab0.fecha_hasta) = $id_meses then tab0.fecha_hasta
    else null
    end AS FECHA_HASTA  
        */
    FROM no_ded_noley tab0

    where 

    tab0.estado = 1 
    and tab0.id_concep_nomina = $id_concep_nomina
    AND tab0.num_doc = '$num_doc'
    AND tab0.id_tipo_doc = $id_tipo_doc
    and tab0.id_periodo = $id_periodo_nuevo 
    and(
        tab0.num_cuotas = 0
        or 
        tab0.cuotas_desc < tab0.num_cuotas 
    )
    and exists (select est.num_doc from no_estado_func_v est where est.num_doc = tab0.num_doc and est.periodo = $id_periodo_nuevo)

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



                        /*
                         * Tag_retro para cuando es retroactivo, para retencion tiene encuenta todo el mes con lo del retroactivo - 20150610
                         * Se agrega fecha de corte, que se usa en la consulta E - 20150625
                         * Se coloca tag en 0, para que en la retencion solo tome la formula correspondiente sin certificados - 20151127
                         * Se coloca tag en 0, validacion para solo retencion - 20161007
                         * Incidente #6468 <-> Se agrega valor_bonif - 20170613
                         */
                        $sql = <<<EOD
select
$salario_minimo as salario_minimo,
case when (SELECT id_concep_rete FROM no_param_concep where id_param_concep = 1) = tab0.id_concep_nomina then 0 else 1 end as tag,
1 as tg_retro,
nvl((select valor_uvt from ts_uvt where vigencia = (select no_periodo.id_anhos from no_periodo where id_periodo = $id_periodo)) , 1) as valor_uvt,
nvl((select valor_fijo from no_concep_ab where id_concep_nomina in (select no_param_concep.id_concep_bonif from no_param_concep where no_param_concep.id_param_concep = 1)) , 1) as valor_bonif, 
0 as promedio,
$vig_ini as vig_ini,
$per_ini as per_ini,
$vig_fin as vig_fin,
$per_fin as per_fin,
$meses_liq as meses_liq,
$dias_liq as dias_liq,
$dias_otra_ent as dias_otra_ent,
$dias_ausenc as dias_ausenc,
'$caracter' as caracter,
nvl('$fecha_ingreso', '') as fecha_ingreso,
nvl('$fecha_termina', '') as fecha_termina,
nvl('$fecha_retiro', '') as fecha_retiro,
to_date('$fecha_corte','YYYY-mm-dd') as fecha_corte,
tab0.*,
tipcon.orden,
connom.codigo,
connom.usa_dias_calen
from no_concepto_periodo tab0

join no_concep_nomina connom
on connom.id_concep_nomina = tab0.id_concep_nomina

join no_tipo_concepto tipcon
on tipcon.id_tipo_concepto = connom.id_tipo_concepto

where tab0.periodo = $id_periodo
AND tab0.num_doc = '$num_doc'
AND tab0.id_tipo_doc = $id_tipo_doc
AND tab0.id_concep_nomina = $id_concep_nomina 

order by 
tab0.id_anhos,
tab0.id_meses,
tab0.id_tipo_doc,
tab0.num_doc,
tipcon.orden,
connom.codigo 
EOD;
                        //Ejecutar SQL
                        $recordsLiq = CN_TABLE::executeSQL($sql);


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

                        if (count($recordsLiq) > 0) {

                            //Liquidar concepto
                            $record_liq = $recordsLiq[0];
                            $valor_sumatoria_logica_n = $this->liquidar($id_periodo, $num_doc, $id_tipo_doc, $id_concep_nomina, $record_liq, $arrayConstantes, $max_ded_noley, $valor_sumatoria_logica_n, $record_consulta, $id_periodo_fecha_corte);
                        } else {
                            /*
                             * Mensaje de error
                             */
                            $mensajeError = "No hay registro para liquidación en el periodo. Concepto: " . $id_concep_nomina;

//                            $this->status = 1;
//                            $this->list_data = array();
//                            $this->mensajeError = $mensajeError;
                            $this->logMessage("[Liquidación Agrupación] " . $mensajeError);
                        }
                    }
//                    die();                    
                    $this->conn->commit();
                }
                MemcacheHandler::getInstance()->set($progress_key, 99);

                /**
                 * Abrir nueva conexion con la Base de Datos
                 */
                $this->conn = Doctrine_Manager::getInstance()->getCurrentConnection();
                $this->conn->beginTransaction();


                /*
                 * COMMIT DE TODAS LAS TRANSACCIONES
                 */
                $this->conn->commit();
                $this->status = 0;
                $this->list_data = array();
                $this->logMessage("[Liquidación Agrupación] Liquidación exitosa.");
                MemcacheHandler::getInstance()->set($progress_key, 100);
            } else {
                MemcacheHandler::getInstance()->set($progress_key, 100);

                /*
                 * COMMIT DE TODAS LAS TRANSACCIONES
                 */
                $this->conn->commit();

                /*
                 * Mensaje de error
                 */
                $mensajeError = "No hay funcionarios para liquidación.";

                $this->status = 1;
                $this->list_data = array();
                $this->mensajeError = $mensajeError;
                $this->logMessage("[Liquidación Agrupación] " . $mensajeError);
            }
        } catch (Exception $e) {
            MemcacheHandler::getInstance()->set($progress_key, 100);

            /*
             * ROLLBACK DE TODAS LAS TRANSACCIONES EN CASO DE QUE OCURRA ALGUN ERROR
             */
            $this->conn->rollback();
            $this->status = 1;
            $this->mensajeError = "[Liquidación Agrupación] Ocurrio un error: " . $e->getMessage();
            $this->list_data = array();
            $this->logMessage("[Liquidación Agrupación] ERROR!");
            $this->logMessage($e->getMessage());
        }
    }

    /**
     * Calcular los meses a liquidar
     * @param type $id_periodo
     * @param type $num_doc
     * @param type $id_tipo_doc
     * @param type $fecha_ingreso
     * @param type $fecha_termina
     * @param type $record
     */
    private function mesesLiquidar($id_periodo, $num_doc, $id_tipo_doc, $fecha_ingreso, $fecha_termina, $record, $fecha_ini, $fecha_fin) {
        /*
         * Variables de calculo
         */
        $meses = 0;
        $dias_otra_entidad = 0;
        $dias_otra_entidad_liq = 0;
        $dias_ausenc = 0;
        $meses_otra_entidad = 0;



        /**
         * Calculo dias certif otra entidad - 20140610
         */
        //Sql
        $sql = <<<EOD
select 
case when FECHA_DESDE < TO_DATE('$fecha_ini','yyyy-mm-dd') then TO_DATE('$fecha_ini','yyyy-mm-dd') else FECHA_DESDE end as FECHA_INI,
case when FECHA_HASTA > TO_DATE('$fecha_fin','yyyy-mm-dd') then TO_DATE('$fecha_fin','yyyy-mm-dd') else FECHA_HASTA end as FECHA_fin,
case when FECHA_HASTA > TO_DATE('$fecha_fin','yyyy-mm-dd') then TO_DATE('$fecha_fin','yyyy-mm-dd') else FECHA_HASTA end 
- 
case when FECHA_DESDE < TO_DATE('$fecha_ini','yyyy-mm-dd') then TO_DATE('$fecha_ini','yyyy-mm-dd') else FECHA_DESDE end as  DIAS, 

ID_CERTIF_OTRA_ENTIDAD,
ID_TIPO_DOC,
NUM_DOC,
NUM_DOC_SOP,
FECHA_SOPORTE,
OBSERVACIONES,
FECHA_DESDE,
FECHA_HASTA,
NUM_DIAS,
aplica_liquidacion

from NO_CERTIF_OTRA_ENTIDAD

where
(
    FECHA_DESDE between TO_DATE('$fecha_ini','yyyy-mm-dd') and TO_DATE('$fecha_fin','yyyy-mm-dd')
    or 
    FECHA_HASTA between to_date('$fecha_ini','yyyy-mm-dd') and to_date('$fecha_fin','yyyy-mm-dd')
)               
AND num_doc = '$num_doc'
AND id_tipo_doc = $id_tipo_doc
EOD;
        //Ejecutar SQL
        $records = CN_TABLE::executeSQL($sql);

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

            $fecha_ini_otra = $value['fecha_ini'];
            $fecha_fin_otra = $value['fecha_fin'];
            $aplica_liq = $value['aplica_liquidacion'];

            if ($aplica_liq == 1) {
                $dias_otra_entidad_liq += CN_TABLE::diasEntreFechas($fecha_ini_otra, $fecha_fin_otra, false);
            }
            $dias_otra_entidad += CN_TABLE::diasEntreFechas($fecha_ini_otra, $fecha_fin_otra, false);
        }

        $this->logMessage("[Liquidación Agrupación] Dias de otra entidad: " . $dias_otra_entidad);
        $meses_otra_entidad = ($dias_otra_entidad * 12) / 360;
        $this->logMessage("[Liquidación Agrupación] Meses de otra entidad: " . $meses_otra_entidad);



        /**
         * Recorrer cada mes desde el ingreso para verificar kardex
         * verificar ingreso y retiro -20140610
         */
        $anho_ini = $record['anho_ini'];
        $fecha_ini = $anho_ini . '-07-01';
        $date1 = new DateTime($fecha_ini);
        $date2 = new DateTime($fecha_ingreso);
        if ($date2 > $date1) {
            $fecha_ingreso_ka = $fecha_ingreso;
        } else {
            $fecha_ingreso_ka = $fecha_ini;
        }
        $fecha_termina_ka = $fecha_termina;

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

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

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

        $dia_ini = $fecha_ingreso_ka[2];
        $mes_ini = $fecha_ingreso_ka[1];
        $anho_ini = $fecha_ingreso_ka[0];
        $dia_fin = $fecha_termina_ka[2];
        $mes_fin = $fecha_termina_ka[1];

        do {

            /*
             * Validar mes completo
             */
            if ($anho_mes_ini <= $anho_mes_fin && $dia_ini == 1) {
                $dias_ausenc = $dias_ausenc + $this->tieneNovKa($id_tipo_doc, $num_doc, $anho_ini, $mes_ini);
            }

            if ($anho_mes_ini > 220001) {
                $this->logMessage("[CN_TABLE] Supero mes 220001.");
                $dias_ausenc = 0;
                $anho_mes_ini = $anho_mes_fin + 1;
            }

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

            $anho_ini = $fecha_ingreso_ka['id_anhos'];
            $mes_ini = $fecha_ingreso_ka['id_meses'];

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


        $this->logMessage("[Liquidación Agrupación] Dias de ausencias-meses: " . $dias_ausenc);



        /*
         * Prima servicios proporcional - Julio 1 anterior a la fecha de retiro y hasta la misma fecha de retiro
         */
        $anho_ini = $record['anho_ini'];
        $fecha_ini = $anho_ini . '-07-01';

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

        if ($date2 > $date1) {
            $meses = CN_TABLE::mesesEntreFechas($fecha_ingreso, $fecha_termina, false);
        } else {
            $meses = CN_TABLE::mesesEntreFechas($fecha_ini, $fecha_termina, false);
        }

        /**
         * Calculo de meses
         */
        $this->logMessage("[Liquidación Definitiva] Meses liquidacion: " . $meses);
        $this->logMessage("[Liquidación Definitiva] Meses Otra Entidad liquidacion: " . $meses_otra_entidad);
        $this->logMessage("[Liquidación Definitiva] Dias Ausencia liquidacion: " . $dias_ausenc);

        /**
         * return meses
         */
        return $meses + $meses_otra_entidad - $dias_ausenc;
    }

    /**
     * Si posee novedad de kardex para el mes y anho - 20140610
     * @param type $anho
     * @param type $mes
     */
    public function tieneNovKa($id_tipo_doc, $num_doc, $anho, $mes) {

        $cant = 0;

        //Sql
        $sql = <<<EOD
select count(num_doc) as cant from(              
  select      
  novka.*,
  tipnov.afecta_antigu,
  tipnov.afecta_alimen
  from no_novedad_kardex novka
  join no_tip_nov_ka tipnov 
  on novka.id_tip_nov_ka = tipnov.id_tip_nov_ka
  and tipnov.afecta_antigu = 1 
  where
    (
        to_date( '01/' || $mes || '/' || $anho, 'dd/mm/yyyy') between novka.fecha_ini and novka.fecha_fin
        or
        TRUNC(LAST_DAY( to_date( $mes || '/' || $anho, 'mm/yyyy')  )) between novka.fecha_ini and novka.fecha_fin
        
        or
        
        novka.fecha_ini between to_date( '01/' || $mes || '/' || $anho, 'dd/mm/yyyy')  
        and TRUNC(LAST_DAY( to_date( $mes || '/' || $anho, 'mm/yyyy')  ))
        or 
        novka.fecha_fin between to_date( '01/' || $mes || '/' || $anho, 'dd/mm/yyyy')  
        and TRUNC(LAST_DAY( to_date( $mes || '/' || $anho, 'mm/yyyy')  ))
        
    )
    AND novka.num_doc = '$num_doc'
    AND novka.id_tipo_doc = $id_tipo_doc
    and novka.estado = 1
)  
EOD;
        //Ejecutar SQL
        $records = CN_TABLE::executeSQL($sql);
        $cant = $records[0]['cant'];

        /*
         * valida que hay novedad de kardex en el mes y anho
         */
        if ($cant > 0) {
            return 1;
        }

        return 0;
    }

    /**
     * Calcular los dias a liquidar (ausencias no afectan antiguedad) 
     * @param type $id_periodo
     * @param type $num_doc
     * @param type $id_tipo_doc
     * @param type $fecha_ini
     * @param type $fecha_fin
     * @param type $fecha_ingreso
     * @param type $fecha_corte
     * @param type $record
     */
    private function diasLiquidar($id_periodo, $num_doc, $id_tipo_doc, $fecha_ini, $fecha_fin, $fecha_ingreso, $fecha_termina, $record) {

        /*
         * Variables de calculo
         */
        $dias_calc = 0;
        $dias_otra_entidad = 0;
        $dias_otra_entidad_liq = 0;
        $dias_ausenc = 0;

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

        /*
         * Fecha final de calculo - 20131203
         */
        $date3 = new DateTime($fecha_fin);
        $date4 = new DateTime($fecha_termina);
        if ($date3 > $date4) {
            $fecha_fin = $fecha_termina;
        }


        /*
         * Si la fecha de ingreso del funcionario es posterior a la fecha inicio, 
         * debe tomar solo desde la fecha de ingreso del funcionario
         */
        if ($date2 > $date1) {
            $this->logMessage("[Liquidación Agrupación] Fecha de ingreso mayor.");

            $dias_calc = CN_TABLE::diasEntreFechas($fecha_ingreso, $fecha_fin, false);
            //Se cambia para que tome desde fecha de ingreso - 20211126::LAVILA
            $fecha_ini = $fecha_ingreso;
        } else {
            $this->logMessage("[Liquidación Agrupación] Fecha de ingreso menor.");

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


        /**
         * Calculo dias certif otra entidad - 20130702
         */
        //Sql
        $sql = <<<EOD
select 
case when FECHA_DESDE < TO_DATE('$fecha_ini','yyyy-mm-dd') then TO_DATE('$fecha_ini','yyyy-mm-dd') else FECHA_DESDE end as FECHA_INI,
case when FECHA_HASTA > TO_DATE('$fecha_fin','yyyy-mm-dd') then TO_DATE('$fecha_fin','yyyy-mm-dd') else FECHA_HASTA end as FECHA_fin,
case when FECHA_HASTA > TO_DATE('$fecha_fin','yyyy-mm-dd') then TO_DATE('$fecha_fin','yyyy-mm-dd') else FECHA_HASTA end 
- 
case when FECHA_DESDE < TO_DATE('$fecha_ini','yyyy-mm-dd') then TO_DATE('$fecha_ini','yyyy-mm-dd') else FECHA_DESDE end as  DIAS, 

ID_CERTIF_OTRA_ENTIDAD,
ID_TIPO_DOC,
NUM_DOC,
NUM_DOC_SOP,
FECHA_SOPORTE,
OBSERVACIONES,
FECHA_DESDE,
FECHA_HASTA,
NUM_DIAS,
aplica_liquidacion

from NO_CERTIF_OTRA_ENTIDAD

where
(
    FECHA_DESDE between TO_DATE('$fecha_ini','yyyy-mm-dd') and TO_DATE('$fecha_fin','yyyy-mm-dd')
    or 
    FECHA_HASTA between to_date('$fecha_ini','yyyy-mm-dd') and to_date('$fecha_fin','yyyy-mm-dd')
)               
AND num_doc = '$num_doc'
AND id_tipo_doc = $id_tipo_doc
EOD;
        //Ejecutar SQL
        $records = CN_TABLE::executeSQL($sql);

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

            $fecha_ini_otra = $value['fecha_ini'];
            $fecha_fin_otra = $value['fecha_fin'];
            $aplica_liq = $value['aplica_liquidacion'];

            if ($aplica_liq == 1) {
                $dias_otra_entidad_liq += CN_TABLE::diasEntreFechas($fecha_ini_otra, $fecha_fin_otra, false);
            }
            $dias_otra_entidad += CN_TABLE::diasEntreFechas($fecha_ini_otra, $fecha_fin_otra, false);
        }

        $this->logMessage("[Liquidación Agrupación] Dias de otra entidad: " . $dias_otra_entidad);

        /*
         * Calculo de dias de ausencias
         * Rango de fechas para la nov kardex - 20130703
         * Se cambia a FECHA_RANGO_SIN_TREINTAYUNO. Si la novedad tiene una fecha de terminación 
         * mayor a la fecha retiro solo debe tener en cuenta hasta la fecha de retiro. - 20130827
         * Se anexa filtro de estado activo - 20131202
         * Se modifica to_date(novka.fecha_ini,'yyyy-mm-dd'), quitando to_date, ya que son campos de fecha - 20220705::LAVILA
         */
        //Sql
        $sql = <<<EOD
select nvl(sum(dias),0) as dias from(
  select 
  dias_habiles_cant( novka.fecha_ini, novka.fecha_fin ) as dias_hab,
  --(novka.fecha_fin - novka.fecha_ini,'yyyy-mm-dd') + 1  as dias,
      
   FECHA_RANGO_SIN_TREINTAYUNO(
        case when NOVKA.FECHA_INI  < TO_DATE('$fecha_ini','yyyy-mm-dd') 
    then TO_DATE('$fecha_ini','yyyy-mm-dd') else NOVKA.FECHA_INI end
    ,
    case when NOVKA.FECHA_FIN  > TO_DATE('$fecha_fin','yyyy-mm-dd') 
    then TO_DATE('$fecha_fin','yyyy-mm-dd') else NOVKA.FECHA_FIN end
    ) as dias,                
                
  novka.* ,
  tipnov.afecta_antigu,
  tipnov.afecta_alimen
  from no_novedad_kardex novka
  join no_tip_nov_ka tipnov 
  on novka.id_tip_nov_ka = tipnov.id_tip_nov_ka
  and tipnov.afecta_antigu = 1 
  where
    (
        novka.fecha_ini between to_date('$fecha_ini','yyyy-mm-dd') and to_date('$fecha_fin','yyyy-mm-dd')
        or novka.fecha_fin between to_date('$fecha_ini','yyyy-mm-dd') and to_date('$fecha_fin','yyyy-mm-dd')
                
        or
        
        TO_DATE('$fecha_ini','yyyy-mm-dd') between novka.fecha_ini and NOVKA.FECHA_FIN
        or 
        TO_DATE('$fecha_ini','yyyy-mm-dd') between novka.fecha_ini and NOVKA.FECHA_FIN
    )
    AND novka.num_doc = '$num_doc'
    AND novka.id_tipo_doc = $id_tipo_doc
    and novka.estado = 1
) 
EOD;
        //Ejecutar SQL
        $records = CN_TABLE::executeSQL($sql);

        if (count($records) > 0) {
            $this->logMessage("[Liquidación Agrupación] Dias de ausencias: " . $records[0]['dias']);
            $dias_ausenc = $records[0]['dias'];
        }

        $this->logMessage("[Liquidación Agrupación] " . $dias_calc . " - " . $dias_ausenc);
        //return $dias_calc + $dias_otra_entidad - $dias_ausenc;
        $array_dias = array(
            'dias_calc' => $dias_calc + $dias_otra_entidad_liq - $dias_ausenc,
            'dias_otra_entidad' => $dias_otra_entidad - $dias_otra_entidad_liq,
            'dias_otra_entidad_liq' => $dias_otra_entidad_liq,
            'dias_ausenc' => $dias_ausenc
        );

        return $array_dias;
    }

    /**
     * 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, $max_ded_noley = 0, $valor_sumatoria_logica_n = 0, $record_consulta, $id_periodo_fecha_corte) {
        $this->logMessage("[Liquidación Agrupación] Liquidar: periodo " . $id_periodo .
                " - funcionario " . $num_doc . " - concepto nomina " . $id_concep_nomina);

        $id_concep_nomina_inicial = $id_concep_nomina;

        /**
         * Consulta a procedimiento de retencion, para el calculo de retencion en la fuente - 20161213
         * Incidente #6468 <-> Se agrega valor_bonif - 20170613
         * Incidente #7791 <-> Concepto nuevo para calculo procedimiento 1 - 20171215
         * Validacion para el valor que toma de no_liquida_nomina, se agrega sum - 20180118
         */
        //Sql
        $sql = <<<EOD
select 
nvl((select no_param_concep.id_concep_rete_proc1 from no_param_concep where no_param_concep.id_param_concep=1),0) as id_concep_rete_proc1,
(select no_param_concep.id_concep_rete from no_param_concep where no_param_concep.id_param_concep=1) as id_concep_rete,
$id_periodo as id_periodo,
$id_periodo as periodo,     
(select no_periodo.id_anhos from no_periodo where id_periodo = $id_periodo) as vig_ini,
(select no_periodo.id_anhos from no_periodo where id_periodo = $id_periodo) as vig_fin,
(select no_periodo.id_meses from no_periodo where id_periodo = $id_periodo) as per_ini,
(select no_periodo.id_meses from no_periodo where id_periodo = $id_periodo) as per_fin,
nvl((select valor_uvt from ts_uvt where vigencia = (select no_periodo.id_anhos from no_periodo where id_periodo = $id_periodo)) , 1) as valor_uvt,
nvl((select valor_fijo from no_concep_ab where id_concep_nomina in (select no_param_concep.id_concep_bonif from no_param_concep where no_param_concep.id_param_concep = 1)) , 1) as valor_bonif,                      
nvl( (select sum(valor_liquidado) as valor_liquidado from no_liquida_nomina where id_periodo = $id_periodo and NUM_DOC = tab0.NUM_DOC and id_concep_nomina = (select par.id_concep_rete from no_param_concep par where par.id_param_concep = 1 )) , -1) as rete,
tab0.id_novedad_proced_rete,
tab0.id_tipo_doc,
tab0.num_doc,
tab0.id_tipo_proced_rete,
--tab0.id_periodo,
tab0.observacion,
tab0.fecha_inicial,
tab0.fecha_terminacion,
tab0.declara_renta,
tab0.estado ,
null as porcentaje  
from (

  select 
  aut.*,
   ROW_NUMBER() OVER (
    partition by aut.num_doc
    ORDER BY aut.id_novedad_proced_rete desc
   ) AS rn
  from no_novedad_proced_rete aut
  left join no_nombramiento_v nom
  on nom.num_doc = aut.num_doc and nom.id_tipo_doc = aut.id_tipo_doc
  where
  aut.estado = 1 
  or (
    aut.estado = 0 and nom.fecha_termina between (select no_periodo.fecha_ini from no_periodo where id_periodo = $id_periodo )  and (select no_periodo.fecha_fin from no_periodo where id_periodo = $id_periodo ) 
  )

)tab0
where
id_tipo_doc = $id_tipo_doc
and num_doc = '$num_doc'   
EOD;
        //Ejecutar SQL
        $record_proc_rete = CN_TABLE::executeSQL($sql);

        $id_tipo_proced_rete = 0;
        $id_concep_rete = 0;
        $id_concep_rete_proc1 = 0;
        if (count($record_proc_rete) > 0) {
            $id_tipo_proced_rete = $record_proc_rete[0]['id_tipo_proced_rete'];
            $id_concep_rete = $record_proc_rete[0]['id_concep_rete'];
            $id_concep_rete_proc1 = $record_proc_rete[0]['id_concep_rete_proc1'];
        }

        //Cambia concepto nomina si es retefuente y es procedimiento 1 - 20171215
        if ($id_concep_rete_proc1 != 0 && $id_tipo_proced_rete == 1 && $id_concep_nomina == $id_concep_rete) {
            $id_concep_nomina = $id_concep_rete_proc1;
            $record_liq['tag'] = 1;
        }

        /*
         * Valores de UVT y Tope Bonif Globales - 20170614
         */
        $record_uvt_bonif = array();
        //Sql
        $sql = <<<EOD
select nvl((select valor_uvt from ts_uvt where vigencia = (select no_periodo.id_anhos from no_periodo where id_periodo = $id_periodo)) , 1) as valor_uvt from dual  
EOD;
        //Ejecutar SQL
        $record_uvt = CN_TABLE::executeSQL($sql);

        if (count($record_uvt) > 0) {
            $valor_uvt = $record_uvt[0]['valor_uvt'];
        }
        $record_uvt_bonif['valor_uvt'] = $valor_uvt;

        //Incidente #6468 <-> Se agrega valor_bonif - 20170613l
        $sql = <<<EOD
select nvl((select valor_fijo from no_concep_ab where id_concep_nomina in (select no_param_concep.id_concep_bonif from no_param_concep where no_param_concep.id_param_concep = 1)) , 1) as valor_bonif from dual  
EOD;
        //Ejecutar SQL
        $record_bonif = CN_TABLE::executeSQL($sql);

        if (count($record_bonif) > 0) {
            $valor_bonif = $record_bonif[0]['valor_bonif'];
        }
        $record_uvt_bonif['valor_bonif'] = $valor_bonif;

        /**
         * Varibles
         */
        $arrayParametros = array();
        $vals_calc = array();
        $valor_liquidado = 0;
        $fecha_desde = $record_liq['fecha_desde'];
        $fecha_hasta = $record_liq['fecha_hasta'];
        $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("[Liquidación Agrupación] Entro a calcular Formula.");

            foreach ($records as $value) {

                //se adiciona un nuevo campo de formula para completar la retencion que es muy grande el proceso - 20210415::LAVILA
                $formula = $value['formula'] . $value['formula_adic'];
                $this->logMessage("[Liquidación Agrupación] 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("[Liquidación Agrupación] 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
                 */
                if ($record_liq['porcentaje'] == '' || $record_liq['porcentaje'] == null) {
                    $record_liq['porcentaje'] = 0;
                }
                $formula = CN_TABLE::reemplazoConsulta($formula, $record_uvt_bonif); //Solo para valores uvt y bonif - 20170614
                $formula = CN_TABLE::reemplazoConsulta($formula, $record_liq);
                $this->logMessage("[Liquidación Agrupación] 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'
                         */
                        if (!isset($vals_calc[$var])) {
                            $formula_agrup = $this->reemplazoAgrupacion(substr($var, 1));
                            $this->logMessage("[$var] [Liquidación Agrupación] Agrupacion: " . $formula_agrup);

                            // $formula = str_replace('{' . $var . '}', $agrup, $formula);
                            $params_agrup = $this->parametrosFormula($formula_agrup);
                            $res_agrup = $this->resultadoParametros($params_agrup, $record_liq, $record_consulta, $vals_calc, $id_periodo_fecha_corte, $id_concep_nomina, $id_tipo_proced_rete, $id_concep_rete, $id_concep_rete_proc1);
                            $formula_agrup = $this->reemplazoParametros($formula_agrup, $res_agrup);

                            $formula_agrup = str_replace('{', ' ', $formula_agrup);
                            $formula_agrup = str_replace('}', ' ', $formula_agrup);
                            $result_agrup = CN_TABLE::aplicarEval($formula_agrup);

                            /*
                             * No cumple con la condicion
                             */
                            //                if ($result === false) {
                            if ($result_agrup == '-9999' || $result_agrup == -9999) {
                                $this->logMessage("[$var] [Liquidación Agrupación] Formula No cumple con la condicion: " . $formula_agrup);
                                $result_agrup = 0;
                            }

                            $vals_calc[$var] = $result_agrup;
                        }

                        $formula = str_replace('{' . $var . '}', $vals_calc[$var], $formula);
                    }
                }
                $this->logMessage("[Liquidación Agrupación] 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'
                 * );
                 */
                //$arrayParametros = $this->resultadoParametros($arrayParametros, $record_liq, $record_consulta, $vals_calc, $id_periodo_fecha_corte);
                $arrayParametros = $this->resultadoParametros($arrayParametros, $record_liq, $record_consulta, $vals_calc, $id_periodo_fecha_corte, $id_concep_nomina, $id_tipo_proced_rete, $id_concep_rete, $id_concep_rete_proc1);


                /*
                 * Reemplazo de parametros(variables) a la formula
                 * Ejemplo: $arrayParametros = array(
                 * 'C1' => '1100',
                 * 'C2' => '55'
                 * );
                 */
                $formula = $this->reemplazoParametros($formula, $arrayParametros);
                $this->logMessage("[Liquidación Agrupación] 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) {
                if ($result == '-9999' || $result == -9999) {
                    $this->logMessage("[Liquidación Agrupación] Formula No cumple con la condicion: " . $formula);
                    $result = 0;
                }


                /*
                 * Acumulan resultados de liquidacion
                 */
                $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)
                     */
                    $this->logMessage("[Liquidación Agrupación] Valor base salarios minimos valor_liquidado:: " . $valor_liquidado);
                    if ($value['cod_tipo'] == 'V') {
                        $this->logMessage("[Liquidación Agrupación] Formula CodTipo: " . $value['cod_tipo']);

                        /*
                         * Valor Base y porcentaje
                         */
                        $porcentaje = $record_liq['porcentaje'];
                        //Valida si es retefuente y redondea al mil - 20210702
                        $valor_liquidado_base = $valor_liquidado;
                        if ($id_concep_nomina == $id_concep_rete) {
                            $valor_liquidado_base = round($valor_liquidado, -3);
                        }
                        if ($porcentaje != 0) {
                            $valor_base = ($valor_liquidado_base * 100) / $record_liq['porcentaje'];
                        } else {
                            $valor_base = ($valor_liquidado_base * 100) / 1;
                        }
                        $this->logMessage("[Liquidación Agrupación] Valor base salarios minimos antes:: " . $valor_base);
                    }
                }
            }
        } else {

            /**
             * Logica de N
             */
            if ($record_liq['caracter'] == 'N') {
                $this->logMessage("[Liquidación Agrupación] Logica de N - Concepto: " . $id_concep_nomina);

                /*
                 * Resta % (se puede para el valor) 
                 */
                //sumar devengados
                //Sql
                $sql = <<<EOD
select 
nvl(sum(liqnom.valor_liquidado),0) as valor_liquidado  
from no_liquida_nomina liqnom
join no_concep_nomina connom
on liqnom.id_concep_nomina = connom.id_concep_nomina
and connom.operador = 1
where
liqnom.id_periodo = $id_periodo
and liqnom.id_tipo_doc = $id_tipo_doc
and liqnom.num_doc = '$num_doc' 
EOD;
                //Ejecutar SQL
                $records_deveng = CN_TABLE::executeSQL($sql);

                if (count($records_deveng) > 0) {

                    $devengado = $records_deveng[0]['valor_liquidado'];

                    //obtener porcentaje de max_ded_noley
                    $devengado_por = ($devengado * $max_ded_noley) / 100;

                    /*
                     * Si es por porcentaje
                     */
                    if ($record_liq['porcentaje'] != '' || $record_liq['porcentaje'] != null) {

                        $valor_logica_n = (0 * $record_liq['porcentaje']) / 100;
                    } else {
                        $valor_logica_n = $record_liq['valor'];
                    }

                    //Validar resta - operar
                    $this->logMessage("[Liquidación Agrupación] Devengado_por: " . $devengado_por . " - Valor_logica_n: " . $valor_logica_n . " - Valor_sumatoria_logica_n: " . $valor_sumatoria_logica_n);
                    if (($devengado_por - $valor_logica_n - $valor_sumatoria_logica_n) >= 0) {
                        $this->logMessage("[Liquidación Agrupación] Validar resta - operar.");

                        $valor_liquidado = $valor_logica_n;
                        $valor_sumatoria_logica_n += $valor_liquidado;
                    } else {
                        $this->logMessage("[Liquidación Agrupación] No Validar resta - operar.");

                        $valor_liquidado = 0;
                    }
                } else {

                    $this->logMessage("[Liquidación Agrupación] No hay valor devengados.");
                    $valor_liquidado = 0;
                }
            } 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
                 */
                if ($record_liq['porcentaje'] != '' || $record_liq['porcentaje'] != null) {
                    $this->logMessage("[Liquidación Agrupación] Calcular porcentaje - " . $record_liq['porcentaje']);


                    //Sql
                    $sql = <<<EOD
select * from no_liquida_nomina 
where id_concep_nomina = (select id_concep_basica from no_param_concep where id_param_concep = 1)
and id_periodo = $id_periodo
and id_tipo_doc = $id_tipo_doc
and num_doc = '$num_doc' 
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("[Liquidación Agrupación] 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;
            }
        }


        //Reversa el concepto nomina si es retefuente y es procedimiento 1 - 20171215
        //if(false){
        if ($id_concep_rete_proc1 != 0 && $id_tipo_proced_rete == 1 && $id_concep_nomina_inicial == $id_concep_rete) {
            $id_concep_nomina = $id_concep_nomina_inicial;

            $valor_uvt_rete = $valor_liquidado;
            $valor_liquidado = 0;
            $this->logMessage("[Liquidación] Valor de uvt de retencion = " . $valor_uvt_rete);

            /**
             * Se adiciona para la consulta en diciembre que no tome el periodo 4-Prima Navidad, 
             * y es formula de concepto de retencion, solo procedimiento 1 - 20181212
             * Se coloca que omita tambien prima de servicios, solo procedimiento 1, (&& $mes == 12) - 20190614
             */
            $consulta_adic = " ";
            if (($id_concep_nomina == $id_concep_rete || $id_concep_nomina == $id_concep_rete_proc1) /* && $mes == 12 */ && $id_tipo_proced_rete == 1) {
                $consulta_adic = " and per.id_tipo_periodo in (4,3) ";
            }

            /*
             * Para retencion procedimiento 1, se aplica reten383 de la tabla uvt - 20171215
             */
            //Sql
            $sql = <<<EOD
select  
reten.* 
from ts_reten383 reten
where 
reten.vigencia = (select no_periodo.id_anhos from no_periodo where id_periodo = $id_periodo)
and $valor_uvt_rete between reten.rango_desde and reten.rango_hasta
order by
reten.tarifa                       
EOD;
            //Ejecutar SQL
            $record_rete = CN_TABLE::executeSQL($sql);

            if (count($record_rete) > 0) {
                $tarifa_rete = $record_rete[0]['tarifa'];
                $uvt_mas = $record_rete[0]['uvt_mas'];
                $uvt_menos = $record_rete[0]['uvt_menos'];

                //Calculo segun uvt y tarifa
                if ($valor_uvt_rete < 95) {
                    $valor_liquidado = 0;
                    $valor_base = 0;
                }
                if (95 < $valor_uvt_rete) {
                    $valor_liquidado = round((($valor_uvt_rete - $uvt_menos) * ($tarifa_rete / 100) * $valor_uvt) + ($uvt_mas * $valor_uvt));
                    $valor_base = $valor_uvt_rete * $valor_uvt;
                }
            }
        }


        /**
         * Registro de liquida nomina por concepto 
         */
        /*
         * Valida creacion de registro
         */
        if ($valor_liquidado > 0) {

            $this->logMessage("[Liquidación Agrupación] El valor liquidado es: " . $valor_liquidado);


            /**
             * SGC: Valida si es retefuente y redondea al mil - 20140320
             */
            $id_concep_nomina_rete = 0;

            //Sql para tomar id de retefuente
            $sql = <<<EOD
select * from no_param_concep where id_param_concep = 1
EOD;
            //Ejecutar SQL
            $records = CN_TABLE::executeSQL($sql);

            if (count($records) > 0) {
                $id_concep_nomina_rete = $records[0]['id_concep_rete'];
            }
            //SGC: Valida si es retefuente y redondea al mil - 20140320
            if ($id_concep_nomina == $id_concep_nomina_rete) {
                $valor_liquidado = round($valor_liquidado, -3);
            }

            //Validar dias mayores a 0 - 20150612
            if ($num_dias < 0) {
                $num_dias = 0;
            }

            /*
             * Crear nueva liquidación
             * 
             * Asignar valores encontrados en persona
             */
            //insert into no_liquida_nomina (id_liquida_nomina,id_tipo_doc,num_doc,id_concep_nomina,
            //id_periodo,valor_liquidado,fecha_desde,fecha_hasta,num_dias) 
            //values ('9','1','17304849','1','13','257100',to_date('22/11/12','DD/MM/RR'),
            //to_date('22/11/12','DD/MM/RR'),'30');
            //Sql
            $porcentaje = str_replace(',', '.', $porcentaje);
            $sql = <<<EOD
insert into no_liquida_nomina (id_tipo_doc, num_doc, id_concep_nomina,
        id_periodo,valor_liquidado,fecha_desde,fecha_hasta,num_dias, valor_base, porcentaje ) 
        values ( $id_tipo_doc, '$num_doc', $id_concep_nomina, $id_periodo, round($valor_liquidado , 0), 
        to_date('$fecha_desde','YYYY-MM-DD'), to_date('$fecha_hasta','YYYY-MM-DD'), $num_dias, round($valor_base, -3), $porcentaje ) 
EOD;
            //Ejecutar SQL
            CN_TABLE::executeSQL($sql);


            /**
             * Se realiza ajuste nuevo una vez termina para ajustar valores y dias directo al concepto original - 20211119::LAVILA
             */
            //Sql
            $sql = <<<EOD
select 
tab0.id_tipo_doc,
tab0.num_doc,
tab0.id_concep_nomina,
tab0.id_periodo,
tab0.valor_ajuste,
 to_date( '01/' || per.id_meses || '/' || per.id_anhos, 'dd/mm/yyyy')  as fecha_desde,
TRUNC(LAST_DAY( to_date(per.id_meses || '/' || per.id_anhos, 'mm/yyyy')  )) as fecha_hasta,
tab0.num_dias,
nvl(tab0.valor_base,0) as valor_base                    
                    
from no_ajuste_nomina tab0
join no_periodo per
on per.id_periodo = tab0.id_periodo 

WHERE 
tab0.aplicar_liq_concep = 1                     
and tab0.id_periodo = $id_periodo 
and tab0.num_doc = '$num_doc'
and tab0.id_tipo_doc = $id_tipo_doc 
and tab0.id_concep_nomina = $id_concep_nomina
EOD;

            //Ejecutar SQL
            $record_ajuste_liq = CN_TABLE::executeSQL($sql);

            foreach ($record_ajuste_liq as $value_liq) {

                $id_tipo_doc = $value_liq['id_tipo_doc'];
                $num_doc = $value_liq['num_doc'];
                $id_concep_nomina = $value_liq['id_concep_nomina'];
                $id_periodo = $value_liq['id_periodo'];
                $valor_ajuste = $value_liq['valor_ajuste'];
                $num_dias = $value_liq['num_dias'];
                $valor_base = $value_liq['valor_base'];

                //Actualizar cada funcionario-concepto de la liquidacion     
                $sql = <<<EOD
update no_liquida_nomina set valor_liquidado = valor_liquidado + $valor_ajuste, 
    num_dias = num_dias + $num_dias, 
    valor_base = valor_base + ($valor_base) 
where 
num_doc = '$num_doc'
and id_concep_nomina = $id_concep_nomina 
and id_periodo = $id_periodo 
and id_tipo_doc = $id_tipo_doc 
EOD;
                //Ejecutar SQL
                CN_TABLE::executeSQL($sql);
            }
        } else {

            $this->logMessage("[Liquidación Agrupación] El valor_liquidado es menor a cero.");
        }

        $this->logMessage("[Liquidación Agrupación] valor_sumatoria_logica_n: " . $valor_sumatoria_logica_n);
        return $valor_sumatoria_logica_n;
    }

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

        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, $record_consulta, $vals_calc, $id_periodo_fecha_corte, $id_concep_nomina_for = 0, $id_tipo_proced_rete = 0, $id_concep_rete = 0, $id_concep_rete_proc1 = 0) {


        /*
         * 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("[Liquidación] Caracter: " . $caracter . ", numero: " . $id_concep_nomina);

            /**
             * Tomar el valor del salario segun concepto periodo, para la fecha de corte prima de navidad - 20141128
             * Se modifica 1005 y 1006 como 1001 para fecha de corte - 20230605::LAVILA
             */
            $id_periodo_certif = $record_liq['periodo'];
            if ($caracter == 'C' && ( $id_concep_nomina == 1 || $id_concep_nomina == 5 || $id_concep_nomina == 6 )) {
                //se cambia R por E primero del periodo - 20150612
                $caracter = 'E';
                $record_liq['id_periodo'] = $id_periodo_fecha_corte;
                $record_liq['periodo'] = $id_periodo_fecha_corte;
                $this->logMessage("[Liquidación] Caracter :: " . $caracter . ", numero: " . $id_concep_nomina);
            }

            $mes = $record_liq['per_fin'];

            /*
             * 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_consulta) > 0) {
//                $this->logMessage("[Liquidación] Caracter: " . $record_consulta[$caracter]['caracter'] . ", consulta: " . $record_consulta[$caracter]['consulta']);
//                die();
//                $consulta = $record[0]['consulta'];

                if (!isset($vals_calc[$caracter . $id_concep_nomina])) {
                    $consulta = $record_consulta[$caracter]['consulta'];

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

                    /**
                     * Se adiciona para la consulta T que no tome el periodo 4-Prima Navidad, 
                     * y es formula de concepto de retencion, solo procedimiento 1 - 20161213
                     * Se coloca que omita tambien prima de servicios, solo procedimiento 1, (&& $mes == 12) - 20190614
                     */
                    $consulta_adic = " ";
                    if (($id_concep_nomina_for == $id_concep_rete || $id_concep_nomina_for == $id_concep_rete_proc1) && $caracter == 'T' && $id_tipo_proced_rete == 1) {
                        $consulta_adic = "  and per.id_tipo_periodo in (4,3) ";
                    }

                    /*
                     * 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  
$consulta_adic 
EOD;
                    //Ejecutar SQL
                    $record = CN_TABLE::executeSQL($sql);

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

                    /**
                     * Si es prima servicios no tome conceptos de certificado - 20190617
                     */
                    $this->logMessage("[Liquidación] Antes no tome conceptos de certificado: " . $caracter . ", numero: " . $id_concep_nomina . ", Mes:: " . $mes);
                    if (($id_concep_nomina_for == $id_concep_rete || $id_concep_nomina_for == $id_concep_rete_proc1) && $id_tipo_proced_rete == 1) {

                        $this->logMessage("[Liquidación] Si es prima servicios no tome conceptos de certificado: " . $caracter . ", numero: " . $id_concep_nomina);

                        //Sql- si es un comcepto de certificado, y en prima se servicios
                        //Se agrega in 4 para omitir tambien prima navidad - 20201011
                        $sql = <<<EOD
SELECT
    *
FROM no_concep_nomina
where
id_concep_nomina = $id_concep_nomina
and aplica_certif = 1  
and (SELECT max(id_tipo_periodo) FROM no_periodo where id_periodo = $id_periodo_certif) in (3,4) 
EOD;
                        //Ejecutar SQL
                        $record_certif = CN_TABLE::executeSQL($sql);

                        if (count($record_certif) > 0) {
                            $valor = 0;
                        }
                    }

                    $vals_calc[$caracter . $id_concep_nomina] = $valor;
                }
                $valor = $vals_calc[$caracter . $id_concep_nomina];
            } else {
                $valor = 0;
            }

            $arrayParametros[$key] = $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();
        $arrayParametros = 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;
    }

}
