DELIMITER $$
DROP FUNCTION IF EXISTS folio_timbre;
CREATE FUNCTION folio_timbre
(recibo$ BIGINT)
RETURNS BIGINT
BEGIN
	DECLARE folio_$ BIGINT DEFAULT(19);
	IF (SELECT timbre FROM recibos WHERE id = recibo$) = 0 THEN
		IF EXISTS (SELECT id FROM timbres) THEN
			SET folio_$ := (SELECT (clave+1) FROM timbres ORDER BY clave DESC LIMIT 1);
		END IF;
		INSERT INTO timbres(clave, cfdi, cancelacion, estado, registro) VALUES(folio_$, '', null, 404, NOW());
		UPDATE recibos SET timbre = (SELECT id FROM timbres WHERE clave = folio_$) WHERE id = recibo$;
	END IF;
	RETURN (SELECT t.clave FROM recibos AS r INNER JOIN timbres AS t ON r.timbre = t.id WHERE r.id = recibo$);
END
$$


DELIMITER $$
DROP FUNCTION IF EXISTS total_recibo;
CREATE FUNCTION total_recibo
(recibo$ BIGINT, tipo$ INT)
RETURNS DECIMAL(8,2)
BEGIN
	DECLARE resultset_$ DECIMAL(8,2);
	CASE tipo$
	WHEN 11 THEN 
    SET resultset_$ := (SELECT pago FROM mantto WHERE recibo = recibo$);
	WHEN 88 THEN 
    SET resultset_$ := (SELECT (ss.importe * s.cantidad) FROM servicio AS s INNER JOIN servicios AS ss ON s.concepto = ss.id WHERE s.recibo = recibo$);
	ELSE 
    SET resultset_$ := (SELECT sum(obtiene_valor_mes(m.recibo, m.periodo) - calculaDescuento(m.descuento, obtiene_valor_mes(m.recibo, m.periodo)) + calculaActualizacion(m.indice, (obtiene_valor_mes(m.recibo, m.periodo) - calculaDescuento(m.descuento, obtiene_valor_mes(m.recibo, m.periodo)))) + calculaRecargo(m.periodo, cast(m.registro as date), obtiene_valor_mes(m.recibo, m.periodo) - calculaDescuento(m.descuento, obtiene_valor_mes(m.recibo, m.periodo)), m.recargo, m.indice))
	 FROM mantto AS m
	 WHERE m.recibo = recibo$);
	END CASE;
	RETURN resultset_$;
END
$$

delimiter $$
drop function if exists calculaDescuento;
create function calculaDescuento
(descuento$ int, cuota$ decimal(10,2))
returns decimal(10,2)
begin
    declare resultset decimal(10,2) default(0);
    if descuento$ > 0 then
        set resultset := (select (cuota$*(descuento/100)) from descuentos where id = descuento$);
    end if;
    return resultset;
end
$$

DELIMITER $$
DROP FUNCTION IF EXISTS obtiene_valor_mes;
CREATE FUNCTION obtiene_valor_mes
(recibo$ BIGINT, periodo$ date)
returns decimal(10,2)
begin
    declare resultset decimal(10,2);
    declare pago decimal(8,2) default(select truncate(pago, 2) from mantto where recibo = recibo$ and periodo = periodo$);
    if pago > 1 then
        set resultset = pago;
    else
        set resultset := (select truncate(c.cuota, 2) from mantto as m inner join cuotas as c on m.cuota = c.id where m.recibo = recibo$ and m.periodo = periodo$);
    end if;
    return resultset;
end 
$$

-- >>> calcula los recargos
DELIMITER $$
DROP FUNCTION IF EXISTS calculaRecargo;
CREATE FUNCTION calculaRecargo
(periodo$ DATE, pago$ DATE, cuota$ DECIMAL(8,2), recargo$ INT, indice$ float)
RETURNS DECIMAL(8,2)
BEGIN
	-- variable que retorna, para el periodo que inicia, mes de inicio, fin, porcentaje de recargo y meses de atraso
	DECLARE mesInicio INT;
	DECLARE mesFin INT;
	DECLARE resultset DECIMAL(8,2);
	DECLARE periodo_$ INT;
	DECLARE atraso_$ INT default(0);
	DECLARE recargo_$ DECIMAL(10,8);
	IF recargo$ <> 0 THEN
		SET recargo_$ := (SELECT ((recargo/100)/12) FROM recargos WHERE id = recargo$);
		SET periodo_$ = YEAR(periodo$);
		periodo:LOOP
			IF (YEAR(periodo$) < YEAR(pago$) AND periodo_$ = YEAR(periodo$)) THEN
				SET mesInicio = MONTH(periodo$);
				SET mesFin= 12;
			ELSEIF (YEAR(periodo$) < YEAR(pago$) AND periodo_$ > YEAR(periodo$) AND periodo_$ < YEAR(pago$)) THEN
				SET mesInicio = 1;
				SET mesFin = 12;
			ELSEIF (YEAR(periodo$) = YEAR(pago$)) THEN
				SET mesInicio = MONTH(periodo$);
				SET mesFin = MONTH(pago$);
			ELSEIF (YEAR(periodo$) < YEAR(pago$) AND periodo_$ = YEAR(pago$)) THEN
				SET mesInicio = 1;
				SET mesFin = MONTH(pago$);
			END IF;
			WHILE mesInicio <= mesFin DO
				SET atraso_$ = (atraso_$+1);
				SET mesInicio = (mesInicio+1);
			END WHILE;
		IF periodo_$ = YEAR(pago$) THEN
			LEAVE periodo;
		END IF;
		SET periodo_$ = (periodo_$+1);
		END LOOP;
    set atraso_$ = atraso_$ - 1;
		 SET resultset = ((cuota$+calculaActualizacion(indice$, cuota$))*(atraso_$*recargo_$));
      -- set resultset = recargo_$*atraso_$;
	ELSE
		SET resultset = 0.00;
	END IF;
	RETURN resultset;
END
$$

-- >>> calcula la actualizacion de cuota con INPC
DELIMITER $$
DROP FUNCTION IF EXISTS calculaActualizacion;
CREATE FUNCTION calculaActualizacion
(indice$ float, cuota$ DECIMAL(8,2))
RETURNS DECIMAL(8,2)
BEGIN
	-- variable que retorna
	DECLARE resultset DECIMAL(8,2) default(0);
	IF indice$ > 0 THEN
		SET resultset = (indice$*cuota$) - cuota$;
	END IF;
	RETURN resultset; 
END
$$

delimiter $$
drop function if exists obtieneIndice;
create function obtieneIndice
(periodo$ date, pago$ date)
returns float
begin
    DECLARE resultset float;
	IF (YEAR(periodo$) < YEAR(NOW()) OR MONTH(periodo$) < MONTH(NOW()) AND YEAR(periodo$) = YEAR(NOW())) THEN
		SET resultset = (obtieneInpc(pago$)/obtieneInpc(periodo$));
	ELSE
		SET resultset = 0.00;
	END IF;
    return resultset;
end
$$

-- >>> obtiene el recargo
DELIMITER $$
DROP FUNCTION IF EXISTS obtieneRecargo;
CREATE FUNCTION obtieneRecargo
(periodo$ DATE)
RETURNS INT
BEGIN
	-- variable que retorna
	DECLARE resultset INT;
	IF (YEAR(periodo$) < YEAR(NOW()) OR YEAR(periodo$) = YEAR(NOW()) AND MONTH(periodo$) < MONTH(NOW())) THEN
		SET resultset := (SELECT id FROM recargos WHERE estado = 11);
	ELSE
		SET resultset = 0;
	END IF;
	RETURN resultset;
END
$$

-- >>> obtiene el descuento correspondiente al periodo de pago y fecha de pago
DELIMITER $$
DROP FUNCTION IF EXISTS obtieneDescuento;
CREATE FUNCTION obtieneDescuento
(inicio$ DATE, fin$ DATE)
RETURNS INT
BEGIN
	-- variable que retorna
	DECLARE resultset INT;
    set inicio$ = cast(concat(year(inicio$),'-',month(inicio$),'-01') as date);
    set fin$ = cast(concat(year(fin$),'-',month(fin$),'-01') as date);
	IF EXISTS (SELECT id FROM descuentos WHERE inicio = inicio$ AND fin = fin$ AND CURRENT_DATE() <= vigencia) THEN
		SET resultset := (SELECT id FROM descuentos WHERE inicio = inicio$ AND fin = fin$ AND CURRENT_DATE() <= vigencia ORDER BY vigencia LIMIT 1);
	ELSE
		SET resultset = 0;
	END IF;
	RETURN resultset;
END
$$

-- >>> obtiene la cuota de mantto correspondiente al periodo
DELIMITER $$
DROP FUNCTION IF EXISTS obtieneCuota;
CREATE FUNCTION obtieneCuota
(predio$ INT, periodo$ INT)
RETURNS INT
BEGIN
	-- variable que retorna y para obtener uso del predio
	DECLARE resultset INT;
	DECLARE uso_$ VARCHAR(10);
	SET uso_$ := (SELECT uso FROM predios WHERE id = predio$);
	-- si el periodo es mayor o igual a 2025 la cuota se agina por terreno o casa y si es socio o no
	IF periodo$ >= 2025 THEN
		-- es terrno socio
		IF uso_$ = '211-88' THEN
			SET resultset := (SELECT id FROM cuotas WHERE periodo = periodo$ AND uso = '211-88');
		-- es terreno no socio
		ELSEIF uso_$ = '211-66' THEN
			SET resultset := (SELECT id FROM cuotas WHERE periodo = periodo$ AND uso = '211-66');
		-- es casa socio
		ELSEIF uso_$ = '212-88' OR uso_$ = '213-88' THEN
			SET resultset := (SELECT id FROM cuotas WHERE periodo = periodo$ AND uso = '212-88');
		-- es casa no socio
		ELSEIF uso_$ = '212-66' OR uso_$ = '213-66' THEN
			SET resultset := (SELECT id FROM cuotas WHERE periodo = periodo$ AND uso = '212-66');
		END IF;
	ELSE
		IF uso_$ = '211-88' OR uso_$ = '211-66' THEN
			-- cuota de terrno
			SET resultset := (SELECT id FROM cuotas WHERE periodo = periodo$ AND uso = '211-88');
		ELSE
			-- cuota de cas
			SET resultset := (SELECT id FROM cuotas WHERE periodo = periodo$ AND uso = '212-88');
		END IF;
	END IF;
	RETURN resultset;
END
$$

-- >>> valida si el periodo esta en convenio, parcial, pagado o en deuda
DELIMITER $$
DROP FUNCTION IF EXISTS estadoPeriodo;
CREATE FUNCTION estadoPeriodo
(periodo$ DATE, predio$ varchar(8))
RETURNS INT
BEGIN
	-- variable que retorna
	DECLARE resultset INT;
    if exists(select 88 from mantto where recibo = (predio$*-1) and periodo = periodo$ and pago = 1) then
        set resultset = 404;
    elseif exists(select 88 from mantto where recibo = (predio$*-1) and periodo = periodo$ and pago <> 1) then
        set resultset = 100;
    elseif exists(select 88 from convenios as c inner join predios as p on c.predio = p.id where descifrar(p.predio) = predio$ and periodo$ between c.inicio and c.fin) then
        set resultset = 300;
    else
        set resultset = 200;
    end if;
	RETURN resultset;
END
$$
