Ver Mensaje Individual
  #2  
Antiguo 07-04-2008
Avatar de Ivanzinho
[Ivanzinho] Ivanzinho is offline
Miembro Premium
 
Registrado: ene 2005
Ubicación: Galicia
Posts: 595
Reputación: 20
Ivanzinho Va por buen camino
Hola chino150, te dejo aquí el código que uso en un procedimiento almacenado para el calculo de cuotas de de amortización de Leasing, pero puede valerte para la amortización de cualquier tipo de prestamo. Espero que puedas sacar algo en limpio, si no entiendes pregunta, ahora no tengo tiempo y te lo pongo tal cual lo tengo yo en un procedimiento almacenado.

Código SQL [-]
CREATE PROCEDURE CALCULOLEASING (
    in_codben integer,
    in_anoben integer,
    in_importe numeric(15,2),
    in_vresidual numeric(15,2),
    in_interes float,
    in_periodicidade integer,
    in_cuotas integer,
    in_fecini date,
    in_mult integer,
    in_iso numeric(15,2))
returns (
    ou_cuota numeric(15,2),
    ou_cfin numeric(15,2),
    ou_pendente numeric(15,2))
as
declare variable v_int float;
declare variable v_acumulado numeric(15,2);
declare variable v_ncuota integer;
declare variable v_dia integer;
declare variable v_mes integer;
declare variable v_ano integer;
declare variable v_pam numeric(15,4);
declare variable v_afi numeric(15,2);
declare variable v_data date;
declare variable v_cuofisini numeric(15,2);
declare variable v_imp numeric(15,2);
begin
  v_data = in_fecini;

  --Calculamos o tipo de interes en tanto por 1 que lle corresponde á
  --periodicidade escollida
  v_int = (in_interes * in_periodicidade)/ 1200;

  if (in_vresidual is null) then --Valor residual igual a unha cuota
    begin
      --Calculamos a cuota mensual
      Ou_cuota = Redondeo(in_importe * Exp((1 + v_int),in_cuotas), 2);

      Ou_cuota = Redondeo(Ou_cuota / ((((1 + v_int) *
                                        (1 -(1 / Exp((1 + v_int), in_cuotas))) *
                                        Exp((1 + v_int), in_cuotas)
                                       )
                                       / v_int) +
                                      1
                                     ), 2);
      in_vresidual = Ou_cuota;
    end
  else  --Valor residual introducido polo usuario
    begin
       Ou_cuota = Redondeo(in_importe - (in_vresidual / Exp((1 + v_int),in_cuotas)), 2);

       Ou_cuota = Redondeo((Ou_cuota * v_int) / ((1+ v_int) * (1 - (1/Exp((1 + v_int), in_cuotas)))), 2);
    end

  v_ncuota = 0;
  v_acumulado = 0;
  ou_pendente = in_importe;
  v_dia = cast(extract(day from in_fecini) as integer);

  while (v_ncuota < in_cuotas - 1) do
    begin
      v_ncuota = v_ncuota +1;

      Ou_cfin = Redondeo((ou_pendente - Ou_cuota) * v_int, 2);

      v_acumulado = Redondeo(v_acumulado + Ou_cfin, 2);

      ou_pendente = Redondeo(ou_pendente - Ou_cuota + Ou_cfin, 2);

      --Se o código do ben é nulo tratase dunha simulación, polo tanto so
      --devolvemos o resultado do calculo das cuotas de leasing
      if (in_codben is null) then
        suspend;
      else --Se non se trata dunha simulación introducimos os datos na táboa de leasing
        begin
          insert into Leasing values (:in_codben, :in_anoben, :v_data, :ou_cuota,
                                      :ou_cfin, :ou_pendente, 0, 0, 0);

          --Calculamos a fecha de pago da próxima cuota
          v_mes = cast(extract(month from v_data) as integer);
          v_ano = cast(extract(year from v_data) as integer);

          if (v_mes = 12) then
            begin
               v_mes = in_periodicidade;
               v_ano = v_ano + 1;
            end
          else
            v_mes = v_mes + in_periodicidade;

          if (v_mes > 12) then
            begin
              v_mes = v_mes - 12;
              v_ano = v_ano + 1;
            end

          if ((v_mes <> 2) or (v_dia <= 28)) then
            v_data = cast(v_mes || '/' || v_dia || '/' || v_ano as date);
          else
            begin
              if (bisiesto(v_ano) = 1) then
                v_data = cast(v_mes || '/' || 29 || '/' || v_ano as date);
              else
                v_data = cast(v_mes || '/' || 28 || '/' || v_ano as date);
            end
        end
    end

  v_ncuota = v_ncuota + 1;

  Ou_cfin = Redondeo(Ou_cuota * (v_ncuota) + in_vresidual - in_importe - v_acumulado, 2);

  Ou_pendente = Redondeo(ou_pendente - ou_cuota + Ou_cfin, 2);

  --Se o código do ben é nulo tratase dunha simulación, polo tanto so devolvemos
  --o resultado do calculo das cuotas de leasing
  if (in_codben is null) then
    suspend;
  else --Se non se trata dunha simulación introducimos os datos na táboa de leasing e actualizamos o valor residual
    begin
      insert into Leasing values (:in_codben, :in_anoben, :v_data, :ou_cuota,
                                  :ou_cfin, :ou_pendente, 0, 0, 0);

      update bens
      set vre_be = :in_vresidual
      where cod_Be = :in_codben and ano_be = :in_anoben;

      -- Introducimos a cuota pertencente ao valor residual no caso de que este
      -- sexa distinto de 0
      if (in_vresidual > 0) then
        begin
          --Calculamos a fecha de pago da próxima cuota
          v_mes = cast(extract(month from v_data) as integer);
          v_ano = cast(extract(year from v_data) as integer);

          if (v_mes = 12) then
            begin
              v_mes = in_periodicidade;
              v_ano = v_ano + 1;
            end
          else
            v_mes = v_mes + in_periodicidade;

          if (v_mes > 12) then
            begin
              v_mes = v_mes - 12;
              v_ano = v_ano + 1;
            end

          if ((v_mes <> 2) or (v_dia <= 28)) then
            v_data = cast(v_mes || '/' || v_dia || '/' || v_ano as date);
          else
            begin
              if (bisiesto(v_ano) = 1) then
                v_data = cast(v_mes || '/' || 29 || '/' || v_ano as date);
              else
                v_data = cast(v_mes || '/' || 28 || '/' || v_ano as date);
            end

          -- Insertamos a cuota Leasing
          insert into Leasing values (:in_codben, :in_anoben, :v_data, :in_vresidual,
                                      0, 0, 0, 0, 0);

          in_cuotas = in_cuotas + 1;
        end

      -- Calculamos a porcentaxe de amortización anual
      select Redondeo(Pam_be/100, 4)
      from bens
      where cod_be = :in_codben and ano_be = :in_anoben
      into :V_PAM;

      v_pam = v_pam * in_mult;

      -- Calculamos a cuota fiscal
      v_afi = Redondeo(in_importe * v_pam, 2);
      v_afi = Redondeo(v_afi / truncar(12/in_periodicidade), 2);

      -- Calculamos a primeira cuota parcial, no caso que non se inicie
      -- a amortización ao principio do periodo
      v_cuofisini = mod((cast(extract(month from in_fecini) as integer) - 1), in_periodicidade);
      v_cuofisini = Redondeo(v_afi * (in_periodicidade - v_cuofisini) / in_periodicidade, 2);

      v_ncuota = 0;
      v_data = in_fecini;

      while ((in_importe > 0) or (v_ncuota < in_cuotas)) do
        begin
          v_ncuota = v_ncuota + 1;

          if (v_ncuota = 1) then
            v_imp = v_cuofisini;
          else if (in_importe = 0) then
            v_imp = 0;
          else if (v_imp >= in_importe) then
            v_imp = in_importe;
          else
            v_imp = v_afi;

          if (v_ncuota <= in_cuotas) then
            update leasing
            set afi_le = :V_IMP, iso_le = Redondeo((cuo_le - cfi_le - :v_imp) * :in_iso, 2)
            where cbe_le = :in_codben and abe_le = :in_anoben and
                  fec_le = :V_DATA;
          else
            insert into leasing values(:in_codben, :in_anoben, :v_data, 0,
                                       0, 0, 0, :V_IMP, Redondeo(-:v_imp * :in_iso, 2));

          if (in_importe > 0) then
            in_importe = in_importe - v_imp;

          --Calculamos a data de pago da próxima cuota
          v_mes = cast(extract(month from v_data) as integer);
          v_ano = cast(extract(year from v_data) as integer);

          if (v_mes = 12) then
            begin
               v_mes = in_periodicidade;
               v_ano = v_ano + 1;
            end
          else
            v_mes = v_mes + in_periodicidade;

          if (v_mes > 12) then
            begin
              v_mes = v_mes - 12;
              v_ano = v_ano + 1;
            end

          if ((v_mes <> 2) or (v_dia <= 28)) then
            v_data = cast(v_mes || '/' || v_dia || '/' || v_ano as date);
          else
            begin
              if (bisiesto(v_ano) = 1) then
                v_data = cast(v_mes || '/' || 29 || '/' || v_ano as date);
              else
                v_data = cast(v_mes || '/' || 28 || '/' || v_ano as date);
            end
        end
    end
end

Los comentarios están en gallego, espero que no sea inconveniente.

Un saúdo, y lo dicho, si no entiendes pregunta, pero ahora mismo tengo que marchar.
__________________
Si no lees esto no vivirás tranquilo
Non lle poñades chatas â obra namentras non se remata. O que pense que vai mal que traballe n’ela; hai sitio para todos. (Castelao)

Última edición por Ivanzinho fecha: 07-04-2008 a las 22:52:08.
Responder Con Cita