<?php

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

    /**
     * Liquidacion de proyecciones
     *
     * @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");

        $records = array();
        $arrayConstantes = array();
        /*
         * Variable para optimizar consultas de formulas en las liquidaciones - 20140117
         */
        $vals_calc = array();


        /*
         * Abrir conexion transaccion
         */
        $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);

        /*
         * Manejar Errores
         */
        try {


            /*
             * (SGC-1, ANM-2, SGR-3, CYC-4, COL-5, INCI-6, LOCAL-7)
             */
            $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 filtro
             */
            //Periodo
            $id_periodo_ant = $id_periodo = $request['id_periodo'];
            $progress_key = $request['progress_key'] . $request['username'];

            $id_anhos = $request['id_anhos'];
            $id_meses = $request['id_meses'];

            //id_agrup_concepto calculo total
            //Se cambia por una nueva 133 antes 107 - 20210812::LAVILA
            $id_agrup_concepto = 133;

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

            //1. TRAIGO EL ID DEL TIPO DE PERIODO QUE SEA PERIODICA = 1

            $id_tipo_periodo = $records[0]['id_tipo_periodo'];

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

            /**
             * Consultar salario minimo
             * 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 = $id_anhos )  
EOD;
            //Ejecutar SQL
            $record_smlv = CN_TABLE::executeSQL($sql);

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

            /*
             * Obtener consultas glodal
             */
            //Sql
            $sql = <<<EOD
select 
ID_CONSULTA,
NOMBRE,
REPLACE( REPLACE(                    
REPLACE( REPLACE( 
    REPLACE( REPLACE( REPLACE(CONSULTA,'no_concepto_periodo','no_concepto_periodo_proy') ,'no_liquida_nomina','no_liquida_nomina_proy'),'no_periodo','no_periodo_proy')
    ,'id_concepto_periodo','id_concepto_periodo_proy') ,'id_liquida_nomina','id_liquida_nomina_proy') 
    ,'no_estado_func','no_estado_func_proy') ,'id_estado_func','id_estado_func_proy')               
    as CONSULTA,
CARACTER
from NO_CONSULTA 
EOD;
            //Ejecutar SQL
            $record_consul = CN_TABLE::executeSQL($sql);
            $record_consulta = array();

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

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


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

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

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

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

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

            /*
             * Iniciar en 0 dias de liquidacion y totales de vacaciones - 20131216
             */
            $dias_liq = 0;
            $wdiasv_tot = 0;


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

            /*
             * Obtener el mes minimo de proyeccion
             */
            //Sql
            $sql = <<<EOD
select 

nvl(min(id_meses),13) as id_meses_min

from(

    SELECT
    tab0.id_anhos,
    mes.id_meses,
    mes.descripcion as mes,
    0 as estado,
    0 as activo
    
    FROM anhos tab0
    
    left join meses mes
    on mes.id_meses != 0
    
    where
    tab0.id_anhos = $id_anhos
    and (tab0.id_anhos,mes.id_meses) not in (
    
        SELECT DISTINCT
        per.id_anhos,
        per.id_meses
        
        FROM no_concepto_periodo tab0
        
        join no_periodo_v per
        on per.id_periodo = tab0.periodo
        
        where
        per.id_anhos = $id_anhos
    
    )

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

            $id_meses_min = 13;
            if (count($record_min) > 0) {
                $id_meses_min = $record_min[0]['id_meses_min'];
            }

            //Sql
            $sql = <<<EOD
SELECT
    *
FROM no_periodo
where
id_tipo_periodo = 1
and id_periodo = $id_periodo
EOD;
            //Ejecutar SQL
            $record_min = CN_TABLE::executeSQL($sql);

            $id_meses_actual = 13;
            if (count($record_min) > 0) {
                $id_meses_actual = $record_min[0]['id_meses'];
            }

            /*
             *  Borrar datos anteriores no_estado_func_proy
             */
            $this->logMessage("[Liquidación proyecciones] Borrar datos posteriores no_estado_func_proy");
            //Sql
            $sql = <<<EOD
delete
FROM no_estado_func_proy tab0

where
tab0.id_anhos = $id_anhos
and tab0.id_meses >= $id_meses
$whereFuncionarioNumDoc $whereFuncionarioTipoDoc 
EOD;
            //Ejecutar SQL
            CN_TABLE::executeSQL($sql);

            /*
             *  Borrar datos anteriores no_concepto_periodo_proy
             */
            $this->logMessage("[Liquidación proyecciones] Borrar datos posteriores no_concepto_periodo_proy");
            //Sql
            $sql = <<<EOD
delete
FROM no_concepto_periodo_proy tab0

where
tab0.id_anhos = $id_anhos
and tab0.id_meses >= $id_meses
$whereFuncionarioNumDoc $whereFuncionarioTipoDoc 
EOD;
            //Ejecutar SQL
            CN_TABLE::executeSQL($sql);


            /*
             *  Borrar datos anteriores no_liquida_nomina_proy
             */
            $this->logMessage("[Liquidación proyecciones] Borrar datos posteriores no_liquida_nomina_proy");
            //Sql
            $sql = <<<EOD
delete
FROM no_liquida_nomina_proy tab0

where
tab0.id_anhos = $id_anhos
and tab0.id_meses >= $id_meses
$whereFuncionarioNumDoc $whereFuncionarioTipoDoc 
EOD;
            //Ejecutar SQL
            CN_TABLE::executeSQL($sql);

            /*
             *  Borrar datos anteriores Periodo-Funcionario Conceptos de la grupacion 133 - 20210610
             */
            //Sql
            $sql = <<<EOD
DELETE FROM no_liquida_nomina_proy tab0 

WHERE
tab0.id_anhos = $id_anhos
and tab0.id_meses <= $id_meses
and tab0.id_concep_nomina in ( SELECT id_concep_nomina FROM no_agrup_deta where no_agrup_deta.id_agrup_concepto = $id_agrup_concepto )
$whereFuncionarioNumDoc $whereFuncionarioTipoDoc 
EOD;
            //Ejecutar SQL
            CN_TABLE::executeSQL($sql);

            /*
             * Proyectar periodos NO_PERIODO_PROY
             */
            if ($id_meses_min == $id_meses) {
                //Borro meses anteriores y copio de periodo general
                //Sql
                $sql = <<<EOD
delete
FROM no_periodo_proy
where
id_anhos = $id_anhos
and id_meses < $id_meses 
EOD;
                //Ejecutar SQL
                //CN_TABLE::executeSQL($sql);//Se omite ya que no se toma lo liquidado original, solo lo proyectado - 20210512::LAVILA
                //Sql
                $sql = <<<EOD
insert into no_periodo_proy

SELECT DISTINCT
tab0.ID_PERIODO,
tab0.ID_ANHOS,
tab0.ID_MESES,
tab0.FECHA_INI,
tab0.FECHA_FIN,
tab0.ID_TIPO_PERIODO,
tab0.ESTADO,
tab0.FECHA_CIERRE,
tab0.FECHA_CIERRE_NOV,
tab0.ACTIVO,
tab0.MAX_DED_NOLEY,
tab0.FECHA_PAGO,
tab0.NUM_DOC_PAGO,
tab0.NOM_ADICIONAL,
tab0.DEFINITIVO,
tab0.FECHA_DEFINITIVO,
tab0.ID_MAE_TER_DEFINITIVO,
tab0.FECHA_TESORERIA,
tab0.OBSERV_TESORERIA

FROM no_periodo tab0

where
tab0.id_anhos = $id_anhos
and tab0.id_meses < $id_meses 
EOD;
                //Ejecutar SQL
                //CN_TABLE::executeSQL($sql);//Se omite ya que no se toma lo liquidado original, solo lo proyectado - 20210512::LAVILA
            }


            if ($id_meses_actual == $id_meses) {

                /*
                 * Borrar datos anteriores no_estado_func_proy - 20211019
                 * Cuando se ejecuta la proyección, y se seleccione para liquidación el primer mes osea el mes de proceso: 
                 * Debe eliminar todas las proyecciones que estén para esta vigencia.
                 */
                $this->logMessage("[Liquidación proyecciones] Borrar datos anteriores no_estado_func_proy; del primer mes por año.");
                //Sql
                $sql = <<<EOD
delete
FROM no_estado_func_proy tab0

where
tab0.id_anhos = $id_anhos
and tab0.id_meses < $id_meses
$whereFuncionarioNumDoc $whereFuncionarioTipoDoc 
EOD;
                //Ejecutar SQL
                CN_TABLE::executeSQL($sql);

                /*
                 *  Borrar datos anteriores no_concepto_periodo_proy
                 */
                $this->logMessage("[Liquidación proyecciones] Borrar datos anteriores no_concepto_periodo_proy");
                //Sql
                $sql = <<<EOD
delete
FROM no_concepto_periodo_proy tab0

where
tab0.id_anhos = $id_anhos
and tab0.id_meses < $id_meses
$whereFuncionarioNumDoc $whereFuncionarioTipoDoc 
EOD;
                //Ejecutar SQL
                CN_TABLE::executeSQL($sql);


                /*
                 *  Borrar datos anteriores no_liquida_nomina_proy
                 */
                $this->logMessage("[Liquidación proyecciones] Borrar datos anteriores no_liquida_nomina_proy");
                //Sql
                $sql = <<<EOD
delete
FROM no_liquida_nomina_proy tab0

where
tab0.id_anhos = $id_anhos
and tab0.id_meses < $id_meses
$whereFuncionarioNumDoc $whereFuncionarioTipoDoc 
EOD;
                //Ejecutar SQL
                CN_TABLE::executeSQL($sql);


                /*
                 *  Borrar datos anteriores no_liquida_aporte_proy
                 */
                $this->logMessage("[Liquidación proyecciones] Borrar datos anteriores no_liquida_aporte_proy");
                //Sql
                $sql = <<<EOD
delete
FROM no_liquida_aporte_proy tab0

where
tab0.id_anhos = $id_anhos
and tab0.id_meses < $id_meses
$whereFuncionarioNumDoc $whereFuncionarioTipoDoc 
EOD;
                //Ejecutar SQL
                CN_TABLE::executeSQL($sql);
            }

            //no tiene filtro de tercero
            if ($num_doc == null) {

                //Sql
                $sql = <<<EOD
delete
FROM no_periodo_proy
where
id_anhos = $id_anhos
and id_meses >= $id_meses 
EOD;
                //Ejecutar SQL
                CN_TABLE::executeSQL($sql);


                //Sql
                $sql = <<<EOD
SELECT
tab0.id_anhos,
mes.id_meses,
mes.descripcion as mes,
0 as estado,
0 as activo

FROM anhos tab0

left join meses mes
on mes.id_meses != 0

where
tab0.id_anhos = $id_anhos
and mes.id_meses >= $id_meses 
and (tab0.id_anhos,mes.id_meses) not in (

    SELECT DISTINCT
    per.id_anhos,
    per.id_meses

    FROM no_concepto_periodo tab0

    join no_periodo_v per
    on per.id_periodo = tab0.periodo

    where
    per.id_anhos = $id_anhos
    and per.estado = 0
                        
)
EOD;
                //Ejecutar SQL
                $record_min = CN_TABLE::executeSQL($sql);

                //creea nuevos periodo_proy
                foreach ($record_min as $value) {

                    $id_anhos_proy = $value['id_anhos'];
                    $id_meses_proy = $value['id_meses'];

                    /*
                     * Se agrega porcentaje del maximo dednoley de los parametros generales - 20140526
                     * (SELECT nvl(max(id_periodo),0)+$id_meses_proy FROM no_periodo), se cambia como toma el id_periodo, para no tomar consecutivo, sino referencia al año mes - 20210512::LAVILA
                     */
                    $sql = <<<EOD
INSERT INTO NO_PERIODO_PROY (ID_MESES,ESTADO,ID_TIPO_PERIODO,ID_ANHOS,FECHA_CIERRE_NOV,ACTIVO,FECHA_INI,FECHA_FIN, MAX_DED_NOLEY, ID_PERIODO)
    VALUES($id_meses_proy,1,1,$id_anhos_proy,last_day(to_date('$id_anhos_proy-$id_meses_proy-01','YYYY-MM-DD')),0,
        to_date('$id_anhos_proy-$id_meses_proy-01','YYYY-MM-DD'),last_day(to_date('$id_anhos_proy-$id_meses_proy-01','YYYY-MM-DD')),
            (select nvl(max_ded_noley,0) as max_ded_noley from no_param_gen where id_param_gen = 1), (SELECT $id_anhos_proy || lpad($id_meses_proy,2,0) FROM dual) )
EOD;

                    CN_TABLE::executeSQL($sql);
                }
            } else {
                //si filtro tercero
                //Obtiene datos del periodo creado
                $sql = <<<EOD
select id_periodo from NO_PERIODO_PROY periodo 
left join no_tipo_periodo tipo ON tipo.id_tipo_periodo = periodo.id_tipo_periodo
where periodo.estado = 1 and periodo.activo = 0 and tipo.periodica = 1
and id_anhos = $id_anhos
and id_meses = $id_meses                     
EOD;

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

                if (count($records_per) == 0) {
                    /*
                     * Se agrega porcentaje del maximo dednoley de los parametros generales - 20140526
                     * (SELECT nvl(max(id_periodo),0)+$id_meses_proy FROM no_periodo), se cambia como toma el id_periodo, para no tomar consecutivo, sino referencia al año mes - 20210512::LAVILA
                     */
                    $sql = <<<EOD
INSERT INTO NO_PERIODO_PROY (ID_MESES,ESTADO,ID_TIPO_PERIODO,ID_ANHOS,FECHA_CIERRE_NOV,ACTIVO,FECHA_INI,FECHA_FIN, MAX_DED_NOLEY, ID_PERIODO)
    VALUES($id_meses,1,1,$id_anhos,last_day(to_date('$id_anhos-$id_meses-01','YYYY-MM-DD')),0,
        to_date('$id_anhos-$id_meses-01','YYYY-MM-DD'),last_day(to_date('$id_anhos-$id_meses-01','YYYY-MM-DD')),
            (select nvl(max_ded_noley,0) as max_ded_noley from no_param_gen where id_param_gen = 1), (SELECT $id_anhos || lpad($id_meses,2,0) FROM dual) )
EOD;

                    CN_TABLE::executeSQL($sql);
                }
            }



            //Obtiene datos del periodo creado
            $sql = <<<EOD
select id_periodo from NO_PERIODO_PROY periodo 
left join no_tipo_periodo tipo ON tipo.id_tipo_periodo = periodo.id_tipo_periodo
where periodo.estado = 1 and periodo.activo = 0 and tipo.periodica = 1
and id_anhos = $id_anhos
and id_meses = $id_meses                     
EOD;

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

            //id del periodo nuevo
            $id_periodo = $periodo = $id_periodo_nuevo = $records[0]['id_periodo'];



            /**
             * Creo estado func del periodo nuevo - 20210513
             */
            $sql = <<<EOD
insert into no_estado_func_proy
select 
null as id_estado_func_proy,
tab0.id_tipo_doc,
tab0.num_doc,
tab0.id_dp,
(select id_anhos from no_periodo_proy where id_periodo = $id_periodo) as id_anhos,
(select id_meses from no_periodo_proy where id_periodo = $id_periodo) as id_meses,
1 as id_tipo_periodo,                    
$id_periodo as periodo,
1 as actual,
tab0.id_ea,
tab0.id_cen_op
from no_estado_func tab0
where 
tab0.periodo = $id_periodo_ant 
EOD;
            CN_TABLE::executeSQL($sql);



            /**
             * Proyectar concepto_periodo
             */
            $this->logMessage("[Liquidación proyecciones] Proyectar concepto_periodo");



            //CREO LOS REGISTRO DE DEVENGADOS Y DEDUCIDOS DE LEY EN NO_CONCEPTO_PERIODO    
            /*
             * Se valida que la fecha hasta(calculo dias) no supere al ultimo dia del periodo - 20130806
             * Se coloca estado 1 en el filtro de no_novedad_kardex, para tomar solo las activas - 20130917
             * Se coloca en el where filtrar por fecha para los concep_ab(1005,1006) qque no deben pasar al siguiente mes por la fecha hasta - 20150309
             * Ya no se toman dias de kardex, ya que mas adelante se descuentan para la AB y deducidos de ley - 20150707
             * Se coloca validacion para operador de las vacaciones, por devolucion de tiempo - 20170110
             * fecha_hasta en la fecha hasta valida igual año no solo mes - 20191122
             */
            $sql = <<<EOD
INSERT INTO NO_CONCEPTO_PERIODO_PROY (
ID_ANHOS,
ID_MESES,
ID_TIPO_PERIODO,
PERIODO,
ID_TIPO_DOC,
NUM_DOC,
ID_CONCEP_NOMINA,
VALOR,
PORCENTAJE,
FECHA_DESDE,
FECHA_HASTA,
NUM_DIAS
)

SELECT 

id_anhos,id_meses,
1 as ID_TIPO_PERIODO,    
periodo,id_tipo_doc,num_doc,
ID_CONCEP_NOMINA,VALOR,PORCENTAJE,FECHA_DESDE,

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

(case 
when fecha_hasta is not null and fecha_hasta <= last_day(to_date('01/$id_meses/$id_anhos','DD/MM/YYYY')) then (fecha_hasta-fecha_desde)
when fecha_hasta is not null and fecha_hasta > last_day(to_date('01/$id_meses/$id_anhos','DD/MM/YYYY')) then ( trunc(last_day(to_date('01/$id_meses/$id_anhos','DD/MM/YYYY'))) - fecha_desde)
else (select perv.no_dias_mes from no_periodo_proy_v perv where perv.id_periodo = $id_periodo_nuevo)
end) - 
(case 
  when dias > 30 and aplica_vacac = 1 then 30 else case when dias > 0 and aplica_vacac = 1 then dias else 0 end 
end) 
as NUM_DIAS 

FROM(

    select  
    (select id_anhos from no_periodo_proy where id_periodo = $id_periodo_nuevo) as id_anhos,
    (select id_meses from no_periodo_proy where id_periodo = $id_periodo_nuevo) as id_meses,
    $id_periodo_nuevo as periodo, tab0.id_tipo_doc, tab0.num_doc, 
    tab0.id_concep_nomina, tab0.valor, tab0.porcentaje, tab1.aplica_vacac,
    
    to_date('01/$id_meses/$id_anhos','DD/MM/YYYY') AS FECHA_DESDE,
    
    
    /*
    case when tab0.fecha_hasta IS NULL then last_day(to_date('01/$id_meses/$id_anhos','DD/MM/YYYY'))
    when extract(month from tab0.fecha_hasta) = $id_meses then tab0.fecha_hasta
    
    else last_day(to_date('01/$id_meses/$id_anhos','DD/MM/YYYY'))
    
    end AS FECHA_HASTA
    */
    case when extract(month from tab0.fecha_hasta) = $id_meses and extract(year from tab0.fecha_hasta) = $id_anhos then tab0.fecha_hasta
    else null
    end as fecha_hasta,   
    
    (    
      select nvl(sum(dias),0) AS DIAS      
      from
      (
        /*select 
        num_doc,
        nvl(sum(dias_rango_mes_sin_treintayuno(novkar.fecha_ini,novkar.fecha_fin,(select id_meses from no_periodo_proy where id_periodo =  $id_periodo_nuevo ))),0) as dias 
        from no_novedad_kardex novkar
        left join no_tip_nov_ka tipnov
        on tipnov.id_tip_nov_ka = novkar.id_tip_nov_ka
        where tipnov.afecta_antigu = 1
        and novkar.estado = 1
        
        and (
          novkar.fecha_ini between to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo_nuevo) ,'dd/mm/yyyy')
          and trunc(last_day( to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo_nuevo) ,'dd/mm/yyyy') )) 
          or
          novkar.fecha_fin between to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo_nuevo) ,'dd/mm/yyyy')
          and TRUNC(LAST_DAY( TO_DATE('01/'|| (select LPAD(ID_MESES,2,'0') ||'/'||ID_ANHOS from NO_PERIODO_proy where ID_PERIODO = $id_periodo_nuevo) ,'dd/mm/yyyy') )) 
          
          or        
          
          to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo_nuevo) ,'dd/mm/yyyy') between novkar.fecha_ini and novkar.fecha_fin
          or
          trunc(last_day( to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo_nuevo) ,'dd/mm/yyyy') )) between novkar.fecha_ini and novkar.fecha_fin
        )
      
        group by num_doc 
        
        union */
        
        select 
        num_doc,
        case when tipnov.operador = 1
        then nvl(sum(DIAS_RANGO_MES_SIN_TREINTAYUNO(novvac.fecha_ini,novvac.fecha_fin,(select id_meses from no_periodo where id_periodo =  $id_periodo_nuevo))),0)
        else nvl(sum(DIAS_RANGO_MES_SIN_TREINTAYUNO(novvac.fecha_ini,novvac.fecha_fin,(select id_meses from no_periodo where id_periodo =  $id_periodo_nuevo))),0) * (-1) end as dias,
        nvl(sum(DIAS_RANGO_MES_SIN_TREINTAYUNO(novvac.fecha_ini,novvac.fecha_fin,(select id_meses from no_periodo where id_periodo =  $id_periodo_nuevo))),0) as dias1        
        from no_novedad_vac novvac
        left join no_tipo_nov_vac tipnov on tipnov.id_tipo_nov_vac = novvac.id_tipo_nov_vac
        where tipnov.tiempo_liqui = 1
        
        and (
          novvac.fecha_ini between to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo_nuevo) ,'dd/mm/yyyy')
          and trunc(last_day( to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo_nuevo) ,'dd/mm/yyyy') )) 
          or
          novvac.fecha_fin between to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo_nuevo) ,'dd/mm/yyyy')
          and TRUNC(LAST_DAY( TO_DATE('01/'|| (select LPAD(ID_MESES,2,'0') ||'/'||ID_ANHOS from NO_PERIODO_proy where ID_PERIODO = $id_periodo_nuevo) ,'dd/mm/yyyy') )) 
          
          or        
          
          to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo_nuevo) ,'dd/mm/yyyy') between novvac.fecha_ini and novvac.fecha_fin
          or
          trunc(last_day( to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo_nuevo) ,'dd/mm/yyyy') )) between novvac.fecha_ini and novvac.fecha_fin
        )
        
        group by num_doc, operador   
      )tab3 where tab0.num_doc = tab3.num_doc
    ) as dias
                    
    from no_concepto_func tab0
    LEFT JOIN no_concep_nomina tab1 ON tab1.id_concep_nomina = tab0.id_concep_nomina 
    where tab0.estado = 1 and tab0.actual = 1 and tab1.id_tipo_concepto != 4
    --and exists (select est.num_doc from no_estado_func_proy_v est where est.num_doc = tab0.num_doc and est.periodo = $id_periodo_nuevo)
    and (
      case when tab0.id_concep_nomina in (select distinct id_concep_nomina from no_concep_ab where estado = 1) 
          and nvl(tab0.fecha_hasta,(select fecha_ini from no_periodo_proy where id_periodo = $id_periodo_nuevo)) < (select fecha_ini from no_periodo_proy where id_periodo = $id_periodo_nuevo)
      then 0
      else 1 end
    ) = 1
    
    /* Se verifica que la fecha  hasta no sea mayor al periodo liquidado - 20210514 */
    and ( id_tipo_doc, num_doc ) in (
    
        SELECT
        id_tipo_doc, num_doc
        FROM no_concepto_func
        where
        id_concep_nomina in (select id_concep_basica from no_param_concep where id_param_concep = 1)
        and estado = 1 and actual = 1
        and ( fecha_hasta >= (select fecha_ini from no_periodo_proy where id_periodo = $id_periodo_nuevo) or fecha_hasta is null )
    
    )
    
    /* Verificar que este activo - 20210610*/
    and ( id_tipo_doc, num_doc ) in (
    
        SELECT
        id_tipo_doc, num_doc
        FROM no_nombramiento_V
        where
        estado = 1
    
    )

)
   
EOD;

            CN_TABLE::executeSQL($sql);

            //VERIFICO SI PARA ALGUN FUNCIONARIO SE DEBE REGISTRAR BONIFICACION POR SERVICIOS
            $sql = <<<EOD
SELECT ID_CONCEP_BONIF FROM NO_PARAM_CONCEP
EOD;

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

            $id_concep_bonif = 0;
            if (count($results) > 0) {
                $id_concep_bonif = $results[0]['id_concep_bonif'];
            }

            /*
             * Bonificacion de servicios en el periodo - Registros activos
             * Se controla que no genere nada para las personas reiradas con fecha de terminación 
             * anterior a la fecha de inicio del nuevo periodo, para evitar los retirados - 20130930
             */
            $sql = <<<EOD
SELECT 
nom.fecha_termina,
bonser.* 
FROM NO_BONIFICA_SERVICIOS bonser
left join no_nombramiento_v nom
on nom.id_tipo_doc = bonser.id_tipo_doc
and nom.num_doc = bonser.num_doc
WHERE 
bonser.ESTADO = 1 
AND bonser.FECHA_BONIFICA >= to_date('01/$id_meses/$id_anhos','DD/MM/YYYY') AND bonser.FECHA_BONIFICA <= last_day(to_date('01/$id_meses/$id_anhos','DD/MM/YYYY')) 
and nvl(nom.fecha_termina,to_date('01/$id_meses/$id_anhos','DD/MM/YYYY')) >= to_date('01/$id_meses/$id_anhos','DD/MM/YYYY')
EOD;


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

            /*
             * VERIFICAR QUE EXISTAN REGISTROS
             */
            if (count($records)) {

                $sql = <<<EOD
SELECT * FROM NO_PERIODO_proy WHERE ID_PERIODO = $id_periodo_nuevo 
EOD;
                $results = CN_TABLE::executeSQL($sql);

                $id_anhos_nuevo = $results[0]['id_anhos'];
                $id_meses_nuevo = $results[0]['id_meses'];

                foreach ($records as $bonificaciones) {

                    $id_bonifica_servicios = $bonificaciones['id_bonifica_servicios'];
                    $fecha_bonifica = $bonificaciones['fecha_bonifica'];
                    $id_tipo_doc = $bonificaciones['id_tipo_doc'];
                    $num_doc = $bonificaciones['num_doc'];

                    $sql = <<<EOD
INSERT INTO NO_CONCEPTO_PERIODO_proy (ID_ANHOS,ID_MESES,ID_TIPO_PERIODO,PERIODO,ID_TIPO_DOC,NUM_DOC,ID_CONCEP_NOMINA,FECHA_DESDE,FECHA_HASTA,PORCENTAJE,NUM_DIAS)
    VALUES($id_anhos_nuevo,$id_meses_nuevo,1,$id_periodo_nuevo,$id_tipo_doc,$num_doc,$id_concep_bonif,
        to_date('01/$id_meses/$id_anhos','DD/MM/YYYY'),last_day(to_date('01/$id_meses/$id_anhos','DD/MM/YYYY')),
            0, $num_dias )
EOD;
                    CN_TABLE::executeSQL($sql);
                }
            }



            /**
             * Liquidar concepto periodo proyectado
             */
            $this->logMessage("[Liquidación proyecciones] Liquidar concepto periodo proyectado");


            /**
             * Se filtran para vacaciones dias de periodos adicionales - 20140613
             * Dias de vacaciones solo se toman del periodo de la nomina liquidada - 20171010
             */
            //Sql
            $sql = <<<EOD
select 
to_char(listagg(id_periodo,',') within group (order by id_periodo)) as  periodos
from no_periodo_proy
where id_anhos = (select id_anhos from no_periodo_proy where id_periodo = $id_periodo )
and id_meses = (select id_meses from no_periodo_proy where id_periodo = $id_periodo )
--and id_tipo_periodo in (1 , 2)  
and id_periodo = $id_periodo                    
EOD;
            //Ejecutar SQL
            $record_per = CN_TABLE::executeSQL($sql);
            $periodos = $record_per[0]['periodos'];

            /*
             * Cargar Periodo-Funcionario-Concepto
             * 
             * Cargar Funcionarios
             * 
             * Para cada persona
             * 
             * Cargar conceptos que apliquen en periodo para la persona, en orden de ejecución
             */
            /*
             * Se modificó la formula de liquidación de Vacaciones,  colocando la condición de Bonificación por servicios.  
             * Por lo tanto se debe verificar que el orden de concpetos para liquidación de la nómina los conceptos 1007, 1008, 1009 y 1010   
             * se liquiden despues del concpeto 1011 - 20130812
             * Se cambia calculo de dias por FECHA_RANGO_SIN_TREINTAYUNO para no tomar los dias 31 en wdiasv - 20130913
             * El orden para tomar los 4000 primero - 20140616
             * Dias num ant para las novedades de incapacidad - 20150224
             * Tag_retro para cuando es retroactivo, para retencion tiene encuenta todo el mes con lo del retroactivo - 20150610
             * Se agrega para los dias wdiasv, que tome reintegros, y opere dias - 20161207
             */
            //Sql
            $sql = <<<EOD
select 
conka.id_concep_ka,
novka.id_novedad_kardex,
nvl(novka.num_dias_ant,0) as num_dias_ant,
$salario_minimo as salario_minimo,
1 as tag,
0 as tg_retro,
tab0.*,
tab0.num_dias as dias_liq,
nvl(vac.dias_vac,0) as wdiasv,
tipcon.orden,
connom.codigo,
connom.usa_dias_calen

from no_concepto_periodo_proy 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 no_concep_ka conka
on conka.id_concep_nomina = tab0.id_concep_nomina

left join no_novedad_kardex novka
on novka.id_tipo_doc = tab0.id_tipo_doc
and novka.num_doc = tab0.num_doc
and novka.id_periodo = tab0.periodo
and novka.id_tip_nov_ka = conka.id_tip_nov_ka
and novka.estado = 1
and novka.fecha_ini = tab0.fecha_desde
and novka.fecha_fin = tab0.fecha_hasta
                    
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_proy 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 )
    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
$whereFuncionarioNumDoc $whereFuncionarioTipoDoc 
and tab0.id_concep_nomina != (select id_concep_rete from no_param_concep where id_param_concep = 1)
and tipcon.id_tipo_concepto != 4
                    
order by 
tab0.id_anhos,
tab0.id_meses,
tab0.id_tipo_doc,
tab0.num_doc,
--tipcon.orden,
case 
  when connom.codigo >= 4000  
      then '0000'
  when connom.id_concep_nomina = (select no_param_concep.id_concep_bonif from no_param_concep where no_param_concep.id_param_concep = 1)  
      then '0001'
      else connom.codigo 
  end ,
tipcon.orden
--connom.codigo 
EOD;
            //Ejecutar SQL
            $records = CN_TABLE::executeSQL($sql);


            /*
             * Recorre los registros de funcionario - concepto nomina
             * para ser liquidados
             */
            $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 Proyecciones] nom_conceptos_a_procesar: " . $nom_conceptos_a_procesar);
            $logPath = sfConfig::get('sf_log_dir') . '/liquidacion.log';
            $custom_logger = new sfFileLogger(new sfEventDispatcher(), array('file' => $logPath));

            foreach ($records as $value) {

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

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

                $custom_logger->info(MemcacheHandler::getInstance()->get($progress_key) . " - Procesado $i de $nom_conceptos_a_procesar conceptos. Funcionario: " . $num_doc . "\n");

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

                // Termina procesamiento de concepto
//                file_put_contents('/home/lavila/Escritorio/liquidacion.log', "Procesado $i de $nom_conceptos_a_procesar conceptos.\n", FILE_APPEND);
                $i++;
//                if ($num_doc == '10292794') {
//                    MemcacheHandler::getInstance()->set($progress_key, 80);
//                    break;
//                }
            }

            $custom_logger->info(MemcacheHandler::getInstance()->get($progress_key) . " - Termino Mencache.\n");
            MemcacheHandler::getInstance()->set($progress_key, 80);

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



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


            /**
             * Reliquidar FSP
             * Se toman conceptos segun la Tabla NO_FONDO_CONCEPTO para el id_descuento_ss = 2 
             */
            /**
             * Consultar salario minimo
             * 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_proy 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;

            /*
             * Se toman conceptos segun la 
             * Tabla NO_FONDO_CONCEPTO para el id_descuento_ss = 2 
             * Se agrega tag y periodo para la consulta de R - 20131216
             * Tag_retro para cuando es retroactivo, para retencion tiene encuenta todo el mes con lo del retroactivo - 20150610
             */
            $custom_logger->info(MemcacheHandler::getInstance()->get($progress_key) . " - Proceso de FSP.\n");
            //Sql
            $sql = <<<EOD
select 
$salario_minimo as salario_minimo,
1 as tag,
0 as tg_retro,
$id_periodo as periodo,                    
tab0.* 
from no_liquida_nomina_proy 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
$whereFuncionarioNumDoc $whereFuncionarioTipoDoc 
order by 
tab0.id_tipo_doc,
tab0.num_doc
EOD;

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

            $i = 0;
            $nom_conceptos_a_procesar = count($record_fsp);
            /**
             * Incidente #5032, Se coloca para nominas adicionales conceptos de deducciones, solo mensuales, mas abajo esta para las adicionales - 20190528
             */
            if ($id_tipo_periodo != 2) {
                foreach ($record_fsp as $value) {

                    $id_liquida_nomina = $value['id_liquida_nomina_proy'];
                    $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'];

                    $custom_logger->info(MemcacheHandler::getInstance()->get($progress_key) . " - FSP - Procesado $i de $nom_conceptos_a_procesar conceptos. Funcionario: " . $num_doc . "\n");

                    //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_proy 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_proy where id_periodo =  $id_periodo))
        else DIAS_RANGO_MES_SIN_TREINTAYUNO(novvac.fecha_ini,novvac.fecha_fin,(select id_meses from no_periodo_proy 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_proy 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_proy 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_proy 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_proy where ID_PERIODO = $id_periodo) ,'dd/mm/yyyy') )) 

              or        


              to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy 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_proy 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);
                    /*
                     * Calcular IBC para vacaciones
                     */
                    // 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, $record_consulta, $vals_calc);

                    $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 base no puede superar 25 salarios minimos - 20151019
                    /* if ($valor_base_vac > ($salario_minimo * 25)) {
                      $valor_base_vac = round(($salario_minimo * 25) - 1, -3);
                      $this->logMessage("[Liquidación Vac] Valor base no puede superar 25 salarios minimos: " . $valor_base_vac);
                      } */

                    /*
                     * Valor base 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_proy 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_proy 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_proy 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_proy 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_proy 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_proy where ID_PERIODO = $id_periodo) ,'dd/mm/yyyy') )) 

             or        

             to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy 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_proy 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'];
                    }

                    //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);
                    $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_proy per
on per.id_periodo = tab0.id_periodo 

WHERE 
tab0.aplicar_liq_concep = 0                     
and 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) {
                        $this->logMessage("[Liquidación Proyecciones] Valor base del FSP::" . $valor_fsp);
                        if ($valor_fsp > 0) {

                            /*
                             * Actualizar valores de FSP
                             */
                            //sentencia sql
                            $sql = <<<EOD
update NO_LIQUIDA_NOMINA_proy set valor_liquidado =  $valor_fsp
        , porcentaje = $porcentaje_fsp
            , valor_base = round( valor_liquidado, -3 ) 
    where id_liquida_nomina_proy = $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_proy 
    where id_liquida_nomina_proy = $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_proy where id_liquida_nomina_proy = $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);
                    }


                    $i++;

                    /*
                     * Iniciar en 0 dias de liquidacion y totales de vacaciones - 20131216
                     */
                    $dias_liq = 0;
                    $wdiasv_tot = 0;
                }
            }
            $custom_logger->info(MemcacheHandler::getInstance()->get($progress_key) . " - FSP - Termino Mencache.\n");
            MemcacheHandler::getInstance()->set($progress_key, 90);

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


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

            /*
             * Inicio del proceso de calculo de Retencion en la fuente concepto 2001
             * Tag_retro para cuando es retroactivo, para retencion tiene encuenta todo el mes con lo del retroactivo - 20150610
             * Solo retefunte
             * Incidente #6468 <-> Se agrega valor_bonif - 20170613
             * Se agregan los que tienen procedimiento 1, solo para la mensual -  20171219
             * Se agrega distinct en consulta procedimiento 1, ya que estaba duplicando registros - 20180117
             * Se coloca para los concepots de no_concepto_periodo no tome func de procedimiento 1 - 20180816
             */
            /** 20181212
             * Según comunicación telefónica con la Dra. Luz Elena Rodriguez , la retenci+on en la fuente para el mes de diciembre debe:
              1.- PROCEDIMIENTO 2: Se recalcula todo el mes con la prima y se descuenta lo aplicado en la prima -> la agrupacion 7 debe tener
              2.- PROCEDIMIENTO 1: NO se recalcula con la PRIMA de NAVIDAD, es decir se liquida solo con la nómina mensual.
             */
            //Sql
            $sql = <<<EOD
select 
$salario_minimo as salario_minimo,
1 as tag,
1 as tg_retro,
nvl((select valor_uvt from ts_uvt where vigencia = (select no_periodo_proy.id_anhos from no_periodo_proy 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,                      
tab0.*,
tab0.num_dias as dias_liq,
tipcon.orden,
connom.codigo,
connom.usa_dias_calen

from (
    select
    tab0.id_concepto_periodo_proy as id_concepto_periodo,
    tab0.id_anhos,
    tab0.id_meses,
    tab0.periodo,
    tab0.id_tipo_doc,
    tab0.num_doc,
    tab0.id_concep_nomina,
    tab0.fecha_desde,
    tab0.fecha_hasta,
    tab0.valor,
    tab0.porcentaje,
    tab0.num_dias,
    tab0.id_periodo_ajuste
    
   from no_concepto_periodo_proy tab0
                    
    where tab0.periodo = $id_periodo
    and tab0.num_doc not in (  
         select distinct 
          aut.num_doc
          from (
               SELECT
               aut.*,
               ROW_NUMBER() OVER (
                partition by aut.num_doc
                ORDER BY aut.ESTADO desc, aut.ID_NOVEDAD_PROCED_RETE desc
               ) AS rn
              from no_novedad_proced_rete aut
          )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.id_tipo_proced_rete = 1 
          and aut.rn = 1
          and (
            aut.estado = 1 
            or (
                aut.estado = 0 and nom.fecha_termina between (select no_periodo_proy.fecha_ini from no_periodo_proy where id_periodo = $id_periodo )  and (select no_periodo_proy.fecha_fin from no_periodo_proy where id_periodo = $id_periodo ) 
            )
          )
    )
    
    union
    
    select     
    rownum as id_concepto_periodo,
    id_anhos,
    id_meses,
    periodo,
    id_tipo_doc,
    num_doc,
    id_concep_nomina,
    fecha_desde,
    fecha_hasta,
    valor,
    porcentaje,
    num_dias,
    id_periodo_ajuste
    
    from(
        select distinct 
        --rownum id_concepto_periodo,
        per.id_anhos as id_anhos,
        per.id_meses as id_meses,
        per.id_periodo as periodo,
        aut.id_tipo_doc,
        aut.num_doc,
        param.id_concep_rete as id_concep_nomina,
        per.fecha_ini as fecha_desde,
        per.fecha_fin as fecha_hasta,
        null as valor,
        1 as porcentaje,
        30 as num_dias,
        per.id_periodo as id_periodo_ajuste,
        per.id_tipo_periodo,
        aut.id_tipo_proced_rete

        from (
               SELECT
               aut.*,
               ROW_NUMBER() OVER (
                partition by aut.num_doc
                ORDER BY aut.ESTADO desc, aut.ID_NOVEDAD_PROCED_RETE desc
               ) AS rn
              from no_novedad_proced_rete aut
        )aut

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

        left join no_periodo_proy per
        on per.id_periodo = $id_periodo

        left join no_param_concep param
        on param.id_param_concep = 1

        where
        aut.id_tipo_proced_rete = 1 
        and aut.rn = 1    
        and (
            aut.estado = 1
            or (
                aut.estado = 0 and nom.fecha_termina between (select no_periodo_proy.fecha_ini from no_periodo_proy where id_periodo = $id_periodo )  
                    and (select no_periodo_proy.fecha_fin from no_periodo_proy where id_periodo = $id_periodo ) 
            ) 
        )
    )
    where
    id_tipo_periodo = 1 
    and id_tipo_proced_rete = 1
)tab0                    

join no_concep_nomina connom
on connom.id_concep_nomina = tab0.id_concep_nomina

join no_tipo_concepto tipcon
on tipcon.id_tipo_concepto = connom.id_tipo_concepto

where tab0.periodo = $id_periodo
$whereFuncionarioNumDoc $whereFuncionarioTipoDoc 
and tab0.id_concep_nomina = (select id_concep_rete from no_param_concep where id_param_concep = 1)
and tab0.porcentaje > 0

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


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

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


                $i++;
                $custom_logger->info(MemcacheHandler::getInstance()->get($progress_key) . " - RETE - Procesado $i de $nom_conceptos_a_procesar conceptos. Funcionario: " . $num_doc . "\n");

                /*
                 * Liquidar periodo-funcionario-concepto nomina
                 * Omitir rete - 20210512::LAVILA
                 */
                //$this->liquidar($id_anhos, $id_meses, $id_periodo_rete, $num_doc, $id_tipo_doc, $id_concep_nomina, $value, $arrayConstantes, $record_consulta);
//                if ($num_doc == '39537708') {
//                    MemcacheHandler::getInstance()->set($progress_key, 80);
//                    break;
//                }
            }

            $custom_logger->info(MemcacheHandler::getInstance()->get($progress_key) . " - RETE - Termino Mencache.\n");
            MemcacheHandler::getInstance()->set($progress_key, 90);

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

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

            /**
             * CALCULO TOTAL - 20210610
             */
            MemcacheHandler::getInstance()->set($progress_key, 1);
            $custom_logger->info(MemcacheHandler::getInstance()->get($progress_key) . " - CALCULO TOTAL - INICIO\n");

            $this->logMessage("Generar calculo total agrup 133.");

            if (true) {
                /*
                 * Cargar Periodo-Funcionario-Concepto
                 * 
                 * Cargar Funcionarios
                 * 
                 * Para cada persona
                 * 
                 * Cargar conceptos que apliquen en periodo para la persona, en orden de ejecución
                 */
                /*
                 * Se modificó la formula de liquidación de Vacaciones,  colocando la condición de Bonificación por servicios.  
                 * Por lo tanto se debe verificar que el orden de concpetos para liquidación de la nómina los conceptos 1007, 1008, 1009 y 1010   
                 * se liquiden despues del concpeto 1011 - 20130812
                 * Se cambia calculo de dias por FECHA_RANGO_SIN_TREINTAYUNO para no tomar los dias 31 en wdiasv - 20130913
                 * Tag_retro para cuando es retroactivo, para retencion tiene encuenta todo el mes con lo del retroactivo - 20150610
                 * Todos los periodos del año y mes - 20170928
                 * Se verifica segnu estado y no fecha_termina - 20210122::LAVILA
                 */
                //Sql
                $sql = <<<EOD
select distinct
tab.id_clase_planta,
tab.tag,
tab.tg_retro,
tab.vig_ini,
tab.per_ini,
extract(YEAR FROM tab.fecha_termina) as vig_fin,
extract(MONTH FROM tab.fecha_termina) as per_fin, 
tab.fecha_ingreso,
tab.fecha_termina,
tab.fecha_retiro,
tab.id_anhos,
tab.id_anhos || '-01-01' as fecha_ini,
case when 7 > tab.id_meses
then tab.id_anhos - 1 else tab.id_anhos end  as anho_ini,
tab.id_meses,
tab.id_tipo_doc,
tab.num_doc,
sum(tab.dias_liq) as dias_liq, 
tab.wdiasv,
tab.orden,
tab.codigo,
tab.usa_dias_calen,
tab.id_concep_nomina 

from(
                    
        select 
        nom.id_clase_planta,
        $salario_minimo as salario_minimo,
        1 as tag,
        0 as tg_retro,
        per.id_anhos as vig_ini,
        1 as per_ini,
        per.id_anhos as vig_fin,
        1 as per_fin, 
        nom.fecha_ingreso,
        (SELECT FECHA_FIN FROM NO_PERIODO_proy where ID_PERIODO = $id_periodo) as fecha_termina,
        (SELECT FECHA_FIN FROM NO_PERIODO_proy where ID_PERIODO = $id_periodo) + 1 as fecha_retiro,
        tab0.id_anhos,
        tab0.id_meses,
        tab0.id_tipo_doc,
        tab0.num_doc,
        tab0.num_dias as dias_liq,
        nvl(vac.dias_vac,0) as wdiasv,
        tipcon.orden,
        connom.codigo,
        connom.usa_dias_calen,
        connom.id_concep_nomina
                    
        from no_concepto_periodo_proy tab0

        join no_periodo_proy per
        on per.id_periodo = tab0.periodo

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

        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_proy 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
         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
         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

        join no_estado_func_proy estfunc
        on tab0.id_tipo_doc = estfunc.id_tipo_doc
        and tab0.num_doc = estfunc.num_doc
        and tab0.periodo = estfunc.periodo
        and estfunc.actual = 1

        where 
        tab0.periodo in ( 
            SELECT ID_PERIODO FROM no_periodo_proy where ID_ANHOS = (SELECT ID_ANHOS FROM no_periodo_proy where ID_PERIODO = $id_periodo)
                and ID_MESES = (SELECT ID_MESES FROM no_periodo_proy where ID_PERIODO = $id_periodo)
        )
        $whereFuncionarioNumDoc $whereFuncionarioTipoDoc 
        and tab0.id_concep_nomina = (select id_concep_basica from no_param_concep where id_param_concep = 1)
        and tipcon.id_tipo_concepto != 4
        ---and nom.fecha_termina is null        
        and (
            nom.estado = 1 
            or (
                nom.estado = 0 and nom.fecha_termina > (select no_periodo_proy.fecha_fin 
                    from no_periodo_proy where id_periodo = $id_periodo )  
            )
        )
                    
)tab
                    
group by
tab.id_clase_planta,
tab.tag,
tab.tg_retro,
tab.vig_ini,
tab.per_ini,
tab.vig_fin,
tab.per_fin, 
tab.fecha_ingreso,
tab.fecha_termina,
tab.fecha_retiro,
tab.id_anhos,
tab.id_meses,
tab.id_tipo_doc,
tab.num_doc,
tab.wdiasv,
tab.orden,
tab.codigo,
tab.usa_dias_calen,
tab.id_concep_nomina 
                    
order by 
tab.id_anhos,
tab.id_meses,
tab.id_tipo_doc,
tab.num_doc,
tab.orden,
case 
  when tab.codigo >= 4000  
      then '0000'
  when tab.id_concep_nomina = (select no_param_concep.id_concep_bonif from no_param_concep where no_param_concep.id_param_concep = 1)  
      then '0001'
      else tab.codigo 
  end   
EOD;
                //Ejecutar SQL
                $records = CN_TABLE::executeSQL($sql);

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

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


                    /*
                     * 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("[liquidacion_proyeccion] 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("[liquidacion_proyeccion] 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'];
                        $id_clase_planta = $value['id_clase_planta'];

                        $custom_logger->info("CALCULO TOTAL - Procesado $i de $nom_conceptos_a_procesar conceptos. Documento: " . $num_doc . "\n");

                        /*
                         * 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("[liquidacion_proyeccion] 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("[liquidacion_proyeccion] Dias de Liquidación: " . $dias_liq);


                            /*
                             * 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,                      
$id_clase_planta as id_clase_planta, 
$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,
$dias_liq as dias_liq,
$dias_otra_ent as dias_otra_ent,
'$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->liquidarProvTotal($id_anhos, $id_meses, $id_periodo, $num_doc, $id_tipo_doc, $id_concep_nomina, $record_liq, $arrayConstantes, $id_agrup_concepto);
                            } 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("[liquidacion_proyeccion] " . $mensajeError);
                            }
                        }

//                    die();
                        $i++;
                    }
                    MemcacheHandler::getInstance()->set($progress_key, 99);
                }
            }

            $custom_logger->info(MemcacheHandler::getInstance()->get($progress_key) . " - CALCULO TOTAL - Termino Mencache.\n");
            MemcacheHandler::getInstance()->set($progress_key, 95);

            $this->conn->commit();

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

            /**
             * APORTES - 20210513
             */
            MemcacheHandler::getInstance()->set($progress_key, 1);
            $custom_logger->info(MemcacheHandler::getInstance()->get($progress_key) . " - APORTES - INICIO\n");

            $dias_trabajado = 0;
            $this->logMessage("Generar aportes.");

            if (true) {


                //sentencia sql
                $sql = <<<EOD
delete from NO_LIQUIDA_APORTE_PROY tab0 
where
tab0.id_anhos = $id_anhos
and tab0.id_meses >= $id_meses                         
$whereFuncionarioNumDoc $whereFuncionarioTipoDoc 
and tab0.tipo_planilla = 'A'                      
EOD;
                //ejecuta y obtiene el resultado del sql
                CN_TABLE::executeSQL($sql);

                /*
                 * Verifique que el funcionario este afiliado a todos los fondos
                 * Validacion para solo activos en el periodo - 20130722
                 */
                //Correcion de consulta filtro con los funcionarios activos(no_estado_func) - 20130826
                //Validacion para que tome el registro de pension funcionario - 20131105
                //Sql
                $sql = <<<EOD
select tab0.num_doc, count(tab0.id_afilia_fondo) 
from no_afilia_fondo tab0
left join no_estado_func_proy tab1
on tab1.id_tipo_doc = tab0.id_tipo_doc and tab1.num_doc = tab0.num_doc
where tab0.estado = 1
and tab1.periodo = $id_periodo
$whereFuncionarioNumDoc $whereFuncionarioTipoDoc 
having count(tab0.id_afilia_fondo) + 
(select count(tab2.id_pension_func) 
from no_pension_func tab2
where
tab2.id_tipo_doc = tab0.id_tipo_doc
and tab2.num_doc = tab0.num_doc
and tab2.estado = 1 )
< (select count(*) from no_clase_fondo)
group by tab0.num_doc, tab0.id_tipo_doc 
EOD;
                //Ejecutar SQL
                $record_total = CN_TABLE::executeSQL($sql);
                if (count($record_total) == 0) {

                    /*
                     * 20130726
                     * Como afectan los dias de vacaciones  el número de días de aporte en AUTOLIQUIDACION. 
                     * Para los casos de interrupcion de vacaciones;
                     * 
                     * 1. Suma días : Tomar los dias de novedade de vacaciones, cuyo tipo de novedad de vacaciones (NO_TIPO_NOV_VAC)
                     * Operador=1 - Tiempo_liqui=1
                     *
                     * 2. Resta días : Tomar los dias de novedade de vacaciones, cuyo tipo de novedad de vacaciones (NO_TIPO_NOV_VAC)
                     * Operador=0 - Tiempo_liqui=1
                     */
                    /*
                     * Cuando es clase fondo id 3-riesgo debe restar los dias de las nov kardex que no afecten antiguedad - 20130729
                     * Se cambia consulta con no_liquida_nomina por vista que toma de los periodo tipo 1 y 2 - 20130827
                     * Para el IBC de Riesgos no se tiene en cuenta la novedad de vacaciones, el valor base y los días deben ser sin contemplar estos días. - 20130917
                     * El número de días de ARP  o ARL  se deben disminuir con el número de días del concepto 4001 reintegro asignacion básica. SGC - Yobany Jimenez: 1 dia incap - 1 Reintegro ARP 
                     * - existe un tipo de novedad ka que afecta los dias de riesgo, se cambia para que tenga en cuenta los dias de patrono - 20140922
                     * Para los parafiscales no completa dias de vacaciones, como tambien en el IBC - 20141202
                     * NOM-135 <-> Solo toma de no_liquida_nomina los que son del periodo normal no del retoractivo - 20150604
                     * Se toma conceptos de ajuste y reintegro para aportes de salud y pension, and liqnom.id_concep_nomina in ( conceptos.id_concep_nomina  ) - 20170330
                     * Se colocan dias de comision otra entidad para liquidar aportes de retiro, nvl(novper.dias,0) - 20171011
                     * Se colocan dias de liq definitiva nvl(diasdef.dias,0) - 20190426
                     * Para salud y pension que sin importar se retire, si sume las novedades - 20210225
                     */
                    //sentencia sql
                    $sql = <<<EOD

INSERT INTO NO_LIQUIDA_APORTE_PROY (ID_CLASE_FONDO,ID_MAE_FONDOS,ID_CONCEP_NOMINA,ID_TIPO_DOC,NUM_DOC,VALOR_BASE,NUM_DIAS,
APORTE_FUNC,APORTE_PATRONO,ID_CEN_OP,ID_TIPO_APORTE,PORCENTAJE_FUNC,PORCENTAJE_PATRONO,TARIFA,ID_ANHOS,ID_MESES,ID_TIPO_PERIODO,ID_PERIODO, UPC_ADICIO, ID_TAE, ID_TAP)


select distinct
tab.ID_CLASE_FONDO,
tab.ID_MAE_FONDOS,
tab.ID_CONCEP_NOMINA,
tab.ID_TIPO_DOC,
tab.NUM_DOC,
tab.VALOR_BASE,

/*
Se pone validacion para no superar los 30 dias - 20130827
*/
case when tab.num_dias >= 30 then 30 else tab.num_dias end as num_dias,
                                
tab.APORTE_FUNC,
tab.APORTE_PATRONO,
tab.ID_CEN_OP,
tab.ID_TIPO_APORTE,
tab.PORCENTAJE_FUNC,
tab.PORCENTAJE_PATRONO,
tab.TARIFA,
tab.ID_ANHOS,
tab.ID_MESES,
tab.ID_TIPO_PERIODO,
tab.ID_PERIODO,
tab.UPC_ADICIO,
tab.id_tae,
tab.id_tap 
from(
                                
        select distinct
        afilia.id_clase_fondo AS ID_CLASE_FONDO,
        fondo.id_mae_fondos AS ID_MAE_FONDOS,
        conceptos.id_concep_nomina AS ID_CONCEP_NOMINA,
        tab0.id_tipo_doc AS ID_TIPO_DOC,
        tab0.num_doc AS NUM_DOC,
        0 AS VALOR_BASE,
        /*
        Dias de Pension y Salud
        */
        case when afilia.id_clase_fondo = 1 
               or afilia.id_clase_fondo = 2 
        then (
            case when 
                extract(month from tab5.fecha_ingreso) || extract(year from tab5.fecha_ingreso) = (select id_meses || id_anhos from no_periodo_proy where id_periodo = $id_periodo )
              or extract(month from tab5.fecha_termina) || extract(year from tab5.fecha_termina) = (select id_meses || id_anhos  from no_periodo_proy where id_periodo = $id_periodo )
            then (
              case when kardex1.cantidad > 0 then kardex1.dias + (
              select nvl(sum(num_dias),0) from no_liquida_nomina_adic_proy 
              where id_periodo = tab0.periodo and id_tipo_doc = tab0.id_tipo_doc 
              and num_doc = tab0.num_doc and id_concep_nomina = (select id_concep_basica from no_param_concep)
              )
              else (
              select nvl(sum(num_dias),0) from no_liquida_nomina_adic_proy 
              where id_periodo = tab0.periodo and id_tipo_doc = tab0.id_tipo_doc 
              and num_doc = tab0.num_doc and id_concep_nomina = (select id_concep_basica from no_param_concep)
              ) end
            )
            else (
              case when kardex1.cantidad > 0 then kardex1.dias + (
              select nvl(sum(num_dias),0) from no_liquida_nomina_adic_proy 
              where id_periodo = tab0.periodo and id_tipo_doc = tab0.id_tipo_doc 
              and num_doc = tab0.num_doc and id_concep_nomina = (select id_concep_basica from no_param_concep)
              )
              else (
              select nvl(sum(num_dias),0) from no_liquida_nomina_adic_proy 
              where id_periodo = tab0.periodo and id_tipo_doc = tab0.id_tipo_doc 
              and num_doc = tab0.num_doc and id_concep_nomina = (select id_concep_basica from no_param_concep)
              ) end
            )  end
        )
        /*
        Dias de riesgos profesionales
        No se tiene en cuenta los dias de vacaciones - 20130917  
        Se corrige los dias de vacaciones, para que la resta sea correcta - 20141022   
        SGC :: kardex5, para restar los dias de novedad kardex que causan liquidacion - 20150205                       
        */
        when afilia.id_clase_fondo = 3
        then(
        ( select case when ( nvl(sum(num_dias),0) - nvl(kardex5.cantidad,0) - nvl(kardex4.cantidad,0) /*- nvl(reint.dias,0)*/ -nvl(kardexlr.cantidad,0) ) < 0 
            then 0 else nvl(sum(num_dias),0) - nvl(kardex5.cantidad,0) - nvl(kardex4.cantidad,0) /*- nvl(reint.dias,0)*/ -nvl(kardexlr.cantidad,0) end  from no_liquida_nomina_adic_proy 
        where id_periodo = tab0.periodo and id_tipo_doc = tab0.id_tipo_doc 
        and num_doc = tab0.num_doc and id_concep_nomina = (select id_concep_basica from no_param_concep) ) - nvl(vac.num_dias_vac,0)                               
        )
        /*
        COL :: Se quita la resta de dias de vacaciones para tener encuenta los dias de vacaciones - nvl(vac.num_dias_vac,0) - 20150123
        NOM-93::SGC Validacion de dias, se vuevle a colocar que no tenga encuenta los dias de vacaciones - nvl(vac.num_dias_vac,0)  - 20150330
        COL :: Se quita la resta de dias de vacaciones para tener encuenta los dias de vacaciones - nvl(vac.num_dias_vac,0) - 20150417
        COL Incidente #5411 :: Se colocan dias se ASIG BAS de otros periodos de nomina, definitiva y adicionales - 20170119
        Se desactiva datos de linea anterior, la vista no_liquida_nomina_adic_proy debe traer dias completos - 20170313 
        Incidente #21553; Se coloca solo para parafiscales que reste dias de reintegro - 20210503
        */    
        else (
        ( select nvl(sum(num_dias),0) from no_liquida_nomina_adic_proy 
        where id_periodo = tab0.periodo and id_tipo_doc = tab0.id_tipo_doc 
        and num_doc = tab0.num_doc and id_concep_nomina = (select id_concep_basica from no_param_concep) ) 
        ) - nvl(reint.dias,0) 
            end + nvl(vac.num_dias_vac,0) + nvl(novper.dias,0) /*+  
        nvl( (select nvl(sum(num_dias),0) from no_liquida_nomina_proy
            where id_periodo in ( (select id_periodo from no_periodo_proy where id_meses = ( select id_meses from no_periodo_proy where id_periodo = tab0.periodo) and id_anhos = ( select id_anhos from no_periodo_proy where id_periodo = tab0.periodo) and id_tipo_periodo != 1) ) 
            and id_tipo_doc = tab0.id_tipo_doc 
            and num_doc = tab0.num_doc and id_concep_nomina = (select id_concep_basica from no_param_concep)) ,0)*/
        + nvl(diasdef.dias,0) /*- nvl(reint.dias,0)*/ as num_dias,
        
        /*
        NOM-85 COL:: Se realiza el cambio para que tome todos los periodos de un mes, como tambien ajuste y reintegro  - 20150325
        */
        (            
            select 
            nvl(sum( liqnom.valor_liquidado * (case when (con.operador) != 1 then (1) else (-1) end) ),0) + nvl(sum(ext.aporte_func),0)  as valor
            from no_liquida_nomina_proy liqnom 
            join no_periodo_proy per on per.id_periodo = liqnom.id_periodo 
            left join no_liquida_extra ext
            on liqnom.id_tipo_doc = ext.id_tipo_doc and liqnom.num_doc = ext.num_doc
            and liqnom.id_concep_nomina = ext.id_concep_nomina and liqnom.id_periodo = ext.id_periodo
            
            left join no_concep_nomina con
            on liqnom.id_concep_nomina = con.id_concep_nomina
                                
            where    1 = 1 and per.id_meses = ( select id_meses from no_periodo_proy where id_periodo = tab0.periodo) and per.id_anhos = ( select id_anhos from no_periodo_proy where id_periodo = tab0.periodo)  
            and liqnom.num_doc = tab0.num_doc and liqnom.id_tipo_doc = tab0.id_tipo_doc  
            --and liqnom.id_concep_nomina in ( conceptos.id_concep_nomina  ) 
            and (
                liqnom.id_concep_nomina in ( conceptos.id_concep_nomina ) 
                or
                liqnom.id_concep_nomina in (select distinct id_concep_ajuste from no_concep_nomina where id_concep_nomina in (conceptos.id_concep_nomina) and id_concep_ajuste is not null)
                or
                liqnom.id_concep_nomina in (select distinct id_concep_rein from no_concep_nomina where id_concep_nomina in (conceptos.id_concep_nomina) and id_concep_rein is not null )
            )  
            and liqnom.id_periodo_ajuste is null                                
        ) AS APORTE_FUNC,

        0 AS APORTE_PATRONO,
        tab0.id_cen_op AS ID_CEN_OP,
        afilia.id_tipo_aporte AS ID_TIPO_APORTE,
        conceptos.porcentaje_func AS PORCENTAJE_FUNC,
        conceptos.porcentaje_patrono AS PORCENTAJE_PATRONO,
        conceptos.tarifa AS TARIFA,
        tab0.ID_ANHOS AS ID_ANHOS,
        tab0.ID_MESES AS ID_MESES,
        tab0.ID_TIPO_PERIODO AS ID_TIPO_PERIODO,
        tab0.periodo AS ID_PERIODO,
        nvl(upcadic.valor_upc ,0) as UPC_ADICIO,
        afisal.id_mae_fondos as id_tae,
        afipen.id_mae_fondos as id_tap

        from no_estado_func_proy_v tab0

        left join no_dp_v cargo ON cargo.id_dp = tab0.id_dp
        left join no_nombramiento_v tab5 on tab5.id_tipo_doc = tab0.id_tipo_doc and tab5.num_doc = tab0.num_doc

        join no_afilia_fondo afilia ON afilia.id_tipo_doc = tab0.id_tipo_doc and afilia.num_doc = tab0.num_doc 
        and  (select fecha_fin from no_periodo_proy where id_periodo =  $id_periodo)
        between afilia.fecha_ingreso and nvl( afilia.fecha_retiro, trunc(last_day( to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy') )) )
        --and afilia.estado = 1

        join no_mae_fondos fondo ON fondo.id_mae_fondos = afilia.id_mae_fondos
            
        /*Se activa resta de dias del concepto de reintegro asignacion basica 4001 - 20190903*/ 
        /*Incidente 14326, Se suspende reintegro de 4001 por conflicto con incapacidades - 20190926*/     
        left join 
        (                        
            select 
            liqnom.num_doc, liqnom.id_tipo_doc,
            --nvl(sum(liqnom.num_dias),0) as dias
            0 as dias  
            from no_liquida_nomina_proy liqnom   
            join no_periodo_proy per on per.id_periodo = liqnom.id_periodo 
            where  1 = 1 
            and per.id_meses = ( select id_meses from no_periodo_proy where id_periodo = $id_periodo)  
            and per.id_anhos = ( select id_anhos from no_periodo_proy where id_periodo = $id_periodo)  
            and liqnom.id_concep_nomina = (select id_concep_nomina from no_concep_nomina  where codigo = '4001')
            and liqnom.id_periodo_ajuste is null
            group by
            liqnom.num_doc, liqnom.id_tipo_doc
        )reint ON reint.id_tipo_doc = tab0.id_tipo_doc and reint.num_doc = tab0.num_doc 
                                
        left join 
        (
        select liquida.id_tipo_doc,liquida.num_doc, sum(liquida.valor_liquidado) VALOR
        from no_liquida_nomina_adic_proy liquida
        where liquida.id_periodo = $id_periodo 
            and (liquida.id_concep_nomina = 1 or liquida.id_concep_nomina = 3 or liquida.id_concep_nomina = 11 or liquida.id_concep_nomina = 14 or liquida.id_concep_nomina = 42)
        group by liquida.id_tipo_doc,liquida.num_doc
        )liquida ON liquida.id_tipo_doc = tab0.id_tipo_doc and liquida.num_doc = tab0.num_doc 

        left join(

        select 
        deta.id_tipo_aporte, deta.porcentaje_func,deta.porcentaje_patrono,descto.id_clase_fondo,
        foncon.id_mae_fondos,foncon.id_concep_nomina, (deta.porcentaje_func+deta.porcentaje_patrono) as tarifa,
        deta.rango_desde, deta.rango_hasta,(select valor_mensual * deta.rango_hasta from no_smdlv where vigencia = extract(year from sysdate)) AS SALARIO, descto.id_descuento_ss
        from no_descto_detalle deta
        left join no_descuento_ss descto ON descto.id_descuento_ss = deta.id_descuento_ss
        left join no_fondo_concepto foncon ON foncon.id_descuento_ss = descto.id_descuento_ss

        ) conceptos ON conceptos.id_tipo_aporte = afilia.id_tipo_aporte 
        and conceptos.id_clase_fondo = afilia.id_clase_fondo and conceptos.id_mae_fondos = afilia.id_mae_fondos
        --and case when conceptos.id_descuento_ss = 2 then liquida.valor else conceptos.salario+1 end > conceptos.salario


        left join no_upc_adicional upcadic
        on upcadic.estado = 1
        and upcadic.id_tipo_doc = tab0.id_tipo_doc and upcadic.num_doc = tab0.num_doc
        and upcadic.id_mae_fondos = afilia.id_mae_fondos and upcadic.id_clase_fondo = afilia.id_clase_fondo

        /*
        Pone el id de salud id_tae en la tabla no_liquida_aporte_proy si se va a trasladar de fondo para mostralo al generar la planilla 
        busca en no_afilia_fondo el ultimo fondo activo, que su fecha de ingreso sea mayor a la fecha inicial del periodo  - 20130826
        */
        left join (
          SELECT
           aut.*,
           ROW_NUMBER() OVER (
            partition by aut.num_doc
            ORDER BY aut.id_afilia_fondo DESC
           ) AS rn
          from no_afilia_fondo aut
          where aut.id_clase_fondo = 2
          and aut.fecha_ingreso >= (select fecha_ini from no_periodo_proy where id_periodo =  $id_periodo)
          and aut.fecha_retiro is null
        )afisal
        on afisal.num_doc = tab0.num_doc 
        and afisal.id_clase_fondo = afilia.id_clase_fondo
        and afisal.rn = 1

        /*
        Pone el id de pension id_tap en la tabla no_liquida_aporte_proy si se va a trasladar de fondo para mostralo al generar la planilla 
        busca en no_afilia_fondo el ultimo fondo activo, que su fecha de ingreso sea mayor a la fecha inicial del periodo  - 20130826
        */
        left join (
          SELECT
           aut.*,
           ROW_NUMBER() OVER (
            partition by aut.num_doc
            ORDER BY aut.id_afilia_fondo DESC
           ) AS rn
          from no_afilia_fondo aut
          where aut.id_clase_fondo = 1
          and aut.fecha_ingreso >= (select fecha_ini from no_periodo_proy where id_periodo =  $id_periodo)
          and aut.fecha_retiro is null
        )afipen
        on afipen.num_doc = tab0.num_doc 
        and afipen.id_clase_fondo = afilia.id_clase_fondo
        and afipen.rn = 1

        /*
        Suma numero de dias de las Novedades de kardex que no afecten antiguedad y causen liquidacion
        las novedas como de 1 a 3 dias son solo informativas - 20130826
        */
        left join
        (
            select tab0.num_doc, count(tab0.id_novedad_kardex) CANTIDAD, max(tab1.suspension) as max_marca,
            nvl(sum( dias_rango_mes_sin_treintayuno(tab0.fecha_ini,tab0.fecha_fin, (select id_meses from no_periodo_proy where id_periodo = $id_periodo) ) ),0) as dias
            from no_novedad_kardex tab0
            left join no_tip_nov_ka tab1 ON tab1.id_tip_nov_ka = tab0.id_tip_nov_ka
            where tab1.afecta_antigu = 0 and tab1.causa_liquidacion = 1 and tab0.estado = 1 
            and
            (select id_anhos || lpad(id_meses,2,'0') as vigper from no_periodo_proy where id_periodo = tab0.id_periodo) <= (select id_anhos || lpad(id_meses,2,'0') as vigper from no_periodo_proy where id_periodo = $id_periodo)
            and (
              to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy') between tab0.fecha_ini and tab0.fecha_fin
              or
              trunc(last_day( to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy') )) between tab0.fecha_ini and tab0.fecha_fin
              or 
              tab0.id_periodo = $id_periodo
            )
            group by tab0.num_doc
        )kardex1 ON kardex1.num_doc = tab0.num_doc

        /*
        Se deben restar dias de kardex solo del mes anterior donde id-4 Incapacidad Laboralx Accidente de trabajo/Enf. pro  - 20130827
        Se deben restar dias de kardex solo de dias anteriores al rango de fecha del periodo actual - 20130917
        Se cambia de id-4 por atributo en  la tabla no_tip_nov_ka de afecta_riesgo, para validar cuales afectan en los dias de ARP-ARL - 20130919
        Se cambia para que tome dias de meses anteriores y sin dia 31, kardek4 inc que afectan riesgo - 20190930
        */
        left join
        (
                                
            select 
            tab.num_doc,
            nvl(sum(tab.cant_dia_riesgo),0) as cantidad
            from(
                                
                    select 
                    
                    case when tab0.prorroga = 1 then nvl(sum( ( case when tab0.fecha_fin >= to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy')
                        then to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy') - 1 else tab0.fecha_fin end ) - tab0.fecha_ini + 1 ),0) 

                        else nvl(sum( ( case when tab0.fecha_fin >= to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy')
                                then to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy') - 1 else tab0.fecha_fin end ) - tab0.fecha_ini + 1 ),0) - tab1.dias_patrono 
                        end as cant_dia_riesgo_ant,
                        
                    nvl(sum( fecha_rango_sin_treintayuno(tab0.fecha_ini, ( case when tab0.fecha_fin >= to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy')
                        then to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy') - 1 else tab0.fecha_fin end ) )  ),0)  - tab1.dias_patrono as cant_dia_riesgo,

                    tab1.dias_patrono,
                    tab0.prorroga,
                                
                    tab0.num_doc, 
                    sum(tab0.num_dias) CANTIDAD_1,
                    nvl(sum( dias_rango_mes(tab0.fecha_ini,tab0.fecha_fin, (select case when id_meses = 1 then 12 else id_meses - 1 end id_meses from no_periodo_proy where id_periodo = $id_periodo) ) ),0) as CANTIDAD_2,

                    nvl(sum( ( case when tab0.fecha_fin >= to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy')
                    then to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy') - 1 else tab0.fecha_fin end ) - tab0.fecha_ini + 1 ),0) as CANTIDAD

                    from no_novedad_kardex tab0
                    left join no_tip_nov_ka tab1 ON tab1.id_tip_nov_ka = tab0.id_tip_nov_ka
                        where tab1.afecta_riesgo = 1 and tab0.estado = 1 

                    and ( 
                        tab0.fecha_inc between to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy 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_proy WHERE ID_PERIODO = $id_periodo) ,'dd/mm/yyyy') )) 
                        /*
                        Validacion para que tome el registro en el periodo de la novedad - 20130820
                        */
                        or tab0.id_periodo = $id_periodo
                    )

                    group by tab0.num_doc, tab0.prorroga, tab1.dias_patrono
            
            )tab
            group by
            tab.num_doc      
                                
        )kardex4 ON kardex4.num_doc = tab0.num_doc
                                
        left join
        (
                                
            select 
            tab.num_doc,
            nvl(sum(case when tab.cant_dia_riesgo > 0 then tab.cant_dia_riesgo else 0 end),0) as cantidad
            from(
                                
                    select 
                    
                      case when tab0.prorroga = 1 and tab0.fecha_ini < to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy')
                           then nvl(sum( ( case when tab0.fecha_fin >= to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy')
                                         then to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy') - 1 else tab0.fecha_fin end ) - tab0.fecha_ini + 1 ),0) 

                      when tab0.prorroga = 0 and tab0.fecha_ini < to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy')
                           then nvl(sum( ( case when  tab0.fecha_fin >= to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy')
                                          then to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy') - 1 else tab0.fecha_fin end ) - tab0.fecha_ini + 1 ),0) - tab1.dias_patrono 
                      else 0
                      end as cant_dia_riesgo,

                    tab1.dias_patrono,
                    tab0.prorroga,
                                
                    tab0.num_doc, 
                    sum(tab0.num_dias) CANTIDAD_1,
                    nvl(sum( dias_rango_mes(tab0.fecha_ini,tab0.fecha_fin, (select case when id_meses = 1 then 12 else id_meses - 1 end id_meses from no_periodo_proy where id_periodo = $id_periodo) ) ),0) as CANTIDAD_2,

                    nvl(sum( ( case when tab0.fecha_fin >= to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy')
                    then to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy') - 1 else tab0.fecha_fin end ) - tab0.fecha_ini + 1 ),0) as CANTIDAD

                    from no_novedad_kardex tab0
                    left join no_tip_nov_ka tab1 ON tab1.id_tip_nov_ka = tab0.id_tip_nov_ka
                        where tab1.causa_liquidacion = 1 and tab0.estado = 1 and tab1.afecta_riesgo != 1

                    and ( 
                        tab0.fecha_inc between to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy 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_proy WHERE ID_PERIODO = $id_periodo) ,'dd/mm/yyyy') )) 
                        /*
                        Validacion para que tome el registro en el periodo de la novedad - 20130820
                        */
                        or tab0.id_periodo = $id_periodo
                    )

                    group by tab0.num_doc, tab0.prorroga, tab1.dias_patrono, tab0.fecha_ini, tab0.fecha_fin
            
            )tab
            group by
            tab.num_doc      
                                
        )kardex5 ON kardex5.num_doc = tab0.num_doc
                  
        /*Se coloca dias para licencia remunerada, resta en riesgo ARL - 20190214*/       
        /*Licencia remunerada descuenta todos los días de meses anteriores - 20190905*/                 
        left join
        (
                                
            select 
            tab.num_doc,
            nvl(sum(case when tab.cant_dia_riesgo > 0 then tab.cant_dia_riesgo else 0 end),0) as cantidad_ant,
            nvl(sum(case when tab.cant_dia_riesgo_completo > 0 then tab.cant_dia_riesgo_completo else 0 end),0) as cantidad
            from(
                                
                    select 
                    
                    nvl(sum( dias_rango_mes_sin_treintayuno(tab0.fecha_ini,tab0.fecha_fin, (select id_meses from no_periodo_proy where id_periodo = $id_periodo) ) ),0) as cant_dia_riesgo,
                    nvl(sum( fecha_rango_sin_treintayuno(tab0.fecha_ini,tab0.fecha_fin ) ),0) as cant_dia_riesgo_completo,

                    tab1.dias_patrono,
                    tab0.prorroga,
                                
                    tab0.num_doc, 
                    sum(tab0.num_dias) CANTIDAD_1,
                    nvl(sum( dias_rango_mes(tab0.fecha_ini,tab0.fecha_fin, (select case when id_meses = 1 then 12 else id_meses - 1 end id_meses from no_periodo_proy where id_periodo = $id_periodo) ) ),0) as CANTIDAD_2,

                    nvl(sum( ( case when tab0.fecha_fin >= to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy')
                    then to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy') - 1 else tab0.fecha_fin end ) - tab0.fecha_ini + 1 ),0) as CANTIDAD

                    from no_novedad_kardex tab0
                    left join no_tip_nov_ka tab1 ON tab1.id_tip_nov_ka = tab0.id_tip_nov_ka
                        
                    where tab1.id_tip_nov_ka in (select id_tip_nov_ka from no_tip_nov_ka where tiempo_remunerado = 1) and tab0.estado = 1 

                    and ( 
                        tab0.fecha_inc between to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy 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_proy WHERE ID_PERIODO = $id_periodo) ,'dd/mm/yyyy') )) 
                        /*
                        Validacion para que tome el registro en el periodo de la novedad - 20130820
                        */
                        or tab0.id_periodo = $id_periodo
                    )

                    group by tab0.num_doc, tab0.prorroga, tab1.dias_patrono, tab0.fecha_ini, tab0.fecha_fin
            
            )tab
            group by
            tab.num_doc      
                                
        )kardexlr ON kardexlr.num_doc = tab0.num_doc

        left join (

            select 

            id_tipo_doc,                  
            num_doc,
            /*
            dias,
            dias_vac,
            num_dias_vac,*/
            sum(dias_vaciones) as num_dias_vac_ant,
            sum(dias_vaciones) - sum(dias_feb) as num_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_proy where id_periodo =  $id_periodo))),0) as dias,
                 nvl(sum( novvac.fecha_fin - novvac.fecha_ini + 1),0) as dias_vac,

                 nvl(sum(dias_rango_mes_sin_treintayuno(novvac.fecha_ini,novvac.fecha_fin,(select id_meses from no_periodo_proy where id_periodo =  $id_periodo))),0) as num_dias_vac,
                 tipnov.operador,

                 case  when tipnov.operador  = 1 
                 then nvl(sum(dias_rango_mes_sin_treintayuno(novvac.fecha_ini,novvac.fecha_fin,(select id_meses from no_periodo_proy where id_periodo =  $id_periodo))),0) 
                 else nvl(sum(dias_rango_mes_sin_treintayuno(novvac.fecha_ini,novvac.fecha_fin,(select id_meses from no_periodo_proy where id_periodo =  $id_periodo))),0) * (-1)
                 end as dias_vaciones,
                                
                --Para el mes de febrero se restan dias 2 o 1 segun año, ya que estos dias se pagan como laborados - 20170314                 
                (case 
                   when (select id_meses from no_periodo_proy where id_periodo = $id_periodo) = 2 and max(novvac.fecha_ini) < (select fecha_fin from no_periodo_proy where id_periodo = $id_periodo) and max(novvac.fecha_fin) > (select fecha_fin from no_periodo_proy where id_periodo = $id_periodo) 
                   then case when to_number((select to_char(fecha_fin,'dd') from no_periodo_proy where id_periodo = $id_periodo)) = 28 then 2 else 1 end
                   else 0 end) * (case  when tipnov.operador  = 1 then 1 else (-1) end) as dias_feb

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

            group by id_tipo_doc, num_doc


        )vac
        on vac.id_tipo_doc = tab0.id_tipo_doc and vac.num_doc = tab0.num_doc   
        
        left join(
            select
            tab0.id_tipo_doc,
            tab0.num_doc,
            nvl(sum( dias_rango_mes_sin_treintayuno(tab0.fecha_ini,tab0.fecha_fin, (select id_meses from no_periodo_proy where id_periodo = $id_periodo) ) ),0) as dias
            from(
                select 
                
                nov.id_tipo_doc,
                nov.num_doc,
                nov.id_novedad,
                nov.fecha_inicial,
                nov.fecha_terminacion,
                nom.fecha_termina,
                
                case when nov.fecha_inicial > (select fecha_ini from no_periodo_proy where id_periodo = $id_periodo) 
                then nov.fecha_inicial 
                else (select fecha_ini from no_periodo_proy where id_periodo = $id_periodo) end as fecha_ini,
                nom.fecha_termina as fecha_fin
                
                from no_novedad_personal nov
                
                join no_nombramiento_v nom
                on nov.id_tipo_doc = nom.id_tipo_doc
                and nov.num_doc = nom.num_doc
                
                where 
                nov.estado = 1
                and nov.id_novedad = 8
                and (
                    (select fecha_ini from no_periodo_proy where id_periodo = $id_periodo) between nov.fecha_inicial and nov.fecha_terminacion
                    or    
                    (select fecha_fin from no_periodo_proy where id_periodo = $id_periodo) between nov.fecha_inicial and nov.fecha_terminacion
                )
                and (
                    nom.fecha_termina between (select fecha_ini from no_periodo_proy where id_periodo = $id_periodo) and (select fecha_fin from no_periodo_proy where id_periodo = $id_periodo)
                )
                
            )tab0  
            
            group by 
            tab0.id_tipo_doc,
            tab0.num_doc 
        )novper
        on novper.id_tipo_doc = tab0.id_tipo_doc and novper.num_doc = tab0.num_doc  
           
        /* Se agrega restar el concepto 4001 - 20210210::LAVILA*/
        left join 
        (                      
            select 
            liqnom.num_doc, liqnom.id_tipo_doc,
            nvl(sum(liqnom.dias),0) as dias 
            from(
                select 
                liqnom.num_doc, liqnom.id_tipo_doc,
                nvl(sum(liqnom.num_dias),0) as dias  
                from no_liquida_nomina_proy liqnom   
                join no_periodo_proy per on per.id_periodo = liqnom.id_periodo 
                where  1 = 1 
                and per.id_meses = ( select id_meses from no_periodo_proy where id_periodo = $id_periodo)  
                and per.id_anhos = ( select id_anhos from no_periodo_proy where id_periodo = $id_periodo)  
                and liqnom.id_concep_nomina = (select id_concep_basica from no_param_concep)
                and liqnom.id_periodo_ajuste is null
                and per.id_tipo_periodo = 5 
                group by
                liqnom.num_doc, liqnom.id_tipo_doc
                
                union
                
                select 
                liqnom.num_doc, liqnom.id_tipo_doc,
                nvl(sum(liqnom.num_dias),0) * (-1) as dias  
                from no_liquida_nomina_proy liqnom   
                join no_periodo_proy per on per.id_periodo = liqnom.id_periodo             
                join no_concep_nomina concep on concep.id_concep_rein = liqnom.id_concep_nomina
                where  1 = 1 
                and per.id_meses = ( select id_meses from no_periodo_proy where id_periodo = $id_periodo)  
                and per.id_anhos = ( select id_anhos from no_periodo_proy where id_periodo = $id_periodo)  
                and concep.id_concep_nomina = (select id_concep_basica from no_param_concep)
                and liqnom.id_periodo_ajuste is null
                and per.id_tipo_periodo = 5 
                group by
                liqnom.num_doc, liqnom.id_tipo_doc
            )liqnom
            group by
            liqnom.num_doc, liqnom.id_tipo_doc
        )diasdef ON diasdef.id_tipo_doc = tab0.id_tipo_doc and diasdef.num_doc = tab0.num_doc     

        where tab0.periodo= $id_periodo 
        and conceptos.id_concep_nomina is not null 
        $whereFuncionarioNumDoc $whereFuncionarioTipoDoc 
        and (
            /*
              Se cambia fecha de termina(ultimo dia de trabajo) por fecha de retiro, 
              para tener encuenta si trabajo en el periodo al menos 1 dia - 20170406                    
              */
            ( tab0.actual = 1 and 
                ( 
                    tab5.fecha_retiro is null 
                    or 
                    tab5.fecha_retiro != to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy') 
                ) 
            )
            or
            ( tab0.actual = 0 
              /*
              Se cambia fecha de termina(ultimo dia de trabajo) por fecha de retiro, 
              para tener encuenta si trabajo en el periodo al menos 1 dia - 20130828                    
              */
              and tab5.fecha_retiro != to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy')
              and tab5.fecha_termina
            between to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy 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_proy WHERE ID_PERIODO = $id_periodo) ,'dd/mm/yyyy') ))
            )
        )
                                
)tab
EOD;

//and tab0.actual = 1 
//and afilia.estado = 1
                    //ejecuta y obtiene el resultado del sql
                    $this->conn->execute($sql);

                    $this->conn->commit();

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


                    /**
                     * Personas con novedad e comision otra entidad id -> 8,
                     * en la liq del nuevo periodo desactiva valores y días de no_concepto_periodo, 
                     * borra registros de aportes de personas con la novedad - 20150313
                     */
                    $sql = <<<EOD
delete  from NO_LIQUIDA_APORTE_PROY
where 
ID_PERIODO = $id_periodo
and num_doc in (
    select 
    
    nov.num_doc 
    
    from no_novedad_personal nov
    
    where 
    nov.estado = 1
    and nov.id_novedad = 8
    and (
        (select fecha_ini from no_periodo_proy where id_periodo = $id_periodo) between nov.fecha_inicial and nov.fecha_terminacion
        or    
        (select fecha_fin from no_periodo_proy where id_periodo = $id_periodo) between nov.fecha_inicial and nov.fecha_terminacion
    )

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


                    /*
                     * Tag_retro para cuando es retroactivo, para retencion tiene encuenta todo el mes con lo del retroactivo - 20150610
                     * Se coloca el orden de clase_fondo, para que tome primero salud y pension antes de ARL, ya que para LR toma dias trabajados en base a estos fondos - 20210203::LAVILA
                     */
                    $sql = <<<EOD
SELECT 
$salario_minimo as salario_minimo,
1 as tag,    
0 as tg_retro,
tab0.num_dias as num_dias, 
nvl(vac.num_dias_vac,0) as wdiasv,
tab0.porcentaje_func,
tab0.porcentaje_patrono,
tab0.aporte_func,
tab0.aporte_patrono,
tab0.id_tipo_doc,
tab0.num_doc, 
tab0.id_clase_fondo, 
tab0.id_concep_nomina, 
tab1.id_agrup_concepto, 
tab2.id_meses, 
tab2.id_anhos,
tab0.tarifa, 
tab0.id_liquida_aporte_proy, 
tab0.id_periodo as periodo,
nvl(kardexlr.cantidad,0) as cantidad_licrem                                
                                
FROM NO_LIQUIDA_APORTE_PROY tab0
LEFT JOIN NO_CLASE_FONDO tab1 ON tab1.id_clase_fondo = tab0.id_clase_fondo
LEFT JOIN no_periodo_proy tab2 ON tab2.id_periodo = tab0.id_periodo

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_proy where id_periodo =  $id_periodo))),0) as dias,
        nvl(sum( novvac.fecha_fin - novvac.fecha_ini + 1),0) as dias_vac,
        nvl(sum(DIAS_RANGO_MES_SIN_TREINTAYUNO(novvac.fecha_ini,novvac.fecha_fin,(select id_meses from no_periodo_proy where id_periodo =  $id_periodo))),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
        (select id_anhos || lpad(id_meses,2,'0') as vigper from no_periodo_proy where id_periodo = novvac.id_periodo) <= (select id_anhos || lpad(id_meses,2,'0') as vigper from no_periodo_proy where id_periodo = $id_periodo)
        and (
          novvac.fecha_ini between to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy 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_proy 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_proy 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_proy where ID_PERIODO = $id_periodo) ,'dd/mm/yyyy') )) 
          or

          to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy 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_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy') )) between novvac.fecha_ini and novvac.fecha_fin
          or 
          novvac.id_periodo = $id_periodo
        )
        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  
                  
/*Se coloca dias para licencia remunerada, resta en riesgo ARL - 20190214*/   
/*Licencia remunerada descuenta todos los días de meses anteriores - 20190905*/                     
left join
(

    select 
    tab.num_doc,
    nvl(sum(case when tab.cant_dia_riesgo > 0 then tab.cant_dia_riesgo else 0 end),0) as cantidad_ant,
    nvl(sum(case when tab.cant_dia_riesgo_completo > 0 then tab.cant_dia_riesgo_completo else 0 end),0) as cantidad
    from(

            select 

            nvl(sum( dias_rango_mes_sin_treintayuno(tab0.fecha_ini,tab0.fecha_fin, (select id_meses from no_periodo_proy where id_periodo = $id_periodo) ) ),0) as cant_dia_riesgo,
            nvl(sum( fecha_rango_sin_treintayuno(tab0.fecha_ini,tab0.fecha_fin ) ),0) as cant_dia_riesgo_completo,

            tab1.dias_patrono,
            tab0.prorroga,

            tab0.num_doc, 
            sum(tab0.num_dias) CANTIDAD_1,
            nvl(sum( dias_rango_mes(tab0.fecha_ini,tab0.fecha_fin, (select case when id_meses = 1 then 12 else id_meses - 1 end id_meses from no_periodo_proy where id_periodo = $id_periodo) ) ),0) as CANTIDAD_2,

            nvl(sum( ( case when tab0.fecha_fin >= to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy')
            then to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy') - 1 else tab0.fecha_fin end ) - tab0.fecha_ini + 1 ),0) as CANTIDAD

            from no_novedad_kardex tab0
            left join no_tip_nov_ka tab1 ON tab1.id_tip_nov_ka = tab0.id_tip_nov_ka

            where tab1.id_tip_nov_ka in (select id_tip_nov_ka from no_tip_nov_ka where tiempo_remunerado = 1) and tab0.estado = 1 

            and ( 
                tab0.fecha_inc between to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy 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_proy WHERE ID_PERIODO = $id_periodo) ,'dd/mm/yyyy') )) 
                /*
                Validacion para que tome el registro en el periodo de la novedad - 20130820
                */
                or tab0.id_periodo = $id_periodo
            )

            group by tab0.num_doc, tab0.prorroga, tab1.dias_patrono, tab0.fecha_ini, tab0.fecha_fin

    )tab
    group by
    tab.num_doc      

)kardexlr ON kardexlr.num_doc = tab0.num_doc
                                
WHERE tab0.ID_PERIODO = $id_periodo
$whereFuncionarioNumDoc $whereFuncionarioTipoDoc 
and tab0.tipo_planilla = 'A'                    
                                
order by
tab0.num_doc,
tab0.id_clase_fondo    
EOD;


                    /**
                     * Recorre los registros de no_liquida_aporte_proy
                     */
                    $records = CN_TABLE::executeSQL($sql);


                    $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("[generar_aportes] nom_conceptos_a_procesar: " . $nom_conceptos_a_procesar);

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

                    foreach ($records as $record) {


                        /*
                         * Variables del record
                         */
                        $id_liquida_aporte = $record['id_liquida_aporte_proy'];
                        $id_tipo_doc = $record['id_tipo_doc'];
                        $num_doc = $record['num_doc'];
                        $id_clase_fondo = $record['id_clase_fondo'];
                        $id_concep_nomina = $record['id_concep_nomina'];
                        $id_agrup_concepto = $record['id_agrup_concepto'];
                        $id_meses = $record['id_meses'];
                        $id_anhos = $record['id_anhos'];
                        $tarifa = $record['tarifa'];
                        $aporte_func = $record['aporte_func'];
                        if ($id_clase_fondo == 1 || $id_clase_fondo == 2) {
                            $dias_trabajado = $record['num_dias']; //Se toman los dias que trabajo en el mes, segun salud y pension - 20190703
                        }

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


                        $arrayParametros = array();

                        $valor_base_vac = 0;

                        //Dias para vacaciones
                        //Se cambia a rango dias sin 31 - 20130705
                        //Se anexa para el operador la suma o resta - 20130726
                        //Se anexa filtro de rango de fechas para tomar solo vacaciones que afecten el periodo  - 20140122
                        //COL - Sandra guerra Julio Vac SegSocial - Dias de agosto + julio, le falta que tome los dias completos - 20140915
                        //Optener el periodo anterior segun fecha inicial de las vacaciones - 20191220          
                        //Para cev se quita que tome num_dias_vac y tag_dias_vac_ant para solo si tuvo dias anterioes de vac - 20210201::LAVILA          
                        //Sql
                        $sql = <<<EOD
select 

tab.id_tipo_doc,                  
tab.num_doc,
/*
dias,
dias_vac,
num_dias_vac,*/
sum( nvl(tab.dias_vaciones,0) + nvl(tab.dia_ant,0)) as num_dias_vac_ant,

sum(nvl(tab.dia_ant,0)) as tag_dias_vac_ant,                                    
case when $entidadCliente in (8,9)
    then sum( nvl(tab.dias_vaciones,0) - nvl(tab.dias_feb,0))
    else sum( nvl(tab.dias_vaciones,0) + nvl(tab.dia_ant,0) - nvl(tab.dias_feb,0)) end as num_dias_vac, 
                                    
min(tab.fecha_ini) as fecha_ini,
max((SELECT
    max(perd.id_periodo)
FROM no_periodo_proy perd where perd.id_tipo_periodo = 1 and perd.fecha_fin < tab.fecha_ini)) as periodo_ant

from(

    select 
    min(novvac.fecha_ini) as fecha_ini,
    novvac.id_tipo_doc,                  
    novvac.num_doc,
    nvl(sum(dias_rango_mes(novvac.fecha_ini,novvac.fecha_fin,(select id_meses 
        from no_periodo_proy where id_periodo =  $id_periodo))),0) as dias,
    nvl(sum( novvac.fecha_fin - novvac.fecha_ini + 1),0) as dias_vac,
    nvl(sum(DIAS_RANGO_MES_SIN_TREINTAYUNO(novvac.fecha_ini,novvac.fecha_fin,(select id_meses from no_periodo_proy where id_periodo =  $id_periodo))),0) as num_dias_vac,
        tipnov.operador,

        case  when tipnov.operador  = 1 
        then nvl(sum(dias_rango_mes_sin_treintayuno(novvac.fecha_ini,novvac.fecha_fin,(select id_meses from no_periodo_proy where id_periodo =  $id_periodo))),0) 
        else nvl(sum(dias_rango_mes_sin_treintayuno(novvac.fecha_ini,novvac.fecha_fin,(select id_meses from no_periodo_proy where id_periodo =  $id_periodo))),0) * (-1)
        --else nvl(sum( novvac.fecha_fin - novvac.fecha_ini + 1),0) * (-1)
        end as dias_vaciones,
            
        case when novvac.id_periodo != $id_periodo then 0 else nvl(sum(dias_rango_mes_sin_treintayuno(novvac.fecha_ini,novvac.fecha_fin,
        
          case when (select id_meses from no_periodo_proy where id_periodo =  $id_periodo) != 1 then (select id_meses from no_periodo_proy where id_periodo =  $id_periodo)-1 
              else 12 end  
          
        )),0) end as dia_ant,
                                
        --Para el mes de febrero se restan dias 2 o 1 segun año, ya que estos dias se pagan como laborados - 20170314                 
        (case 
           when (select id_meses from no_periodo_proy where id_periodo = $id_periodo) = 2 and max(novvac.fecha_ini) < (select fecha_fin from no_periodo_proy where id_periodo = $id_periodo) and max(novvac.fecha_fin) > (select fecha_fin from no_periodo_proy where id_periodo = $id_periodo) 
           then case when to_number((select to_char(fecha_fin,'dd') from no_periodo_proy where id_periodo = $id_periodo)) = 28 then 2 else 1 end
           else 0 end) * (case  when tipnov.operador  = 1 then 1 else (-1) end) as dias_feb
            
   
    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 (select id_anhos || lpad(id_meses,2,'0') from no_periodo_proy where id_periodo = novvac.id_periodo) <= (select id_anhos || lpad(id_meses,2,'0') from no_periodo_proy where id_periodo = $id_periodo)
    and novvac.num_doc = $num_doc
    and
    ( 
          novvac.fecha_ini  between to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy 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_proy 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_proy 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_proy WHERE ID_PERIODO = $id_periodo) ,'dd/mm/yyyy') )) 
        or
          to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy 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_proy 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,
    tipnov.operador, novvac.id_periodo
)tab 

group by tab.id_tipo_doc, tab.num_doc
EOD;

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

                        /*
                         * Calcular IBC para vacaciones
                         */
                        // Se agrega al calculo la formula (({A39}/30)*$wdiasv)) - 20130517
                        // Toma los dias de vacaciones para el mes a liquidar
                        $wdiasv = 0;
                        $periodo_ant = null;
                        $record['tag_dias_vac_ant'] = 0;
                        if (count($record_vac) > 0) {
                            $wdiasv = $record_vac[0]['num_dias_vac'];
                            $periodo_ant = $record_vac[0]['periodo_ant'];
                            $record['tag_dias_vac_ant'] = $record_vac[0]['tag_dias_vac_ant'];
                        }
                        //Validar que hay dias
                        if ($wdiasv != 0) {
                            //Optener el periodo anterior segun fecha inicial de las vacaciones - 20191220  
                            if ($periodo_ant != null && $aplica_ibc_ant_vac == 1) {

                                $sql = <<<EOD
SELECT
    *
FROM no_liquida_aporte_proy
where
id_periodo = $periodo_ant
and id_tipo_doc = $id_tipo_doc
and num_doc = $num_doc
and id_clase_fondo = 2
and tipo_planilla = 'A' 
EOD;

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

                                $valor_liqapo = $record_liqapo[0]['valor_base'];

                                $formula = "(($valor_liqapo/30)*$wdiasv)";
                            } else {
                                $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, $record, $record_consulta, $vals_calc);

                            $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
                            //Se quita redondeo a la milesima - 20130827
                            $valor_base_vac = round($result, 0);
                        }

                        $this->logMessage("[Liquidación Vac] Valor base de IBC vacaciones: " . $valor_base_vac);
                        $this->logMessage("---------------------------------------------------------------------");


                        // 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("[generar_aportes] Existen aportes.");

                        $arrayParametros = array();

                        // Se agrega al calculo la formula (({A39}/30)*$wdiasv)) - 20130517
                        // Toma los dias de vacaciones para el mes a liquidar
                        $wdiasv = $record['wdiasv'];
                        $num_dias = $record['num_dias'];
                        $cantidad_licrem = $record['cantidad_licrem'];

                        /*
                         * Solo para ARP id_clase_fondo 3 no se tiene encuenta el tiempo de vacaciones - 20130917
                         * Para el IBC de Riesgos no se tiene en cuenta la novedad de vacaciones, el valor base y los días deben ser sin contemplar estos días. - 20130917
                         * Para los parafiscales tampoco se tiene encuenta el valor base de vacaciones - 20131023
                         * Para los parafiscales no completa dias de vacaciones - 20141124
                         */
                        if ($id_clase_fondo == 3) {
                            /**
                             * Segun dias de licrem si tiene novedad - 20190214
                             */
                            if ($cantidad_licrem != 0) {
                                /*
                                 * Se toman los dias que trabajo en el mes - 20190703
                                 * Se agrega para que si fue de vacaciones, tome $wdiasv a los dias de trabajo y no reste doble vez los dias - 20191030
                                 */
                                //$formula = "( ({A$id_agrup_concepto}+(0)) / 30 * $num_dias)";
                                $formula = "( ({A$id_agrup_concepto}+(0)) / ($dias_trabajado - $wdiasv) * $num_dias)";
                            } else {
                                $formula = "({A$id_agrup_concepto}+(0))";
                            }
                        } elseif ($id_clase_fondo == 1 || $id_clase_fondo == 2) {
                            $formula = "({A$id_agrup_concepto}+($valor_base_vac))";
                        } else {
                            $formula = "({A$id_agrup_concepto}+(0))";
                        }
                        $this->logMessage("[Liquidación Agrupación] Formula Inicial: " . $formula);

                        /*
                         * Reemplaza en la consulta los filtros y valores del SQL, que vienen en el record
                         * Ejemplo: select raz_soc from id_cia where id_cia = $id_cia
                         * Reemplaza $id_cia por el valor en el record
                         */
                        $formula = CN_TABLE::reemplazoConsulta($formula, $record);
                        $this->logMessage("[Liquidación Agrupación] Formula consulta los filtros: " . $formula);

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

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

//        var_dump($vars);

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

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



                        /*
                         * Cambio de A1 por relacion con los conceptos C1
                         * Ejemplo: 'A1' => '0'
                         */
//                            $agrup = $this->reemplazoAgrupacion($id_agrup_concepto);
//                            $this->logMessage("[Liquidación Agrupación] Agrupacion: " . $agrup);


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


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


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

                        //$valor_base = round($result, -3);
                        if ($id_clase_fondo == 1 || $id_clase_fondo == 2 || $id_clase_fondo == 3) {
                            //Ya no se redondea IBC al mil, sino hacia arriba el valor - 20170307
                            //$valor_base = CN_TABLE::ceiling($result, 1000);
                            $valor_base = CN_TABLE::ceiling($result, 1);
                        } else {
                            //Ya no se redondea IBC al mil, sino hacia arriba el valor - 20170307
                            $valor_base = CN_TABLE::ceiling($result, 1);
                        }

                        /*
                         * Base del valor smlv por los dias del funcionario - 20130625
                         * Valor sin redondeo - 20130923
                         * Se toma mejor dias trabajos segun pension y salud, y no los $num_dias de aportes - 20210203:LAVILA
                         */
//                            $valor_base_smlv = round(($salario_minimo / 30) * $num_dias, -3);
                        $valor_base_smlv_arl = ($salario_minimo / 30) * $num_dias;
                        $valor_base_smlv = ($salario_minimo / 30) * $dias_trabajado;

                        $tag_valor_base = true;

                        //Valor base no puede superar 25 salarios minimos
                        $this->logMessage("[Liquidación Agrupación] Valor base25: " . $valor_base . " - Valor_base_smlv25:" . $valor_base_smlv);
                        $tag_valor_base_tope = false;
                        if ($valor_base > ($valor_base_smlv * 25)) {
                            $this->logMessage("[Liquidación Agrupación] Valor base no puede superar 25 salarios minimos. Valor_base_smlv:" . $valor_base_smlv);
                            /**
                             * El IBC opara parafiscales (CCF, ICBF y SENA) no tiene límite.
                             * Está limitando el IBC de parafiscales a 25 smlv, este tope sí es valido pára salud, pensión y ARL. - 20140814
                             * Redondeo al mil mas cercano - 20160519
                             */
                            if ($id_clase_fondo == 1 || $id_clase_fondo == 2 || $id_clase_fondo == 3) {
                                $valor_base = ($valor_base_smlv * 25);
                                //Extraemos la parte entera - 20141027
                                $valor_base_mod = fmod($valor_base, 1);
                                $valor_base = $valor_base - $valor_base_mod;
                                $tag_valor_base = false;

                                //$valor_base = round(($valor_base_smlv * 25) - 1, -3);
                                /**
                                 * Maximo tope permitido por ley - 20160519
                                 * Se activa Maximo tope permitido por ley sin redondeo/ceil - 20170718
                                 */
                                //$salario_minimo_tope = round(($salario_minimo * 25), -3);
                                //$salario_minimo_tope = CN_TABLE::ceiling(($salario_minimo * 25), 1000);
                                $salario_minimo_tope = CN_TABLE::ceiling(($salario_minimo * 25), 1);
                                if ($valor_base > $salario_minimo_tope) {
                                    $valor_base = $salario_minimo_tope;
                                    $tag_valor_base_tope = true;
                                } else {
                                    //Redondeo al mil mas cercano - 20160519
                                    //Sin redondeo - 20171018
                                    //$valor_base = round($valor_base, -3);
                                    //$valor_base = CN_TABLE::ceiling($valor_base, 1000);
                                    $valor_base = CN_TABLE::ceiling($valor_base, 1);
                                }
                            }
                        }
                        //Valida salario minimo - 20130523
                        elseif ($valor_base < $valor_base_smlv) {
                            //Solo para ARP id_clase_fondo 3 - 20130523
                            if ($id_clase_fondo == 3) {
                                $this->logMessage("[Liquidación Agrupación] ARP id_clase_fondo 3.");
                                //$valor_base = round($valor_base_smlv, -3);
                                //$valor_base_smlv = round($valor_base_smlv_arl, 0, PHP_ROUND_HALF_UP);//Se cambio ya que no toma correcto para inci, se toma base calculado - 20210219:LAVILA
                                $valor_base_smlv = round($valor_base, 0, PHP_ROUND_HALF_UP);
                                //$valor_base = CN_TABLE::ceiling($valor_base_smlv, 1000);
                                //Ya no se redondea valor de riesgo -- 20170307
                                $valor_base = CN_TABLE::ceiling($valor_base_smlv, 1);
                            }
                        }

                        $this->logMessage("[Liquidación Agrupación] Valor base: " . $valor_base . " - Valor_base_smlv:" . $valor_base_smlv);

                        /**
                         * Validar si se redondea valor o se deja valor entero del resultado - 20141027
                         */
                        if ($tag_valor_base) {
                            //round ( $valor_base * tarifa / 100 , -2)
                            $valor_calculo = ( $valor_base * $tarifa / 100 );
                            //Redondeo con ceiling - 20170223
                            //$valor_calculo = round($valor_calculo, 0, PHP_ROUND_HALF_UP);
                            $this->logMessage("[Liquidación Agrupación] Valor PHP_ROUND_HALF_UP: " . $valor_calculo);
                            //Se trunca a dos decimales el resultado - 20171117
                            $valor_calculo = CN_TABLE::truncate($valor_calculo, 2);
                            $valor_calculo = CN_TABLE::ceiling($valor_calculo, 100);
                            $this->logMessage("[Liquidación Agrupación] Valor ceiling: " . $valor_calculo);
                            //Proceso para calcular el total del aporte redondeado a la centena
                            /*
                              if (($valor_calculo + 50) == round($valor_calculo, -2)) {
                              $valor_calculo = $valor_calculo - 50;
                              } else {
                              $valor_calculo = round($valor_calculo, -2);
                              } */
                        } else {

                            $valor_calculo = ( $valor_base * $tarifa / 100 );
                            //Extraemos la parte entera 
                            $valor_calculo_mod = fmod($valor_calculo, 1);
                            $valor_calculo = $valor_calculo - $valor_calculo_mod;
                            //Redondeo al cien mas cercano - 20160519
                            //$valor_calculo = round($valor_calculo, -2);
                            $valor_calculo = CN_TABLE::ceiling($valor_calculo, 100);

                            //Tope maximo de ley no redondea, solo los decimales - 20160519
                            if ($id_clase_fondo == 3) {
                                $this->logMessage("[Liquidación Agrupación] Tope maximo de ley no redondea, solo los decimales. Valor_base::" . $valor_base);
                                if ($tag_valor_base_tope) {
                                    $valor_calculo_tope = ( $valor_base * $tarifa / 100 );
                                    $valor_calculo = ceil($valor_calculo_tope);
                                    $this->logMessage("[Liquidación Agrupación] Tope maximo de ley no redondea, solo los decimales. Valor_calculo::" . $valor_calculo);
                                }
                            }
                        }

                        $aporte_func = $aporte_func;


                        /*
                         * Actualizar registro aporte
                         * Se calcula el valor del patrono, valor total aporte calculado menos el aporte funcionario
                         * Cuando el IBC  de cualquier tipo de aporte de NEGATIVO  inmediatamente este valor debe ser (0),   
                         * DIAS DE APORTE (0)  Y VALOR DE APORTE (0) - 20150205
                         */
                        if ($valor_base < 0) {

                            //sentencia sql
                            $sql = <<<EOD
update NO_LIQUIDA_APORTE_PROY set valor_base = 0
        , aporte_patrono =  0
            , aporte_func =  0
                , num_dias =  0
    where id_liquida_aporte_proy = $id_liquida_aporte 
EOD;
                        } else {
                            /*
                             * NOM-115 <-> SGC::Nomina - Autoliquidación de Aportes, solo para parafiscales - 20150430
                             * NOM-464 <-> SGC::Nomina - Se coloca validacion para dias igual a 0 - 20170123
                             */
                            if (($valor_base == 0 || $num_dias == 0 ) && $id_clase_fondo != 1 && $id_clase_fondo != 2 && $id_clase_fondo != 3) {
                                //sentencia sql
                                $sql = <<<EOD
update NO_LIQUIDA_APORTE_PROY set valor_base = 0
        , aporte_patrono =  0
            , aporte_func =  0
                , num_dias =  0
    where id_liquida_aporte_proy = $id_liquida_aporte 
EOD;
                                //ejecuta y obtiene el resultado del sql
                                CN_TABLE::executeSQL($sql);
                            } else {
                                //sentencia sql
                                $sql = <<<EOD
update NO_LIQUIDA_APORTE_PROY set valor_base = $valor_base
        , aporte_patrono =  case when porcentaje_patrono > 0 then $valor_calculo - $aporte_func else 0 end 
            , aporte_func =  case when porcentaje_patrono = 0 then $valor_calculo else $aporte_func end
    where id_liquida_aporte_proy = $id_liquida_aporte 
EOD;
                                //ejecuta y obtiene el resultado del sql
                                CN_TABLE::executeSQL($sql);
                            }
                        }


                        /*
                         * Valida si es fondo de solidaridad
                         */
                        if ($id_clase_fondo == 1 && $tarifa == 1) {
                            $this->logMessage("[Liquidación Agrupación] Valida si es fondo de solidaridad.");
//                        if (true) {

                            $valor_base_vac = 0;
                            $array_valor_base = $this->valor_base_fsp_aportes($valor_base, $salario_minimo, $valor_base_vac);
                            $valor_fsp = $array_valor_base['valor_fsp'];
                            $porcentaje_fsp = $array_valor_base['porcentaje_fsp'];

                            //Se redondea el 5 hacia arriba - 20140522
                            //Se elimina redondeo hacia arriba - 20140730 : $valor_base_fsp = CN_TABLE::redondeoValor((($valor_base +1) * 0.5 / 100), -2);
                            //$tag_valor_base_tope si supera el ope no redondea a 100, y la diferencia la resta de $valor_fsp - 20160816
                            if ($tag_valor_base_tope) {
                                $valor_base_fsp = CN_TABLE::redondeoValor((($valor_base) * 0.5 / 100), 0);
                                //$valor_base_fsp_dif = CN_TABLE::redondeoValor((($valor_base) * 0.5 / 100), -2) - $valor_base_fsp;
                                //Redondeo es hacia arriba - 20170303
                                $valor_base_fsp_dif = CN_TABLE::ceiling((($valor_base) * 0.5 / 100), 100) - $valor_base_fsp;
                                $valor_fsp = $valor_fsp - $valor_base_fsp_dif;
                            } else {
                                //$valor_base_fsp = CN_TABLE::redondeoValor((($valor_base) * 0.5 / 100), -2);
                                //Redondeo es hacia arriba - 20170303
                                $valor_base_fsp = CN_TABLE::ceiling((($valor_base) * 0.5 / 100), 100);
                            }

                            //Validar que el valor fsp es mayor a cero
                            if ($valor_fsp > 0) {

                                /*
                                 * Actualizar valor aporte_func
                                 */
                                //sentencia sql
                                $sql = <<<EOD
update NO_LIQUIDA_APORTE_PROY set aporte_func =  $valor_fsp
        , porcentaje_func = $porcentaje_fsp
        , tarifa = $porcentaje_fsp
            , valor_base_fsp = $valor_base_fsp 
    where id_liquida_aporte_proy = $id_liquida_aporte 
EOD;
                                //ejecuta y obtiene el resultado del sql
                                CN_TABLE::executeSQL($sql);
                            } else {

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


//                                MemcacheHandler::getInstance()->set($progress_key, 100);
//                                exit("-");
                        }

                        $i++;
                    }
                    MemcacheHandler::getInstance()->set($progress_key, 98);

                    /*
                     * (SGC-1, ANM-2, SGR-3, CYC-4, COL-5, INCI-6, LOCAL-7)
                     */
                    $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++;
                    }

                    /**
                     * SQL para optener registros de aportes licencia no remunerada - 20131119
                     * No debe llevar registro de pension de aportes licencia no remunerada - 20140729
                     * Se coloca que para CYC, se toma el valor de pension para lic no remunerada - 20170131
                     * Se corrige por dias de retiro - 20170228
                     * Redondeo es hacia arriba y por metodo de ceil - 20170303
                     * La base no se redondea al mil - 20171219
                     * Se coloca que para SGC - 20180808
                     * Se activa para todos - 20190213
                     */
                    //Sql
                    $sql = <<<EOD
SELECT
    tab3.c37_num_dias as num_dias_licnorem,
    /*case when $entidadCliente in (1,4)
        then tab3.PENSION + tab3.salud
        else tab3.salud end as aporte_patrono_licnorem,*/                                
--    tab3.salud as aporte_patrono_licnorem,
    tab3.PENSION + tab3.salud as aporte_patrono_licnorem,
    tab3.PENSION,
    tab3.salud,
    tab3.id_periodo,tab3.id_clase_fondo,
    tab3.id_mae_fondos,
    tab3.id_concep_nomina,
    tab3.codigo,tab3.fondo,
    tab3.num_doc,
    tab3.id_tipo_doc

        FROM(

        select
                                
        tab3.c37_num_dias,
                                
        case when tab1.id_clase_fondo =1 then nvl((case when  tab1.porcentaje_func != 1  then tab3.c47_pension else 0 end),0)
        when tab1.id_clase_fondo = 2 then 0
        when tab1.id_clase_fondo = 3 then 0
        else 0 end AS PENSION,
        
         case when tab1.id_clase_fondo =1 then 0
        when tab1.id_clase_fondo = 2 then nvl(tab3.c55_salud,0) 
        when tab1.id_clase_fondo = 3 then 0
        else 0 end AS salud
        ,
        
        
        tab1.id_periodo as id_periodo,
        tab1.id_clase_fondo,
        tab1.id_concep_nomina,
        tab2.id_mae_fondos,
        tab2.codigo as codigo,
        tab1.id_tipo_doc,
        tab1.num_doc,
        tab2.num_doc as num_doc_mae,
        tab2.razon_social AS FONDO,
                                
        case when tab1.id_clase_fondo =1 then tab1.aporte_func
        when tab1.id_clase_fondo = 2 then 0
        when tab1.id_clase_fondo = 3 then 0
        else 0 end AS APORTE_FUNC_PENSION,
        case when tab1.id_clase_fondo =1 then tab1.aporte_patrono
            +nvl((case when  tab1.porcentaje_func != 1  then tab3.c47_pension else 0 end),0)
        when tab1.id_clase_fondo = 2 then 0
        when tab1.id_clase_fondo = 3 then 0
        else 0 end AS APORTE_PATRONO_PENSION,
        case when tab1.id_clase_fondo =1 then tab1.aporte_patrono+tab1.aporte_func
            +nvl((case when  tab1.porcentaje_func != 1  then tab3.c47_pension else 0 end),0)
        when tab1.id_clase_fondo = 2 then 0
        when tab1.id_clase_fondo = 3 then 0
        else 0 end AS TOTAL_PENSION,

        case when tab1.id_clase_fondo =1 then 0
        when tab1.id_clase_fondo = 2 then tab1.aporte_func
        when tab1.id_clase_fondo = 3 then 0
        else 0 end AS APORTE_FUNC_SALUD,
        case when tab1.id_clase_fondo =1 then 0
        when tab1.id_clase_fondo = 2 then tab1.aporte_patrono+nvl(tab3.c55_salud,0)
        when tab1.id_clase_fondo = 3 then 0
        else 0 end AS APORTE_PATRONO_SALUD,
        case when tab1.id_clase_fondo =1 then 0
        when tab1.id_clase_fondo = 2 then tab1.aporte_patrono+tab1.aporte_func+tab1.upc_adicio+nvl(tab3.c55_salud,0)
        when tab1.id_clase_fondo = 3 then 0
        else 0 end AS TOTAL_SALUD,

        case when tab1.id_clase_fondo =1 then 0
        when tab1.id_clase_fondo = 2 then tab1.upc_adicio
        when tab1.id_clase_fondo = 3 then 0
        else 0 end AS UPC_ADICIO,

        case when tab1.id_clase_fondo =1 then 0
        when tab1.id_clase_fondo = 2 then 0
        when tab1.id_clase_fondo = 3 then tab1.aporte_patrono
        else 0 end AS APORTE_PATRONO_ARP,

        case when tab1.id_clase_fondo =1 then 0
        when tab1.id_clase_fondo = 2 then 0
        when tab1.id_clase_fondo = 3 then tab1.aporte_patrono
        else 0 end AS TOTAL_ARP,

        case when tab1.id_clase_fondo =1 then 0
        when tab1.id_clase_fondo = 2 then 0
        when tab1.id_clase_fondo = 3 then 0
        else tab1.aporte_patrono end AS PARAFISCALES


        from no_liquida_aporte_proy tab1

        left join no_mae_fondos tab2 ON tab2.id_mae_fondos = tab1.id_mae_fondos

        left join (
        select
licnoremun.*
from
(

select

tab0.num_doc AS C4_num_doc,
                                
--30-nvl(salud1.dias,0) - nvl(30- case when nvl( to_number(to_char(tab5.fecha_termina,'dd')) ,0) != 31 then nvl( to_number(to_char(tab5.fecha_termina,'dd')) ,0) else 30 end ,0)  as c37_num_dias,
nvl(30-nvl(pension2.dias-nvl(kardex4.cantidad,0),0)- (tab5.dias_retiro),0) as c37_num_dias, 
    
--Se forza redondeo hacia arriba - 20170307
--La base no se redondea al mil - 20171219
ceil( ( ( round( nvl(tab6.asignacion_basica,0)/30*(30-nvl(pension2.dias-nvl(kardex4.cantidad,0),0)- (tab5.dias_retiro))  )
 * nvl( case when ( max_marca = 0 or max_marca_susinc = 1 ) then pension2.tarifa else 0 end ,0) ) ) /100)*100  as c47_pension,

ceil( ( ( round( nvl(tab6.asignacion_basica,0)/30*(30-nvl(salud1.dias-nvl(kardex4.cantidad,0),0)- (tab5.dias_retiro))  )
 * nvl( case when ( max_marca = 0 or max_marca_susinc = 1 ) then salud1.tarifa else 0 end ,0) ) ) /100)*100  as c55_salud

from no_estado_func_proy_v tab0

left join centro_operacion tab1 ON tab1.id_cen_op = tab0.id_cen_op
left join departamento tab2 ON tab2.id_depto = tab1.id_depto
left join municipios tab3 ON tab3.codmun = tab1.codmun
left join no_datos_funcionario_v tab4 ON tab4.id_tipo_doc = tab0.id_tipo_doc and tab4.num_doc = tab0.num_doc

--left join no_nombramiento tab5 on tab5.id_tipo_doc = tab0.id_tipo_doc and tab5.num_doc = tab0.num_doc
left join (
  SELECT
   case when aut.fecha_termina
  between to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy 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_proy WHERE ID_PERIODO = $id_periodo) ,'dd/mm/yyyy') )) 
  then (30 - to_char(aut.fecha_termina,'dd') ) else 0 end as dias_retiro,                                
   aut.*,
   ROW_NUMBER() OVER (
    partition by aut.num_doc
    ORDER BY aut.estado DESC
   ) AS rn
  from no_nombramiento aut
)tab5
on tab5.id_tipo_doc = tab0.id_tipo_doc
and tab5.num_doc = tab0.num_doc
and tab5.rn = 1

--left join no_dp_v tab6 on tab6.id_dp = tab0.id_dp
/*
Se cambia para tomar valor de concepto_periodo para el concepto_nomina 1001 del periodo de tipo mensual o nomina adicional - 20130827
*/
left join(

    select * from(
            select
            concep.id_tipo_doc,
            concep.num_doc,
            concep.valor as asignacion_basica ,

             ROW_NUMBER() OVER (
              PARTITION BY concep.num_doc
              order by per.id_tipo_periodo asc, concep.fecha_hasta desc
             ) as rn

            from no_concepto_periodo_proy concep

            join no_periodo_proy per
            on concep.PERIODO = per.id_periodo

            where
            concep.id_concep_nomina = (select id_concep_basica from no_param_concep)

            and (per.id_tipo_periodo = 1 or per.id_tipo_periodo = 2)
            and (select id_anhos || lpad(id_meses,2,'0') from no_periodo_proy where id_periodo = concep.PERIODO) = (select id_anhos || lpad(id_meses,2,'0') from no_periodo_proy where id_periodo = $id_periodo)
    )where rn = 1

)tab6 ON tab6.id_tipo_doc = tab0.id_tipo_doc and tab6.num_doc = tab0.num_doc
and tab6.rn = 1


left join
(
    select tab0.num_doc, count(tab0.id_novedad_kardex) CANTIDAD, max(tab1.suspension) as max_marca
    from no_novedad_kardex tab0
    left join no_tip_nov_ka tab1 ON tab1.id_tip_nov_ka = tab0.id_tip_nov_ka
    where tab1.afecta_antigu = 1 and tab0.estado = 1
     /*
    and (
      tab0.fecha_ini between to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy 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_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy') ))
      or
      tab0.fecha_fin between to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy 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_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy') ))
      or
      tab0.id_periodo = $id_periodo
    )*/
    and
    (select id_anhos || lpad(id_meses,2,'0') as vigper from no_periodo_proy where id_periodo = tab0.id_periodo) <= (select id_anhos || lpad(id_meses,2,'0') as vigper from no_periodo_proy where id_periodo = $id_periodo)
    and (
      to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy') between tab0.fecha_ini and tab0.fecha_fin
      or
      trunc(last_day( to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy') )) between tab0.fecha_ini and tab0.fecha_fin
      or
      tab0.id_periodo = $id_periodo
      or
      tab0.fecha_fin between to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy 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_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy') ))
    )
    group by tab0.num_doc
)kardex1 ON kardex1.num_doc = tab0.num_doc

/*
Se cambia de id-4 por atributo en  la tabla no_tip_nov_ka de afecta_riesgo, para validar cuales afectan en los dias de ARP-ARL - 20130919
*/
left join
(
    select tab0.num_doc, sum(tab0.num_dias) CANTIDAD
    from no_novedad_kardex tab0
    left join no_tip_nov_ka tab1 ON tab1.id_tip_nov_ka = tab0.id_tip_nov_ka
    where tab1.afecta_riesgo = 1 and tab0.estado = 1 and tab0.fecha_inc between to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy 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_proy WHERE ID_PERIODO = $id_periodo) ,'dd/mm/yyyy') ))
    group by tab0.num_doc
)kardex4 ON kardex4.num_doc = tab0.num_doc

/*
Incapacidad -> Suspensión por Incapacidad  - 20150312
*/
left join
(
    select tab0.num_doc, count(tab0.id_novedad_kardex) as max_marca_susinc
    from no_novedad_kardex tab0
    left join no_tip_nov_ka tab1 ON tab1.id_tip_nov_ka = tab0.id_tip_nov_ka
    where tab1.afecta_antigu = 1 and tab0.estado = 1 
    and tab0.id_tip_nov_ka = (select no_param_concep.id_nov_ka_susinc from no_param_concep where no_param_concep.id_param_concep = 1)
     /*   
    and (
      tab0.fecha_ini between to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy 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_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy') )) 
      or
      tab0.fecha_fin between to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy 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_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy') )) 
      or 
      tab0.id_periodo = $id_periodo
    )*/
    and
    (select id_anhos || lpad(id_meses,2,'0') as vigper from no_periodo_proy where id_periodo = tab0.id_periodo) <= (select id_anhos || lpad(id_meses,2,'0') as vigper from no_periodo_proy where id_periodo = $id_periodo)
    and (
      to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy') between tab0.fecha_ini and tab0.fecha_fin
      or
      trunc(last_day( to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy') )) between tab0.fecha_ini and tab0.fecha_fin
      or 
      tab0.id_periodo = $id_periodo
    )
    group by tab0.num_doc
)kardex5 ON kardex5.num_doc = tab0.num_doc


left join
(
    select tab0.num_doc, sum(tab0.aporte_func) as aporte, sum(tab0.aporte_patrono) as aporte_patrono, max(tab0.num_dias) as dias, max(nvl(tab0.valor_base,0)) as ibc,
    max(tab0.tarifa)/100 as TARIFA/*, tab0.aporte_func AS APORTE*/
    from no_liquida_aporte_proy tab0
    where tab0.id_periodo = $id_periodo and tab0.id_clase_fondo = 1
    and tab0.tipo_planilla = 'A'
    group by tab0.num_doc
)pension1 ON pension1.num_doc = tab0.num_doc

left join
(
    select tab0.num_doc, sum(tab0.aporte_func) as aporte, sum(tab0.aporte_patrono) as aporte_patrono, max(tab0.num_dias) as dias, max(nvl(tab0.valor_base,0)) as ibc,
    max(tab0.porcentaje_patrono/100) as TARIFA--, tab0.aporte_func AS APORTE
    from no_liquida_aporte_proy tab0
    where tab0.id_periodo = $id_periodo and tab0.id_clase_fondo = 1 and tab0.porcentaje_patrono > 0 -- and  ( tab0.tarifa = 16 or tab0.tarifa = 26 )
    and tab0.tipo_planilla = 'A'
    group by tab0.num_doc
)pension2 ON pension2.num_doc = tab0.num_doc

left join
(
    select tab0.num_doc, sum(tab0.aporte_func) AS APORTE, sum(tab0.aporte_patrono) as aporte_patrono, sum(tab0.valor_base_fsp) as aporte_fsp, max(tab0.num_dias) AS DIAS, MAX(nvl(tab0.valor_base,0)) AS IBC/*,
    tab0.tarifa/100 as TARIFA, tab0.aporte_func AS APORTE*/
    from no_liquida_aporte_proy tab0
    where tab0.id_periodo = $id_periodo and tab0.id_clase_fondo = 1 and tab0.porcentaje_patrono = 0 
    and tab0.tipo_planilla = 'A'
    group by tab0.num_doc
)pension3 ON pension3.num_doc = tab0.num_doc

left join
(
    select tab0.num_doc, sum(tab0.aporte_func) AS APORTE, sum(tab0.aporte_patrono) as aporte_patrono, max(tab0.num_dias) AS DIAS, MAX(nvl(tab0.valor_base,0)) AS IBC,
    max(tab0.porcentaje_patrono)/100 as TARIFA/*, tab0.aporte_func AS APORTE*/
    from no_liquida_aporte_proy tab0
    where tab0.id_periodo = $id_periodo and tab0.id_clase_fondo = 2
    and tab0.tipo_planilla = 'A'
    group by tab0.num_doc
)salud1 ON salud1.num_doc = tab0.num_doc


WHERE tab0.periodo = $id_periodo
and (tab0.actual = 1 or
  ( tab0.actual = 0
    /*
    Se cambia fecha de termina(ultimo dia de trabajo) por fecha de retiro,
    para tener encuenta si trabajo en el periodo al menos 1 dia - 20130828
    */
    and tab5.fecha_retiro != to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy')
    and tab5.fecha_termina
  between to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy 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_proy WHERE ID_PERIODO = $id_periodo) ,'dd/mm/yyyy') ))
  )
)
and kardex1.cantidad > 0

)licnoremun

        )tab3 on tab3.C4_num_doc = tab1.num_doc
        
        
        
         )tab3

where tab3.id_periodo = $id_periodo
and (tab3.PENSION + tab3.salud) > 0
--and (tab3.salud) > 0
EOD;

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

                    foreach ($record_licnorem as $value) {

                        $aporte_patrono_licnorem = $value['aporte_patrono_licnorem'];
                        $num_dias_licnorem = $value['num_dias_licnorem'];
                        $id_tipo_doc = $value['id_tipo_doc'];
                        $num_doc = $value['num_doc'];
                        $id_clase_fondo = $value['id_clase_fondo'];
                        $id_mae_fondos = $value['id_mae_fondos'];
                        $id_concep_nomina = $value['id_concep_nomina'];
                        $id_periodo_filtro = $value['id_periodo'];

                        /*
                         * Actualizar liquida_aporte valor aporte_patrono_licnorem
                         */
                        //sentencia sql
                        $sql = <<<EOD
update no_liquida_aporte_proy set aporte_patrono_licnorem = $aporte_patrono_licnorem, num_dias_licnorem = $num_dias_licnorem
    where id_tipo_doc = $id_tipo_doc
    and num_doc = $num_doc
    and id_clase_fondo = $id_clase_fondo
    and id_mae_fondos = $id_mae_fondos
    and id_concep_nomina = $id_concep_nomina
    and id_periodo = $id_periodo_filtro
EOD;
                        //ejecuta y obtiene el resultado del sql
                        CN_TABLE::executeSQL($sql);
                    }

                    MemcacheHandler::getInstance()->set($progress_key, 99);

                    /**
                     * Recalculo de aporte patrono para parafiscales, 
                     * para personas con vacaciones, que su registro puede modificarse por el doble registro de la planilla - 20170309
                     * Se verifica que toma segun planilla los dias calculados y no siempre 30, se valida que tenga dias diferente de 0 - 20210423
                     */
                    //Ejecutar SQL
                    $sql = <<<EOD
select 
tab0.id_tipo_doc,
tab0.num_doc,
vaca.num_dias_vac,
liq.id_liquida_aporte_proy,
liq.id_clase_fondo,
liq.id_mae_fondos,
liq.id_concep_nomina,
liq.valor_base,
liq.num_dias,
liq.aporte_patrono,
liq.tarifa,
ceil( ( (liq.valor_base/liq.num_dias*vaca.num_dias_vac) *liq.tarifa/100) /100)*100 as aaa,
ceil( ( (liq.valor_base/liq.num_dias*(liq.num_dias-vaca.num_dias_vac)) *liq.tarifa/100) /100)*100 as bbb,
(ceil( ( (liq.valor_base/liq.num_dias*vaca.num_dias_vac) *liq.tarifa/100) /100)*100) + (ceil( ( (liq.valor_base/liq.num_dias*(liq.num_dias-vaca.num_dias_vac)) *liq.tarifa/100) /100)*100) as ccc,

( (ceil( ( (liq.valor_base/liq.num_dias*vaca.num_dias_vac) *liq.tarifa/100) /100)*100) + (ceil( ( (liq.valor_base/liq.num_dias*(liq.num_dias-vaca.num_dias_vac)) *liq.tarifa/100) /100)*100) ) - liq.aporte_patrono as dif

from no_estado_func_proy_v tab0

left join no_liquida_aporte_proy liq
on tab0.id_tipo_doc = liq.id_tipo_doc
and tab0.num_doc = liq.num_doc
and liq.id_periodo = $id_periodo

left join centro_operacion tab1 on tab1.id_cen_op = tab0.id_cen_op
left join departamento tab2 on tab2.id_depto = tab1.id_depto
left join municipios tab3 on tab3.codmun = tab1.codmun
left join no_datos_funcionario_v tab4 on tab4.id_tipo_doc = tab0.id_tipo_doc and tab4.num_doc = tab0.num_doc

--left join no_nombramiento tab5 on tab5.id_tipo_doc = tab0.id_tipo_doc and tab5.num_doc = tab0.num_doc
left join (
  select
  case when aut.fecha_termina
  between to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy 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_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy') )) 
  then (30 - to_char(aut.fecha_termina,'dd') ) else 0 end as dias_retiro,
   aut.*,
   row_number() over (
    partition by aut.num_doc
    order by aut.estado desc, aut.fecha_ingreso desc
   ) as rn
  from no_nombramiento aut
)tab5
on tab5.id_tipo_doc = tab0.id_tipo_doc 
and tab5.num_doc = tab0.num_doc
and tab5.rn = 1

/*
Se coloca, tab0.id_periodo en la agrupacion, para tener encuenta todas las novedades - 20161104
*/
left join
(
    select 

   id_tipo_doc,                  
   num_doc,
   sum( nvl(cantidad_vaciones,0) ) as cantidad,
   sum(dias_vaciones) as num_dias_vac,
   max(fecha_ini) as fecha_ini2, 
   case when max(fecha_ini) < to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy') then to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy') else max(fecha_ini) end as fecha_ini,
   max(fecha_fin) as fecha_fin2,
   case when max(fecha_fin) > trunc(last_day( to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy') ))  then trunc(last_day( to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy') ))  else max(fecha_fin) end as fecha_fin

   from( 

       select 
       
       case  when tipnov.operador  = 1 
                 then nvl(sum(dias_rango_mes_sin_treintayuno(tab0.fecha_ini,tab0.fecha_fin,(select id_meses from no_periodo_proy where id_periodo =  $id_periodo))),0) 
                 else nvl(sum(dias_rango_mes_sin_treintayuno(tab0.fecha_ini,tab0.fecha_fin,(select id_meses from no_periodo_proy where id_periodo =  $id_periodo))),0) * (-1)
                 end as dias_vaciones,
                 
       max(tab0.fecha_ini) as fecha_ini, max(tab0.fecha_fin) as fecha_fin,
       tab0.id_tipo_doc, tab0.num_doc, count(tab0.id_novedad_vac) cantidad,
        tipnov.operador,

        case  when tipnov.operador  = 1 
        /*then 1
        else (-1)*/
        then tab0.num_dias_vac
        else (-1 * tab0.num_dias_vac)
        --else nvl(sum( tab0.fecha_fin - tab0.fecha_ini + 1),0) * (-1)
        end as cantidad_vaciones

       from no_novedad_vac tab0
       left join no_tipo_nov_vac tipnov on tipnov.id_tipo_nov_vac = tab0.id_tipo_nov_vac
       
       where 
       --tipnov.ID_TIPO_NOV_VAC = 1 and
       tipnov.tiempo_liqui = 1 and
       (select id_anhos || lpad(id_meses,2,'0') from no_periodo_proy where id_periodo = tab0.id_periodo) <= (select id_anhos || lpad(id_meses,2,'0') from no_periodo_proy where id_periodo = $id_periodo) and
       
      /*
       tab0.fecha_ini between to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy 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_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy') )) 
       */
       /*Marca de vacaciones para todo el tiempo de duracion - 20130917*/
      ( 
          tab0.fecha_ini  between to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy 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_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy') )) 
          or
          tab0.fecha_fin  between to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy 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_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy') )) 
        or
          to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy') between tab0.fecha_ini and tab0.fecha_fin
          or
          trunc(last_day( to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy') )) between tab0.fecha_ini and tab0.fecha_fin
        )
        /* Valida que no sea un dia 31, ya que no se cuenta para liquidacion, que posea dias de vac en el periodo liquidado - 20141031 */        
        --and to_char(tab0.fecha_ini,'dd') != 31
        and dias_rango_mes_sin_treintayuno(tab0.fecha_ini,tab0.fecha_fin,(select id_meses from no_periodo_proy where id_periodo = $id_periodo)) > 0
        
        group by tab0.id_tipo_doc, tab0.num_doc,
       tipnov.operador, tab0.num_dias_vac, tab0.id_periodo

   ) 

   group by id_tipo_doc, num_doc
)vaca on vaca.num_doc = tab0.num_doc

where tab0.periodo = $id_periodo 
$whereFuncionarioNumDoc $whereFuncionarioTipoDoc 
and (tab0.actual = 1 or
  ( tab0.actual = 0 
    /*
    Se cambia fecha de termina(ultimo dia de trabajo) por fecha de retiro, 
    para tener encuenta si trabajo en el periodo al menos 1 dia - 20130828                    
    */
    and tab5.fecha_retiro != to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy')
    and tab5.fecha_termina
  between to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo_proy 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_proy where id_periodo = $id_periodo) ,'dd/mm/yyyy') ))
  )
)
and vaca.num_dias_vac>0
and liq.id_clase_fondo not in (1,2,3)
and liq.num_dias != 0                                

order by
tab0.num_doc,
liq.id_clase_fondo  
EOD;

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

                    foreach ($record_vac_doble as $value) {

                        $id_liquida_aporte = $value['id_liquida_aporte_proy'];
                        $aporte_patrono = $value['ccc'];
                        $dif = $value['dif'];

                        $this->logMessage("[generar_aportes] Valor id_liquida_aporte_proy::" . $id_liquida_aporte);
                        $this->logMessage("[generar_aportes] Valor aporte_patrono::" . $aporte_patrono);
                        $this->logMessage("[generar_aportes] Valor dif::" . $dif);

                        if ($dif != 0) {
                            //sentencia sql
                            $sql = <<<EOD
update no_liquida_aporte_proy set aporte_patrono = $aporte_patrono 
    where id_liquida_aporte_proy = $id_liquida_aporte 
EOD;
                            //ejecuta y obtiene el resultado del sql
                            CN_TABLE::executeSQL($sql);
                        }
                    }


                    /**
                     * Actualizar ibc para las personas de comision - 2020115
                     */
                    //Ejecutar SQL
                    $sql = <<<EOD
SELECT
liq.id_liquida_aporte_proy,
liq.num_doc,
nvl(conf.valor,0) as valor

FROM no_liquida_aporte_proy liq

left join no_concepto_func conf
on conf.id_tipo_doc = liq.id_tipo_doc
and conf.num_doc = liq.num_doc
and conf.id_concep_nomina = 1
and conf.actual = 1

where 
liq.id_periodo = $id_periodo
and liq.tipo_planilla = 'A'
and liq.valor_base = 0
and liq.num_doc in (

    select 
    nov.num_doc
    from no_novedad_personal nov
    where
    nov.estado = 1
    and nov.id_novedad = 8                
    and (
        (select fecha_ini from no_periodo_proy where id_periodo = $id_periodo) between nov.fecha_inicial and nov.fecha_terminacion
        or    
        (select fecha_fin from no_periodo_proy where id_periodo = $id_periodo) between nov.fecha_inicial and nov.fecha_terminacion
    )

)  
EOD;

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

                    foreach ($record_comis as $value) {

                        $valor_base = $value['valor'];
                        $id_liquida_aporte = $value['id_liquida_aporte_proy'];

                        //sentencia sql
                        $sql = <<<EOD
update no_liquida_aporte_proy set valor_base = $valor_base
    where id_liquida_aporte_proy = $id_liquida_aporte  
        and id_periodo = $id_periodo
EOD;
                        //ejecuta y obtiene el resultado del sql
                        CN_TABLE::executeSQL($sql);
                    }

                    MemcacheHandler::getInstance()->set($progress_key, 99);
                } else {


                    //Anexo del mensaje la identificacion de quien genero el error. -- 20130826
                    $mensaje_func = '';
                    foreach ($record_total as $key => $value) {
                        $mensaje_func .= $value['num_doc'] . ' - ';
                    }

                    MemcacheHandler::getInstance()->set($progress_key, 99);
                    $mensaje = "Verifique que el funcionario(s) este afiliado a todos los fondos. Funcionario(s): " . $mensaje_func;

                    $this->status = 2;
                    $this->mensajeError = $mensaje;
                    throw new Exception($mensaje);
                }
            }


            $custom_logger->info(MemcacheHandler::getInstance()->get($progress_key) . " - APORTES - Termino Mencache.\n");
            MemcacheHandler::getInstance()->set($progress_key, 95);


            /*
             * COMMIT DE TODAS LAS TRANSACCIONES
             */
            $this->conn->commit();
            MemcacheHandler::getInstance()->set($progress_key, 100);

            $this->status = 0;
            $this->list_data = array();
            $this->logMessage("[Liquidación proyecciones] Liquidación exitosa");
            $custom_logger->info(MemcacheHandler::getInstance()->get($progress_key) . " TERMINO - Liquidación exitosa.\n");
        } catch (Exception $e) {
//            MemcacheHandler::getInstance()->set($progress_key, 99);
            //ROLLBACK DE TODAS LAS TRANSACCIONES EN CASO DE QUE OCURRA ALGUN ERROR
            $this->conn->rollback();
//            MemcacheHandler::getInstance()->set($progress_key, 100);

            $this->status = 1;
            $this->totalRows = 0;
            $this->startRow = 0;
            $this->endRow = 0;
            $this->mensajeError = "[Liquidación proyecciones] Ocurrio un error: " . $e->getMessage();
            $this->list_data = array();
            $this->logMessage("[Liquidación proyecciones] ERROR!!!");
            $this->logMessage($e->getMessage());
        }
    }

    /**
     * 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_anhos, $id_meses, $id_periodo, $num_doc, $id_tipo_doc, $id_concep_nomina, $record_liq, $arrayConstantes, $record_consulta, $tag_rete_contingente = 0) {

        $this->logMessage("[Liquidación Proyecciones] Liquidar: periodo " . $id_periodo . " - funcionario " . $num_doc . " - concepto nomina " . $id_concep_nomina);
        $this->logMessage("[Liquidación Proyecciones] Liquidar: tag_rete_contingente " . $tag_rete_contingente);

        $id_concep_nomina_inicial = $id_concep_nomina;

        /*
         * (SGC-1, ANM-2, SGR-3, CYC-4, COL-5, INCI-6, LOCAL-7)
         */
        $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++;
        }



        /**
         * Consultar salario minimo
         * 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 = $id_anhos )  
EOD;
        //Ejecutar SQL
        $record_smlv = CN_TABLE::executeSQL($sql);

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

        /**
         * 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_proy.id_anhos from no_periodo_proy where id_periodo = $id_periodo) as vig_ini,
(select no_periodo_proy.id_anhos from no_periodo_proy where id_periodo = $id_periodo) as vig_fin,
(select no_periodo_proy.id_meses from no_periodo_proy where id_periodo = $id_periodo) as per_ini,
(select no_periodo_proy.id_meses from no_periodo_proy where id_periodo = $id_periodo) as per_fin,
nvl((select valor_uvt from ts_uvt where vigencia = (select no_periodo_proy.id_anhos from no_periodo_proy 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_proy 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_proy.fecha_ini from no_periodo_proy where id_periodo = $id_periodo )  and (select no_periodo_proy.fecha_fin from no_periodo_proy where id_periodo = $id_periodo ) 
  )

)tab0
where
id_tipo_doc = $id_tipo_doc
and num_doc = '$num_doc'

order by
tab0.estado desc,
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;
        }

        /*
         * 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_proy.id_anhos from no_periodo_proy 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;

        //Mes del periodo - 20181212
        $sql = <<<EOD
select id_meses from no_periodo_proy where id_periodo = $id_periodo  
EOD;
        //Ejecutar SQL
        $record_per = CN_TABLE::executeSQL($sql);
        $mes = $record_per[0]['id_meses'];

        /**
         * Varibles
         */
        $arrayParametros = array();
        /*
         * Variable para optimizar consultas de formulas en las liquidaciones - 20140117
         */
        $vals_calc = array();
        $valor_liquidado = 0;
        $fecha_desde = $record_liq['fecha_desde'];
        $fecha_hasta = $record_liq['fecha_hasta'];
        $num_dias = $record_liq['num_dias'];

        //Concepto Nomina 1009 Vacaciones
        if ($id_concep_nomina == 9) {
            $record_liq['vig_ini'] = $record_liq['id_anhos'];
            $record_liq['per_ini'] = 1;
            $record_liq['vig_fin'] = $record_liq['id_anhos'];
            $record_liq['per_fin'] = $record_liq['id_meses'];
        }
        /**
         * Concepto Nomina 1016 y 1017, para liquidar en la mensual - 20151218
         */
        if ($id_concep_nomina == 16 || $id_concep_nomina == 17) {
            $record_liq['vig_ini'] = $record_liq['id_anhos'];
            $record_liq['per_ini'] = $record_liq['id_meses'];
            $record_liq['vig_fin'] = $record_liq['id_anhos'];
            $record_liq['per_fin'] = $record_liq['id_meses'];
        }

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

        /*
         * 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
         * Se agrega tag_fondo y aplica_ibc_ant_vac para conocer si el id es de fondo - 20200710::LAVILA
         */
        $tag_fondo = 0;
        $aplica_ibc_ant_vac = 0;
        $valor_liquidado_fondo = 0;
        //Sql
        $sql = <<<EOD
select distinct 
(select count(*) from no_fondo_concepto where id_concep_nomina = $id_concep_nomina) as tag_fondo,
(select aplica_ibc_ant_vac from no_param_gen where id_param_gen = 1) as tag_aplica_ibc_ant_vac,
formu.* 
from no_formula formu

WHERE formu.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;

        /*
         * Variables y estructura para manejo de consultas con variables bind - 20130829
         */
//        $record_var_bind = array(
//            'id_concep_nomina' => 'id_concep_nomina'
//        );
//        $record_bind = array(
//            'id_concep_nomina' => $id_concep_nomina
//        );
        //Ejecutar SQL
        $records = CN_TABLE::executeSQL($sql);
//        $records = CN_TABLE::executeBindSQL($sql, null, $record_var_bind, $record_bind);

        /*
         * Valida si posee formula el concepto
         * Se agrega tag_fondo para conocer si el id es de fondo - 20200710::LAVILA
         */
        if (count($records) > 0) {
            $this->logMessage("[Liquidación Proyecciones] Entro a calcular Formula.");

            $tag_fondo = $records[0]['tag_fondo'];
            $aplica_ibc_ant_vac = $records[0]['tag_aplica_ibc_ant_vac'];

            if ($tag_fondo != 0 && $aplica_ibc_ant_vac == 1) {
                $this->logMessage("[Liquidación Proyecciones] IBC del mes anterior de las vacaciones.");

                //Sql - IBC del mes anterior de las vacaciones
                $sql = <<<EOD
SELECT
id_periodo,
id_tipo_doc,
num_doc,
sum(valor_base) as valor_base
FROM no_liquida_aporte_proy
where
id_periodo = (

        (SELECT
max(perd.id_periodo)
FROM no_periodo_proy perd where perd.id_tipo_periodo = 1 and perd.fecha_fin < ( select 
                max(novvac.fecha_ini) as fecha_ini

                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 = 1 
                and novvac.num_doc = '$num_doc'
                and novvac.id_periodo in ( $id_periodo )
                group by novvac.id_tipo_doc, novvac.num_doc ) )

)
--and id_tipo_doc = 1
and num_doc = '$num_doc'
and id_clase_fondo = 2
and tipo_planilla = 'A' 

group by
id_periodo,
id_tipo_doc,
num_doc   
EOD;
                $records_fondo = CN_TABLE::executeSQL($sql);

                if (count($records_fondo) > 0) {
                    $this->logMessage("[Liquidación Proyecciones] Calculo IBC del mes anterior de las vacaciones.");

                    $valor_base_fondo = $records_fondo[0]['valor_base'];
                    $valor_liquidado_fondo = $valor_base_fondo;

                    $this->logMessage("[Liquidación Proyecciones] Calculo IBC del mes anterior valor_liquidado_fondo::" . $valor_liquidado_fondo);
                }
            }

            foreach ($records as $value) {

                //se adiciona un nuevo campo de formula para completar la retencion que es muy grande el proceso - 20210415::LAVILA
                $formula = $value['formula'] . $value['formula_adic'];
                $this->logMessage("[Liquidación Proyecciones] Formula Inicial: " . $formula);

                //Se agrega tag_fondo para conocer si el id es de fondo - 20200710::LAVILA
                if ($tag_fondo != 0 && $valor_liquidado_fondo != 0) {

                    $formula = str_replace('{A39}', $valor_liquidado_fondo, $formula);
                    $this->logMessage("[Liquidación Proyecciones] Calculo IBC del mes anterior Formula: " . $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 Proyecciones] Formula Constante: " . $formula);

                /*
                 * Reemplaza en la consulta los filtros y valores del SQL, que vienen en el record
                 * Ejemplo: select raz_soc from id_cia where id_cia = $id_cia
                 * Reemplaza $id_cia por el valor en el record
                 */
                $formula = CN_TABLE::reemplazoConsulta($formula, $record_uvt_bonif); //Solo para valores uvt y bonif - 20170614
                $formula = CN_TABLE::reemplazoConsulta($formula, $record_liq);
                $this->logMessage("[Liquidación Proyecciones] 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'
                         */
                        $this->logMessage("[Liquidación Proyecciones] vals_calc: " . $var);
                        if (!isset($vals_calc[$var])) {
                            $formula_agrup = $this->reemplazoAgrupacion(substr($var, 1));
                            $this->logMessage("[$var] [Liquidación Agrupación] Agrupacion: " . $formula_agrup);

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

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

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

                            $vals_calc[$var] = $result_agrup;
                        }

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


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


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


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


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


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

                //CYC: Valor y base extra rete contingente, quitar valor de resta; negativo - 20191128
                if ($tag_rete_contingente == 1 && $result < 0) {
                    $result = 0;
                }


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


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

                    /*
                     * Valor Base y porcentaje
                     */
                    $valor_base = round(($valor_liquidado * 100) / $record_liq['porcentaje']);
                    $this->logMessage("[Liquidación Proyecciones] Valor base salarios minimos antes:: " . $valor_base);

                    /*
                     * No puede superar el salario_minimo - solo conceptos de fondos - 20151019
                     */
                    //Sql
                    $sql = <<<EOD
select * from no_fondo_concepto
where id_concep_nomina = $id_concep_nomina  
EOD;
                    //Ejecutar SQL
                    $record_foncon = CN_TABLE::executeSQL($sql);
                    if (count($record_foncon) > 0) {
                        $id_descuento_ss = $record_foncon[0]['id_descuento_ss'];
                        $this->logMessage("[Liquidación Proyecciones] Conceptos de fondos:: " . $id_concep_nomina);

                        /**
                         * Valor base no puede superar 25 salarios minimos - 20151019
                         */
                        //solo para $id_descuento_ss - id=2 FSP
                        if ($valor_liquidado >= ($salario_minimo * 25)) {
                            $valor_base = round(($salario_minimo * 25) - 1, -1);
                            $valor_liquidado = round(($salario_minimo * 25) - 1, -1);
                        } else if ($valor_liquidado >= $salario_minimo && $id_descuento_ss != 2) {
                            $valor_base = round(($salario_minimo * 25) - 1, -1);
                            $valor_liquidado = $salario_minimo;
                        }

                        $this->logMessage("[Liquidación Proyecciones] Valor base no puede superar 25 salarios minimos - valor_liquidado:: " . $valor_liquidado);
                        $this->logMessage("[Liquidación Proyecciones] Valor base no puede superar 25 salarios minimos:: " . $valor_base);
                    }

                    /**
                     * Valor liquidado 0 por dias 0 - 20191119
                     */
                    if ($num_dias <= 0) {
                        $this->logMessage("[Liquidación Proyecciones] Valor liquidado 0 por dias 0:: " . $num_dias);
                        $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 Proyecciones] Calcular porcentaje - " . $record_liq['porcentaje']);


                //Sql
                $sql = <<<EOD
select * from no_liquida_nomina_proy 
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;
                    $this->logMessage("[Liquidación Proyecciones] No hay registros id_concep_basica ");
                } else {
                    $this->logMessage("[Liquidación Proyecciones] Hay registros id_concep_basica ");
                }

                //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'];
                $this->logMessage("[Liquidación Proyecciones] porcentaje - " . $porcentaje . " :: valor_base - " . $valor_base);

                /*
                 * usa_dias_calen - 20160311
                 */
                if (!is_null($record_liq['num_dias'])) {
                    if ($record_liq['usa_dias_calen'] == 0) { //Mensual
                        $num_dias_pre = 30;
                        //Incidente #4012 <-> Se deja dias 30 para, que tome en base 30 - 20160719
                        //$num_dias_pre = $record_liq['num_dias']; // ? Revisar
                    } else { //Por días calendario
                        $num_dias_pre = $record_liq['num_dias'];
                    }
                    //para dias diferentes de  30 - 20160311
                    if ($num_dias_pre != 30) {

                        /*
                         * Se deja como estaba error ceil, se arreglo para que si no es por formula ni porcentaje, camcule correctamente, y no den decimales erroneos - 20171211
                         * Antes: $result = ($result / 30) * $num_dias_pre;
                         */
                        $result = ($result * $num_dias_pre) / 30;
                    }
                }
            } else {
                $this->logMessage("[Liquidación Proyecciones] 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'];
                    }
                    /*
                     * Se deja como estaba error ceil, se arreglo para que si no es por formula ni porcentaje, camcule correctamente, y no den decimales erroneos - 20171211
                     * Antes: $result = ($record_liq['valor'] / 30) * $num_dias;
                     */
                    $result = ($record_liq['valor'] * $num_dias) / 30;
                } else {
                    $num_dias = 'null';
                    $result = $record_liq['valor'];
                }
            }

            $valor_liquidado += $result;
        }


        //Reversa el concepto nomina si es retefuente y es procedimiento 1 - 20171215
        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 Proyecciones] Valor de uvt de retencion = " . $valor_uvt_rete);

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

            /*
             * Para retencion procedimiento 1, se aplica reten383 de la tabla uvt - 20171215
             */
            //Sql
            $sql = <<<EOD
select  
reten.* 
from ts_reten383 reten
where 
reten.vigencia = (select no_periodo_proy.id_anhos from no_periodo_proy 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 retencion anteriores, diferentes al periodo
                    //Sql
                    $sql = <<<EOD
select nvl(sum(liqnom.valor_liquidado),0) as valor  
from no_liquida_nomina_proy liqnom   

join no_periodo_proy per on per.id_periodo = liqnom.id_periodo 
where    
1 = 1 
and per.id_meses = ( select id_meses from no_periodo_proy where id_periodo = $id_periodo)  
and per.id_anhos = ( select id_anhos from no_periodo_proy 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      
$consulta_adic       
EOD;
                    //Ejecutar SQL
                    $record_rete_t = CN_TABLE::executeSQL($sql);
                    //Resta retencion de otros periodos proc1 - 20180705
                    if (count($record_rete_t) > 0) {
                        $valor_liquidado = $valor_liquidado - $record_rete_t[0]['valor'];
                    }
                }
            }
        }


        /*
         * Valida creacion de registro
         */
        $this->logMessage("[Liquidación Proyecciones] Valor de liquidacion = " . $valor_liquidado);
        if ($valor_liquidado > 0) {

            //Redondeo por decimales, hacia arriba, por calculo de AB en Autoliquidacion - 20171117
            //Se deja como estaba error ceil, se arreglo para que si no es por formula ni porcentaje, camcule correctamente, y no den decimales erroneos - 20171211
            $valor_liquidado = CN_TABLE::ceiling($valor_liquidado, 1);

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


            /**
             * SGC: Valida si es retefuente y redondea al mil - 20140320
             * Tag COVID redondea conceptos al 1000 - 20200709
             */
            $id_concep_nomina_rete = 0;

            //Sql para tomar id de retefuente
            $sql = <<<EOD
select 
(SELECT count(*) FROM no_concep_nomina  where upper(descripcion) like '%COVID%' and id_concep_nomina = $id_concep_nomina) as tag_covid,
par.* 
from no_param_concep  par
where par.id_param_concep = 1 
EOD;
            //Ejecutar SQL
            $records = CN_TABLE::executeSQL($sql);

            $tag_covid = 0;
            if (count($records) > 0) {
                $id_concep_nomina_rete = $records[0]['id_concep_rete'];
                $tag_covid = $records[0]['tag_covid'];
            }
            //SGC: Valida si es retefuente y redondea al mil - 20140320
            //CYC: Valor y base extra rete contingente - 20191128
            $tag_concep_contingente = 0;
            if ($id_concep_nomina == $id_concep_nomina_rete) {

                $tag_concep_contingente = 1;

                $valor_liquidado = round($valor_liquidado, -3);

                //borra registro de retefuente si tenia registrado un valor antes - 20190530
                $sql = <<<EOD
DELETE FROM no_liquida_nomina_proy 
    where id_concep_nomina = $id_concep_nomina_rete and id_periodo = $id_periodo  
        and num_doc = '$num_doc' and id_tipo_doc = $id_tipo_doc
EOD;
                //Ejecutar SQL
                if ($tag_rete_contingente == 0) {
                    CN_TABLE::executeSQL($sql);
                }
            }


            /**
             * COVID redondea conceptos al 1000 - 20200709
             */
            if ($tag_covid != 0) {
                $valor_liquidado = round($valor_liquidado, -3);
            }


            /**
             * Valor base no puede superar 25 salarios minimos - 20151019
             */
            $this->logMessage("[Liquidación Proyecciones] Valor base salarios minimos:: " . $valor_base);
            /* if ($valor_base > ($salario_minimo * 25)) {
              $valor_base = round(($salario_minimo * 25) - 1, -1);
              $this->logMessage("[Liquidación Proyecciones] Valor base no puede superar 25 salarios minimos:: " . $valor_base);
              $valor_liquidado = $salario_minimo;
              } */

            /*
             * Crear nueva liquidación
             * 
             * Asignar valores encontrados en persona
             * Se valida con nvl los dias, pone null si no hay - 20150324
             */
            if ($tag_rete_contingente == 1 && $tag_concep_contingente == 1) {

                $sql = <<<EOD
update no_liquida_nomina_proy 
set valor_liq_extra = round( $valor_liquidado, 0),
valor_base_extra = round( $valor_base, 0)
where
id_periodo = $id_periodo
and id_tipo_doc = $id_tipo_doc
and num_doc = '$num_doc'
and id_concep_nomina = $id_concep_nomina 
EOD;
            } else {
                //Sql
                $sql = <<<EOD
insert into no_liquida_nomina_proy (id_tipo_doc, num_doc, id_concep_nomina,id_anhos,id_meses,id_tipo_periodo,
        id_periodo,valor_liquidado,fecha_desde,fecha_hasta,num_dias, valor_base, porcentaje ) 
        values ( $id_tipo_doc, '$num_doc', $id_concep_nomina,$id_anhos,$id_meses,1,
            $id_periodo, round( $valor_liquidado, 0), 
        to_date('$fecha_desde','YYYY-MM-DD'), to_date('$fecha_hasta','YYYY-MM-DD'), nvl('$num_dias',null), round( $valor_base, 0), $porcentaje ) 
EOD;
            }
            /*
             * Variables y estructura para manejo de consultas con variables bind - 20130829
             */
//            $record_var_bind = array(
//                'id_tipo_doc' => 'id_tipo_doc',
//                'num_doc' => 'num_doc',
//                'id_concep_nomina' => 'id_concep_nomina',
//                'id_periodo' => 'id_periodo',
//                'valor_liquidado' => 'valor_liquidado',
//                'fecha_desde' => 'fecha_desde',
//                'fecha_hasta' => 'fecha_hasta',
//                'num_dias' => 'num_dias',
//                'valor_base' => 'valor_base',
//                'porcentaje' => 'porcentaje'
//            );
//            $record_bind = array(
//                'id_tipo_doc' => $id_tipo_doc,
//                'num_doc' => $num_doc,
//                'id_concep_nomina' => $id_concep_nomina,
//                'id_periodo' => $id_periodo,
//                'valor_liquidado' => $valor_liquidado,
//                'fecha_desde' => $fecha_desde,
//                'fecha_hasta' => $fecha_hasta,
//                'num_dias' => $num_dias,
//                'valor_base' => $valor_base,
//                'porcentaje' => $porcentaje
//            );
            //Ejecutar SQL
            CN_TABLE::executeSQL($sql);
//            CN_TABLE::executeBindSQL($sql, null, $record_var_bind, $record_bind);
        }
        //Valida si es retefuente y el valor es negativo - 20130724
        elseif ($valor_liquidado < 0) {
            $this->logMessage("[Liquidación Proyecciones] El valor_liquidado es menor a cero.");

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

            //Sql para tomar id de retefuente
            $sql = <<<EOD
select 
liq.* 
from no_liquida_nomina_proy liq
left join no_periodo_proy per on per.id_periodo = liq.id_periodo
where
liq.num_doc = $num_doc
and liq.id_concep_nomina = $id_concep_nomina
and liq.id_periodo != $id_periodo
and per.id_anhos = (select no_periodo_proy.id_anhos from no_periodo_proy where no_periodo_proy.id_periodo = $id_periodo)
and per.id_meses = (select no_periodo_proy.id_meses from no_periodo_proy where no_periodo_proy.id_periodo = $id_periodo) 
EOD;
            //Ejecutar SQL
            $records = CN_TABLE::executeSQL($sql);
            $tag_rete_per = false;
            if (count($records) > 0) {
                $tag_rete_per = true;
            }

            //Valida si es retefuente y los dias mayores a cero
            //Valida que tenga liquidacion en otro periodo del mismo mes - 20151119
            if ($id_concep_nomina == $id_concep_nomina_rete && $num_dias > 0 && $tag_rete_per) {

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

                /*
                 * Crear nueva liquidación
                 * 
                 * Asignar valores encontrados en persona
                 */
                $valor_liquidado = $valor_liquidado * (-1);
                //Validar la diferencia entre el redondeo - 20180601
                $porcentaje = str_replace(',', '.', $porcentaje);
                if ($valor_liquidado >= 1000) {

                    //Sql
                    $sql = <<<EOD
insert into no_liquida_nomina_proy (id_tipo_doc, num_doc, id_concep_nomina,id_anhos,id_meses,id_tipo_periodo,
        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_anhos,$id_meses,1, $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;

                    //Para la ANM no aplica registro de devolucion retefuente - 20150715
                    //Se quita por el cambio del 20151119
//                if ($entidadCliente != 2) {
                    /**
                     * Ejecutar SQL
                     */
                    CN_TABLE::executeSQL($sql);
//                }
                }
            } else {
                $this->logMessage("[Liquidación Proyecciones] No es retefuente. Valores- " . $id_concep_nomina_rete . " - " . $id_concep_nomina);
            }
        } else {

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

//        $logPath = sfConfig::get('sf_log_dir') . '/liquidacion.log';
//        $custom_logger = new sfFileLogger(new sfEventDispatcher(), array('file' => $logPath));
//        $custom_logger->info("[Liquidación Proyecciones] memory_get_usage pre liquidar: " . CN_TABLE::convert(memory_get_usage()) . "\n");
//        unset($records, $record_var_bind, $record_bind, $record_liq, $record_consulta);
//        $custom_logger->info("[Liquidación Proyecciones] memory_get_usage post liquidar: " . CN_TABLE::convert(memory_get_usage()) . "\n");
    }

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

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

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

        return $formula;
    }

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

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

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

        return $formula;
    }

    /**
     * Obtener resultados de los parametros(variables)
     * Ejemplo: 'C1' => '0'
     * 
     * Conceptos de $id_concep_nomina_for = 0, $id_tipo_proced_rete = 0, $id_concep_rete = 0, para retencion en la fuente - 201612123
     * 
     * @param type $arrayParametros
     * @param type $record_liq
     * @param type $record_consulta
     * @param type $vals_calc
     * @return int
     */
    private function resultadoParametros($arrayParametros, $record_liq, $record_consulta, $vals_calc, $id_concep_nomina_for = 0, $id_tipo_proced_rete = 0, $id_concep_rete = 0, $id_concep_rete_proc1 = 0, $tag_rete_contingente = 0) {

//        $logPath = sfConfig::get('sf_log_dir') . '/liquidacion.log';
//        $custom_logger = new sfFileLogger(new sfEventDispatcher(), array('file' => $logPath));
//
//        $custom_logger->info("[Liquidación Proyecciones] memory_get_usage ini resultadoParametros: " . CN_TABLE::convert(memory_get_usage()) . "\n");




        /*
         * (SGC-1, ANM-2, SGR-3, CYC-4, COL-5, INCI-6, LOCAL-7)
         */
        $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++;
        }


        $tag_adicional = false;
        if (isset($record_liq['caracter_adic']) && $record_liq['caracter_adic'] == 'M') {
            $tag_adicional = true;
        }


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

            //Sacar caracter y numero(id_concep_nomina) para consulta
            $caracter = substr($key, 0, 1);

            //Valida Tag adicional - solo para los T
            if ($tag_adicional && $caracter == 'T') {
                $caracter = "M";
            }

            $id_concep_nomina = substr($key, 1);
            $this->logMessage("[Liquidación Proyecciones] Caracter: " . $caracter . ", numero: " . $id_concep_nomina . ", tag_rete_contingente: " . $tag_rete_contingente);


            /*
             * CYC: Valor y base extra rete contingente - 20191128
             * Se deja quemado por ahora el id agrupacion (114-APORTES VOLUNTARIOS-AFC LIQ RETEN) para no tener en cuenta
             */

            if ($tag_rete_contingente == 1) {

                //Sql
                $sql = <<<EOD
SELECT * FROM no_agrup_deta where id_agrup_concepto = 114 and id_concep_nomina = $id_concep_nomina                              
EOD;

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

                if (count($record_contingente) > 0) {
                    $this->logMessage("[Liquidación Proyecciones] Valor rete contingente por Caracter: " . $id_concep_nomina);
                    $tag_rete_contingente_cal = 1;
                } else {
                    $tag_rete_contingente_cal = 0;
                }
            } else {
                $tag_rete_contingente_cal = 0;
            }
            $this->logMessage("[Liquidación Proyecciones] Valor tag_rete_contingente_cal por Caracter: " . $tag_rete_contingente_cal);

            /*
             * 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
            //CYC: Valor y base extra rete contingente - 20191128
            if (count($record_consulta) > 0 && $tag_rete_contingente_cal == 0) {
//                $this->logMessage("[Liquidación Proyecciones] Caracter: " . $record_consulta[$caracter]['caracter'] . ", consulta: " . $record_consulta[$caracter]['consulta']);
//                die();
//                $consulta = $record[0]['consulta'];

                $this->logMessage("[Liquidación Proyecciones] Concat vals_calc: " . $caracter . $id_concep_nomina);
                if (!isset($vals_calc[$caracter . $id_concep_nomina])) {
                    $consulta = $record_consulta[$caracter]['consulta'];


                    /*
                     * Calculo cesantias intereses - 20200113
                     */
                    if (isset($record_liq['periodo_ces']) && $caracter == 'X') {
                        $this->logMessage("[Liquidación Proyecciones] Calculo cesantias intereses: " . $caracter . " - Periodo: " . $record_liq['periodo_ces']);
                        $consulta = str_replace('$id_periodo', $record_liq['periodo_ces'], $consulta);
                    }


                    /*
                     * Variables y estructura para manejo de consultas con variables bind - 20130829
                     */
                    //Reemplazo de $ por : para variables bind
//                $consulta = str_replace('$', ':', $consulta);
                    //Reemplazo de id_concep_nomina
                    $consulta = str_replace('$id_concep_nomina', $id_concep_nomina, $consulta);

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

                    /*
                     * Reemplaza en la consulta los filtros y valores del SQL, que vienen en el record
                     * Ejemplo: select raz_soc from id_cia where id_cia = $id_cia
                     * Reemplaza $id_cia por el valor en el record
                     */
                    $consulta = CN_TABLE::reemplazoConsulta($consulta, $record_liq);

                    /*
                     * Ejecutar SQL de consulta
                     * select nvl(sum(valor_liquidado),0) as valor from no_liquida_nomina where id_periodo = :periodo - ejemplo bind
                     */
                    //Sql
                    $sql = <<<EOD
$consulta
$consulta_adic                             
EOD;
                    /*
                     * Variables y estructura para manejo de consultas con variables bind - 20130829
                     */
//                $record_var_bind = array(
//                    'id_tipo_doc' => 'id_tipo_doc',
//                    'num_doc' => 'num_doc',
//                    'id_concep_nomina' => 'id_concep_nomina',
//                    'id_periodo' => 'id_periodo'
//                );
                    //Get the variables within the consulta
//        $custom_logger->info("[Liquidación Proyecciones] memory_get_usage 1 resultadoParametros: " . CN_TABLE::convert(memory_get_usage()) . "\n");
//                $vars = array();
//                CN_TABLE::getVarsInConsulta($vars, $sql);
//                $record_var_bind = $vars;
////                var_dump($record_var_bind);
//                $record_bind = $record_liq;
//                $record_bind['id_concep_nomina'] = $id_concep_nomina;
                    //Ejecutar SQL
                    $record = CN_TABLE::executeSQL($sql);
//                $sql = str_replace("'", null, $sql);
//                $custom_logger->info("[Liquidación Proyecciones] memory_get_usage 2 resultadoParametros: " . CN_TABLE::convert(memory_get_usage()) . "\n");
//                $record = CN_TABLE::executeBindSQL($sql, null, $record_var_bind, $record_bind);
//                $custom_logger->info("[Liquidación Proyecciones] memory_get_usage 3 resultadoParametros: " . CN_TABLE::convert(memory_get_usage()) . "\n");
                    /*
                     * Validar registros SQL
                     */
                    if (count($record) > 0) {
                        $valor = $record[0]['valor'];
                    } else {
                        $valor = 0;
                    }
                    $vals_calc[$caracter . $id_concep_nomina] = $valor;
                }
                $valor = $vals_calc[$caracter . $id_concep_nomina];
            } else {
                $valor = 0;
            }

            $arrayParametros[$key] = $valor;

            $this->logMessage("[Liquidación Proyecciones] Valor por Caracter: " . $valor);
        }
        //Destruye una variable especificada
//        $custom_logger->info("[Liquidación Proyecciones] memory_get_usage pre resultadoParametros: " . CN_TABLE::convert(memory_get_usage()) . "\n");
//        unset($vars, $record_var_bind, $record_bind, $record_liq, $record, $key, $sql, $valor, $record_consulta, $consulta, $caracter);
//        $custom_logger->info("[Liquidación Proyecciones] memory_get_usage post resultadoParametros: " . CN_TABLE::convert(memory_get_usage()) . "\n");
        return $arrayParametros;
    }

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

        $vars = array();
        $arrayParametros = array();
        CN_TABLE::getVarsInFormula($vars, $formula);

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

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

        return $arrayParametros;
    }

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

        $agrup = '( ';

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

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

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

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

        $agrup .= ' )';

        return $agrup;
    }

    /**
     * Ejecutar Formula, para la minima 20150429
     * 
     * @param type $formula
     * @param type $arrayConstantes
     * @param int $record_liq
     * @param type $record_consulta
     * @param type $vals_calc
     * @return int
     */
    public function ejecutarFormula($formula, $arrayConstantes, $record_liq, $record_consulta, $vals_calc, $id_concep_nomina_for = 0, $id_tipo_proced_rete = 0, $id_concep_rete = 0, $tag_rete_contingente = 0) {

        $this->logMessage("[Liquidación Proyecciones] Entro a calcular Formula.");


        $this->logMessage("[Liquidación Proyecciones] Formula Inicial: " . $formula);

        $id_concep_rete_proc1 = 0;

        /*
         *  Buscar las constantes, variables, fórmulas(parametros) y agrupaciones que use la fórmula
         */
        //Reemplazo de constantes            
        $formula = $this->reemplazoConstante($formula, $arrayConstantes, $record_consulta);
        $this->logMessage("[Liquidación Proyecciones] 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_liq);
        $this->logMessage("[Liquidación Proyecciones] 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 Proyecciones] Agrupacion: " . $agrup);

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


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


        /*
         * Obtener resultados de los parametros(variables)
         * Ejemplo: $arrayParametros = array(
         * 'C1' => '0',
         * 'C2' => '0'
         * );
         */
        $arrayParametros = $this->resultadoParametros($arrayParametros, $record_liq, $record_consulta, $vals_calc, $id_concep_nomina_for, $id_tipo_proced_rete, $id_concep_rete, $id_concep_rete_proc1, $tag_rete_contingente);

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


        /*
         * Acumulan resultados de liquidacion
         */
        $valor_liquidado = $result;

        return $valor_liquidado;
    }

    /**
     * Calcular FSP aporte funcionario
     * @param type $valor_base
     * @param type $salario_minimo
     * @return int
     */
    private function valor_base_fsp($valor_base, $salario_minimo, $valor_base_vac = 0, $wdiasv = 0, $dias_liq, $num_doc, $id_periodo) {

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


        /*
         * (SGC-1, ANM-2, SGR-3, CYC-4, COL-5, INCI-6, LOCAL-7)
         */
        $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++;
        }

        /*
         * 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;
        $horas_extras = 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_proy 
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 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 Proyecciones] Valida si la persona - valor_bonif :: " . $valor_bonif);


        /**
         * Para las personas que tienen horas extras se toma solo el valor completo y no por los dias de trabajo 30 - 20150617
         */
        //Sql
        $sql = <<<EOD
select nvl(sum(valor_liquidado),0) as valor 
from no_liquida_nomina_proy 
where num_doc = $num_doc and id_tipo_doc = 1 
and id_concep_nomina in (select distinct no_tipo_hr_extra.id_concep_nomina from no_tipo_hr_extra)  
and id_periodo = $id_periodo            
EOD;
        //Ejecutar SQL
        $records = CN_TABLE::executeSQL($sql);

        /*
         * Valida si posee el concepto
         */
        if (count($records) > 0 && $dias_liq > 0) {
            $horas_extras = $records[0]['valor']; //horas_extras completa
        }
        $this->logMessage("[Liquidación Proyecciones] Valida si la persona - horas extras :: " . $horas_extras);


        /*
         * Operaciones
         * Se quita la resta (- $valor_bonifs), toma el valor proporcional de los dias trabajados - 20150203 NO VA, porque el valor esta en la base por la agrupacion
         * 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
         */
        //$wvalor_base = (($valor_base + $valor_bonif) / ($dias_liq + $wdiasv)) * 30;
        //$wvalor_base = (($valor_base - $valor_bonifs + $valor_bonif) / ($dias_liq + $wdiasv)) * 30;
        $wvalor_base = (($valor_base - $valor_bonifs - $horas_extras) / ($dias_liq + $wdiasv) * 30 ) + ($valor_bonif + $horas_extras);

        // 9 - CEV PUB, se omite si supera el tope de 20 smlv, par aque no tome segun dias de vac - 20191213
        if ($entidadCliente == 9) {
            $wvalor_base = $valor_base;
        }

        /**
         * Valida si la persona ingreso en el mes o se retira para tomar los dias en cuenta - 20140307
         */
        $this->logMessage("[Liquidación Proyecciones] 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_proy per where per.id_periodo = $id_periodo) and (select per.fecha_fin from no_periodo_proy per where per.id_periodo = $id_periodo)
or 
nom.fecha_termina between (select per.fecha_ini from no_periodo_proy per where per.id_periodo = $id_periodo) and (select per.fecha_fin from no_periodo_proy per where per.id_periodo = $id_periodo)
)                
EOD;
        //Ejecutar SQL
        $records = CN_TABLE::executeSQL($sql);

        /*
         * Valida si posee formula el concepto
         */
        if (count($records) > 0) {
            $wvalor_base = $valor_base + $valor_base_vac + $valor_bonif;
            $this->logMessage("[Liquidación Proyecciones] Valida si posee formula el concepto - wvalor_base :: " . $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 Proyecciones] 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 Proyecciones] valor_base_fsp:: porcentaje: " . $porcentaje);
        $this->logMessage("[Liquidación Proyecciones] 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
        );

        return $array_fsp;
    }

    /**
     * Calcular FSP aporte funcionario
     * @param type $valor_base
     * @param type $salario_minimo
     * @return int
     */
    private function valor_base_fsp_aportes($valor_base, $salario_minimo, $valor_base_vac = 0) {

        $valor = 0;
        $valorfps1 = 0;
        $valorfps2 = 0;
        $porcentaje = 0;

        /*
         * Operaciones
         */

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

        $valorfps1 = $valor_base * 0.5 / 100;
        $valorfps2 = $valor_base * ($porcentaje - 0.5) / 100;

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

        return $array_fsp;
    }

    /**
     * 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("[liquidacion_proyeccion] Dias de otra entidad: " . $dias_otra_entidad);
        $meses_otra_entidad = ($dias_otra_entidad * 12) / 360;
        $this->logMessage("[liquidacion_proyeccion] 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);
        $this->logMessage("[CN_TABLE] fecha_ini: " . $fecha_ini . ' - fecha_ingreso: ' . $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 + 0; //$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("[liquidacion_proyeccion] 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("[liquidacion_proyeccion] Meses liquidacion: " . $meses);

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

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

        /*
         * Variables de calculo
         */
        $dias_causa_ult = 0; // - 202010202::LAVILA
        $dias = 0;
        $dias_base = 0;
        $dias_array = array();
        $dias_kardex = 0;
        $dias_vac = 0;
        $dias_otra_entidad = 0;
        $dias_otra_entidad_liq = 0;
        $dias_otra_entidad_extra = 0; //Para forzar el calculo de 1016 - 20181116

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

        /*
         * (SGC-1, ANM-2, SGR-3, CYC-4, COL-5, INCI-6, LOCAL-7)
         */
        $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++;
        }

        $num_dias_vac = 15;
        $id_concep_interes_ces = 0; //Para CEV pub concepto de interes para los dias igual que cesantias - 20210121::LAVILA
        if ($entidadCliente == 8) {
            $id_concep_interes_ces = 18;
        }
        if ($entidadCliente == 9) {
            $num_dias_vac = 25; //dias cev publica - 20191126
        }

        /*
         * Calculo de dias por concepto
         */
        //Vacaciones proporcional - Tabla de causacion vacaciones
        if ($id_concep_nomina == 7 || $id_concep_nomina == 8 || $id_concep_nomina == 9 || $id_concep_nomina == 10) {
            /*
             * 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 
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'];
                $dias_causa_ult = $records[0]['dias_disfrutados'];

                //Sql
                $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')
EOD;
                //Ejecutar SQL
                $records_vac = CN_TABLE::executeSQL($sql);

                $dias_vac = $records_vac[0]['saldos_dias'] * 360 / $num_dias_vac;
                $this->logMessage($records_vac[0]['saldos_dias'] . "[liquidacion_proyeccion] dias_vac: " . $dias_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;

                /**
                 * Se toma para novedad kardex desde Enero 1 - 20200113
                 */
                $anho_ini = $record['anho_ini'];
                $fecha_ini = $anho_ini . '-01-01';

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

                if ($date2 > $date1) {
                    $fecha_ini_ka = $fecha_ingreso;
                } else {
                    $fecha_ini_ka = $fecha_ini;
                }
            }
        }
        //Prima servicios proporcional - Julio 1 anterior a la fecha de retiro y hasta la misma fecha de retiro
        elseif ($id_concep_nomina == 16 || $id_concep_nomina == 19) {

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

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

            if ($date2 > $date1) {
                $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_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;
            $dias_otra_entidad_extra = 180; //Para forzar liquidacion de concepto 1016 - 20181116

            /*
             * 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
             */
            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 || $id_concep_nomina == $id_concep_interes_ces) {

            $fecha_ini = $record['fecha_ini'];

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

            $this->logMessage("[liquidacion_proyeccion] 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_ka = $fecha_ingreso;
                    $dias = CN_TABLE::diasEntreFechas($fecha_ingreso, $fecha_termina, false);
                } else {
                    $fecha_ini_ka = $fecha_ini;
                    $dias = CN_TABLE::diasEntreFechas($fecha_ini, $fecha_termina, false);
                }
            } else {
                $dias = 0;
            }


            //Dias de proporcionalidad bonificacion por servicios - 20140224
            $dias = $dias;
        }
        //Bonificacion por servicios
        elseif ($id_concep_nomina == 11) {

            /*
             * Registro ultimo de bonificacion
             */
            //Sql
            $sql = <<<EOD
select * from no_bonifica_servicios
where 
num_doc =  '$num_doc'  and  id_tipo_doc = $id_tipo_doc
and to_date('$fecha_termina','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_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("[liquidacion_proyeccion] Id de concepto sin identificar.");
//            $dias = 360;
        }

        $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
         */
        //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 TO_DATE(NOVKA.FECHA_INI,'yyyy-mm-dd')  < TO_DATE('$fecha_ini_ka','yyyy-mm-dd') 
    then TO_DATE('$fecha_ini_ka','yyyy-mm-dd') else TO_DATE(NOVKA.FECHA_INI,'yyyy-mm-dd') end
    ,
    case when TO_DATE(NOVKA.FECHA_FIN,'yyyy-mm-dd')  > TO_DATE('$fecha_fin_ka','yyyy-mm-dd') 
    then TO_DATE('$fecha_fin_ka','yyyy-mm-dd') else TO_DATE(NOVKA.FECHA_FIN,'yyyy-mm-dd') 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'];

        //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
        if ($id_concep_nomina != 11) {
            $this->logMessage("[liquidacion_proyeccion] Restar dias kardex: " . $dias_kardex);
            $dias_liq = $dias - $dias_kardex;
        } else {
            $dias_liq = $dias;
        }

        /*
         * Calcula de concepto 1008
         */
        if ($id_concep_nomina == 7 || $id_concep_nomina == 8) {
            $this->logMessage("[liquidacion_proyeccion] Concepto - Dias liquidacion: " . $dias_liq . " - Num Dias Vac: " . $num_dias_vac);
            $dias_liq = ($dias_liq * $num_dias_vac) / 360; //Dias completos

            /*
             * Se restan dias del periodo segun liquidacion de los dias disfrutados - 20210202::LAVILA
             */
            $dias_liq = $dias_liq - $dias_causa_ult;
            $this->logMessage("[liquidacion_proyeccion] Concepto - Dias liquidacion: " . $dias_liq . " - Dias Causa ULT: " . $dias_causa_ult);
            if ($dias_liq < 0) {
                $this->logMessage("[liquidacion_proyeccion] Concepto - Dias 0");
                $dias_liq = 0;
            } else {

                $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("[liquidacion_proyeccion] Concepto - Dias liquidacion: " . $dias_liq . " - Dias Base: " . $dias_base . " - Dias Mod: " . $dias_liq_mod);

                //Dias con festivos
                //Empieza a contar desde el siguiente dia habil
                //Sql
                //No aplica para CEV PUB - 20210202::LAVILA
                //No se colocan dias en calendario - 20210812::LAVILA
                if ($entidadCliente != 9) {
                    /*
                      $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); */
                    $records[0]['dias'] = $dias_base;
                } else {
                    $records[0]['dias'] = $dias_base;
                }

                $dias_liq = $records[0]['dias'] + round($dias_liq_mod, 2); //redondeo a dos decimales - 20140728 
            }
        }


        /**
         * Calculo de dias
         */
        $this->logMessage("[liquidacion_proyeccion] 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_extra,
            '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 liquidarProvTotal($id_anhos, $id_meses, $id_periodo, $num_doc, $id_tipo_doc, $id_concep_nomina, $record_liq, $arrayConstantes, $id_agrup_concepto) {
        $this->logMessage("[liquidacion_proyeccion] Liquidar: periodo " . $id_periodo .
                " - funcionario " . $num_doc . " - concepto nomina " . $id_concep_nomina);

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

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

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

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

            foreach ($records as $value) {

                //se adiciona un nuevo campo de formula para completar la retencion que es muy grande el proceso - 20210415::LAVILA
                $formula = $value['formula'] . $value['formula_adic'];
                $this->logMessage("[liquidacion_proyeccion] 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("[liquidacion_proyeccion] 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_liq);
                $this->logMessage("[liquidacion_proyeccion] 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->reemplazoAgrupacionProvTotal(substr($var, 1));
                        $this->logMessage("[liquidacion_proyeccion] Agrupacion: " . $agrup);

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


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


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


                /*
                 * Reemplazo de parametros(variables) a la formula
                 * Ejemplo: $arrayParametros = array(
                 * 'C1' => '1100',
                 * 'C2' => '55'
                 * );
                 */
                $formula = $this->reemplazoParametrosProvTotal($formula, $arrayParametros);
                $this->logMessage("[liquidacion_proyeccion] 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("[liquidacion_proyeccion] 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("[liquidacion_proyeccion] 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("[liquidacion_proyeccion] 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_proy 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("[liquidacion_proyeccion] 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("[liquidacion_proyeccion] Calcular porcentaje - " . $record_liq['porcentaje']);


                    //Sql
                    $sql = <<<EOD
select * from no_liquida_nomina_proy 
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("[liquidacion_proyeccion] 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) {
            $valor_liquidado = round(($valor_liquidado * $num_dias) / 360);
        }

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

            $this->logMessage("[liquidacion_proyeccion] 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_provision (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_proy (id_tipo_doc, num_doc, id_concep_nomina,id_anhos,id_meses,id_tipo_periodo,
        id_periodo,valor_liquidado,fecha_desde,fecha_hasta,num_dias, valor_base, porcentaje, id_periodo_ajuste ) 
        values ( $id_tipo_doc, '$num_doc', $id_concep_nomina,$id_anhos,$id_meses,1,
            $id_periodo, round( $valor_liquidado, 0), 
        to_date('$fecha_desde','YYYY-MM-DD'), to_date('$fecha_hasta','YYYY-MM-DD'), nvl('$num_dias',null), round( $valor_base, 0), $porcentaje, 0 ) 
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.");

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

                $this->logMessage("[Liquidación] Valida si es prima_navidad 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_proy (id_tipo_doc, num_doc, id_concep_nomina,id_anhos,id_meses,id_tipo_periodo,
        id_periodo,valor_liquidado,fecha_desde,fecha_hasta,num_dias, valor_base, porcentaje, id_periodo_ajuste ) 
        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_anhos,$id_meses,1, $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, 0 ) 
EOD;
                //Ejecutar SQL
                CN_TABLE::executeSQL($sql);
            } else {
                $this->logMessage("[Liquidación] No es retefuente. Valores - " . $id_concep_nomina);
            }
        } else {

            $this->logMessage("[liquidacion_proyeccion] El valor_liquidado es cero.");
        }
    }

    /**
     * Reemplaza los parametros(variables) a la formula
     * Ejemplo: $key: C1 / $value: valor - 2+5
     * @param type $formula
     * @param type $arrayParametros
     */
    private function reemplazoParametrosProvTotal($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 resultadoParametrosProvTotal($arrayParametros, $record_liq) {

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

            //Sacar caracter y numero(id_concep_nomina) para consulta
            $caracter = substr($key, 0, 1);
            $id_concep_nomina = substr($key, 1);
            $this->logMessage("[liquidacion_proyeccion] 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 parametrosFormulaProvTotal($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 reemplazoAgrupacionProvTotal($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;
    }

}
