<?php

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

    /**
     * Genera bases de liquidacion segun agrupacion
     *
     * @param sfRequest $request A request object
     */
    public function executeList(sfWebRequest $request) {

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

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

        /*
         * Formato de fecha
         */
        //Sql
        $sql = <<<EOD
ALTER SESSION SET NLS_DATE_FORMAT = "YYYY-MM-DD" 
EOD;
        //Ejecutar SQL
        CN_TABLE::executeSQL($sql);

        try {

            /*
             * Variables de filtro
             */
            //id_periodo
            $id_periodo = $request['id_periodo_filtro'];
            $id_periodo_actual = $request['id_periodo'];

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

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

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


            /*
             * Traer funcionarios activos para el periodo
             * o que tambien esten retirados en el periodo
             * Debe tomar tambien el primer dia del siguiente mes - 20130729
             * se agregan variables para validar retiro primer dia mes - 20150219
             * Si no es periodo mensual, no genera registro - 20170502
             */
            //Sql
            $sql = <<<EOD
select distinct
    
--tab0.id_estado_func,
tab0.id_tipo_doc,
tab0.num_doc,
--tab0.id_dp,
tab0.id_anhos,
tab0.id_meses,
tab0.periodo,
--tab0.actual,
--tab0.id_ea,
--tab0.ID_CEN_OP,
nombra.id_nombramiento,
nombra.fecha_nombra,
case when extract(month from nombra.fecha_ingreso) || extract(year from nombra.fecha_ingreso) = (select id_meses || id_anhos from no_periodo where id_periodo = $id_periodo) 
then nombra.fecha_ingreso else null end as fecha_ingreso,
case when extract(month from nombra.fecha_retiro - 1) || extract(year from nombra.fecha_retiro - 1) = (select id_meses || id_anhos from no_periodo where id_periodo = $id_periodo) 
then nombra.fecha_termina else null end as fecha_termina,
case when extract(month from nombra.fecha_retiro - 1) || extract(year from nombra.fecha_retiro - 1) = (select id_meses || id_anhos from no_periodo where id_periodo = $id_periodo) 
then nombra.fecha_retiro else null end as fecha_retiro,
nombra.fecha_termina as fecha_termina_real,
nombra.fecha_retiro as fecha_retiro_real,
case when nombra.fecha_retiro = (select fecha_ini from no_periodo where id_periodo = $id_periodo) then 1 else 0 end as retiro_primerdiames
                    
from no_estado_func_v tab0

left join no_periodo perd
on perd.ID_PERIODO = tab0.PERIODO

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

WHERE tab0.periodo = $id_periodo
and perd.ID_TIPO_PERIODO = 1
$whereFuncionarioNumDoc $whereFuncionarioTipoDoc 
and ( tab0.actual = 1 

    or (nombra.estado = 1 or
      ( nombra.estado = 0 
        and nombra.fecha_retiro
      between to_date('01/'|| (select lpad(id_meses,2,'0') ||'/'||id_anhos from no_periodo where id_periodo = $id_periodo) ,'dd/mm/yyyy')
      and trunc(last_day( TO_DATE('01/'|| (SELECT LPAD(ID_MESES,2,'0') ||'/'||ID_ANHOS FROM NO_PERIODO WHERE ID_PERIODO = $id_periodo) ,'dd/mm/yyyy') ) +1 )
      )
    )

)

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

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

                foreach ($records as $value) {

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

                    /*
                     * Datos por record
                     */
                    $fecha_ingreso = $value['fecha_ingreso'];
                    $fecha_termina = $value['fecha_termina'];
                    $fecha_termina_real = $value['fecha_termina_real'];
                    $fecha_retiro = $value['fecha_retiro'];
                    $fecha_retiro_real = $value['fecha_retiro_real'];
                    $retiro_primerdiames = $value['retiro_primerdiames'];
                    $num_doc = $value['num_doc'];
                    $id_tipo_doc = $value['id_tipo_doc'];

                    $anho_ini = $value['id_anhos'];
                    $mes_ini = $value['id_meses'];
                    $anho_fin = $value['id_anhos'];
                    $mes_fin = $value['id_meses'];

                    /*
                     * Calcular los dias a liquidar (ausencias no afectan antiguedad)
                     */
                    $dias_liq = $this->diasLiquidar($id_periodo, $num_doc, $id_tipo_doc, $fecha_ingreso, $fecha_termina, $value);
                    $this->logMessage("[Base Liquidación Cesantias] Dias de Liquidación: " . $dias_liq);

                    //Validar dias menores a 0 - 20180928
                    if ($dias_liq < 0) {
                        $dias_liq = 0;
                    }

                    /**
                     * Registra las bases segun agrupacion
                     */
                    $sql = <<<EOD
insert into no_base_liquidacion                               
select 
null as ID_BASE_LIQUIDACION,
periodo as ID_PERIODO,
tab0.ID_TIPO_DOC,
tab0.NUM_DOC,
tab0.ID_CONCEP_NOMINA,
case when tab0.TIPO_VALOR = 'C' then round((valor/30)*$dias_liq) else valor end as VALOR_BASE,
$dias_liq as DIAS,
tab0.TIPO_VALOR 

from (

    select 
    tab0.id_estado_func,
    tab0.id_tipo_doc,
    tab0.num_doc,
    tab0.id_dp,
    tab0.id_anhos,
    tab0.id_meses,
    tab0.periodo,
    tab0.actual,
    tab0.id_ea,
    tab0.id_cen_op,
    tab0.rn,
    agr.id_concep_nomina,
    agr.tipo_valor,
    cons.nombre as nombre_valor,
    (select no_concep_nomina.codigo from no_concep_nomina where no_concep_nomina.id_concep_nomina = agr.id_concep_nomina) as codigo,
    (select no_concep_nomina.descripcion from no_concep_nomina where no_concep_nomina.id_concep_nomina = agr.id_concep_nomina) as descripcion,
    nvl(no_consulta_sql_f($anho_ini,$mes_ini,$anho_fin,$mes_fin,tab0.id_tipo_doc,tab0.num_doc,agr.id_concep_nomina,agr.tipo_valor,tab0.periodo) ,0) as valor
    
    from no_estado_func_v tab0
    left join no_agrup_deta agr on agr.id_agrup_concepto = $id_agrup_concepto
    left join no_consulta cons on to_char(cons.caracter) = to_char(agr.tipo_valor)

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

)tab0
EOD;
                    //Ejecutar SQL
                    $this->conn->execute($sql);
                }

                /*
                 * COMMIT DE TODAS LAS TRANSACCIONES
                 */
                $this->conn->commit();
                $this->status = 0;
                $this->list_data = array();
                $this->logMessage("[Base Liquidación Cesantias] Liquidación exitosa.");
            } else {
                /*
                 * COMMIT DE TODAS LAS TRANSACCIONES
                 */
                $this->conn->commit();

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

                $this->status = 0;
                $this->list_data = array();
                //$this->mensajeError = $mensajeError;
                $this->logMessage("[base_liquidacion Cesantias] " . $mensajeError);
            }
        } catch (Exception $e) {

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

    /**
     * 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
     */
    private function diasLiquidar($id_periodo, $num_doc, $id_tipo_doc, $fecha_ingreso, $fecha_termina, $record) {

        /*
         * Variables de calculo
         */
        $dias_calc = 0;
        $dias_kardex = 0;

        /*
         * Calculo de dias diferencia
         */
        //Sql
        $sql = <<<EOD
select 
to_date(fecha_termina, 'yyyy-mm-dd') - to_date(fecha_ingreso, 'yyyy-mm-dd') + 1 as dias,
to_date(fecha_termina, 'yyyy-mm-dd') as fecha_termina,
to_date(fecha_ingreso, 'yyyy-mm-dd') as fecha_ingreso
from (
select
nvl('$fecha_ingreso',to_date( per.id_anhos || '-' || per.id_meses || '-01', 'yyyy-mm-dd') ) as fecha_ingreso,
nvl('$fecha_termina',trunc(last_day( to_date( per.id_anhos || '-' || per.id_meses, 'yyyy-mm') ) ) ) as fecha_termina
from no_periodo per
where 
per.id_periodo = $id_periodo
)
EOD;
        //Ejecutar SQL
        $records = CN_TABLE::executeSQL($sql);

        if (count($records) > 0) {
            $this->logMessage("[Liquidación Cesantias] Dias de diferencia: " . $records[0]['dias']);

            $fecha_ingreso = $records[0]['fecha_ingreso'];
            $fecha_termina = $records[0]['fecha_termina'];
            $dias = CN_TABLE::diasEntreFechas($fecha_ingreso, $fecha_termina, false);
//            $dias_calc = $records[0]['dias'];
            $dias_calc = $dias;


            /*
             * Claculo de dias de novedad de kardex que afectan antiguedad
             * 
             * Se restan dias de kardex del mes unicamente - 20130627
             * Verificacion del mes de periodo a liqudiar cesantias - 20130826
             * Solo coloca en 0 para los que estan todo en mes en la novedad de kardex - 20170822
             * Si la fecha de la novedad es igual o menor al periodo, toma todos los dias, asi sean del mes de registro la novedad - 20190909
             */
            $fecha_ini = $records[0]['fecha_ingreso'];
            $fecha_fin = $records[0]['fecha_termina'];
            //Sql
            $sql = <<<EOD
select nvl(sum(dias_ka),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,
  --DIAS_RANGO_MES_SIN_TREINTAYUNO( NOVKA.FECHA_INI, NOVKA.FECHA_FIN, (select extract(month from fecha_ini) from no_periodo where id_periodo =  $id_periodo) ) as DIAS_KA,
  case when NOVKA.FECHA_FIN <= (select fecha_fin from no_periodo where id_periodo = $id_periodo) then novka.num_dias 
      else DIAS_RANGO_MES_SIN_TREINTAYUNO( NOVKA.FECHA_INI, NOVKA.FECHA_FIN, (select extract(month from fecha_ini) from no_periodo where id_periodo =  $id_periodo) ) end DIAS_KA,
  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 
  and novka.estado = 1
  where
    (
        novka.fecha_ini between to_date('$fecha_ini','yyyy-mm-dd') and to_date('$fecha_fin','yyyy-mm-dd')
        or 
        NOVKA.FECHA_FIN between TO_DATE('$fecha_ini','yyyy-mm-dd') and TO_DATE('$fecha_fin','yyyy-mm-dd')
        
        or
        
        TO_DATE('$fecha_ini','yyyy-mm-dd') between novka.fecha_ini and NOVKA.FECHA_FIN
        or 
        TO_DATE('$fecha_fin','yyyy-mm-dd') between novka.fecha_ini and NOVKA.FECHA_FIN
        
        or
        novka.id_periodo =  $id_periodo
    )
    AND novka.num_doc = '$num_doc'
    AND novka.id_tipo_doc = $id_tipo_doc
) 
EOD;
            //Ejecutar SQL
            $recordsKa = CN_TABLE::executeSQL($sql);

            $dias_kardex = $recordsKa[0]['dias'];


            /**
             * Dias de suspension id_nov_ka_susinc - 20190909
             */
            $fecha_fin = $records[0]['fecha_termina'];
            //Sql
            $sql = <<<EOD
select 

DIAS_RANGO_MES_SIN_TREINTAYUNO( 
case when (select fecha_ini from no_periodo where id_periodo = $id_periodo) < nov.fecha_ini then (select fecha_ini from no_periodo where id_periodo = $id_periodo) else nov.fecha_ini end, 
case when nov.fecha_fin > (select fecha_fin from no_periodo where id_periodo = $id_periodo) then (select fecha_fin from no_periodo where id_periodo = $id_periodo) else nov.fecha_fin end, 
(select id_meses from no_periodo where id_periodo = $id_periodo)
) as dias_nov_sus,

(case when (select count(con.id_concepto_periodo) as cant from no_concepto_periodo con 
    where con.num_doc = nov.num_doc and con.periodo = $id_periodo and con.id_concep_nomina = (select id_concep_basica from no_param_concep where id_param_concep = 1) ) > 0 then 1 else 0 end) as concepto_periodo,
(case when (select count(est.id_estado_func) as cant from no_estado_func est where est.num_doc = nov.num_doc and est.periodo = $id_periodo ) > 0 then 1 else 0 end) as estado_func,
nov.* 

from no_novedad_kardex nov

where 
nov.estado = 1
and nov.num_doc = $num_doc 
and nov.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 (
    (select fecha_ini from no_periodo where id_periodo = $id_periodo) between nov.fecha_ini and nov.fecha_fin
    or    
    (select fecha_fin from no_periodo where id_periodo = $id_periodo) between nov.fecha_ini and nov.fecha_fin
) 
EOD;
            //Ejecutar SQL
            $recordsKa_sus = CN_TABLE::executeSQL($sql);

            if (count($recordsKa_sus) > 0) {
                $dias_kardex += $recordsKa_sus[0]['dias_nov_sus'];
            }
        }


        /**
         * Calculo de dias de novedad kardex
         */
        $this->logMessage("[Liquidación Cesantias] " . $dias_calc . " - " . $dias_kardex);

        if (($dias_calc - $dias_kardex) > 30) {
            $dias_cesantias = 30;
        } else {
            $dias_cesantias = $dias_calc - $dias_kardex;
        }

        /**
         * Incidente #7746, si tiene prima liquida cesantias mensuales - 20171214
         */
        if ($dias_cesantias == 0) {

            //Sql
            $sql = <<<EOD
select 
liq.* 
from no_liquida_nomina liq

where
liq.num_doc = '$num_doc'
AND liq.id_tipo_doc = $id_tipo_doc
and liq.id_periodo in ( select no_periodo.id_periodo from no_periodo 
                        where no_periodo.id_tipo_periodo in (3,4) 
                        and no_periodo.id_anhos = (select id_anhos from no_periodo where id_periodo = $id_periodo) 
                        and no_periodo.id_meses = (select id_meses from no_periodo where id_periodo = $id_periodo) 
                        )   
EOD;
            //Ejecutar SQL
            $recordsPrima = CN_TABLE::executeSQL($sql);

            if (count($recordsPrima) > 0) {
                $dias_cesantias = 30;
            }
        }

        return $dias_cesantias;
    }

}
