<?php

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

    /**
     * Liquidacion Definitiva
     *
     * @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();

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


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

            /**
             * 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 = $request['id_periodo_filtro'];
            $id_periodo_actual = $request['id_periodo'];
            $progress_key = $request['progress_key'] . $request['username'];

            //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'];
            }

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

            /*
             * COMMIT DE TODAS LAS TRANSACCIONES
             * Se deja para que siempre elimine los registros de la liq, para controlar los retirados y sus anulaciones - 20160727
             */
            $this->conn->commit();


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

            /*
             * 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,VALOR_BASE,PORCENTAJE,NUM_DIAS_BASE) 

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,
tab0.valor_base,
tab0.porcentaje,
tab0.num_dias_base
                    
from no_ajuste_nomina tab0
join no_periodo per
on per.id_periodo = tab0.id_periodo 
                    
WHERE tab0.id_periodo = $id_periodo 
$whereFuncionarioNumDoc $whereFuncionarioTipoDoc  
and tab0.valor_ajuste != 0   
EOD;
            //Ejecutar SQL
            CN_TABLE::executeSQL($sql);

            /**
             * se filtran para vacaciones dias de periodos adicionales - 20140613
             * Se cambia wm_concat por LISTAGG - 20190220
             */
            //Sql
            $sql = <<<EOD
select 
--to_char(wm_concat(id_periodo)) as  periodos
LISTAGG(id_periodo, ',') WITHIN GROUP (ORDER BY id_periodo) as periodos 
from no_periodo
where id_anhos = (select id_anhos from no_periodo where id_periodo = $id_periodo )
and id_meses = (select id_meses from no_periodo where id_periodo = $id_periodo )
and id_tipo_periodo in (1 , 2)  
EOD;
            //Ejecutar SQL
            $record_per = CN_TABLE::executeSQL($sql);
            $periodos = $record_per[0]['periodos'];


            /**
             * Funcionarios con novedad de retiro en el mes del periodo filtrado
             * Se verifico validacion cuando es de periodo mes 7 Julio para tomar el mismo año - 20130724
             * Tag_retro para cuando es retroactivo, para retencion tiene encuenta todo el mes con lo del retroactivo - 20150610
             * Se cambia para el nombramiento, para que tome el ultimo que este como retirado, y no el actual - 20170120
             * Incidente #6468 <-> Se agrega valor_bonif - 20170613
             */
            //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, 
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, 
$salario_minimo as salario_minimo,
1 as tag,
1 as tg_retro,
per.id_anhos as vig_ini,
1 as per_ini,
extract(YEAR FROM nom.fecha_retiro) as vig_fin,
extract(MONTH FROM nom.fecha_retiro) as per_fin, 
tab0.*,
nom.fecha_ingreso,
nom.fecha_termina,
nom.fecha_retiro,
per.id_anhos,
per.id_meses,
per.id_anhos || '-01-01' as fecha_ini,
case when 7 > per.id_meses
then per.id_anhos - 1 else per.id_anhos end  as anho_ini
from no_novedad_personal tab0

join no_novedades novs
on novs.id_novedad = tab0.id_novedad

join no_tipo_novedad tipnov
on tipnov.id_tipo_novedad = novs.id_tipo_novedad

join no_periodo per
on per.id_periodo = tab0.id_periodo

left join (    
  SELECT
   aut.*,
   ROW_NUMBER() OVER (
    partition by aut.num_doc
    ORDER BY aut.num_doc desc, aut.fecha_retiro desc
   ) AS rn
  from no_nombramiento aut
  where 
  aut.fecha_retiro is not null
)nom
on tab0.num_doc = nom.num_doc
and tab0.id_tipo_doc = nom.id_tipo_doc
and nom.rn = 1

/*no_nombramiento_v nom
on tab0.num_doc = nom.num_doc
and tab0.id_tipo_doc = nom.id_tipo_doc*/
--and nom.estado = 1

where 
tipnov.id_tipo_novedad = 2
and per.id_meses = (select id_meses from no_periodo where id_periodo = $id_periodo)   
and per.id_anhos = (select id_anhos from no_periodo where id_periodo = $id_periodo) 
$whereFuncionarioNumDoc $whereFuncionarioTipoDoc 
and tab0.estado = 1                 

and (nom.estado = 1 or
  ( nom.estado = 0 
    and (nom.fecha_retiro
  between to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo where id_periodo = $id_periodo) ,'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_actual) ,'dd/mm/yyyy') ))
  or nom.fecha_retiro = trunc(last_day( to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo where id_periodo = $id_periodo) ,'dd/mm/yyyy') )) + 1 )
  )
)
EOD;
            //Ejecutar SQL
            $records = CN_TABLE::executeSQL($sql);

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

                /**
                 * Obtener concep_periodo por agrupacion - Orden a liquidar
                 * Se quitan conceptos de liquidaciones de prima de servicios y navidad para la agrupacion de la definitiva, excepto retencion - 20150703
                 * Se deja solo para meses menores a 7 para servicios y navidad 13(para que tome todos los meses) - 20160719
                 */
                $sql = <<<EOD
select 
* 
from no_agrup_deta
where id_agrup_concepto = $id_agrup_concepto
and ID_CONCEP_NOMINA not in (

    select distinct
    liq.id_concep_nomina 
    from no_liquida_nomina liq
    where
    id_periodo in (
        select 
        per.id_periodo 
        from no_periodo per
        where
        per.id_tipo_periodo in (3,4)
        and per.id_anhos = (select id_anhos from no_periodo where id_periodo = $id_periodo)
        and per.id_meses = (select id_meses from no_periodo where id_periodo = $id_periodo)
        and per.id_meses < case when per.id_tipo_periodo = 3 then 7 else 13 end
    )
    and liq.id_concep_nomina != (select no_param_concep.id_concep_rete from no_param_concep where no_param_concep.id_param_concep = 1)

)
order by 
orden,
id_agrup_deta 
EOD;
                //Ejecutar SQL
                $records_agrup = CN_TABLE::executeSQL($sql);


                /*
                 * Por funcionario 
                 */
                $i = 1;
                $nom_conceptos_a_procesar = count($records);

                // 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 Definitiva] nom_conceptos_a_procesar: " . $nom_conceptos_a_procesar);
                foreach ($records as $value) {

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

                    $this->logMessage("[Liquidación Definitiva] Existen liquidaciones.");

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

                    /*
                     * Calcular los meses a liquidar
                     */
//                    $meses_liq = 0;

                    $anho_ini = $value['id_anhos'];
                    $fecha_ini = $anho_ini . '-07-01';
                    $anho_fin = $anho_ini + 1;
                    $fecha_fin = $anho_fin . '-07-01';
                    $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;
                    }

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

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

                        /*
                         * Calcular los dias a liquidar
                         */
                        $dias_liq_array = $this->diasLiquidar($id_periodo, $num_doc, $id_tipo_doc, $fecha_ingreso, $fecha_termina, $value, $id_concep_nomina);

                        $dias_liq = $dias_liq_array['num_dias'];
                        $dias_liq_base = $dias_liq_array['num_dias_base'];
                        $dias_otra_ent = $dias_liq_array['dias_otra_entidad'];

                        $this->logMessage("[Liquidación Definitiva] Dias de Liquidación: " . $dias_liq);


                        /**
                         * Tag_def para cambiar el tipo valor de la formula por M
                         * Tag_retro para cuando es retroactivo, para retencion tiene encuenta todo el mes con lo del retroactivo - 20150610
                         * Incidente #6468 <-> Se agrega valor_bonif - 20170613
                         */
                        $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,  
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 tag_def,
$salario_minimo as salario_minimo,
1 as tag,
1 as tg_retro,
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,
0 as dias_ausenc,
'$caracter' as caracter,
nvl('$fecha_ingreso', '') as fecha_ingreso,
nvl('$fecha_termina', '') as fecha_termina,
nvl('$fecha_retiro', '') as fecha_retiro,
$dias_liq as num_dias,
$dias_liq_base as num_dias_base,
null as porcentaje,
$num_doc as num_doc,
$id_tipo_doc as id_tipo_doc,
$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);

                        /*
                         * Validar registro
                         */
                        if (count($recordsLiq) > 0) {

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

//                            $this->status = 1;
//                            $this->list_data = array();
//                            $this->mensajeError = $mensajeError;
                            $this->logMessage("[Liquidación Definitiva] " . $mensajeError);
                        }
                    }
//                    die();
                    $i++;



                    /**
                     * INICIO :: Calculo Salud / Pension Liq Def - 20141014
                     */
                    $this->logMessage("[Liquidación Definitiva] Calculo Salud / Pension Liq Def");

                    /*
                     * Traer conceptos por funcionario de salud / pension
                     */
                    $sql = <<<EOD
select distinct
desdet.porcentaje_func,
desdet.porcentaje_patrono,
foncon.id_descuento_ss,
foncon.id_concep_nomina,
afifon.* 
from no_afilia_fondo afifon

join no_fondo_concepto foncon
on foncon.id_mae_fondos = afifon.id_mae_fondos

join no_descto_detalle desdet
on desdet.id_tipo_aporte = afifon.id_tipo_aporte
and foncon.id_descuento_ss = desdet.id_descuento_ss

where
afifon.NUM_DOC = $num_doc
and afifon.estado = 1
and afifon.id_clase_fondo in (1,2)

order by
afifon.id_clase_fondo     
EOD;
                    //Ejecutar SQL
                    $recordsFondo = CN_TABLE::executeSQL($sql);

                    /**
                     * Recorrer Agrupaciones
                     */
                    foreach ($recordsFondo as $valueFondo) {

                        /*
                         * Variables agrup_concep
                         */
                        $id_concep_nomina = $valueFondo['id_concep_nomina'];
                        $porcentaje = $valueFondo['porcentaje_func'];
                        $caracter = "T";



                        /*
                         * Tag_def para cambiar el tipo valor de la formula por M
                         * Tag_retro para cuando es retroactivo, para retencion tiene encuenta todo el mes con lo del retroactivo - 20150610
                         * Incidente #6468 <-> Se agrega valor_bonif - 20170613
                         */
                        $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, 
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, 
1 as tag_def,
$salario_minimo as salario_minimo,
1 as tag,
0 as tg_retro,
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,
30 as dias_liq,
0 as wdiasv,
$dias_otra_ent as dias_otra_ent,
0 as dias_ausenc,
'$caracter' as caracter,
nvl('$fecha_ingreso', '') as fecha_ingreso,
nvl('$fecha_termina', '') as fecha_termina,
nvl('$fecha_retiro', '') as fecha_retiro,
30 as num_dias,
$dias_liq_base as num_dias_base,
$porcentaje as porcentaje,
$num_doc as num_doc,
$id_tipo_doc as id_tipo_doc,
$id_periodo as id_periodo,
$id_periodo as periodo,
$id_concep_nomina as id_concep_nomina
from dual     
EOD;
                        //Ejecutar SQL
                        $records = CN_TABLE::executeSQL($sql);

                        /*
                         * Recorre los registros de funcionario - concepto nomina
                         * para ser liquidados
                         */
                        foreach ($records as $value) {
                            $this->logMessage("[Liquidación Definitiva] Existen liquidaciones.");

                            $id_periodo = $value['periodo'];
                            $num_doc = $value['num_doc'];
                            $id_tipo_doc = $value['id_tipo_doc'];
                            $id_concep_nomina = $value['id_concep_nomina'];

                            /*
                             * Liquidar periodo-funcionario-concepto nomina
                             */
                            $this->liquidar($id_periodo, $num_doc, $id_tipo_doc, $id_concep_nomina, $value, $arrayConstantes);
                        }
                    }

                    /*
                     * FSP - 20141014
                     */
                    /**
                     * Consultar salario minimo
                     * Tag_def para cambiar el tipo valor de la formula por M
                     * Se cambia a vigencia el periodo del filtro - 20140403
                     * (select nvl(valor_mensual, 0) as valor_mensual from no_smdlv where vigencia = extract(year from sysdate))  
                     */
                    $salario_minimo = 550000;
                    //Sql
                    $sql = <<<EOD
(select nvl(valor_mensual, 0) as valor_mensual from no_smdlv where vigencia = (select id_anhos from no_periodo where id_periodo = $id_periodo ))  
EOD;
                    //Ejecutar SQL
                    $record_smlv = CN_TABLE::executeSQL($sql);

                    if (count($record_smlv) > 0) {
                        $salario_minimo = $record_smlv[0]['valor_mensual'];
                    }

                    $valor_base = 0;



                    /*
                     * Tag_retro para cuando es retroactivo, para retencion tiene encuenta todo el mes con lo del retroactivo - 20150610
                     */
                    //Sql
                    $sql = <<<EOD
select 
0 as tag_def,
$salario_minimo as salario_minimo,
1 as tag,
0 as tg_retro,
$id_periodo as periodo,                    
tab0.* 
from no_liquida_nomina tab0
left join no_fondo_concepto foncon
on tab0.id_concep_nomina = foncon.id_concep_nomina
where foncon.id_descuento_ss = 2
and tab0.id_periodo = $id_periodo
and tab0.num_doc = $num_doc
order by 
tab0.id_tipo_doc,
tab0.num_doc
EOD;

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

                    foreach ($record_fsp as $value) {

                        $id_liquida_nomina = $value['id_liquida_nomina'];
                        $valor_base = $value['valor_liquidado'];
                        $valor_base_vac = 0;
                        $num_doc = $value['num_doc'];
                        $id_tipo_doc = $value['id_tipo_doc'];
                        $num_dias_fsp = $value['num_dias'];
                        $id_concep_nomina = $value['id_concep_nomina'];


                        /*
                         * Calcular IBC para vacaciones - 20170503
                         */
                        //Dias para vacaciones
                        //Se habilita novedvac para el periodo a liquidar - filtro id_periodo - 20130722 Se deshablita - 20130723
                        //Toma los dias de vacaciones para el mes a liquidar - 20130723
                        //Sql
                        $sql = <<<EOD
select  nvl(num_dias_vac,0) as dias_vac from (    
    select 
    novvac.id_tipo_doc,                  
    novvac.num_doc,
    nvl(sum(dias_rango_mes(novvac.fecha_ini,novvac.fecha_fin,(select id_meses 
        from no_periodo where id_periodo =  $id_periodo))),0) as dias,
    nvl(sum( novvac.fecha_fin - novvac.fecha_ini + 1),0) as dias_vac,

    nvl(sum( 
        case when TIPNOV.operador = 1
        then DIAS_RANGO_MES_SIN_TREINTAYUNO(novvac.fecha_ini,novvac.fecha_fin,(select id_meses from no_periodo where id_periodo =  $id_periodo))
        else DIAS_RANGO_MES_SIN_TREINTAYUNO(novvac.fecha_ini,novvac.fecha_fin,(select id_meses from no_periodo where id_periodo =  $id_periodo)) * (-1)
        end     
    ),0) as num_dias_vac

    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.ID_PERIODO = $id_periodo
      and (
              novvac.fecha_ini between to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo where id_periodo = $id_periodo) ,'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) ,'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) ,'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) ,'dd/mm/yyyy') )) 

              or        


              to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo where id_periodo = $id_periodo) ,'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) ,'dd/mm/yyyy') )) between novvac.fecha_ini and novvac.fecha_fin
     )
      and novvac.NUM_DOC = $num_doc
      group by novvac.id_tipo_doc, novvac.num_doc
)
EOD;

                        //Ejecutar SQL
                        $record_vac = CN_TABLE::executeSQL($sql);
                        // Se agrega al calculo la formula (({A39}/30)*$wdiasv)) - 20130517
                        // Toma los dias de vacaciones para el mes a liquidar
                        $wdiasv = 0;
                        if (count($record_vac) > 0) {
                            $wdiasv = $record_vac[0]['dias_vac'];
                        }
                        $formula = "(({A39}/30)*$wdiasv)";
                        $this->logMessage("[Liquidación Vac] Formula Inicial: " . $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("[Liquidación Vac] Agrupacion: " . $agrup);

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

                        $arrayParametros = $this->parametrosFormula($formula);
                        $arrayParametros = $this->resultadoParametros($arrayParametros, $value);

                        $formula = $this->reemplazoParametros($formula, $arrayParametros);
                        /*
                         * 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 Vac] Formula No cumple con la condicion: " . $formula);
                            $result = 0;
                        }
                        //Valor base de IBC vacaciones
                        $valor_base_vac = round($result, -3);
                        $this->logMessage("[Liquidación Vac] Valor base de IBC vacaciones: " . $valor_base_vac);


                        /*
                         * Valor vase formula FSP
                         */
                        $valor_base = round($valor_base, -3);
                        //                $valor_base = round($valor_base);
                        //valor base no puede superar 25 salarios minimos
                        if ($valor_base > ($salario_minimo * 25)) {
                            $valor_base = round(($salario_minimo * 25) - 1, -3);
                            //                    $valor_base = round(($salario_minimo * 25) - 1);
                        }


                        /*
                         * Variables del concepto 1 asignacion basica para los dias de liquidacion y totales de vacaciones - 20131216
                         * Anexo de conceptos de enfermedad por el tipo de novedad que causa liquidacion - 20131217
                         * Se agrega filtro de vacaciones para que tome novedad por la fecha y no solo el periodo - 20140526 
                         * Se quita condicion anterior - 20140605
                         * Se agregan periodos adicionales para el periodo filtrado, para que tenga en cuenta los dias de vac - 20150123 Revisar Gloria Amparo
                         * Se agrega para los dias wdiasv, que tome reintegros, y opere dias - 20161207
                         */
                        //Sql
                        $sql = <<<EOD
select 
tab0.id_tipo_doc,
tab0.num_doc,
--tab0.id_concep_nomina,
--sum(tab0.num_dias) as dias_liq,
sum(case when connom.operador = 1 then tab0.num_dias else tab0.num_dias*(-1) end ) as dias_liq,
max(nvl(vac.dias_vac,0)) as wdiasv

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
                    
left join (
    
    select 
    novvac.id_tipo_doc,                  
    novvac.num_doc,
    nvl(sum(dias_rango_mes(novvac.fecha_ini,novvac.fecha_fin,(select id_meses 
        from no_periodo where id_periodo =  $id_periodo))),0) as dias,
    nvl(sum( novvac.fecha_fin - novvac.fecha_ini + 1),0) as num_dias_vac,
    --nvl(sum(FECHA_RANGO_SIN_TREINTAYUNO(novvac.fecha_ini,novvac.fecha_fin)),0) as dias_vac
    nvl(sum(     
    case when tipnov.operador = 1 
    then FECHA_RANGO_SIN_TREINTAYUNO(novvac.fecha_ini,novvac.fecha_fin)
    else FECHA_RANGO_SIN_TREINTAYUNO(novvac.fecha_ini,novvac.fecha_fin) * (-1) end    
    ),0) as dias_vac 
                        
    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 tipnov.operador in (0,1) and novvac.id_periodo in ( $periodos )
    /*                    
    and (    
             novvac.id_periodo = $id_periodo
              or
             novvac.fecha_ini between to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo where id_periodo = $id_periodo) ,'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) ,'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) ,'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) ,'dd/mm/yyyy') )) 

             or        

             to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo where id_periodo = $id_periodo) ,'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) ,'dd/mm/yyyy') )) between novvac.fecha_ini and novvac.fecha_fin
    )
    */
    group by novvac.id_tipo_doc, novvac.num_doc

)vac
on vac.id_tipo_doc = tab0.id_tipo_doc and vac.num_doc = tab0.num_doc

where tab0.periodo = $id_periodo
and tab0.num_doc = $num_doc
and tab0.id_tipo_doc = $id_tipo_doc

and ( 
  tab0.id_concep_nomina in (select id_concep_rein from no_concep_nomina where id_concep_nomina = (select no_param_concep.ID_CONCEP_BASICA from no_param_concep where id_param_concep = 1)) 
  or tab0.id_concep_nomina in (select id_concep_ajuste from no_concep_nomina where id_concep_nomina = (select no_param_concep.ID_CONCEP_BASICA from no_param_concep where id_param_concep = 1)) 
  or  tab0.id_concep_nomina = (select no_param_concep.ID_CONCEP_BASICA from no_param_concep where id_param_concep = 1) 
  or tab0.id_concep_nomina in (SELECT DISTINCT
    kar.ID_CONCEP_NOMINA 
    FROM NO_CONCEP_KA kar
    join NO_TIP_NOV_KA tipkar
    on tipkar.ID_TIP_NOV_KA = kar.ID_TIP_NOV_KA
    where tipkar.CAUSA_LIQUIDACION = 1) 
)
                        
and tipcon.id_tipo_concepto != 4
             
group by
tab0.id_tipo_doc,
tab0.num_doc
    --,tab0.id_concep_nomina  
EOD;
                        //Ejecutar SQL
                        $record_smlv = CN_TABLE::executeSQL($sql);

                        if (count($record_smlv) > 0) {
                            $dias_liq = $record_smlv[0]['dias_liq'];
                            $wdiasv_tot = $record_smlv[0]['wdiasv'];
                        } else {
                            $wdiasv_tot = 0;
                        }



                        //Sql
                        $sql = <<<EOD
select nvl(sum(valor),0) as valor from no_concepto_func 
    where num_doc = $num_doc and id_tipo_doc = 1 
        and id_concep_nomina = (select no_param_concep.id_concep_basica from no_param_concep where no_param_concep.id_param_concep = 1) 
            and estado = 1 and actual = 1
EOD;

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

                        $salario = $record_asig[0]['valor'];


                        /**
                         * Valor base de todo el mes para el tope deFSP, el calculo si es la base de la formula - 20190506
                         */
                        $formula = "(({A18}/1)*1)";
                        $this->logMessage("[Liquidación FSP] Formula Inicial: " . $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("[Liquidación FSP] Agrupacion: " . $agrup);

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

                        $arrayParametros = $this->parametrosFormula($formula);
                        $value['tag_def'] = 0; //Para que no cambie por el tipo M sino tome lo de la formula
                        $arrayParametros = $this->resultadoParametros($arrayParametros, $value);

                        $formula = $this->reemplazoParametros($formula, $arrayParametros);
                        /*
                         * 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 FSP] Formula No cumple con la condicion: " . $formula);
                            $result = 0;
                        }
                        //Valor base de IBC vacaciones
                        $valor_base_fsp = round($result, -3);
                        $this->logMessage("[Liquidación FSP] Valor base de FSP: " . $valor_base_fsp);

                        //Anexo dias totales y de vacaciones totales - 20131217
                        $array_valor_base = $this->valor_base_fsp($valor_base, $salario_minimo, $valor_base_vac, $wdiasv_tot, $dias_liq, $num_doc, $id_periodo, $salario, $valor_base_fsp);
                        $valor_fsp = $array_valor_base['valor_fsp'];
                        $porcentaje_fsp = $array_valor_base['porcentaje_fsp'];

                        /**
                         * SQL de consulta para validar si el concepto de FSP es por ajuste - 20131129
                         */
                        //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
from no_ajuste_nomina tab0
join no_periodo per
on per.id_periodo = tab0.id_periodo 
WHERE tab0.id_periodo = $id_periodo 
and tab0.NUM_DOC = $num_doc
and tab0.id_concep_nomina = $id_concep_nomina
EOD;

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

                        /*
                         * Validar si el FSP es por ajuste - 20131129
                         */
                        if (count($record_fsp_ver) == 0) {
                            if ($valor_fsp > 0) {

                                /*
                                 * Actualizar valores de FSP
                                 */
                                //sentencia sql
                                $sql = <<<EOD
update NO_LIQUIDA_NOMINA set valor_liquidado =  $valor_fsp
        , porcentaje = $porcentaje_fsp
            , valor_base = round( valor_liquidado, -3 ) 
    where id_liquida_nomina = $id_liquida_nomina 
        and id_periodo = $id_periodo
EOD;
                                //ejecuta y obtiene el resultado del sql
                                CN_TABLE::executeSQL($sql);
                            } else {

                                /*
                                 * Borrar del FSP
                                 */
                                //sentencia sql
                                $sql = <<<EOD
delete from NO_LIQUIDA_NOMINA where id_liquida_nomina = $id_liquida_nomina 
and id_periodo = $id_periodo
EOD;
                                //ejecuta y obtiene el resultado del sql
                                CN_TABLE::executeSQL($sql);
                            }
                        } else {

                            $valor_ajuste = $record_fsp_ver[0]["valor_ajuste"];

                            /*
                             * Borrar del FSP que no estan en la tabla de ajustes - 20140515
                             */
                            //sentencia sql
                            $sql = <<<EOD
delete from NO_LIQUIDA_NOMINA where id_liquida_nomina = $id_liquida_nomina 
and id_periodo = $id_periodo
and valor_liquidado != $valor_ajuste
EOD;
                            //ejecuta y obtiene el resultado del sql
                            CN_TABLE::executeSQL($sql);
                        }
                    }


                    /**
                     * FIN :: Calculo Salud / Pension Liq Def
                     */
//                    die();


                    /**
                     * Solo retefunte
                     * Tag_def para cambiar el tipo valor de la formula por M
                     * Inicio del proceso de calculo de Retencion en la fuente concepto 2001
                     * Incidente #6468 <-> Se agrega valor_bonif - 20170613
                     * Si el porcentaje es 0 coloca 1 para el procedimiento 1 - 20181108
                     * Se toma unicamente los de estado 1 y actual 1, que son los vigentes - 20190425
                     */
                    $this->logMessage("[Liquidación Definitiva] Inicio del proceso de calculo de Retencion en la fuente concepto 2001");
                    //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,
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, 
1 as tag_def,
$salario_minimo as salario_minimo,
1 as tag,
1 as tg_retro,
0 as meses_liq,
'O' as caracter, 
0 as num_dias, 
0 as num_dias_base,
0 as dias_liq,
0 as dias_otra_ent,
0 as dias_ausenc,
$id_periodo as id_periodo,
$id_periodo as periodo,
tab0.id_concep_func,
tab0.id_tipo_doc,
tab0.num_doc,
tab0.id_concep_nomina,
tab0.valor,
case when tab0.porcentaje = 0 then 1 else tab0.porcentaje end as porcentaje,
tab0.estado,
tab0.actual,
tab0.fecha_desde,
tab0.fecha_hasta, 
tab0.fecha_desde as fecha_ingreso,
tab0.fecha_hasta as fecha_termina,
tab0.fecha_hasta as fecha_retiro
from no_concepto_func tab0
WHERE 1 = 1 
AND tab0.num_doc = '$num_doc'
AND tab0.id_tipo_doc = $id_tipo_doc 
and tab0.id_concep_nomina = (select id_concep_rete from no_param_concep where id_param_concep = 1)
and tab0.estado = 1
and tab0.actual = 1
order by 
tab0.id_tipo_doc,
tab0.num_doc 
EOD;
                    //Ejecutar SQL
                    $records = CN_TABLE::executeSQL($sql);


                    /*
                     * Recorre los registros de funcionario - concepto nomina
                     * para ser liquidados
                     */
                    foreach ($records as $value) {
                        $this->logMessage("[Liquidación Definitiva] Existen liquidaciones.");

                        $id_periodo = $value['periodo'];
                        $num_doc = $value['num_doc'];
                        $id_tipo_doc = $value['id_tipo_doc'];
                        $id_concep_nomina = $value['id_concep_nomina'];

                        /*
                         * Liquidar periodo-funcionario-concepto nomina
                         */
                        $this->liquidar($id_periodo, $num_doc, $id_tipo_doc, $id_concep_nomina, $value, $arrayConstantes);
                    }
                }
                /*
                 * Memcache al 100 porciento
                 */
                MemcacheHandler::getInstance()->set($progress_key, 100);

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

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

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

                $this->status = 1;
                $this->list_data = array();
                $this->mensajeError = $mensajeError;
                $this->logMessage("[Liquidación Definitiva] " . $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();

            /**
             * Respuesta del servicio
             */
            $this->status = 1;
            $this->mensajeError = "[Liquidación Definitiva] Ocurrio un error: " . $e->getMessage();
            $this->list_data = array();
            $this->logMessage("[Liquidación Definitiva] 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);

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

    /**
     * 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 mesesLiquidar2($id_periodo, $num_doc, $id_tipo_doc, $fecha_ingreso, $fecha_termina, $record) {
        /*
         * Variables de calculo
         */
        $meses = 0;

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

    /**
     * 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_ingreso
     * @param type $fecha_termina
     * @param type $record
     * @param type $id_concep_nomina
     * @return int
     */
    private function diasLiquidar($id_periodo, $num_doc, $id_tipo_doc, $fecha_ingreso, $fecha_termina, $record, $id_concep_nomina) {

        /*
         * (SGC-1, ANM-2, SGR-3, CYC-4, COL-5, INCI-6, LOCAL-7, CEV-8, CEV_PUB-9)
         */
        $array = sfYaml::load(dirname(__FILE__) . '/../../../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++;
        }

        /*
         * Variables de calculo
         */
        $dias = 0;
        $dias_base = 0;
        $dias_array = array();
        $dias_kardex = 0;
        $dias_vac = 0;
        $dias_otra_entidad = 0;
        $dias_otra_entidad_liq = 0;

        $fecha_ini_causa_vac = $fecha_ini_ka = $fecha_ingreso;
        $fecha_fin_ka = $fecha_termina;
        $fecha_retiro = $record['fecha_retiro'];

        //Validacion segun entidad - 20190221
        //Movi antes de Calculo de dias por concepto - 20200122
        if ($entidadCliente == 8) {
            if ($id_concep_nomina == 16) {
                $id_concep_nomina = 17;
            }
        }

        /*
         * Calculo de dias por concepto
         */
        //Vacaciones proporcional - Tabla de causacion vacaciones
        if ($id_concep_nomina == 8 || $id_concep_nomina == 9 || $id_concep_nomina == 10) {

            //Solo para 1009 y 1010, toma periodos completos de causacion - 20170428
            $whereValidacion = "";
            if ($id_concep_nomina == 9 || $id_concep_nomina == 10) {
                $whereValidacion = "and saldos_dias = num_dias  ";
            }

            /*
             * Calculo de dias de ausencias
             */
            //Sql
            $sql = <<<EOD
select * from no_causa_vacac  
where 
num_doc =  '$num_doc'  and  id_tipo_doc = $id_tipo_doc 
and to_date('$fecha_termina','yyyy-mm-dd') between fecha_ini and fecha_fin 
order by FECHA_INI desc 
EOD;
            //Ejecutar SQL
            $records = CN_TABLE::executeSQL($sql);

            if (count($records) > 0) {

                //Consulta para dias de otros periodos de vacaciones no tomados - 20130620
                $id_causa_vacac = $records[0]['id_causa_vacac'];

                //Sql
                // Incidente #6076, solo para 1009 y 1010, toma periodos completos de causacion - 20170428
                $sql = <<<EOD
select sum(nvl(SALDOS_DIAS,0)) as saldos_dias 
from no_causa_vacac  
where 
num_doc =  '$num_doc'  and  id_tipo_doc = $id_tipo_doc 
and ID_CAUSA_VACAC != $id_causa_vacac
--and TO_DATE('$fecha_termina','yyyy-mm-dd') <= FECHA_FIN 
and FECHA_INI <= TO_DATE('$fecha_termina','yyyy-mm-dd') 
$whereValidacion     
EOD;
                //Ejecutar SQL
                $records_vac = CN_TABLE::executeSQL($sql);

                $num_dias_vac = 15;
                if ($entidadCliente == 9) {
                    $num_dias_vac = 25; //dias cev publica - 20191126
                }

                $dias_vac = $records_vac[0]['saldos_dias'] * 360 / $num_dias_vac;
                $this->logMessage($records_vac[0]['saldos_dias'] . " [Liquidación Definitiva] dias_vac: " . $dias_vac);

                $fecha_ini_causa_vac = $fecha_ini = $records[0]['fecha_ini'];
                $fecha_fin = $fecha_termina;

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

                //Se toman dias de la tabla de nombramientos que posee hasta el dia que trabaja en fecha_termina
                $dias = $dias + $dias_vac;
            }
        }
        //Prima servicios proporcional - Julio 1 anterior a la fecha de retiro y hasta la misma fecha de retiro
        elseif ($id_concep_nomina == 16) {

            $anho_ini = $record['anho_ini'];
            $fecha_ini = $anho_ini . '-07-01';

            $this->logMessage("[Liquidación Definitiva] Prima de servicios - Enero 1 a la fecha de retiro." . $fecha_ini . " - " . $fecha_termina);

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

            if ($date2 > $date1) {
                $fecha_ini_causa_vac = $fecha_ini_ka = $fecha_ingreso;
                if ($date2 <= $date4) { //Se valida que la fecha de terminacion no sea menor - 20140722
                    $dias = CN_TABLE::diasEntreFechas($fecha_ingreso, $fecha_termina, false);
                }
            } else {
                $fecha_ini_causa_vac = $fecha_ini_ka = $fecha_ini;
                if ($date1 <= $date4) { //Se valida que la fecha de terminacion no sea menor - 20140722
                    $dias = CN_TABLE::diasEntreFechas($fecha_ini, $fecha_termina, false);
                }
            }
            //Se toman dias de la tabla de nombramientos que posee hasta el dia que trabaja en fecha_termina
            $dias = $dias;

            /*
             * Se añaden dias desde que ingresa antes de Julio 1 del anho anterior - 20130725
             * Se quitan los dias, esta inflando los dias de la validacion del calculo de la formula - 20140723
             * Se habilita nuevamente los dias antes del 1 de Julio, para que permita liquidar 1016, se agrega validacion en fechas $date2 < $date1 - 20151020
             */
            if ($date2 < $date1) {
                $dias_otra_entidad += CN_TABLE::diasEntreFechas($fecha_ingreso, $fecha_ini, false);
            }
        }
        //Prima de navidad proporcional - Enero 1 a la fecha de retiro
        elseif ($id_concep_nomina == 17 || $id_concep_nomina == 20) {

            $fecha_ini = $record['fecha_ini'];

            $date1 = new DateTime($fecha_ini);
            $date2 = new DateTime($fecha_ingreso);
            //fecha_terminacion
            $date3 = new DateTime($fecha_termina);

            $this->logMessage("[Liquidación Definitiva] Prima de navidad proporcional - Enero 1 a la fecha de retiro." . $fecha_ini . " - " . $fecha_termina);

            /*
             * Validar que la fecha de terminacion sea mayor a la fecha inicial
             */
            if ($date3 >= $date1) {

                /*
                 * Si la fecha de ingreso del funcionario es posterior a la fecha 1 de enero del mismo anho, 
                 * debe tomar solo desde la fecha de ingreso del funcionario
                 */
                if ($date2 > $date1) {
                    $fecha_ini_causa_vac = $fecha_ini_ka = $fecha_ingreso;
                    $dias = CN_TABLE::diasEntreFechas($fecha_ingreso, $fecha_termina, false);
                } else {
                    $fecha_ini_causa_vac = $fecha_ini_ka = $fecha_ini;
                    $dias = CN_TABLE::diasEntreFechas($fecha_ini, $fecha_termina, false);
                }
            } else {
                $dias = 0;
            }


            //Se toman dias de la tabla de nombramientos que posee hasta el dia que trabaja en fecha_termina
            $dias = $dias;
        }
        //Dias de proporcionalidad bonificacion por servicios - 20140224 
        elseif ($id_concep_nomina == 11) {

            /*
             * Registro ultimo de bonificacion
             */
            //Se cambia para que tome la fecha de retiro, por si su ultimo dia trabajado corresponde al final de la bonificacion - 20150128
            //Sql
            $sql = <<<EOD
select * from no_bonifica_servicios
where 
num_doc =  '$num_doc'  and  id_tipo_doc = $id_tipo_doc
and to_date('$fecha_retiro','yyyy-mm-dd') between fecha_ingresa and fecha_bonifica
order by fecha_bonifica desc 
EOD;
            //Ejecutar SQL
            $records = CN_TABLE::executeSQL($sql);
            if (count($records) > 0) {

                //Consulta para dias de otros periodos de vacaciones no tomados - 20130620
                $fecha_ini_causa_vac = $fecha_ingresa = $records[0]['fecha_ingresa'];

                $date1 = new DateTime($fecha_ingresa);
                $date2 = new DateTime($fecha_termina);

                if ($date2 > $date1) {
                    $dias = CN_TABLE::diasEntreFechas($fecha_ingresa, $fecha_termina, false);
                }

                $dias = $dias;
            }
        } else {
            $this->logMessage("[Liquidación Definitiva] Id de concepto sin identificar.");
//            $dias = 360;

            /**
             * Otros Conceptos - se toma en base en 1020
             */
            $fecha_ini = $record['fecha_ini'];

            $date1 = new DateTime($fecha_ini);
            $date2 = new DateTime($fecha_ingreso);
            //fecha_terminacion
            $date3 = new DateTime($fecha_termina);

            $this->logMessage("[Liquidación Definitiva] Prima de navidad proporcional - Enero 1 a la fecha de retiro." . $fecha_ini . " - " . $fecha_termina);

            /*
             * Validar que la fecha de terminacion sea mayor a la fecha inicial
             */
            if ($date3 >= $date1) {

                /*
                 * Si la fecha de ingreso del funcionario es posterior a la fecha 1 de enero del mismo anho, 
                 * debe tomar solo desde la fecha de ingreso del funcionario
                 */
                if ($date2 > $date1) {
                    $fecha_ini_causa_vac = $fecha_ini_ka = $fecha_ingreso;
                    $dias = CN_TABLE::diasEntreFechas($fecha_ingreso, $fecha_termina, false);
                } else {
                    $fecha_ini_causa_vac = $fecha_ini_ka = $fecha_ini;
                    $dias = CN_TABLE::diasEntreFechas($fecha_ini, $fecha_termina, false);
                }
            } else {
                $dias = 0;
            }


            //Se toman dias de la tabla de nombramientos que posee hasta el dia que trabaja en fecha_termina
            $dias = $dias;
        }


        $fecha_ini = $fecha_ingreso;
        $fecha_fin = $fecha_termina;

        /**
         * 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 y dias desde fecha_ingreso: " . $dias_otra_entidad);


        /*
         * Claculo de dias de novedad de kardex que afectan antiguedad
         */
        /*
         * Se cambio a fechas contando dias habiles - 20130527
         * 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
         * $fecha_ini_ka = $fecha_ini_causa_vac, para que tome como fecha inicial la de la novedad de vac o bonif, la ultima - 20150218
         */
        $fecha_ini_ka = $fecha_ini_causa_vac;
        //Sql
        $sql = <<<EOD
select nvl(sum(dias),0) as dias from(
  select 
  dias_habiles_cant( to_date(novka.fecha_ini,'yyyy-mm-dd'), to_date(novka.fecha_fin,'yyyy-mm-dd') ) as dias_hab,
  (to_date(novka.fecha_fin,'yyyy-mm-dd') - to_date(novka.fecha_ini,'yyyy-mm-dd')) + 1  as dias_cal,  
    
   FECHA_RANGO_SIN_TREINTAYUNO(
        case when NOVKA.FECHA_INI  < TO_DATE('$fecha_ini_ka','yyyy-mm-dd') 
    then TO_DATE('$fecha_ini_ka','yyyy-mm-dd') else NOVKA.FECHA_INI end
    ,
    case when NOVKA.FECHA_FIN  > TO_DATE('$fecha_fin_ka','yyyy-mm-dd') 
    then TO_DATE('$fecha_fin_ka','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_ka','yyyy-mm-dd') and to_date('$fecha_fin_ka','yyyy-mm-dd')
        or novka.fecha_fin between to_date('$fecha_ini_ka','yyyy-mm-dd') and to_date('$fecha_fin_ka','yyyy-mm-dd')
                
        or
        
        TO_DATE('$fecha_ini_ka','yyyy-mm-dd') between novka.fecha_ini and NOVKA.FECHA_FIN
        or 
        TO_DATE('$fecha_ini_ka','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
        $recordsKa = CN_TABLE::executeSQL($sql);

        $dias_kardex = $recordsKa[0]['dias'];
        $this->logMessage("[Liquidación Definitiva] Dias Kardex: " . $dias_kardex);

        //Restar dias
        //no restar dias de kardex si es concepto 1011, ya que al registrar la novedad kardex este corre los dias de bonificacion - 20140903
        //no restar dias de kardex si es concepto 1008,1009,1010, ya que al registrar la novedad kardex este corre los dias de vacaciones - 20141121
        //se habilita la resta,  esto se controla por medio de solo restar nov de kardex del ultimo periodo de causa de vac y bonif servc - 20150218
        if ($id_concep_nomina != 11 && $id_concep_nomina != 8 && $id_concep_nomina != 9 && $id_concep_nomina != 10) {
            $dias_liq = $dias - $dias_kardex;
        } else {
            $dias_liq = $dias - $dias_kardex;
        }

        $this->logMessage("[Liquidación Definitiva] Dias_liq: " . $dias_liq . " Dias_kardex: " . $dias_kardex);

        /*
         * Calcula de concepto 1008
         */
        if ($id_concep_nomina == 8) {

            $num_dias_vac = 15;
            if ($entidadCliente == 9) {
                $num_dias_vac = 25; //dias cev publica - 20191126
            }

            $dias_liq = ($dias_liq * $num_dias_vac) / 360; //Dias completos
            $dias_liq_mod = fmod($dias_liq, 1); //Se agrego los dias (decimales) para calculo completo de los dias de vacaciones - 20140424
            //$dias_base = round($dias_liq);
            $dias_base = $dias_liq - $dias_liq_mod; //Se quita redondeo de los dias para tomar dias completos - 20140521

            $this->logMessage("[Liquidación Definitiva] Concepto 1008 - Dias liquidacion: " . $dias_liq . " - Dias Base: " . $dias_base . " - Dias Mod: " . $dias_liq_mod);


            /**
             * Para personas con Comisión de Servicio Otra Entidad toma desde el dia de inicio de la comision - 20171023
              to_char(nov.fecha_inicial,'yyyy-mm-dd') as fecha_termina, se cambia para tomar el dia fecha_terminacion de la novedad de otra comision, caso: SGC 43080155 - LUZ ELENA SANCLEMENTE QUIROZ - 20191217
             */
            //Sql
            $sql = <<<EOD
select 
to_char(nov.fecha_terminacion,'yyyy-mm-dd') as fecha_termina,
nov.* 
from no_novedad_personal nov

where
to_date('$fecha_termina','yyyy-mm-dd') between nov.fecha_inicial and nov.fecha_terminacion
and nov.num_doc = '$num_doc'
and nov.id_tipo_doc = $id_tipo_doc
and nov.id_novedad = 8
and nov.estado = 1

order by
nov.fecha_inicial desc 
EOD;
            //Ejecutar SQL
            $records_termina = CN_TABLE::executeSQL($sql);
            if (count($records_termina) > 0) {
                $fecha_termina = $records_termina[0]['fecha_termina'];
            }

            //Dias con festivos
            //Empieza a contar desde el siguiente dia habil
            //Sql
            $sql = <<<EOD
select 
DIAS_HABILES(TO_DATE('$fecha_termina','yyyy-mm-dd'), 1),
DIAS_HABILES( DIAS_HABILES(TO_DATE('$fecha_termina','yyyy-mm-dd'), 1) , $dias_base - 1),
DIAS_HABILES( DIAS_HABILES(TO_DATE('$fecha_termina','yyyy-mm-dd'), 1) , $dias_base - 1) - DIAS_HABILES(TO_DATE('$fecha_termina','yyyy-mm-dd'), 1) + 1 as dias from DUAL
EOD;
            //Ejecutar SQL
            $records = CN_TABLE::executeSQL($sql);


            /*
             * Validar dias base mayor a 0 - 20141023
             */
            if ($dias_base <= 0) {
                $records[0]['dias'] = 0;
                $dias_base = 0;
            }

            /*
             * Para el CEV privada toma dias completos no los pone en el calendario concepto 1008 - 20191015
             * CEV PUB - 20191126
             */
            if ($entidadCliente == 8 || $entidadCliente == 9) {
                $dias_liq = $dias_base + round($dias_liq_mod, 2);
            } else {
                $dias_liq = $records[0]['dias'] + round($dias_liq_mod, 2); //redondeo a dos decimales - 20140728 
            }
        }


        /**
         * Calculo de dias
         */
        $this->logMessage("[Liquidación Definitiva] Dias liquidacion: " . $dias_liq . " - Dias Base: " . $dias_base . " - Dias Kardex: " . $dias_kardex);
        $dias_array = array(
            'num_dias' => $dias_liq,
            'dias_otra_entidad' => $dias_otra_entidad - $dias_otra_entidad_liq,
            'dias_otra_entidad_liq' => $dias_otra_entidad_liq,
            'num_dias_base' => $dias_base
        );
        return $dias_array;
    }

    /**
     * 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("[Liquidación Definitiva] Liquidar: periodo " . $id_periodo .
                " - funcionario " . $num_doc . " - concepto nomina " . $id_concep_nomina);

        $id_concep_nomina_inicial = $id_concep_nomina;

        /*
         * (SGC-1, ANM-2, SGR-3, CYC-4, COL-5, INCI-6, LOCAL-7, CEV-8, CEV_PUB-9)
         */
        $array = sfYaml::load(dirname(__FILE__) . '/../../../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++;
        }

        /**
         * 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' 

order by
tab0.id_novedad_proced_rete desc  
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;
            $record_liq['porcentaje'] = 1; // Porcentaje para pasar la formula - 20190827
        }

        /*
         * 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();
        $valor_liquidado = 0;
        $fecha_desde = $record_liq['fecha_ingreso'];
        $fecha_hasta = $record_liq['fecha_termina'];
        $fecha_retiro = $record_liq['fecha_retiro'];
        $num_dias = $record_liq['num_dias'];
        $num_dias_base = $record_liq['num_dias_base'];

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

        /*
         *  Cargar fórmulas por concepto
         */
        /*
         * Cargar fórmulas por concepto
         * Se modifico formula Para aporte en salud, pensión y FSP  existe un tope máximo de aporte de 25 SMLV
         * se toma del id_concep_nomina asociado al descuento - 20130814
         */
        //Sql
        $sql = <<<EOD
select distinct * from no_formula 
   WHERE id_concep_nomina =   (    
   
  select distinct 
  nvl( id_concep_nomina_ss, ID_CONCEP_NOMINA) as ID_CONCEP_NOMINA 
  from
  (
  
      select 
      formula.ID_FORMULA,
      formula.ID_CONCEP_NOMINA,
      formula.FORMULA,
      formula.NOMBRE,
      formula.COD_TIPO,
      foncon.id_descuento_ss,
      des.id_concep_nomina as id_concep_nomina_ss
      from no_formula formula
      left join no_fondo_concepto foncon
      on formula.id_concep_nomina = foncon.id_concep_nomina
      left join no_descuento_ss des
      on foncon.id_descuento_ss = des.id_descuento_ss
      where formula.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 Definitiva] Entro a calcular Formula.");

            foreach ($records as $value) {

                $formula = $value['formula'];
                $this->logMessage("[Liquidación Definitiva] 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 Definitiva] 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 Definitiva] 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("[Liquidación Definitiva] Agrupacion: " . $agrup);

                        $formula = str_replace('{' . $var . '}', $agrup, $formula);
                    }
                }
                $this->logMessage("[Liquidación Definitiva] 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);


                /*
                 * Reemplazo de parametros(variables) a la formula
                 * Ejemplo: $arrayParametros = array(
                 * 'C1' => '1100',
                 * 'C2' => '55'
                 * );
                 */
                $formula = $this->reemplazoParametros($formula, $arrayParametros);
                $this->logMessage("[Liquidación Definitiva] 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 Definitiva] 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) && $record_liq['porcentaje'] != 0) {
                    /*
                     * Tipo de formula
                     * V - Valor base 
                     * R - Valor restado 
                     * F - Valor de la fórmula (Uso normal)
                     */
                    if ($value['cod_tipo'] == 'V') {
                        $this->logMessage("[Liquidación Definitiva] Formula CodTipo: " . $value['cod_tipo']);

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

            /**
             * Logica de N
             */
            if ($record_liq['caracter'] == 'N') {
                $this->logMessage("[Liquidación Definitiva] 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
                    if (($devengado_por - $valor_logica_n - $valor_sumatoria_logica_n) <= 0) {

                        $valor_liquidado = $valor_logica_n;
                        $valor_sumatoria_logica_n += $valor_liquidado;
                    } else {

                        $valor_liquidado = 0;
                    }
                } else {

                    $this->logMessage("[Liquidación Definitiva] 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 y diferente de 0
                 */
                if (($record_liq['porcentaje'] != '' || $record_liq['porcentaje'] != null) && $record_liq['porcentaje'] != 0) {
                    $this->logMessage("[Liquidación Definitiva] 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 Definitiva] 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;
            }
        }


        //Dias de proporcionalidad bonificacion por servicios - 20140224
        if ($id_concep_nomina == 11) {

            $this->logMessage("[Liquidación Definitiva] Dias de proporcionalidad bonificacion por servicios: " . $valor_liquidado);
            $this->logMessage("[Liquidación Definitiva] Dias de proporcionalidad num_dias: " . $num_dias);
            $valor_liquidado = round(($valor_liquidado * $num_dias) / 360);
        }

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

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

                    //Resta los valores de retenciono anteriores, diferentes al periodo - 20181108
                    //Sql
                    $sql = <<<EOD
select nvl(sum(liqnom.valor_liquidado),0) as valor  
from no_liquida_nomina liqnom   

join no_periodo per on per.id_periodo = liqnom.id_periodo 
where    
1 = 1 
and per.id_meses = ( select id_meses from no_periodo where id_periodo = $id_periodo)  
and per.id_anhos = ( select id_anhos from no_periodo where id_periodo = $id_periodo)   
and liqnom.num_doc = '$num_doc'  and liqnom.id_tipo_doc = $id_tipo_doc  
    and liqnom.id_concep_nomina = $id_concep_nomina_inicial  
and per.id_periodo != $id_periodo                        
EOD;
                    //Ejecutar SQL
                    $record_rete_t = CN_TABLE::executeSQL($sql);
                    //Resta retencion de otros periodos proc1 - 20180705
                    if (count($record_rete_t) > 0) {
                        //Solo para entidad_cliente que lo permitan, por ahora para ninguna aplica - 20190516
                        //Se activa para CEV y CEV PUB, que reste en la liq def - 20190827
                        if ($entidadCliente == 8 || $entidadCliente == 9) {
                            $valor_liquidado = $valor_liquidado - $record_rete_t[0]['valor'];
                        }
                    }
                }
            }
        }

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

            $this->logMessage("[Liquidación Definitiva] 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);
            }


            /*
             * 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, valor_base, porcentaje) 
            //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
            $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, num_dias_base ) 
        values ( $id_tipo_doc, '$num_doc', $id_concep_nomina, $id_periodo, round($valor_liquidado), 
        to_date('$fecha_desde','YYYY-MM-DD'), to_date('$fecha_retiro','YYYY-MM-DD'), $num_dias,
            round($valor_base), $porcentaje, $num_dias_base ) 
EOD;
            //Ejecutar SQL
            CN_TABLE::executeSQL($sql);
        }
        /*
         * Valida si es prima_navidad y el valor es negativo - 20131217
         */ elseif ($valor_liquidado < 0) {
            $this->logMessage("[Liquidación] El valor_liquidado es menor a cero.");

            //Se activa para CEV y CEV PUB, devolucion de retefuente - 20190828
            $tag_devol = false;
            if ($entidadCliente == 8 || $entidadCliente == 9) {
                if ($id_concep_nomina == $id_concep_rete) {
                    $tag_devol = true;
                }
            }

            //Valida si es prima_navidad
            if ($id_concep_nomina == 17 || $tag_devol) {

                $this->logMessage("[Liquidación] Valida si es retefuente y el valor es negativo.");

                /*
                 * Crear nueva liquidación
                 * 
                 * Asignar valores encontrados en persona
                 */
                $valor_liquidado = $valor_liquidado * (-1);

                //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, valor_base, porcentaje ) 
        values ( $id_tipo_doc, '$num_doc', 
                    (select case when tab0.id_concep_rein is null then tab0.id_concep_nomina 
    else tab0.id_concep_rein end as id_concep_nomina
from no_concep_nomina tab0    
where tab0.id_concep_nomina = $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, 0), $porcentaje ) 
EOD;
                //Ejecutar SQL
                CN_TABLE::executeSQL($sql);
            } else {
                $this->logMessage("[Liquidación] No es retefuente. Valores - " . $id_concep_nomina);
            }
        } else {

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

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

        /*
         * Tag definitiva cambia caracter por M - 20141014
         */
        $tag_def = $record_liq['tag_def'];

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

            //Valida Tag definitiva
            //Se oimite concepto 442,de aportes salud año anterior  CYC - 20190626
            if ($tag_def == 1 && $id_concep_nomina != 442) {
                $caracter = "M";
            }


            $this->logMessage("[Liquidación Definitiva] 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;
        }

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

    /**
     * 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
        //Si en el mes que verifica esta retirado, no lo toma encuenta para descontar, ya que no se suma en los meses - 20181130
        $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 
                
  left join no_nombramiento_v nom
  on nom.id_tipo_doc = novka.id_tipo_doc
  and nom.num_doc = novka.num_doc
                
  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 (   
            nom.fecha_termina is null 
            or nom.fecha_termina not 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 FSP aporte funcionario
     * 
     * $valor_base_fsp Valor base de todo el mes para el tope deFSP, el calculo si es la base de la formula - 20190506
     * 
     * @param type $valor_base
     * @param type $salario_minimo
     * @param type $valor_base_vac
     * @param int $wdiasv
     * @param type $dias_liq
     * @param type $num_doc
     * @param type $id_periodo
     * @param type $wvalor_base_extra
     * @param type $valor_base_fsp
     * @return int
     */
    private function valor_base_fsp($valor_base, $salario_minimo, $valor_base_vac = 0, $wdiasv = 0, $dias_liq, $num_doc, $id_periodo, $wvalor_base_extra = 0, $valor_base_fsp = 0) {

        $this->logMessage("[Liquidación] valor_base_fsp:: valor_base: " . $valor_base . " - valor_base_vac: " . $valor_base_vac);
        $this->logMessage("[Liquidación] valor_base_fsp:: wdiasv: " . $wdiasv . " - dias_liq: " . $dias_liq);
        $this->logMessage("[Liquidación] valor_base_fsp:: wvalor_base_extra: " . $wvalor_base_extra . " - valor_base_fsp: " . $valor_base_fsp);


        /*
         * WBASE=   BASE TOTAL que ya estamos hayando
         * WVRBASE=(WBASE/(WDIAST+WDIASV))*30
         * Sobre WVRBASE  verifica si debe calcular FSP y sobre ella misma ubicar el porcentaje 
         * Si aplica y tiene el porcentaje,  aplica el porcentaje sobre WBASE
         * 20131216
         */
        $valor = 0;
        $valorfps1 = 0;
        $valorfps2 = 0;
        $porcentaje = 0;
        $valor_bonif = 0;
        $valor_bonifs = 0;


        /**
         * Para las personas que tienen bonificacion por servicios se toma este valor proporcional a los dias laborados - 20140605
         */
        //Sql
        $sql = <<<EOD
select nvl(sum(valor_liquidado),0) as valor from no_liquida_nomina 
where num_doc = $num_doc and id_tipo_doc = 1 
and id_concep_nomina = (select no_param_concep.id_concep_bonif from no_param_concep where no_param_concep.id_param_concep = 1) 
and id_periodo = $id_periodo            
EOD;
        //Ejecutar SQL
        $records = CN_TABLE::executeSQL($sql);

        /*
         * Valida si posee formula el concepto
         */
        if (count($records) > 0 && $dias_liq > 0) {
            $valor_bonifs = $records[0]['valor']; //bonificacion completa
            $valor_bonif = (($valor_bonifs * $dias_liq) / 30); //bonificacion por dias laborales
        }
        $this->logMessage("[Liquidación] Valida si la persona - valor_bonif :: " . $valor_bonif);



        /*
         * Operaciones
         * Se separa el valor bonif del redondeo a 30 dias laborales, ya que en el proceso anterior ya se realiza su calculo para los 30 dias - 20150218
         */
        if (($dias_liq + $wdiasv) <= 0) {
            $wdiasv = 1;
        }
        //$wvalor_base = (($valor_base - $valor_bonifs + $valor_bonif) / ($dias_liq + $wdiasv)) * 30;
        $wvalor_base = (($valor_base - $valor_bonifs) / ($dias_liq + $wdiasv) * 30 ) + ($valor_bonif);


        /**
         * Valida si la persona ingreso en el mes o se retira para tomar los dias en cuenta - 20140307
         */
        $this->logMessage("[Liquidación] Valida si la persona - wvalor_base :: " . $wvalor_base . " - Salario Minimo :: " . $salario_minimo);
        //Sql
        $sql = <<<EOD
select 
nom.* 
from no_nombramiento_v nom
where 
nom.id_tipo_doc = 1
and nom.num_doc = $num_doc
and (
nom.fecha_ingreso between (select per.fecha_ini from no_periodo per where per.id_periodo = $id_periodo) and (select per.fecha_fin from no_periodo per where per.id_periodo = $id_periodo)
or 
nom.fecha_termina between (select per.fecha_ini from no_periodo per where per.id_periodo = $id_periodo) and (select per.fecha_fin from no_periodo per where per.id_periodo = $id_periodo)
)                 
EOD;
        //Ejecutar SQL
        $records = CN_TABLE::executeSQL($sql);


        /*
         * Valida si ingreso en el mes de retiro - 20150320 
         */
        if (count($records) > 0) {
            //Incidente #6860, se quita $valor_bonif, ya que no debe ser asi segun proceso mesa de ayuda - 20170803
            //Se quita el valor bonif ya que esta en $valor_base_fsp - 20150218
            //$wvalor_base = $valor_base + $valor_base_vac + $valor_bonif;
            //$wvalor_base = $valor_base + $valor_base_vac + $valor_base_fsp;
            $wvalor_base = ($valor_base - $valor_bonifs) + $valor_base_vac + $valor_base_fsp;
            $this->logMessage("[Liquidación] Valida si posee formula el concepto - wvalor_base :: " . $wvalor_base);
        } else {

            //salario completo
            $wvalor_base = $wvalor_base_extra + $valor_base_fsp;
            $this->logMessage("[Liquidación] wvalor_base_extra :: " . $wvalor_base);
        }
        //Cambio de verificacion del valor base - 20131216
        if (($wvalor_base) > ($salario_minimo * 4) && ($wvalor_base) <= ($salario_minimo * 16)) {
            $porcentaje = 1;
        } elseif (($wvalor_base) > ($salario_minimo * 16) && ($wvalor_base) <= ($salario_minimo * 17)) {
            $porcentaje = 1.2;
        } elseif (($wvalor_base) > ($salario_minimo * 17) && ($wvalor_base) <= ($salario_minimo * 18)) {
            $porcentaje = 1.4;
        } elseif (($wvalor_base) > ($salario_minimo * 18) && ($wvalor_base) <= ($salario_minimo * 19)) {
            $porcentaje = 1.6;
        } elseif (($wvalor_base) > ($salario_minimo * 19) && ($wvalor_base) <= ($salario_minimo * 20)) {
            $porcentaje = 1.8;
        } elseif (($wvalor_base) > ($salario_minimo * 20)) {
            $porcentaje = 2;
        }

        /* INCI - 20140122
         * Patricia Montoya Falla, C.C. 35.462.698,
          Esperanza Verdugo, C.C.  46.662.659
          Yanerys Irina de la Hoz, C.C.  57.290.110
          Vladimir Yanken Cifuentes, C.C. 79.526.123
          Gustavo Pulido Casas, C.C. 93.288.443
         * 39773464
         */
        /* if ($num_doc == '35462698' || $num_doc == '46662659' || $num_doc == '57290110' || $num_doc == '79526123' || $num_doc == '93288443' || $num_doc == '51788859') {
          if (($valor_base + $valor_base_vac) > ($salario_minimo * 4) && ($valor_base + $valor_base_vac) <= ($salario_minimo * 16)) {
          $porcentaje = 1;
          } elseif (($valor_base + $valor_base_vac) > ($salario_minimo * 16) && ($valor_base + $valor_base_vac) <= ($salario_minimo * 17)) {
          $porcentaje = 1.2;
          } elseif (($valor_base + $valor_base_vac) > ($salario_minimo * 17) && ($valor_base + $valor_base_vac) <= ($salario_minimo * 18)) {
          $porcentaje = 1.4;
          } elseif (($valor_base + $valor_base_vac) > ($salario_minimo * 18) && ($valor_base + $valor_base_vac) <= ($salario_minimo * 19)) {
          $porcentaje = 1.6;
          } elseif (($valor_base + $valor_base_vac) > ($salario_minimo * 19) && ($valor_base + $valor_base_vac) <= ($salario_minimo * 20)) {
          $porcentaje = 1.8;
          } elseif (($valor_base + $valor_base_vac) > ($salario_minimo * 20)) {
          $porcentaje = 2;
          }
          }
          //num_doc in (13507148, 51653492 ,79250331 ,52779827 ,20404209)
          if ($num_doc == '51653492' || $num_doc == '79250331') {
          $porcentaje = 0;
          }
         */
        /**
         * Se redondea valor al sumar al final y no $valorfps1 / $valorfps2, por separado  - 20140616
         */
        $this->logMessage("[Liquidación] valor_base_fsp:: valor_base: " . $valor_base);
//        $valorfps1 = round($valor_base * 0.5 / 100, -2);
//        $valorfps2 = round($valor_base * ($porcentaje - 0.5) / 100, -2);
        $valorfps1 = $valor_base * 0.5 / 100;
        $valorfps2 = $valor_base * ($porcentaje - 0.5) / 100;
        $this->logMessage("[Liquidación] valor_base_fsp:: valorfps1: " . $valorfps1 . " - valorfps2: " . $valorfps2);

        //se cambia el redondeo al sumar valores como esta en autoliquidacion
        //$valor = round(($valorfps1 + $valorfps2) - 1, -2);
        //$valor = CN_TABLE::redondeoValor($valorfps1, -2) + CN_TABLE::redondeoValor($valorfps2, -2);
        $valor = CN_TABLE::ceiling($valorfps1, 100) + CN_TABLE::ceiling($valorfps2, 100);

        //Valida que si porcentaje 0, el valor de aporte es 0 - 20170307
        if ($porcentaje == 0) {
            $valor = 0;
        }

        $array_fsp = array(
            'valor_fsp' => $valor,
            'porcentaje_fsp' => $porcentaje
        );

        $this->logMessage("[Liquidación] valor_base_fsp:: valor_fsp: " . $valor . " - porcentaje_fsp: " . $porcentaje);

        return $array_fsp;
    }

}
