<?php 

use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;


/*
	Controlador que sirve para albergar funciones que se utilizan varias veces en otros Controladores.
*/

class FuncionesController extends Controller{

	private function plantilla_mensaje(string $cuerpo_mensaje) : string{
		/*	HEAD	*/
		$mensaje = '<html>';
        $mensaje .= '<table width="100%" border="0" cellspacing="0" cellpadding="0" style="background-color:#ffffff">';

        $mensaje .= '<tr>';
        //$mensaje .= '<td align="center" style="background-color: #245b99">';
        $mensaje .= '<td align="center">';
        //$mensaje .= '<img src="http://localhost/proyecto/images/barra.png">';
        //$mensaje .= '<img src="https://i92.servimg.com/u/f92/19/77/04/53/barra10.png">';
        $mensaje .= '<img src="http://sidcai.fonacit.gob.ve/images/cintillo-principal.jpg" width="100%">';
        $mensaje .= '</td >';
        $mensaje .= '</tr>';

        $mensaje .= "<tr>";
        $mensaje .= "<td style='padding-left: 60px; padding-right: 60px; padding-top:20px; text-align:center'>";
        $mensaje .= "<h2>SIDCAI</h2>";
        $mensaje .= "</td>";
        $mensaje .= "</tr>";

        $mensaje .= '<tr>';
        $mensaje .= '<td height="16" colspan="3" style="padding-left: 60px; padding-right: 60px;">';
        $mensaje .= '<hr color="#000066">';
        $mensaje .= '</td>';
        $mensaje .= '</tr>';


        /*  FIN HEAD  */

        /*  BODY  */
        $mensaje .= "<tr>";
        $mensaje .= "<td style='padding-left: 60px; padding-right: 60px; padding-top:20px; padding-bottom: 20px'>";
        $mensaje .= "Estimada empresa:<br><br>";
        $mensaje .= $cuerpo_mensaje;
        $mensaje .= "</td>";
        $mensaje .= "</tr>";
        /*  FIN BODY  */

        /*  FOOTER  */
        $mensaje .= "<tr>";
        $mensaje .= "<td style='padding-left: 60px; padding-right: 60px'>";
        $mensaje .= '<p>Muchas Gracias;<br />';
        $mensaje .= '<strong>Fondo Nacional de Ciencia, Tecnología e Innovación (FONACIT).<br />';
        $mensaje .= 'Ministerio de Ciencia y Tecnología e Innovación.</strong></p><br>';
        $mensaje .= "</td>";
        $mensaje .= "</tr>";

        $mensaje .= "<tr>";
        $mensaje .= "<td style='padding-left: 60px; padding-right: 60px; padding-bottom: 30px;'>";
        $mensaje .= '<p><center>Para mayor información comuníquese con el <b>Fondo Nacional de Ciencia  Tecnología e ';
        $mensaje .= 'Innovación - FONACIT</b><br>';
        $mensaje .= 'Av. Universidad, Esquina El Chorro, Torre Ministerial, Planta Baja, Taquilla Única <br>';
        $mensaje .= 'Teléfonos: 0212-5052580 / 0212-5052548 / 0212-5054884 / 0212-5052503 / 0212-5052718.<br>';
        $mensaje .= 'Horario: Lunes a jueves 8:30 AM a 11.30 AM y 1:30 PM a 3:30 PM - Viernes 8:30 AM a 11.30 AM</center><br><br>';
        $mensaje .= '<strong>Nota:</strong> este email es una respuesta automática del sistema. No lo responda.</p>';
        $mensaje .= "</td>";
        $mensaje .= "</tr>";


        $mensaje .= '</table>';
        $mensaje .= '<html>';
        /*	FIN FOOTERs	*/

        return $mensaje;
	}


	public static function enviarCorreo(array $para, array $nombre, string $titulo, string $mensaje) : bool{
		require_once(Yii::app()->basePath . '/extensions/phpmailer/src/PHPMailer.php');
		require_once(Yii::app()->basePath . '/extensions/phpmailer/src/SMTP.php');
		require_once(Yii::app()->basePath . '/extensions/phpmailer/src/Exception.php');


		$mail = new PHPMailer;

		$usuario = Yii::app()->params['emailAtencion']; 

		$exitoso = false;

		try {
		    //Server settings
		    //Server settings
		    // $mail->SMTPDebug = SMTP::DEBUG_SERVER;                      // Enable verbose debug output
		    $mail->SMTPDebug = 0;                      // Enable verbose debug output
		    $mail->isSMTP();   
		    $mail->SMTPOptions = array(
                  'ssl' => array(
                      'verify_peer' => false,
                      'verify_peer_name' => false,
                      'allow_self_signed' => true
                  )
              );
		   /* $mail->Host       = 'saturno.fonacit.gob.ve';                    // Set the SMTP server to send through
		    $mail->SMTPAuth   = true;                                   // Enable SMTP authentication
		    $mail->Username   = $usuario;                     // SMTP username
		    $mail->CharSet 	  = 'UTF-8';
		    $mail->Password   = '4ib7nexm$$';                               // SMTP password
		    //$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;         // Enable TLS encryption; `PHPMailer::ENCRYPTION_SMTPS` encouraged
		    $mail->Port       = 25;    */                                // TCP port to connect to, use 465 for `PHPMailer::ENCRYPTION_SMTPS` above

			$Host = Yii::app()->params['Host']; 
			$SMTPAuth = Yii::app()->params['SMTPAuth']; 
			$CharSet = Yii::app()->params['CharSet']; 
			$Password = Yii::app()->params['Password']; 
			$Port = Yii::app()->params['Port']; 
			$mail->Host       = $Host;                    // Set the SMTP server to send through
		    $mail->SMTPAuth   = $SMTPAuth;                                   // Enable SMTP authentication
		    $mail->Username   = $usuario;                     // SMTP username
		    $mail->CharSet 	  = $CharSet;
		    $mail->Password   = $Password;                               // SMTP password
     	    $mail->Port       = $Port;  
		    //Recipients
		    $mail->setFrom($usuario, 'SIDCAI');

		    for($i = 0; $i < count($para); $i++){
	       	 	$mail->AddAddress($para[$i], $nombre[$i]); 
	        }

		    // $mail->addReplyTo('info@example.com', 'Information');
		    // $mail->addCC('cc@example.com');
		    // $mail->addBCC('bcc@example.com');

		    // Attachments
		    // $mail->addAttachment('/var/tmp/file.tar.gz');         // Add attachments
		    // $mail->addAttachment('/tmp/image.jpg', 'new.jpg');    // Optional name

		    // Content
		    $mail->isHTML(true);                                  // Set email format to HTML
		    $mail->Subject = $titulo;
		    // $mail->Body    = 'This is the HTML message body <b>in bold!</b>';
		    $mail->AltBody = '';
		    $mail->Body = self::plantilla_mensaje($mensaje);

		    if($mail->Send()){
				$exitoso = true;
			}else{
				$exitoso = false;
			}
		} catch (Exception $e) {
		    echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
		}

		return $exitoso;
	}

	/* 
	Función para generar un código alfanumérico con N de longitud
	$tipo = 
	1. Numérico
	2. Alfabético
	3. Alfanumérico
	4. Alfanumérico con simbolos
	*/
	public function generarCodigo(int $longitud, int $tipo = 1) : string{
		if($tipo == 1)
			$alpha = "1234567890";
		if($tipo == 2)
			$alpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
		if($tipo == 3)
			$alpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
		if($tipo == 4)
			$alpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!?@#$%_-.";

		$code = "";

		for($i=0;$i<$longitud;$i++){
		    $code .= $alpha[rand(0, strlen($alpha)-1)];
		}

		return $code;
	}

	/**
		Convierte la fecha en el formato enviado por formato_salida
		$fecha_entrada  => "2000-12-31", "2000/12/31", "31-12-2000", "31/12/2000"
		$formato_salida => "yyyy-mm-dd", "yyyy/mm/dd", "dd-mm-yyyy", "dd/mm/yyyy"
		$hora 			=> Por defecto true, si es true significa que el formato de entrada vendrá con la fecha y hora
	**/
	public static function convertirFecha($fecha_entrada, $formato_salida, $hora = true){
		if($fecha_entrada != "" && $formato_salida != ""){
			// Se convierte en mayusculas para evitar inconvenientes
			$formato_salida  = strtoupper($formato_salida);
			$fecha_hora = "";

			// Primera verifica si el formato de entrada viene con hora
			if(strpos($fecha_entrada, " ") !== false){
				$fecha = explode(" ", $fecha_entrada);
				$fecha_entrada = $fecha[0];
				$fecha_hora = " ".$fecha[1];
			}

			if($hora == false)
				$fecha_hora = "";

			$fecha  = explode("/", $fecha_entrada);
			$salida = explode("/", $formato_salida);
			$salidaFormato = "/";

			if(count($fecha) < 2)
				$fecha  = explode("-", $fecha_entrada);

			if(count($salida) < 2){
				$salida = explode("-", $formato_salida);
				$salidaFormato = "-";
			}

			if(strlen($fecha[0])  == strlen($salida[0]))
				return $fecha[0].$salidaFormato.$fecha[1].$salidaFormato.$fecha[2] . $fecha_hora;
			else
				return $fecha[2].$salidaFormato.$fecha[1].$salidaFormato.$fecha[0] . $fecha_hora;
		}
	}

	/**
	 * Obtiene la moneda de la fecha solicitada.
	 */
	public static function obtenerMoneda(string $fecha) : string{
		$connection = Yii::app()->db;
		$sql = "SELECT mone_simbolo FROM sidcai_moneda WHERE :fecha >= mone_fechainicio AND :fecha <= (CASE WHEN mone_fechafin != null THEN mone_fechafin ELSE '2099-12-31' END) ORDER BY mone_codigo_pk DESC LIMIT 1";
		$command = $connection->createCommand();
		$command->text = $sql;
		$command->bindParam(':fecha', $fecha);
		$model = $command->queryRow();

		return ($model != null) ? $model['mone_simbolo'] : '';
	}


	/**
	 * Obtiene la moneda de la fecha solicitada en la unidad tributaria.
	 */
	public static function obtenerMonedaUT(string $fecha_inicio_declaracion, string $fecha_fin_declaracion) : string{
		$fecha_inicio_declaracion = date("Y-m-d", strtotime($fecha_inicio_declaracion." -1 year"));
		$criteria = new CDbCriteria;
		$criteria->condition = 'unid_habilitado = true';
		$criteria->addBetweenCondition('unid_fechacomienzo', $fecha_inicio_declaracion, $fecha_fin_declaracion);
		$criteria->order = 'unid_codigo_pk DESC';

		$unidad_tributaria = SidcaiUnidadtributaria::model()->findAll($criteria);

		$fecha_ut = "";
		$valor_UT = 0;

		if($unidad_tributaria != NULL){
			// Se suman los 183 dias a las fecha de comienzo, y aquella fecha que no supere la fecha de fin es el registro correcto.
			foreach($unidad_tributaria as $uni){
				$fecha_inicio_sumada = date("Y-m-d",strtotime($uni->unid_fechacomienzo." +183 day")); 

				if(strtotime($fecha_inicio_sumada) < strtotime($fecha_fin_declaracion)){
					$fecha_ut = $uni->unid_fechacomienzo;
					$valor_UT = $uni->unid_valor;
					break;
				}			
			}
		}

		$moneda = self:: obtenerMoneda($fecha_ut);

		return ($moneda != "") ? $moneda : '';
	}

	/**
	 * Obtiene el monto con la reconversión en la fecha dada.
	 * $fecha => Tiene que ser la fecha del monto, si el monto es del 2015, la fecha tiene que ser "2015-xx-xx", así devolverá el monto con la reconversión actual.

	 * Es importante usarlo cuando hay un monto que el Aportante tiene que pagar, esto hará que le muestre el monto con la reconverisón vigente.

	 * El parametro $no_reconversion es usado en obtenerInteresesMoratorios.
	 */
	public static function reconversion(string $fecha, float $monto, bool $no_reconversion = false) : float{
		$model = SidcaiMoneda::model()->find(
			[
				'select' => 'mone_simbolo, mone_division, mone_fechainicio',
				'order'  => 'mone_codigo_pk DESC',
				'limit'  => 1
			]
		);
		$dividir = 1;
		$devolver = "";

		if($model != null && $no_reconversion == false){		
			// Se obtiene la moneda por medio de la fecha en la que se quiere saber la reconversión.	
			$moneda = self::obtenerMoneda($fecha);
			// Con la moneda obtenida, ya se puede saber todo el registro.
			$model2 = SidcaiMoneda::model()->find('mone_simbolo = :mone_simbolo', [':mone_simbolo' => $moneda]);

			if($model2 != null){
				if($model->mone_simbolo != $model2->mone_simbolo){				
					// Obtendrá los registros con las cuales se harán las divisiones.
					$division = SidcaiMoneda::model()->findAll(
						[
							'condition' => 'mone_codigo_pk >= :id',
							'params' 	=> [
								':id' => $model2->mone_codigo_pk,
							],
							'order' => 'mone_codigo_pk DESC'
						]
					);

					if($division != null){
						// // Hace la multiplicación para saber entre cuanto se tiene que dividir el monto.
						for($i = 0; $i < (count($division) - 1); $i++){
							$dividir = $dividir * $division[$i]['mone_division'];
						}
					}
				}

				$devolver = $monto / $dividir;
			}		
		}else{
			if($no_reconversion){
				$devolver = $monto;
			}
		}

		return $devolver;
	}


	/**
	 * Obtiene el valor de la Unidad Tributaria.
	 * Resta 1 año a la fecha de inicio de declaración para poder agarrar varios registro y obtener la fecha que tenga más de 183 días de vigencia.
	 */
	public static function obtenerUT(string $fecha_inicio_declaracion, string $fecha_fin_declaracion) : float{
		$fecha_inicio_declaracion = date("Y-m-d", strtotime($fecha_inicio_declaracion." -1 year"));
		$criteria = new CDbCriteria;
		$criteria->condition = 'unid_habilitado = true';
		$criteria->addBetweenCondition('unid_fechacomienzo', $fecha_inicio_declaracion, $fecha_fin_declaracion);
		$criteria->order = 'unid_codigo_pk DESC';

		$unidad_tributaria = SidcaiUnidadtributaria::model()->findAll($criteria);

		$UT		  = NULL;
		$valor_UT = 0;

		if($unidad_tributaria != NULL){
			// Se suman los 183 dias a las fecha de comienzo, y aquella fecha que no supere la fecha de fin es el registro correcto.
			foreach($unidad_tributaria as $uni){
				$fecha_inicio_sumada = date("Y-m-d",strtotime($uni->unid_fechacomienzo." +183 day")); 

				if(strtotime($fecha_inicio_sumada) < strtotime($fecha_fin_declaracion)){
					$valor_UT = $uni->unid_valor;
					break;
				}			
			}
		}else{
			$unidad_tributaria = SidcaiUnidadtributaria::model()->find(
				array(
					'limit' => 1,
					'order' => 'unid_codigo_pk DESC'
				)
			);

			$valor_UT = $unidad_tributaria->unid_valor;
		}


		if($valor_UT == 1200){
			if(strtotime($fecha_fin_declaracion) > strtotime("2018-08-20"))
				$valor_UT = $valor_UT / 100000;
		}

		return $valor_UT;
	}

	/****** En caso de que se quiera mostrar los errores de cada input, solo muestra un error a la vez. *******/
	public static function erroresModel($model, string $nombre_model) : string{
		$errores = "";
		
		foreach($model->errors as $key => $error){
			if(array_key_exists($key, $nombre_model::attributeLabels()))
				return "<b>".$nombre_model::attributeLabels()[$key]."</b>: ".$error[0];
		}

		return $errores;
	}

	/**
	 * Obtiene la cantidad de días que tiene el año solicitado
	 * Devuelve => 365 o 366
	 * Usada para sacar el Factor en los intereses moratorios
	 */
	public static function cal_days_in_year(string $year) : int{
	    $days = 0; 

	    for($month = 1; $month <= 12; $month++){ 
	    	$days = $days + cal_days_in_month(CAL_GREGORIAN, $month, $year);
	    }

	 return $days;
	}

	/**
	 * Valor del Petro
	 */
	public static function obtenerValorPetro() : float{
		// peticiones http php json
		// Código: https://parzibyte.me/blog/2019/08/21/peticion-http-php-json-formulario/

		$url = "https://petroapp-price.petro.gob.ve/price/";

		// Los datos JSON
		/*$datos = [
		    "coins" => ["PTR", "BTC"],
		    "fiats" => ["USD", "EUR", "RUB", "CNY", "BS"],
		];*/
		/*$datos = [
		    "coins" => ["PTR"],
		    "fiats" => ["BS"],
		];

		// Crear opciones de la petición HTTP
		$opciones = array(
		    "http" => array(
		        "header" => "Content-Type:application/json",
		        "method" => "POST",
		        "content" => json_encode($datos), # Agregar el contenido definido antes
		    ),
		);
		# Preparar petición
		$contexto = stream_context_create($opciones);
		# Hacerla
		$resultado = file_get_contents($url, false, $contexto);
		if($resultado === false){
		    return "Error en petición.";
		}

		# si no salimos allá arriba, todo va bien
		$resultado = json_decode($resultado);
		$valor_petro = $resultado->data->PTR->BS;*/
		$valor_petro = 35771706.47;

		return $valor_petro;
	}

	/**
	 * Obtener el resultado de una función sin redondear.
	 * Máximo hasta la cifra en $number "214748"
	 */
	public static function truncateFloat($number, $digitos){
	    $raiz = 10;
	    $multiplicador = pow ($raiz,$digitos);
	    $resultado = ((int)($number * $multiplicador)) / $multiplicador;
	    return number_format($resultado, $digitos, '.', '');
	}

	/**
	 * Permite a los perfiles enviados en el array acceder al contenido.
	 */
	public static function permitirPerfil(array $perfiles) : bool{
		$cantidad = count($perfiles);
		$existe = false;
		if($cantidad > 0){
			for($i = 0; $i < $cantidad; $i++){
				if(in_array($perfiles[$i], Yii::app()->user->getState("perfiles"))){	
					$existe = true;
					break;
				}
			}
		}

		return $existe;
	}


	/**
	 * Crea código QR.
	 */
	public static function crearQR(string $mensaje, $destino = null, $correcion, $tamano = 2, $padding = 2){
		require_once(Yii::app()->basePath . '/extensions/phpqrcode/qrlib.php');

		$qr_ec_level = QR_ECLEVEL_L;

		switch ($correcion) {
			case 'L':
				$qr_ec_level = QR_ECLEVEL_L;
				break;
			case 'M':
				$qr_ec_level = QR_ECLEVEL_M;
				break;
			case 'Q':
				$qr_ec_level = QR_ECLEVEL_Q;
				break;
			case 'H':
				$qr_ec_level = QR_ECLEVEL_H;
				break;
		}

		ob_start();
		QRCode::png($mensaje, $destino, $qr_ec_level, $tamano, $padding);
		$imageString = base64_encode( ob_get_contents() );
		ob_end_clean();

		return $imageString;
	}

	/**
	 * Verifica si la empresa tiene intereses moratorios y en caso de tenerlos devuelve el monto que le corresponde a sus interes moratorios.
	 */
	public static function obtenerInteresesMoratorios($declaracion, $array_declaraciones, $fecha_ultimo_pago = false, $para_intereses = false) : float{
		// Se importa el controlador para hacer uso del método "cal_days_in_year".

		$date = new DateTime("now", new DateTimeZone('America/Caracas'));

		$hoy = $date->format('Y-m-d');

		$anio = $date->format("Y");
		$dia  = $date->format('d');
		// Se obtiene los datos de la declaración a saber los intereses moratorios.
		$declaracion = SidcaiDeclaracioncti::model()->findByPk($declaracion);
		// Se busca la última declaración del array (puede exitir el caso de que tenga más de una declaración).
		$id_ultima_declaracion = $array_declaraciones[(count($array_declaraciones) - 1)];
		$ultima_declaracion = SidcaiDeclaracioncti::model()->findByPk($id_ultima_declaracion);

		// Se le da al Aportante 15 días para que pague sus Intereses Moratorios, de lo contrario tendrá un nuevo monto.
		if(count($array_declaraciones) > 1){
			$dias15 = date("Y-m-d", strtotime($ultima_declaracion->decl_fechadeclaracion."+ ".self::diasAfiscalizacion()." day"));
		}else{
			// Cuando solo tiene una sola declaración y pasó su fecha a declarar y pagar.
			$dias15 = date("Y-m-d", strtotime($ultima_declaracion->decl_fechadeclaracion."+ ".self::diasAfiscalizacion(true)." day"));
		}

		if(strtotime($hoy) <= strtotime($dias15) || $para_intereses){
			$hoy  = $ultima_declaracion->decl_fechadeclaracion;
			$fec  = explode("-", $declaracion->decl_fechadeclaracion);
			$dia  = $fec[2];
			$anio = $fec[0];
		}

		if($fecha_ultimo_pago){
			$array_declaraciones_string = implode(",", $array_declaraciones);
			// Se busca la fecha del último pago.
			$ultimo_pago = SidcaiDeclaracionDetalle::model()->find([
				'condition' => 'codigo_declaraciones = :codigo_declaraciones AND apor_codigo_fk = :apor_codigo_fk',
				'params' => [
					':codigo_declaraciones' => $array_declaraciones_string,
					':apor_codigo_fk' => $ultima_declaracion->apor_codigo_fk,
				],
				'order' => 'deta_codigo_pk DESC'
			]);


			if($ultimo_pago != null){
				$hoy  = $ultimo_pago->decl_fechapago;
				$fec  = explode("-", $ultimo_pago->decl_fechapago);
				$dia  = $fec[2];
				$anio = $fec[0];
			}
		}


		$fecha_inicio 		= $declaracion->decl_fechafin;
		// Se suma un día de su fecha fin para comenzar a calcular los intereses.
		$dia_desde_sumar 	= date("Y-m-d", strtotime($fecha_inicio."+1 day"));
		$fecha_inicio 		= $dia_desde_sumar;
		$fecha_inicio_array = explode("-", $fecha_inicio);

		$fecha_fin_array = explode('-', $hoy);

		$datetime1 = new DateTime($fecha_inicio, new DateTimeZone('America/Caracas'));
		$datetime2 = new DateTime($hoy, new DateTimeZone('America/Caracas'));

		# obtenemos la diferencia entre las dos fechas
		$interval = $datetime2->diff($datetime1);

		# obtenemos la diferencia en meses
		$intervalMeses = $interval->format("%m");
		# obtenemos la diferencia en años y la multiplicamos por 12 para tener los meses
		$intervalAnos = $interval->format("%y")*12;

		$meses = $intervalMeses + $intervalAnos;


		// Obtiene desde que mes se va a obtener los intereses
		if($fecha_inicio_array[1] > 9){
		    $desde_mes = $fecha_inicio_array[1]; 
		}else{
		    $desde_mes = ($fecha_inicio_array[1] / 10 * 10);
		}

		$contador = 0;
		$anio = $fecha_inicio_array[0];
		$mes = $desde_mes;

		$dia = $fecha_inicio_array[2];

		$connection = Yii::app()->db;

		$no_reconversion = ($para_intereses) ? true : false;

		$deuda = self::reconversion($declaracion->decl_fechadeclaracion, $declaracion->decl_montorequerido, $no_reconversion);

		$intereses_moratorios = 0.00;

		for($i = $desde_mes; $i <= ($meses + $desde_mes); $i++){
		    if($mes > 12){
		        $mes = 1;
		        $anio++;
		    }

		    if($mes < 10)
		        $mes = "0$mes"; 


		    $fecha = "$anio-$mes-01";

		    // Se obtiene cuantos días hay en el mes.
		    $dias_en_mes = date('t', strtotime($fecha));

		    $sql = "SELECT tasa_interes FROM sidcai_tasainteres WHERE :fecha >= tasa_fechainicio AND :fecha <= (CASE WHEN tasa_fechafin != null THEN tasa_fechafin ELSE '2099-12-31' END) ORDER BY tasa_codigo_pk DESC LIMIT 1";
		    $command = $connection->createCommand();
		    $command->text = $sql;
		    $command->bindParam(':fecha', $fecha);
		    $model = $command->queryRow();

		    $dias_en_anio = self::cal_days_in_year($anio);

		    $fecha = "$anio-$mes-$dias_en_mes";


		    $tasa_interes       = $model['tasa_interes'];
		    $tasa_incrementada  = $tasa_interes * 1.2;
		    // $tasa_incrementada  = self::truncateFloat($tasa_incrementada, 4);
		    // $factor             = self::truncateFloat(($tasa_incrementada / 100 / 365), 11);
		    $tasa_incrementada  = bcdiv($tasa_incrementada, '1', 4);
		    $factor 			= bcdiv(($tasa_incrementada / 100 / 365), '1', 4);

		    $dia_factor = ($i == ($meses + $desde_mes)) ? $fecha_fin_array[2] : $dias_en_mes;

		    $resultado = $factor * $deuda * $dia_factor;
		    $intereses_moratorios += $resultado;
		    $mes++;
		}

		return bcdiv(self::reconversion($declaracion->decl_fechadeclaracion, $intereses_moratorios, $no_reconversion), '1', 2);
	}

	/**
	 * Devuelve el monto de la Multa Material
	 */
	public static function obtenerMultaMaterial(float $monto_requerido) : float{
		$multa_material = $monto_requerido / 2;

		return bcdiv($multa_material, '1', 2);
	}

	/**
	 * Obtiene los intereses moratorios desde el area de fiscalización.
	 */
	public static function obtenerInteresesMoratoriosMultaFormal(int $declaracion, array $array_declaraciones, array $array_declaraciones_multa, bool $para_intereses = false) : float{
		$date = new DateTime("now", new DateTimeZone('America/Caracas'));

		$hoy = $date->format('Y-m-d');

		$anio = $date->format("Y");
		$dia  = $date->format('d');
		// Se obtiene los datos de la declaración a saber los intereses moratorios.
		$declaracion = SidcaiDeclaracioncti::model()->findByPk($declaracion);
		// Se busca la última declaración del array (puede exitir el caso de que tenga más de una declaración).
		$id_ultima_declaracion = max($array_declaraciones);
		$ultima_declaracion = SidcaiDeclaracioncti::model()->findByPk($id_ultima_declaracion);

		// Se busca el último pago de la multa formal para dar 15 días que se van a congelar.
		$multa_colocada = SidcaiDeclaracionMulta::model()->find([
			'condition' => 'decl_codigo_fk = :decl_codigo_fk AND mult_codigo_fk != :mult_codigo_fk AND mult_habilitada = :mult_habilitada',
			'params' => [
				':decl_codigo_fk' => max($array_declaraciones_multa),
				':mult_codigo_fk' => 1,
				':mult_habilitada' => TRUE
			]
		]);

		if($multa_colocada != null){
			// Se le da al Aportante 15 días para que pague sus Intereses Moratorios, de lo contrario tendrá un nuevo monto.
			$dias15 = date("Y-m-d", strtotime($multa_colocada->decl_mult_fecha."+15 day"));

			if(strtotime($hoy) <= strtotime($dias15) || $para_intereses){
				$hoy  = $multa_colocada->decl_mult_fecha;
			}
		}


		$fecha_inicio 		= $declaracion->decl_fechafin;
		// Se suma un día de su fecha fin para comenzar a calcular los intereses.
		$dia_desde_sumar 	= date("Y-m-d", strtotime($fecha_inicio."+1 day"));
		$fecha_inicio 		= $dia_desde_sumar;
		$fecha_inicio_array = explode("-", $fecha_inicio);

		$fecha_fin_array = explode('-', $hoy);

		$datetime1 = new DateTime($fecha_inicio, new DateTimeZone('America/Caracas'));
		$datetime2 = new DateTime($hoy, new DateTimeZone('America/Caracas'));

		# obtenemos la diferencia entre las dos fechas
		$interval = $datetime2->diff($datetime1);

		# obtenemos la diferencia en meses
		$intervalMeses = $interval->format("%m");
		# obtenemos la diferencia en años y la multiplicamos por 12 para tener los meses
		$intervalAnos = $interval->format("%y")*12;

		$meses = $intervalMeses + $intervalAnos;


		// Obtiene desde que mes se va a obtener los intereses
		if($fecha_inicio_array[1] > 9){
		    $desde_mes = $fecha_inicio_array[1]; 
		}else{
		    $desde_mes = ($fecha_inicio_array[1] / 10 * 10);
		}

		$contador = 0;
		$anio = $fecha_inicio_array[0];
		$mes = $desde_mes;

		$dia = $fecha_inicio_array[2];

		$connection = Yii::app()->db;
		$deuda = self::reconversion($declaracion->decl_fechadeclaracion, $declaracion->decl_montorequerido);

		$intereses_moratorios = 0.00;

		for($i = $desde_mes; $i <= ($meses + $desde_mes); $i++){
		    if($mes > 12){
		        $mes = 1;
		        $anio++;
		    }

		    if($mes < 10)
		        $mes = "0$mes"; 

		    $fecha = "$anio-$mes-01";

		    // Se obtiene cuantos días hay en el mes.
		    $dias_en_mes = date('t', strtotime($fecha));

		    $sql = "SELECT tasa_interes FROM sidcai_tasainteres WHERE :fecha >= tasa_fechainicio AND :fecha <= (CASE WHEN tasa_fechafin != null THEN tasa_fechafin ELSE '2099-12-31' END) ORDER BY tasa_codigo_pk DESC LIMIT 1";
		    $command = $connection->createCommand();
		    $command->text = $sql;
		    $command->bindParam(':fecha', $fecha);
		    $model = $command->queryRow();

		    $dias_en_anio = self::cal_days_in_year($anio);

		    $fecha = "$anio-$mes-$dias_en_mes";

		    $tasa_interes       = $model['tasa_interes'];
		    $tasa_incrementada  = $tasa_interes * 1.2;
		    $tasa_incrementada  = bcdiv($tasa_incrementada, '1', 4);
		    $factor 			= bcdiv(($tasa_incrementada / 100 / 365), '1', 4);

		    $dia_factor = ($i == ($meses + $desde_mes)) ? $fecha_fin_array[2] : $dia_factor = $dias_en_mes;

		    $resultado = $factor * $deuda * $dia_factor;
		    $intereses_moratorios += $resultado;
		    $mes++;
		}

		return bcdiv($intereses_moratorios, '1', 2);
	}

	/**
	 * Obtiene el fin del periodo gravable.
	 */
	public static function obtenerFinPeriodoGravable(string $inicio_periodo_grvable) : string{
		$fecha_fin_declarar =  new DateTime($inicio_periodo_grvable);;
		$fecha_fin_declarar = self::addYears($fecha_fin_declarar, +1);
		$fecha_fin_declarar = $fecha_fin_declarar->format('Y-m-d');
		return  date('Y-m-d', strtotime($fecha_fin_declarar."-1 day"));
	}

	/**
	 * Obtiene los periodos a declarar y pagar de la declaración.
	 */
	public function obtenerPeriodosDeclarar(string $fin_periodo_gravable) : array{
		$fin_periodo_gravable = self::convertirFecha($fin_periodo_gravable, "yyyy-mm-dd");

		$fecha_inicio_declarar =  new DateTime($fin_periodo_gravable);
		$fecha_inicio_declarar = self::addMonths($fecha_inicio_declarar, +3);
		$fecha_inicio_declarar = $fecha_inicio_declarar->format('Y-m-d');
		$fecha_inicio_declarar = date('Y-m-d', strtotime($fecha_inicio_declarar."+1 day"));

		$fecha_fin_declarar =  new DateTime($fecha_inicio_declarar);
		$fecha_fin_declarar = self::addMonths($fecha_fin_declarar, +3);
		$fecha_fin_declarar = $fecha_fin_declarar->format('Y-m-d');
		$fecha_fin_declarar = date('Y-m-d', strtotime($fecha_fin_declarar."-1 day"));

		return [
			'fecha_inicio_declarar' => $fecha_inicio_declarar,
			'fecha_fin_declarar' => $fecha_fin_declarar,
		];
	}

	/**
	 * Agrega un mes a la fecha de forma mas precisa.
	 * Código: https://www.php.net/manual/es/datetime.modify.php
	 */	
	public static function addMonths($date, $months){
	    $years = floor(abs($months / 12));
	    $leap = 29 <= $date->format('d');
	    $m = 12 * (0 <= $months?1:-1);
	    for ($a = 1;$a < $years;++$a) {
	        $date = addMonths($date, $m);
	    }
	    $months -= ($a - 1) * $m;
	   
	    $init = clone $date;
	    if (0 != $months) {
	        $modifier = $months . ' months';
	       
	        $date->modify($modifier);
	        if ($date->format('m') % 12 != (12 + $months + $init->format('m')) % 12) {
	            $day = $date->format('d');
	            $init->modify("-{$day} days");
	        }
	        $init->modify($modifier);
	    }
	   
	    $y = $init->format('Y');
	    if ($leap && ($y % 4) == 0 && ($y % 100) != 0 && 28 == $init->format('d')) {
	        $init->modify('+1 day');
	    }
	    return $init;
	}

	/**
	 * Agrega un año a la fecha de forma mas precisa.
	 * Código: https://www.php.net/manual/es/datetime.modify.php
	 */	
	public static function addYears($date, $years){
	    return self::addMonths($date, 12 * $years);
	}

	public static function cifras_en_letras($numero, $con_centimos = true){
		Yii::import('application.vendors.cifras_en_letras.CifrasEnLetras');

		$concatenar = "";

		if($con_centimos){		
			$centimos = explode(".", $numero);

			$concatenar = " céntimos";

			if(isset($centimos[1])){
				if($centimos[1] == 0.00){
					$concatenar = " sin céntimos";
				}
			}
		}

		return CifrasEnLetras::convertirNumeroEnLetras($numero).$concatenar;
	}

	/**
	 * Muestra las declaraciones en Verificar Pago.
	 */
	public static function mostrarDeclaracionesVerificarPago(array $declaraciones) : string{
		$tabla = "";

		if($declaraciones != null){
			for($i = 0; $i < count($declaraciones); $i++){
				$declaracion = SidcaiDeclaracioncti::model()->findByPk($declaraciones[$i]);

				$tabla .= "<tr>";
				$tabla .= "<td>$declaracion->decl_codigo_pk</td>";

				$fecha_declaracion = self::convertirFecha($declaracion->decl_fechadeclaracion, "dd/mm/yyyy");

				$tabla .= "<td>$fecha_declaracion</td>";
				$tabla .= "<td>".$declaracion->estaCodigoFk->esta_nombre."</td>";

				$ejercicio_economico = self::convertirFecha($declaracion->decl_fechainicio_base, "dd/mm/yyyy");
				$ejercicio_economico .= " " .self::convertirFecha($declaracion->decl_fechafin_base, "dd/mm/yyyy");

				$tabla .= "<td>$ejercicio_economico</td>";

				$tabla .= "<td>";
				$tabla .= "<button style='padding: 8px' type='button' class='btn btn-info' data-toggle='modal' data-target='#modalDeclaracion' title='Ver declaración' onclick='mostrarDeclaracion(".$declaracion->decl_codigo_pk.", $declaracion->apor_codigo_fk)' id='" .$declaracion->decl_codigo_pk. "'><i class='material-icons'>visibility</i></button>";

				if(strtotime($declaracion->decl_fechadeclaracion) > strtotime($declaracion->decl_fechafin)){				
					$tabla .= TbHtml::linkButton('<span class="material-icons">picture_as_pdf</span>', [
						'url' => Yii::app()->baseUrl.'/declaracion/acta_reparo/'.$declaracion->decl_codigo_pk,
						'class' => 'btn btn-danger btn-sm',
						'style' => 'padding: 8px',
						'target' => '_blank'
					]);
				}

				$tabla .= "</td>";
				$tabla .= "</tr>";
			}			
		}

		if($tabla == ""){
			$tabla = "<tr><td colspan='5'>No hay declaraciones</td></tr>";
		}

		return $tabla;
	}

	/**
	 * Muestra todas las declaraciones que tiene la empresa en las 2 base de datos.
	 */
	public static function mostrarDeclaraciones(array $declaraciones, string $rif) : string{
		$tabla = "";
		$tabla_historico = "";

		$rif_empresa = $rif;

		$sql = "SELECT apor_codigo_pk FROM sidcai_aportante WHERE apor_rif = :apor_rif AND esta_codigoestatus_fk = 2003";
		$comando = Yii::app()->db2->createCommand($sql);
		$comando->bindParam(":apor_rif", $rif_empresa);
		$empresa_historico = $comando->queryRow();
			
		$sql = "SELECT * FROM sidcai_declaracioncti WHERE apor_codigo_fk = :apor_codigo_fk ORDER BY decl_codigo_pk DESC";
		$comando = Yii::app()->db2->createCommand($sql);
		$comando->bindParam(':apor_codigo_fk', $empresa_historico['apor_codigo_pk']);
		$dcl = $comando->queryAll();

		if($dcl != null){
			foreach($dcl as $declaracion){
				$tabla_historico .= "<tr>";
				$tabla_historico .= "<td><a target='_blank' href='".Yii::app()->baseUrl."/analista/declaracion/".$declaracion['decl_codigo_pk']."'>".$declaracion['decl_codigo_pk']."</a></td>";

				$fecha_declaracion = self::convertirFecha($declaracion['decl_fechadeclaracion'], "dd/mm/yyyy");

				$tabla_historico .= "<td>".$fecha_declaracion."</td>";

				$ejercicio_economico = self::convertirFecha($declaracion['decl_fechainicio_base'], "dd/mm/yyyy");
				$ejercicio_economico .= " " .self::convertirFecha($declaracion['decl_fechafin_base'], "dd/mm/yyyy");
				$tabla_historico .= "<td>".$ejercicio_economico."</td>";

				$estatus = SidcaiEstatus::model()->findByPk($declaracion['esta_codigo_fk']);
				$tabla_historico .= "<td>" .$estatus->esta_nombre. "</td>";

				$tabla_historico .= "<td>";
				$tabla_historico .= "<button style='padding: 8px' type='button' class='btn btn-info' data-toggle='modal' data-target='#modalDeclaracion' title='Ver declaración' onclick='mostrarDeclaracion(".$declaracion['decl_codigo_pk'].", ".$declaracion['apor_codigo_fk'].")' id='" .$declaracion['decl_codigo_pk']. "'><i class='material-icons'>visibility</i></button>";

				$tabla_historico .= "</td>";

				$tabla_historico .= "</td>";
				$tabla_historico .= "</tr>";
			}
		}

		if($declaraciones != null){
			for($i = 0; $i < count($declaraciones); $i++){
				$declaracion = SidcaiDeclaracioncti::model()->findByPk($declaraciones[$i]);

				$tabla .= "<tr>";
				$tabla .= "<td><a target='_blank' href='".Yii::app()->baseUrl."/analista/declaracion/".$declaracion->decl_codigo_pk."'>".$declaracion->decl_codigo_pk."</a></td>";

				$fecha_declaracion = self::convertirFecha($declaracion->decl_fechadeclaracion, "dd/mm/yyyy");

				$tabla .= "<td>$fecha_declaracion</td>";

				$ejercicio_economico = self::convertirFecha($declaracion->decl_fechainicio_base, "dd/mm/yyyy");
				$ejercicio_economico .= " " .self::convertirFecha($declaracion->decl_fechafin_base, "dd/mm/yyyy");

				$tabla .= "<td>$ejercicio_economico</td>";
				
				$tabla .= "<td>".$declaracion->estaCodigoFk->esta_nombre."</td>";

				$tabla .= "<td>";
				$tabla .= "<button style='padding: 8px' type='button' class='btn btn-info' data-toggle='modal' data-target='#modalDeclaracion' title='Ver declaración' onclick='mostrarDeclaracion(".$declaracion->decl_codigo_pk.", $declaracion->apor_codigo_fk)' id='" .$declaracion->decl_codigo_pk. "'><i class='material-icons'>visibility</i></button>";

				$fecha_fin = date("Y-m-d",strtotime($declaracion->decl_fechafin." +".$declaracion->decl_dias_prorroga." day"));

				// Se busca si la declaración tiene otras relacionadas
				$tiene_relacionadas = SidcaiDeclaracionRelacionada::model()->find([
					'condition' => 'decl_codigo_fk = :decl_codigo_fk OR decl_atrasada_fk = :decl_atrasada_fk',
					'params' => [
						':decl_codigo_fk' => $declaraciones[$i],
						':decl_atrasada_fk' => $declaraciones[$i],
					]
				]);

				if(strtotime($declaracion->decl_fechadeclaracion) > strtotime(date('Y-m-d', strtotime($fecha_fin."+".$declaracion->decl_dias_prorroga." day"))) || $tiene_relacionadas != null){				
					$tabla .= TbHtml::linkButton('<span class="material-icons">picture_as_pdf</span>', [
						'url' => Yii::app()->baseUrl.'/declaracion/acta_reparo/'.$declaracion->decl_codigo_pk,
						'class' => 'btn btn-danger btn-sm',
						'style' => 'padding: 8px',
						'target' => '_blank'
					]);

					$id = $declaracion->decl_codigo_pk;

					if($tiene_relacionadas != null){
						$id = $tiene_relacionadas->decl_codigo_fk;
					}

					// Se busca multa formal
					$multa_formal = SidcaiDeclaracionMulta::model()->find([
						'condition' => 'decl_codigo_fk = :decl_codigo_fk AND mult_codigo_fk != :mult_codigo_fk AND mult_habilitada = :mult_habilitada',
						'params' => [
							':decl_codigo_fk' => $id,
							':mult_codigo_fk' => 1,
							':mult_habilitada' => TRUE
						]
					]);

					if($multa_formal != null){
						$tabla .= TbHtml::linkButton('<span class="material-icons">picture_as_pdf</span>', [
							'url' => Yii::app()->baseUrl.'/declaracion/acta_reparo_deberes_formales/'.$declaracion->decl_codigo_pk,
							'class' => 'btn btn-danger btn-sm',
							'style' => 'padding: 8px',
							'target' => '_blank'
						]);
					}
				}

				$tabla .= "</td>";
				$tabla .= "</tr>";
			}			
		}

		if($tabla == "" && $tabla_historico == ""){
			$tabla = "<tr><td colspan='5'>No hay declaraciones</td></tr>";
		}

		return $tabla.$tabla_historico;
	}


	/**
	 * Datos del Google Recaptcha V3
	 */
	public static function reCaptcha(string $token) {
		$secret = Yii::app()->params['recaptcha_key_secret'];
		$token = CHtml::encode($token);
		$response = file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=$secret&response=$token");
		$response = json_decode($response);
		return $response;
	}


	/**
	 * En caso de haber prorroga para las declaraciones
	 */
	public static function diasProrroga(string $fecha_fin) : int{
		$parametro = SidcaiParametro::model()->find();

		$date = new DateTime("now", new DateTimeZone('America/Caracas'));
		$hoy = $date->format('Y-m-d');

		$dias = 0;

		if(strtotime($hoy) <= strtotime($parametro->para_fecha_tope_prorroga)){
			if(strtotime($fecha_fin) < strtotime($parametro->para_fecha_tope_prorroga)){			
				$date1 = new DateTime($fecha_fin);
				$date2 = new DateTime($parametro->para_fecha_tope_prorroga);
				$diff = $date1->diff($date2);
				$dias = $diff->days;
			}
		}

		return $dias;
	}

	/**
	 * Cantidad de días que tienen que transcurrir para que la declaración sea enviada a fiscalización
	 * $una_declaracion => Sí es TRUE es que solo es cuando la empresa no está pagando con declaraciones atrasadas/relacionadas
	 */
	public static function diasAfiscalizacion($una_declaracion = false) : string{
		return "15";
	}


	/**
	 * Detalles de la declaración
	 * @return array
	 */
	public static function detallesDeclaracion(int $id_declaracion, string $codigo_declaraciones) : string{
		$detalle_declaracion = SidcaiDeclaracionDetalle::model()->findAll([
			'condition' => 'codigo_declaraciones = :codigo_declaraciones',
			'params' => [':codigo_declaraciones' => $codigo_declaraciones],
			'order' => 'deta_codigo_pk DESC'
		]);

		$tabla = "";

		if($detalle_declaracion != null){
			$declaracion = SidcaiDeclaracioncti::model()->findByPk($id_declaracion);

			foreach($detalle_declaracion as $d){
				$monto_detalle = FuncionesController::obtenerMoneda($d->decl_fechapago)." ".number_format($d->decl_monto, 2, ',', '.');

				// Fecha de pago
				$fecha_pago = FuncionesController::convertirFecha($d->decl_fechapago, "dd/mm/yyyy");

				// Fecha de registro del pago
				$fecha_registro = FuncionesController::convertirFecha($d->fecha_registro, "dd/mm/yyyy");

				// Modalidad
				$modalidad_pago = ($d->decl_modalidadpago == 2) ? 'Transferencia' : 'Desconocido';

				// Numero de cuenta bancaria con tooltip
				$cuenta = SidcaiBanco::model()->findByPk($d->banc_codigo_fk);
				$tooltip_banco = "<span data-tooltip='".$cuenta->banc_nombre."'>".$cuenta->banc_ruta."</span>";

				// Motivo de Rechazo
				$motivo_rechazo = "";
				if($d->rech_codigo_fk !== NULL){
					$m_rechazo = SidcaiRechazarPago::model()->findByPk($d->rech_codigo_fk);
					$motivo_rechazo = $m_rechazo->rech_descripcion;
				}

				// Monto
				$moneda = FuncionesController::obtenerMoneda($d->decl_fechapago);
				$monto  = $moneda." ".number_format($d->decl_monto, 2, ",", ".");

				if($d->analista_fk !== null)
					$analista_tooltip = "<span data-tooltip='".$d->analistaFk->usua_nombre." ".$d->analistaFk->usua_apellido."'>".$d->analistaFk->usua_documento."</span>";
				else
					$analista_tooltip = "";

				$usuario_auditor_tooltip = "N/A";

				if($d->audit_usua !== NULL)
					$usuario_auditor_tooltip = "<span data-tooltip='".$d->auditUsua->usua_nombre." ".$d->auditUsua->usua_apellido."'>".$d->auditUsua->usua_documento."</span>";


				if($d->decl_pago_aceptado === NULL)
					$estatus_pago = "<span class='text-dark font-weight-bold'>n/a</span>";
				else if($d->decl_pago_aceptado == FALSE)
					$estatus_pago = "<span class='text-danger font-weight-bold'>Rechazado</span>";
				else
					$estatus_pago = "<span class='text-success font-weight-bold'>Aceptado</span>";	


				$tabla .= '  
					<div class="card m-5">
					<div class="card-body">
				';

				$tabla .= '  
					<div class="row mb-2">
					<div class="col-12 col-sm-4">
					<b class="text-black-secondary">ID:</b> '.$d->deta_codigo_pk.'
					</div>
					<div class="col-12 col-sm-4">
					<b class="text-black-secondary">Fecha de Pago:</b> '.$fecha_pago.'
					</div>
					<div class="col-12 col-sm-4">
					<b class="text-black-secondary">Modalidad:</b> '.$modalidad_pago.' 
					</div>
					</div>
				';

				$tabla .= '  
					<div class="row mb-2">
					<div class="col-12 col-sm-4">
					<b class="text-black-secondary">Banco:</b> '.$tooltip_banco.'
					</div>
					<div class="col-12 col-sm-4">
					<b class="text-black-secondary">Referencia:</b> '.$d->decl_referencia.' 
					</div>
					<div class="col-12 col-sm-4">
					<b class="text-black-secondary">Monto:</b> '.$monto.' 
					</div>
					</div>
				';

				$tabla .= '  
					<div class="row mb-2">
					<div class="col-12 col-sm-4">
					<b class="text-black-secondary">Analista:</b> '.$analista_tooltip.'
					</div>
					<div class="col-12 col-sm-4">
					<b class="text-black-secondary">Auditor:</b> '.$usuario_auditor_tooltip.' 
					</div>
					<div class="col-12 col-sm-4">
					<b class="text-black-secondary">Alicuota:</b> '.$declaracion->decl_alicuota.' % 
					</div>
					</div>
				';

				$tabla .= '  
					<div class="row mb-2">
					<div class="col-12 col-sm-4">
					<b class="text-black-secondary">Estatus:</b> '.$estatus_pago.'
					</div>
					<div class="col-12 col-sm-8">
					<b class="text-black-secondary">Motivo:</b> '.$motivo_rechazo.' 
					</div>
					</div>
				';

				$tabla .= '  
					<div class="row mb-2">
					<div class="col-12 col-sm-4">
					<b class="text-black-secondary">Fecha Registro:</b> '.$fecha_registro.'
					</div>
					<div class="col-12 col-sm-4">
					</div>
					<div class="col-12 col-sm-4">
					<button style="padding: 10px" type="button" class="btn btn-warning" data-toggle="modal" data-target="#modalComprobante" title="Ver comprobante" onclick="comprobante('.$d->deta_codigo_pk.', 1)"><i class="fas fa-file-invoice"></i> comprobante</button>
					</div>
					</div>
				';

				$tabla .= '  
				   </div>
				   </div>
				';
			}			
		}else{
			$tabla = "<div class='text-center m5'>No hay datos.</div>";
		}
		
		return $tabla;
	}


	/**
	 * Comprobantes de la declaración TESORERIA
	 * @return array
	 */
	public static function comprobantesDeclaracionTesoreria(int $id_declaracion, string $codigo_declaraciones) : string{
		$detalle_declaracion = SidcaiDeclaracionDetalle::model()->findAll([
			'condition' => 'codigo_declaraciones = :codigo_declaraciones',
			'params' => [':codigo_declaraciones' => $codigo_declaraciones],
			'order' => 'deta_codigo_pk DESC'
		]);

		$tabla = "";

		if($detalle_declaracion != null){
			$declaracion = SidcaiDeclaracioncti::model()->findByPk($id_declaracion);

			foreach($detalle_declaracion as $d){
				$monto_detalle = FuncionesController::obtenerMoneda($d->decl_fechapago)." ".number_format($d->decl_monto, 2, ',', '.');

				// Fecha de pago
				$fecha_pago = FuncionesController::convertirFecha($d->decl_fechapago, "dd/mm/yyyy");

				// Fecha de registro del pago
				$fecha_registro = FuncionesController::convertirFecha($d->fecha_registro, "dd/mm/yyyy");

				// Modalidad
				$modalidad_pago = ($d->decl_modalidadpago == 2) ? 'Transferencia' : 'Desconocido';

				// Numero de cuenta bancaria con tooltip
				$cuenta = SidcaiBanco::model()->findByPk($d->banc_codigo_fk);
				$tooltip_banco = "<span data-tooltip='".$cuenta->banc_nombre."'>".$cuenta->banc_ruta."</span>";

				// Motivo de Rechazo
				$motivo_rechazo = "";
				if($d->rech_codigo_fk !== NULL){
					$m_rechazo = SidcaiRechazarPago::model()->findByPk($d->rech_codigo_fk);
					$motivo_rechazo = $m_rechazo->rech_descripcion;
				}

				// Monto
				$moneda = FuncionesController::obtenerMoneda($d->decl_fechapago);
				$monto  = $moneda." ".number_format($d->decl_monto, 2, ",", ".");

				if($d->analista_fk !== null)
					$analista_tooltip = "<span data-tooltip='".$d->analistaFk->usua_nombre." ".$d->analistaFk->usua_apellido."'>".$d->analistaFk->usua_documento."</span>";
				else
					$analista_tooltip = "";

				$usuario_auditor_tooltip = "N/A";

				if($d->audit_usua !== NULL)
					$usuario_auditor_tooltip = "<span data-tooltip='".$d->auditUsua->usua_nombre." ".$d->auditUsua->usua_apellido."'>".$d->auditUsua->usua_documento."</span>";


				if($d->decl_pago_aceptado === NULL)
					$estatus_pago = "<span class='text-dark font-weight-bold'>n/a</span>";
				else if($d->decl_pago_aceptado == FALSE)
					$estatus_pago = "<span class='text-danger font-weight-bold'>Rechazado</span>";
				else
					$estatus_pago = "<span class='text-success font-weight-bold'>Aceptado</span>";	


				$tabla .= '  
					<div class="card m-5">
					<div class="card-body">
				';

				$tabla .= '  
					<div class="row mb-2">
					<div class="col-12 col-sm-4">
					<b class="text-black-secondary">ID:</b> '.$d->deta_codigo_pk.'
					</div>
					<div class="col-12 col-sm-4">
					<b class="text-black-secondary">Fecha de Pago:</b> '.$fecha_pago.'
					</div>
					<div class="col-12 col-sm-4">
					<b class="text-black-secondary">Modalidad:</b> '.$modalidad_pago.' 
					</div>
					</div>
				';

				$tabla .= '  
					<div class="row mb-2">
					<div class="col-12 col-sm-4">
					<b class="text-black-secondary">Banco:</b> '.$tooltip_banco.'
					</div>
					<div class="col-12 col-sm-4">
					<b class="text-black-secondary">Referencia:</b> '.$d->decl_referencia.' 
					</div>
					<div class="col-12 col-sm-4">
					<b class="text-black-secondary">Monto:</b> '.$monto.' 
					</div>
					</div>
				';

				$tabla .= '  
					<div class="row mb-2">
					<div class="col-12 col-sm-4">
					<b class="text-black-secondary">Analista:</b> '.$analista_tooltip.'
					</div>
					<div class="col-12 col-sm-4">
					<b class="text-black-secondary">Auditor:</b> '.$usuario_auditor_tooltip.' 
					</div>
					<div class="col-12 col-sm-4">
					<b class="text-black-secondary">Alicuota:</b> '.$declaracion->decl_alicuota.' % 
					</div>
					</div>
				';

				$tabla .= '  
					<div class="row mb-2">
					<div class="col-12 col-sm-4">
					<b class="text-black-secondary">Estatus:</b> '.$estatus_pago.'
					</div>
					<div class="col-12 col-sm-8">
					<b class="text-black-secondary">Motivo:</b> '.$motivo_rechazo.' 
					</div>
					</div>
				';

				$tabla .= '  
					<div class="row mb-2">
					<div class="col-12 col-sm-4">
					<b class="text-black-secondary">Fecha Registro:</b> '.$fecha_registro.'
					</div>
					<div class="col-12 col-sm-4">
					</div>
					<div class="col-12 col-sm-4">
					<button style="padding: 10px" type="button" class="btn btn-warning" data-toggle="modal" data-target="#modalComprobante" title="Ver comprobante" onclick="comprobante('.$d->deta_codigo_pk.', 1)"><i class="fas fa-file-invoice"></i> comprobante</button>
					</div>
					</div>
				';

				$tabla .= '  
				   </div>
				   </div>
				';
			}			
		}else{
			$tabla = "<div class='text-center m5'>No hay datos.</div>";
		}
		
		return $tabla;
	}



	/**
	 * Devuelve un array
	 * Array y string con las declaraciones
	 * Array y string con las declaraciones con multa
	 * Si tiene multa
	 * Array con las declaraciones (object)
	 * Cantidad de declaraciones
	 * Id de la última declaración
	 * Cantidad de pagos realizados en la declaración sin multas formales
	 * Si la útlima declaración es extemporanea.

	 * El parametro solo el id de la declaración y el id de la empresa. 
	 */
	public static function obtenerDeclaraciones(int $id_declaracion, int $id_empresa) : array{
		$date = new DateTime("now", new DateTimeZone('America/Caracas'));
		$hoy = $date->format('Y-m-d');

		$tiene_multa = false;
		$array_declaraciones 				= [];
		$array_declaraciones_multa 			= [];
		$array_declaraciones_string 		= "";
		$array_declaraciones_multa_string 	= "";

		// Se busca primero si tiene declaraciones asociadas
		$tiene_declaraciones_asociadas = SidcaiDeclaracionRelacionada::model()->find([
			'condition' => 'decl_codigo_fk = :decl_codigo_fk OR decl_atrasada_fk = :decl_atrasada_fk',
			'params' => [
				':decl_codigo_fk' => $id_declaracion,
				':decl_atrasada_fk' => $id_declaracion,
			]
		]);

		if($tiene_declaraciones_asociadas != null){
			$declaraciones_asociadas = SidcaiDeclaracionRelacionada::model()->findAll([
				'condition' => 'decl_codigo_fk = :decl_codigo_fk',
				'params' => [
					':decl_codigo_fk' => $tiene_declaraciones_asociadas->decl_codigo_fk
				],
				'order' => 'decl_atrasada_fk ASC'
			]);

			foreach($declaraciones_asociadas as $da){
				array_push($array_declaraciones, $da->decl_atrasada_fk);
			}

			array_push($array_declaraciones, $tiene_declaraciones_asociadas->decl_codigo_fk);
		}else{
			array_push($array_declaraciones, $id_declaracion);
		}

		$array_declaraciones_string = implode(',', $array_declaraciones);

		$id_ultima_declaracion = max($array_declaraciones);

		// Cantidad de pagos realizados en la declaración.
		$pagos = SidcaiDeclaracionDetalle::model()->findAll([
			'condition' => 'codigo_declaraciones = :codigo_declaraciones AND apor_codigo_fk = :apor_codigo_fk AND decl_pago_aceptado = :decl_pago_aceptado',
			'params' => [
				':codigo_declaraciones' => $array_declaraciones_string,
				':apor_codigo_fk' 		=> $id_empresa,
				':decl_pago_aceptado' 	=> TRUE
			]
		]);

		$cantidad_pagos = count($pagos);

		// Si la ultima declaración es extemporanea.
		$extemporaneo = false;

		// Fecha de declaración de la última declaración.
		$fecha_declaracion_ultima = "";
		// Días de prorroga de la última declaración
		$dias_prorroga_ultima = null;

		$declaraciones = [];

		// Indica si la o las declaraciones posee un acta de recaudación.
		$posee_acta_recaudacion = true;

		for($i = 0; $i < count($array_declaraciones); $i++){
			$decl = SidcaiDeclaracioncti::model()->findByPk($array_declaraciones[$i]);

			if($decl->decl_montorequerido > 0.00 && (strtotime($hoy) > strtotime(date('Y-m-d', strtotime($decl->decl_fechafin."+".$decl->decl_dias_prorroga." day"))))){

				$consultar = false;

				if($id_ultima_declaracion == $decl->decl_codigo_pk){
					if($decl->esta_codigo_fk == 1003){
						// Es para cuando se está consultando y no agarre que la declaración que ya finalizó como exitosa la agarre como extemporanea.
						$consultar = true;
					}

					$extemporaneo = true;

					if($pagos != null){

						if(($pagos[($cantidad_pagos - 1)]->decl_pago_aceptado == TRUE) && (strtotime($pagos[($cantidad_pagos - 1)]->decl_fechapago) <= strtotime(date('Y-m-d', strtotime($decl->decl_fechafin."+".$decl->decl_dias_prorroga." day")))))
							$posee_acta_recaudacion = false;
					}
				}

				if($consultar == false){
					array_push($array_declaraciones_multa, $decl->decl_codigo_pk);
				}
			}

			array_push($declaraciones, $decl);
		}

		if($array_declaraciones_multa != null){
			$tiene_multa = true;
			$array_declaraciones_multa_string = implode(",", $array_declaraciones_multa);
		}		


		// Verifica si tiene multa formal
		$tiene_multa_formal = false;

		for($i = 0; $i < count($array_declaraciones_multa); $i++){
			$verificando_multa_formal = SidcaiDeclaracionMulta::model()->find([
				'condition' => 'decl_codigo_fk = :decl_codigo_fk AND mult_codigo_fk != :mult_codigo_fk AND mult_habilitada = :mult_habilitada',
				'params' => [
					':decl_codigo_fk' => $array_declaraciones_multa[$i],
					':mult_codigo_fk' => 1,
					':mult_habilitada' => TRUE
				]
			]);

			if($verificando_multa_formal != null){
				$tiene_multa_formal = true;
				break;
			}
		}

		return [
			'tiene_multa' 						=> $tiene_multa,
			'array_declaraciones' 				=> $array_declaraciones,
			'array_declaraciones_string' 		=> $array_declaraciones_string,
			'array_declaraciones_multa' 		=> $array_declaraciones_multa,
			'array_declaraciones_multa_string' 	=> $array_declaraciones_multa_string,
			'declaraciones' 					=> $declaraciones,
			'cantidad_declaraciones'			=> count($array_declaraciones),
			'cantidad_declaraciones_multa'		=> count($array_declaraciones_multa),
			'id_ultima_declaracion'				=> $id_ultima_declaracion,
			'cantidad_pagos'					=> $cantidad_pagos,
			'extemporaneo'						=> $extemporaneo,
			'tiene_multa_formal'				=> $tiene_multa_formal,
			'posee_acta_recaudacion'			=> $posee_acta_recaudacion,
		];
	}

	/**
	 * Devuelve el monto total del aporte de una declaración (o declaraciones asociadas).
	 * Devuelve el monto con la reconversión (en caso de haber).
	 * El parametro solo necesita un array con todas la declaraciones. 
	 * El parametro "$consultar" solo es para cuando se quiera consultar el monto, esto es para que no se haga la reconversión en caso de haber.
	 */
	public static function obtenerMontoAporte(array $array_declaraciones, bool $consultar = false) : float{
		$monto_requerido_aporte = 0.00;

		for($i = 0; $i < count($array_declaraciones); $i++){
			$decl = SidcaiDeclaracioncti::model()->findByPk($array_declaraciones[$i]);

			if($consultar)
				$monto_requerido_aporte += $decl->decl_montorequerido;
			else
				$monto_requerido_aporte += bcdiv($decl->decl_montorequerido, '1', 2);
		}

		return bcdiv($monto_requerido_aporte, '1', 2);
	}


	/**
	 * Devuelve el monto total de los intereses moratorios de una declaración que ya ha sido creada (o declaraciones asociadas).
	 * Devuelve el monto con la reconversión (en caso de haber).
	 * El parametro necesita un array de las declaraciones con multa y el id de la empresa.
	* El parametro "$consultar" solo es para cuando se quiera consultar el monto, esto es para que no se haga la reconversión en caso de haber.
	 */
	public static function obtenerMontosInteresesMoratorios(array $array_declaraciones_multa, int $id_empresa, bool $consultar = false, bool $tiene_multa_formal) : float{
		$monto_requerido_intereses = 0.00;

		for($i = 0; $i < count($array_declaraciones_multa); $i++){
			$intereses = SidcaiMultaInteres::model()->find([
				'select' => 'mult_monto, fecha_registro',
				'condition' => 'decl_codigo_fk = :decl_codigo_fk AND mult_habilitada = :mult_habilitada AND apor_codigo_fk = :apor_codigo_fk AND multa_formal = :multa_formal',
				'params' => [
					':decl_codigo_fk' => $array_declaraciones_multa[$i],
					':mult_habilitada' => TRUE,
					':apor_codigo_fk' => $id_empresa,
					':multa_formal' => $tiene_multa_formal
				]

			]);

			if($intereses != null){
				if($consultar)
					$monto_requerido_intereses += $intereses->mult_monto;
				else
					$monto_requerido_intereses += bcdiv(self::reconversion($intereses->fecha_registro, $intereses->mult_monto), '1', 2);
			}
		}


		return bcdiv($monto_requerido_intereses, '1', 2);
	}

	/**
	 * Devuelve el monto total de la multa material de una declaración que ya ha sido creada (o declaraciones asociadas).
	 * Devuelve el monto con la reconversión (en caso de haber).
	 * El parametro solo necesita un array de las declaraciones con multa.
	 * El parametro "$consultar" solo es para cuando se quiera consultar el monto, esto es para que no se haga la reconversión en caso de haber.
	 */
	public static function obtenerMontosMultaMaterial(array $array_declaraciones_multa, bool $consultar = false) : float{
		$monto_requerido_multa_material = 0.00;

		for($i = 0; $i < count($array_declaraciones_multa); $i++){		
			$multa_material = SidcaiDeclaracionMulta::model()->find([
				'select' => 'decl_mult_monto, decl_mult_fecha',
				'condition' => 'decl_codigo_fk = :decl_codigo_fk AND mult_habilitada = :mult_habilitada',
				'params' => [
					':decl_codigo_fk' => $array_declaraciones_multa[$i],
					':mult_habilitada' => TRUE,
				]

			]);

			if($multa_material != null){			
				if($consultar)
					$monto_requerido_multa_material += $multa_material->decl_mult_monto;
				else
					$monto_requerido_multa_material += bcdiv(self::reconversion($multa_material->decl_mult_fecha, $multa_material->decl_mult_monto), '1', 2);
			}
		}

		return bcdiv($monto_requerido_multa_material, '1', 2);
	}

	public static function obtenerMontosMultaFormal(array $array_declaraciones_multa, bool $consultar = false){
		$monto_requerido_multa_formal = 0.00;

		if(count($array_declaraciones_multa) > 0 && !empty($array_declaraciones_multa)){
			$multa_formal = SidcaiDeclaracionMulta::model()->findAll([
				'select' => 'decl_mult_monto, decl_mult_fecha',
				'condition' => 'decl_codigo_fk = :decl_codigo_fk AND mult_habilitada = :mult_habilitada AND mult_codigo_fk != :mult_codigo_fk',
				'params' => [
					':decl_codigo_fk' => $array_declaraciones_multa[0],
					':mult_habilitada' => TRUE,
					':mult_codigo_fk' => 1
				]
			]);

			if($multa_formal != null){
				foreach($multa_formal as $m){
					if($consultar)
						$monto_requerido_multa_formal += $m->decl_mult_monto;
					else
						$monto_requerido_multa_formal += bcdiv(self::reconversion($m->decl_mult_fecha, $m->decl_mult_monto), '1', 2);
				}
			}
		}

		return bcdiv($monto_requerido_multa_formal, '1', 2);
	}

	/**
	 * Devuelve el monto Aportado por la empresa.
	  * El tercer parametro solo es para cuando se quiera consultar el monto, esto es para que no se haga la reconversión en caso de haber.
	  * El parametro "$consultar" solo es para cuando se quiera consultar el monto, esto es para que no se haga la reconversión en caso de haber.
	 */
	public static function obtenerMontoAportado(array $declaraciones, int $id_empresa, bool $consultar = false) : float{
		$monto_aportado = 0.00;

		$detalles = SidcaiDeclaracionDetalle::model()->findAll([
			'condition' => 'codigo_declaraciones = :codigo_declaraciones AND apor_codigo_fk = :apor_codigo_fk AND decl_pago_aceptado = :decl_pago_aceptado',
			'params' => [
				':codigo_declaraciones' => $declaraciones['array_declaraciones_string'],
				':apor_codigo_fk' => $id_empresa,
				':decl_pago_aceptado' => TRUE
			]
		]);

		if($detalles != null){
			foreach($detalles as $d){
				if($consultar)
					$monto_aportado += $d->decl_monto;
				else
					$monto_aportado += bcdiv(self::reconversion($d->decl_fechapago, $d->decl_monto), '1', 2);
			}

			$monto_aportado = bcdiv($monto_aportado, '1', 2);
		}

		return $monto_aportado;
	}

	/**
	 *	Devuelve el monto requerido que la empresa tiene que aportar (incluyendo los intereses de mora, multa material y multa formal)
	 */
	public static function obtenerMontoRequerido(array $declaraciones, int $id_empresa, bool $consultar = false) : float{
		$monto_aporte = self::obtenerMontoAporte($declaraciones['array_declaraciones']);
		$monto_intereses = 0.00;
		$monto_multa_material = 0.00;
		$monto_multa_formal = 0.00;

		if($declaraciones['tiene_multa']){
			$monto_intereses 		= self::obtenerMontosInteresesMoratorios($declaraciones['array_declaraciones_multa'], $id_empresa, $consultar, $declaraciones['tiene_multa_formal']);
			$monto_multa_material 	= self::obtenerMontosMultaMaterial($declaraciones['array_declaraciones_multa'], $consultar);
			$monto_multa_formal = self::obtenerMontosMultaFormal($declaraciones['array_declaraciones_multa'], $consultar);
		}

		return bcdiv(($monto_aporte + $monto_intereses + $monto_multa_material + $monto_multa_formal), '1', 2);
	}

	/**
	 * Devuelve el monto faltante de la suma de Aporte y en caso de tener intereses moratorios y multa material.
	 */
	public static function obtenerMontoFaltante(array $declaraciones, int $id_empresa, bool $consultar = false) : float{
		// Se busca si tiene crédito fiscal
		$buscar_credito = SidcaiCreditoFiscal::model()->find([
			'condition' => '(apor_codigo_fk = :apor_codigo_fk AND cred_habilitado = :cred_habilitado) OR (apor_codigo_fk = :apor_codigo_fk AND decl_codigo_fk_destino = :decl_codigo_fk_destino) ',
			'params' => [
				':apor_codigo_fk' => $id_empresa,
				':cred_habilitado' => TRUE,
				':decl_codigo_fk_destino' => $declaraciones['id_ultima_declaracion'],
			]
		]);

		$monto_credito_fiscal = 0.00;

		if($buscar_credito != null){
			if($consultar)
				$monto_credito_fiscal = $buscar_credito->cred_monto;
			else
				$monto_credito_fiscal = self::reconversion($buscar_credito->cred_fecha, $buscar_credito->cred_monto);
			$monto_credito_fiscal = bcdiv($monto_credito_fiscal, '1', 2);
		}

		$monto_requerido = self::obtenerMontoRequerido($declaraciones, $id_empresa, $consultar);
		$monto_aportado  = self::obtenerMontoAportado($declaraciones, $id_empresa, $consultar);
		$monto_aportado = $monto_aportado + $monto_credito_fiscal;

		$monto_faltante = $monto_requerido - $monto_aportado;

		return bcdiv($monto_faltante, '1', 2);
	}


	/**
	 * Crea un nuevo registro de Intereses Moratorios y Multa Material (En caso de que hallan cambiado por que la empresa aún no ha pagado y se pasó su 15 días o su última declaración se volvió extemporanea)
	 */
	public static function revisarInteresesMulta(array $declaraciones, int $id_empresa) : bool{
		if($declaraciones['tiene_multa']){
			$date = new DateTime("now", new DateTimeZone('America/Caracas')); 
			$hoy = $date->format('Y-m-d H:i:s');

			$declaracion = SidcaiDeclaracioncti::model()->findByPk($declaraciones['array_declaraciones'][0]);

			$transaction = $declaracion->dbConnection->beginTransaction();

			$analista = null;

			// Se busca el analista que tiene asignado la declaración.
			$buscar_analista = SidcaiDeclaracionAnalista::model()->find([
				'select' => 'usua_codigo_fk',
				'condition' => 'decl_codigo_fk = :decl_codigo_fk AND usua_habilitado = :usua_habilitado',
				'params' => [
					':decl_codigo_fk' => $declaraciones['id_ultima_declaracion'],
					'usua_habilitado' => TRUE
				]
			]);

			if($buscar_analista != null)
				$analista = $buscar_analista->usua_codigo_fk;

			// Intereses Moratorios
			for($i = 0; $i < count($declaraciones['array_declaraciones_multa']); $i++){	
				$monto = 0.00;
				$monto_del_dia = 0.00;

				if($declaraciones['tiene_multa_formal'])
					$monto_del_dia = self::obtenerInteresesMoratoriosMultaFormal($declaraciones['array_declaraciones_multa'][$i], $declaraciones['array_declaraciones'], $declaraciones['array_declaraciones_multa']);
				else
					$monto_del_dia = self::obtenerInteresesMoratorios($declaraciones['array_declaraciones_multa'][$i], $declaraciones['array_declaraciones'], false, false);
                // arreglo de bug del recalculo de interes moratorio
				$intereses = SidcaiMultaInteres::model()->find([
					//'select' => 'fecha_registro, mult_monto, analista_fk, mult_habilitada,decl_codigo_fk',
					'condition' => 'decl_codigo_fk = :decl_codigo_fk AND mult_habilitada = :mult_habilitada AND multa_formal = :multa_formal',
					'params' => [
						':decl_codigo_fk' 	=> $declaraciones['array_declaraciones_multa'][$i],
						':mult_habilitada' 	=> TRUE,
						':multa_formal' 	=> $declaraciones['tiene_multa_formal']
					],
					'order' => 'mult_codigo_pk DESC'
				]);

				if($intereses != null){
					$monto = bcdiv(self::reconversion($intereses->fecha_registro, $intereses->mult_monto), '1', 2);

					if($monto != $monto_del_dia){	
						$intereses->mult_habilitada = 0;
						if(!$intereses->save()){
							$transaction->rollBack();
							return false;
						}

						$nuevo_intereses = new SidcaiMultaInteres;
						$nuevo_intereses->apor_codigo_fk 	= $id_empresa;
						$nuevo_intereses->decl_codigo_fk  	= $declaraciones['array_declaraciones_multa'][$i];
						$nuevo_intereses->mult_monto 		= $monto_del_dia;
						$nuevo_intereses->analista_fk 		= $analista;
						$nuevo_intereses->fecha_registro 	= $hoy;

						if(!$nuevo_intereses->save()){
							$transaction->rollBack();
							return false;
						}
					}
				}else{
					// Ingresará al else si la última declaración pasó a ser extemporanea
					$nuevo_intereses = new SidcaiMultaInteres;
					$nuevo_intereses->apor_codigo_fk 	= $id_empresa;
					$nuevo_intereses->decl_codigo_fk  	= $declaraciones['array_declaraciones_multa'][$i];
					$nuevo_intereses->mult_monto 		= $monto_del_dia;
					$nuevo_intereses->analista_fk 		= $analista;
					$nuevo_intereses->fecha_registro 	= $hoy;

					if(!$nuevo_intereses->save()){
						$transaction->rollBack();
						return false;
					}
				}
			}


			// Multa material
			for($i = 0; $i < count($declaraciones['array_declaraciones_multa']); $i++){	
				$monto = 0.00;
				$monto_del_dia = 0.00;

				$declaracion = SidcaiDeclaracioncti::model()->findByPk($declaraciones['array_declaraciones_multa'][$i]);
				$monto_del_dia = self::obtenerMultaMaterial($declaracion->decl_montorequerido);
                // arreglando la multa material
				$multa_material = SidcaiDeclaracionMulta::model()->find([
					//'select' => 'decl_mult_fecha, decl_mult_monto, usua_codigo_fk, mult_habilitada',
					'condition' => 'decl_codigo_fk = :decl_codigo_fk AND mult_habilitada = :mult_habilitada AND mult_codigo_fk = :mult_codigo_fk',
					'params' => [
						':decl_codigo_fk' 	=> $declaraciones['array_declaraciones_multa'][$i],
						':mult_habilitada' 	=> TRUE,
						':mult_codigo_fk' 	=> 1
					],
					'order' => 'decl_mult_codigo_pk DESC'
				]);

				if($multa_material != null){
					$monto = bcdiv(self::reconversion($multa_material->decl_mult_fecha, $multa_material->decl_mult_monto), '1', 2);
				   
					if($monto != $monto_del_dia){
						$multa_material->mult_habilitada = 0;
						if(!$multa_material->save()){
							$transaction->rollBack();
							return false;
						}

						$nuevo_multa_material = new SidcaiDeclaracionMulta;
						$nuevo_multa_material->decl_codigo_fk 	= $declaraciones['array_declaraciones_multa'][$i];
						$nuevo_multa_material->usua_codigo_fk 	= $analista;
						$nuevo_multa_material->mult_codigo_fk  	= 1;
						$nuevo_multa_material->decl_mult_monto 	= $monto_del_dia;
						$nuevo_multa_material->decl_mult_fecha 	= $hoy;

						if(!$nuevo_multa_material->save()){
							$transaction->rollBack();
							return false;
						}
					}
				}else{
					$nuevo_multa_material = new SidcaiDeclaracionMulta;
					$nuevo_multa_material->decl_codigo_fk 	= $declaraciones['array_declaraciones_multa'][$i];
					$nuevo_multa_material->usua_codigo_fk 	= $analista;
					$nuevo_multa_material->mult_codigo_fk  	= 1;
					$nuevo_multa_material->decl_mult_monto 	= $monto_del_dia;
					$nuevo_multa_material->decl_mult_fecha 	= $hoy;

					if(!$nuevo_multa_material->save()){
						$transaction->rollBack();
						return false;
					}
				}
			}

			$transaction->commit();
		}
		return true;
	}


	/**
	 * Devuelve los montos de los intereses en un array con su respectiva declaración en el acta de reparo de recaúdaíón.
	 */
	public static function detallesInteresesMoratoriosActa(array $array_declaraciones_multa, bool $consultar = false, bool $fiscalizacion = false) : array{
		$devolver = [];

		for($i = 0; $i < count($array_declaraciones_multa); $i++){	
			if($fiscalizacion){
				$intereses = SidcaiMultaInteres::model()->find([
					'select' => 'fecha_registro, mult_monto, mult_habilitada',
					'condition' => 'decl_codigo_fk = :decl_codigo_fk AND multa_formal = :multa_formal',
					'params' => [
						':decl_codigo_fk' 	=> $array_declaraciones_multa[$i],
						':multa_formal' 	=> TRUE,
					],
					'order' => 'mult_codigo_pk DESC'
				]);

				if($intereses != null){
					if($consultar){
						if($intereses->mult_habilitada == true)
							$monto = $intereses->mult_monto;
						else
							continue;
					}
					else
						$monto = bcdiv(self::reconversion($intereses->fecha_registro, $intereses->mult_monto), '1', 2);

					$devolver[$array_declaraciones_multa[$i]] = bcdiv($monto, '1', 2);
				}
			}else{
				// Primero se verifica si existe intereses con multa formal
				$existe_multa_formal = SidcaiMultaInteres::model()->find([
					'select' => 'mult_habilitada',
					'condition' => 'decl_codigo_fk = :decl_codigo_fk AND multa_formal = :multa_formal',
					'params' => [
						':decl_codigo_fk' 	=> $array_declaraciones_multa[$i],
						':multa_formal' 	=> TRUE,
					],
					'order' => 'mult_codigo_pk DESC'
				]);

				$tiene_multa_formal = ($existe_multa_formal != null) ? true : false;

				$intereses = SidcaiMultaInteres::model()->find([
					'select' => 'fecha_registro, mult_monto, mult_habilitada',
					'condition' => 'decl_codigo_fk = :decl_codigo_fk AND multa_formal = :multa_formal',
					'params' => [
						':decl_codigo_fk' 	=> $array_declaraciones_multa[$i],
						':multa_formal' 	=> FALSE,
					],
					'order' => 'mult_codigo_pk DESC'
				]);

				if($intereses != null){
					if($consultar){
						if($intereses->mult_habilitada == true || $tiene_multa_formal == true)
							$monto = $intereses->mult_monto;
						else
							continue;
					}
					else
						$monto = bcdiv(self::reconversion($intereses->fecha_registro, $intereses->mult_monto), '1', 2);

					$devolver[$array_declaraciones_multa[$i]] = bcdiv($monto, '1', 2);
				}
			}
		}

		return $devolver;
	}

	/**
	 * Devuelve los montos de los intereses en un array con su respectiva declaración
	 * 150000 => 49416.15
	 * 150001 => 4324325.43
	 * 150002 => 496546547416.75
	 */
	public static function detallesInteresesMoratorios(array $array_declaraciones_multa, bool $consultar = false, bool $tiene_multa_formal = false) : array{
		$devolver = [];


		for($i = 0; $i < count($array_declaraciones_multa); $i++){	

			$intereses = SidcaiMultaInteres::model()->find([
				'select' => 'fecha_registro, mult_monto',
				'condition' => 'decl_codigo_fk = :decl_codigo_fk AND mult_habilitada = :mult_habilitada AND multa_formal = :multa_formal',
				'params' => [
					':decl_codigo_fk' 	=> $array_declaraciones_multa[$i],
					':mult_habilitada' 	=> TRUE,
					':multa_formal' 	=> $tiene_multa_formal,
				],
				'order' => 'mult_codigo_pk DESC'
			]);

			if($intereses != null){
				if($consultar)
					$monto = $intereses->mult_monto;
				else
					$monto = bcdiv(self::reconversion($intereses->fecha_registro, $intereses->mult_monto), '1', 2);

				$devolver[$array_declaraciones_multa[$i]] = bcdiv($monto, '1', 2);
			}
		}

		return $devolver;
	}

	/**
	 * Devuelve los montos de las multas materiales en un array con su respectiva declaración
	 * 150000 => 49416.15
	 * 150001 => 4324325.43
	 * 150002 => 496546547416.75
	 */
	public static function detallesMultaMaterial(array $array_declaraciones_multa, bool $consultar = false) : array{
		$devolver = [];

		for($i = 0; $i < count($array_declaraciones_multa); $i++){		
			$multa_material = SidcaiDeclaracionMulta::model()->find([
    			'select' => 'decl_mult_monto, decl_mult_fecha',
    			'condition' => 'decl_codigo_fk = :decl_codigo_fk AND mult_habilitada = :mult_habilitada AND mult_codigo_fk = :mult_codigo_fk',
    			'params' => [
    				':decl_codigo_fk' => $array_declaraciones_multa[$i],
    				':mult_habilitada' => TRUE,
    				':mult_codigo_fk' => 1
    			],
    			'order' => 'decl_mult_codigo_pk DESC'
    		]);

			if($multa_material != null){
				if($consultar)
					$monto = $multa_material->decl_mult_monto;
				else
					$monto = bcdiv(self::reconversion($multa_material->decl_mult_fecha, $multa_material->decl_mult_monto), '1', 2);

				$devolver[$array_declaraciones_multa[$i]] = bcdiv($monto, '1', 2);
			}
		}

		return $devolver;
	}



	/**
	 * Devuelve los montos de las multas formales en un array con su respectiva declaración
	 * 150000 => 49416.15
	 * 150001 => 4324325.43
	 * 150002 => 496546547416.75
	 */
	public static function detallesMultaFormal(array $array_declaraciones_multa, bool $consultar = false) : array{
		$devolver = [];

		for($i = 0; $i < count($array_declaraciones_multa); $i++){	
			$monto_for = 0.00;

			$multa_formal = SidcaiDeclaracionMulta::model()->findAll([
    			'select' => 'decl_mult_monto, decl_mult_fecha',
    			'condition' => 'decl_codigo_fk = :decl_codigo_fk AND mult_habilitada = :mult_habilitada AND mult_codigo_fk != :mult_codigo_fk',
    			'params' => [
    				':decl_codigo_fk' => $array_declaraciones_multa[$i],
    				':mult_habilitada' => TRUE,
    				':mult_codigo_fk' => 1
    			],
    			'order' => 'decl_mult_codigo_pk DESC'
    		]);

			if($multa_formal != null){
				foreach($multa_formal as $m){				
					if($consultar)
						$monto_for += $m->decl_mult_monto;
					else
						$monto_for += bcdiv(self::reconversion($m->decl_mult_fecha, $m->decl_mult_monto), '1', 2);
				}

				$devolver[$array_declaraciones_multa[$i]] = bcdiv($monto_for, '1', 2);
			}
		}

		return $devolver;
	}

	/**
	 * Obtiene el porcentaje de contribución de la empresa
	 */
	public static function porcentajeContribucion(int $id_ciiu) : string{
		$ciiu = SidcaiCiiu::model()->findByPk($id_ciiu);

		$devolver = "0.50";

		if($ciiu != null){
			$devolver = ($ciiu->ciiu_porcentaje_2010_priv == null) ? $ciiu->ciiu_porcentaje_2010 : $ciiu->ciiu_porcentaje_2010_priv;
		}

		return $devolver;
	}

	/**
	 * Devuelve TRUE si se requiere algo que solo sea cuando la empresa se encuentra durante el proceso de renovación.
	 */
	public static function mostrarRenovar(int $id_empresa) : bool{
		$empresa = SidcaiAportante::model()->findByPk($id_empresa);

        $dia_cierre = $empresa->apor_diacierre;
        $mes_cierre = $empresa->apor_mescierre;

        // Se verifica si el Aportante ha cambiado su Ejercicio Fiscal para obtener su última modificación de "Día" y "Mes".
        $existe = SidcaiEjercicioFiscal::model()->find(
            array(
                'condition' => 'apor_codigo_fk = :apor_codigo_fk',
                'params' => array(':apor_codigo_fk' => $id_empresa),
                'order' => 'ejercicio_fiscal_pk DESC',
            )
        );

        // Sí el aportante ha cambiado su Ejercicio Fiscal usará los datos del "SidcaiEjercicioFiscal".
        if($existe != null){
            $dia_cierre = $existe->apor_diacierre;
            $mes_cierre = $existe->apor_mescierre;
        }

        if($mes_cierre < 10){
        	$mes_cierre = "0".$mes_cierre;
        }

        $date = new DateTime("now", new DateTimeZone('America/Caracas'));
        $hoy_dia = $date->format('d');
        $hoy_mes = $date->format('m');
        $hoy_anio = $date->format('Y');
        $hoy = $date->format('Y-m-d');

        // Se busca la última declaración 
        $declaracion = SidcaiDeclaracioncti::model()->find([
            'select' => 'esta_codigo_fk, decl_fechadeclaracion, decl_fechafin_base',
            'condition' => 'apor_codigo_fk = :apor_codigo_fk AND (esta_codigo_fk = :estatus1  OR esta_codigo_fk = :estatus2 OR esta_codigo_fk = :estatus3 OR esta_codigo_fk = :estatus4 OR esta_codigo_fk = :estatus5 OR esta_codigo_fk = :estatus6 OR esta_codigo_fk = :estatus7)',
            'params' => [
            	':apor_codigo_fk' => $id_empresa,
            	':estatus1' => 1003,
            	':estatus2' => 1004,
            	':estatus3' => 1001,
            	':estatus4' => 1006,
            	':estatus5' => 1010,
            	':estatus6' => 1011,
            	':estatus7' => 1008,
            ],
            'order' => 'decl_codigo_pk DESC'
		]);
		


        if($declaracion != null){
        	if($declaracion->esta_codigo_fk == 1003 || $declaracion->esta_codigo_fk == 1004){
	        	// Si el año actual es el mismo que la declaración y el día y mes del cierre fiscal es igual que no muestre "Renovar"
	        	$anio_declaracion 	= explode("-", $declaracion->decl_fechadeclaracion);
				$fecha_fin_base 	= explode("-", $declaracion->decl_fechafin_base);
	        	/*if(intval($hoy_anio) > intval($anio_declaracion[0])){
	    			if(strtotime($hoy) > strtotime($declaracion->decl_fechadeclaracion)){
	        			if(strtotime($hoy) > strtotime($hoy_anio."-".$mes_cierre."-".$dia_cierre)){
	        				return true;
	        			}else{
	        				return false;
						}
						if(strtotime($hoy) > strtotime($declaracion->decl_fechafin_base.'+1 year')){
	        				return true;
	        			}else{
	        				return false;
						}
						
	        		}else{
	        			return false;
					}*/
					if(strtotime($hoy) > strtotime($declaracion->decl_fechafin_base.'+1 year')){
						return true;
					}
	        	/*}else
	        		return true;*/
        	}
        }

        return false;
	}


	/**
	 * Devuelve los datos de las multas formales seleccionadas
	 * @return array
	 */
	public static function multasFormalesSeleccionadas(int $id_declaracion) : array{
		$datos = [];

		$multas = [];

		// Se busca todas las multas formales seleccionadas
		$multas_formales = SidcaiDeclaracionMulta::model()->findAll([
			'select' => 'mult_codigo_fk',
			'condition' => 'decl_codigo_fk = :decl_codigo_fk AND mult_habilitada = :mult_habilitada AND mult_codigo_fk != :mult_codigo_fk',
			'params' => [
				':decl_codigo_fk' => $id_declaracion,
				':mult_habilitada' => TRUE,
				':mult_codigo_fk' => 1
			]
		]);

		foreach($multas_formales as $m){
			array_push($multas, $m->mult_codigo_fk);
		}
		
		$multa_mayor = 0;
		$id_mayor = NULL;

		// Se obtiene el id de la multa con mayor monto.
		if(count($multas) > 1){
			for($i = 0; $i < count($multas); $i++){
				$multa = SidcaiMulta::model()->findByPk($multas[$i]);

				if($multa != null){
					if($multa_mayor < $multa->mult_unidadestributarias){
						$multa_mayor = $multa->mult_unidadestributarias;
						$id_mayor = $multa->mult_codigo_pk;
					}
				}
			}
		}


		if(count($multas) == 0 || empty($multas)){
			$datos['tiene_multas'] = false;
		}else{
			$datos['tiene_multas'] = true;

			$cantidad_ut 	= 0;
			$cantidad_ut_82 = 0;

			for($i = 0; $i < count($multas); $i++){
				$mult = SidcaiMulta::model()->findByPk($multas[$i]);

				$detalles_multa = [];

				if($mult != null){
					$valor_unidad_tributaria = $mult->mult_unidadestributarias;

					$detalles_multa['ley'] = $mult->mult_ley;
					$detalles_multa['ut'] = $mult->mult_unidadestributarias;

					if($id_mayor != NULL){
						if($id_mayor == $multas[$i]){
							$art82 = $valor_unidad_tributaria;
							$detalles_multa['art82'] = $mult->mult_unidadestributarias; // Art.82
						}else{
							$art82 = ($mult->mult_unidadestributarias / 2);
							$detalles_multa['art82'] = $art82; // Art.82
						}
					}else{
						$art82 = $valor_unidad_tributaria;
						$detalles_multa['art82'] =$mult->mult_unidadestributarias; // Art.82
					}

					$detalles_multa['descripcion'] = $mult->mult_descripcion;
					$detalles_multa['ley'] = $mult->mult_ley;
					$detalles_multa['ley'] = $mult->mult_ley;


					$cantidad_ut 	= $cantidad_ut + $mult->mult_unidadestributarias;
					$cantidad_ut_82 = $cantidad_ut_82 + $art82;
				}

				$datos['multas_seleccionadas'][] = $detalles_multa;
			}

			$ut_actual = SidcaiUnidadtributaria::model()->find([
				'order' => 'unid_codigo_pk DESC',
				'limit' => 1
			]);

			$total_multa = $ut_actual->unid_valor * $cantidad_ut_82;

			$datos['valor_ut'] 		= $ut_actual->unid_valor;
			$datos['cantidad_ut'] 	= $cantidad_ut;
			$datos['cantidad_ut_82'] = $cantidad_ut_82;
			$datos['total_multa'] = $total_multa;
		}

		
		return $datos;
	}

	/**
	 * Devuelve la tabla de las multas formales para el acta de reparo que emite fiscalización
	 */
	public static function tablaMultasFormalesActa(int $id_declaracion) : string{
		$multa = self::multasFormalesSeleccionadas($id_declaracion);

		$tabla = "";

		if($multa['tiene_multas']){
			for($i = 0; $i < count($multa['multas_seleccionadas']); $i++){
				$m = $multa['multas_seleccionadas'][$i];

				$tabla .= '<tr>';
				$tabla .= '<td style="text-align: justify">'.$m['descripcion'].'</td>';
				$tabla .= '<td>'.$m['ley'].'</td>';
				$tabla .= '<td>'.number_format($m['ut'], 0, ',', '.').'</td>';
				$tabla .= '<td>'.number_format($m['art82'], 0, ',', '.').'</td>';
				$tabla .= '</tr>';
			}

			$date = new DateTime("now", new DateTimeZone('America/Caracas'));
			$hoy = $date->format('Y-m-d');

			$ut_actual = SidcaiUnidadtributaria::model()->find([
				'order' => 'unid_codigo_pk DESC',
				'limit' => 1
			]);

			$total_multa = $ut_actual->unid_valor * $multa['cantidad_ut_82'];

			$valor_ut 	 = self::obtenerMoneda($hoy)." ".number_format($ut_actual->unid_valor, 2, ",", ".");
			$total_multa = self::obtenerMoneda($hoy)." ". number_format($total_multa, 2, ",", ".");

			$tabla .= "<tr>";
			$tabla .= "<td colspan='2' style='text-align: right'><b>TOTALES</b></td>";
			$tabla .= "<td><b>".number_format($multa['cantidad_ut'], 0, ",", ".") ." U.T</b></td>";
			$tabla .= "<td><b>".number_format($multa['cantidad_ut_82'], 0, ",", ".") ." U.T</b></td>";
			$tabla .= "</tr>";
		}else{
			$tabla = "<tr><td colspan='4'><center>No hay multas seleccionadas.</center></td></tr>";
		}

		return $tabla;
	}

	/**
	 * Reemplaza caracteres especiales para ser mostrado en PDF
	 */
	public static function reemplazar_caracteres(string $texto) : string{
        $caracteres_reemplazar = ["&AMP;" => "&", "&QUOT;" => '"'];

        foreach($caracteres_reemplazar as $key => $value){
        	$texto = str_replace($key, $value, $texto);
        }

        return $texto;
	}


	/**
	 * Fecha 
	 */
	public static function obtenerFecha(string $formato = 'Y-m-d') : string {
		$date = new DateTime("now", new DateTimeZone('America/Caracas'));
		$hoy = $date->format($formato);
		return $hoy;
	}
}

?>
