[firebase-br] Numeric x Decimal x Double Precission x Float

Hélio Oliveira hpensador em gmail.com
Qua Set 4 10:58:45 -03 2013


Bom dia Colegas!

Firebird 2.0

Colegas tenho uma rotina de geração de um relatório gerencial que 
reproduzem os valores gerados na SEFIP, porém estou com um problema na 
base do arredondamento dos valores. Se trunco (utilizando a SP_Trunc) ou 
não, nunca consigo chegar ao valor exato gerado pelo aplicativo SEFIP. 
Este relatório é obtido a partir de uma Stored Procedure, já fiz testes 
com os tipos NUMERIC e DOUBLE PRECISSION sem obter sucesso.

Qual a experiência de vocês em situações tipicas como esta minha e qual 
o melhor tipo a ser utilizado nesta situação. Abaixo a SP na integra.

create or alter procedure GPS (
     MES       integer,
     ANO       integer,
     SEQUENCIA integer)
returns (
     COD_LOTACAO               varchar(7),
     NOME_LOTACAO              varchar(505),
     COD_SECRETARIA            varchar(7),
     NOME_SECRETARIA           varchar(50),
     QTDE_FUNCIONARIO_LOTACAO  integer,
     BASE_CALC_INSS            numeric(12,2),
     VALOR_SALARIO_FAMILIA     numeric(12,2),
     VALOR_SALARIO_MATERNIDADE numeric(12,2),
     VALOR_INSS_EMPRESA        numeric(12,2),
     VALOR_RAT                 numeric(12,2),
     VALOR_INSS_FUNCIONARIO    numeric(12,2),
     VALOR_INSS_RECOLHER       numeric(12,2))
as
declare variable TOTAL_PROVENTOS_INSS numeric(12,2);
declare variable TOTAL_DESCONTOS_INSS numeric(12,2);
declare variable PERC_INSS_EMPRESA    numeric(6,2);
declare variable ALIQUOTA_SAT         numeric(6,2);
declare variable ALIQUOTA_FAP         numeric(6,2);
declare variable COD_INSS             integer;
declare variable CODIGO_SF            integer;
declare variable CODIGO_SM            integer;
declare variable MATRICULA            integer;
declare variable BC_INSS              numeric(12,2);
declare variable VLR_INSS             double precision;
declare variable VLR_RAT              double precision;
begin
   select c.codigo_inss,
          c.codigo_sal_fam,
          c.codigo_sal_mat
   from config c
   into :cod_inss, codigo_sf, :codigo_sm;
   /* Aliquotas de calculo do INSS */
   select tm.aliq_fap
   from tabela_mensal tm
   where tm.mes = :mes
     and tm.ano = :ano into :aliquota_fap;
   /* */
   select ma.percentual_ce,
          ma.sefip_sat
   from mesano ma
   where ma.mes = :mes
     and ma.ano = :ano
   into :perc_inss_empresa, :aliquota_sat;
   /* Neste laço é feita a busca de todos os códigos de lotação
      presentes no capa-variavel do mês */
   for select distinct cv.codigo_lotacao
       from capa_variavel cv
       where cv.mes       = :mes
         and cv.ano       = :ano
         and cv.sequencia = :sequencia
       order by cv.codigo_lotacao
   into :cod_lotacao do
   begin
     /* Código e nome da Secretaria */
     select l.codigo,
            l.nome
     from lotacao l
     where l.codigo = substring(:cod_lotacao from 1 for 2) || '00000'
       and l.nivel  = 1
     into :cod_secretaria, :nome_secretaria;
     /* Nome da Lotação */
     select l.nome
     from lotacao l
     where l.codigo = :cod_lotacao into :nome_lotacao;
     /* Total de Funcionários da Lotação */
     select count(matricula)
     from capa_variavel cv
     where cv.mes            = :mes
       and cv.ano            = :ano
       and cv.sequencia      = :sequencia
       and cv.codigo_lotacao = :cod_lotacao into :qtde_funcionario_lotacao;

     base_calc_inss     = 0;
     valor_inss_empresa = 0;
     valor_rat          = 0;
     for select cv.matricula
         from capa_variavel cv
         where cv.mes = :mes
           and cv.ano = :ano
           and cv.sequencia = :sequencia
           and cv.codigo_lotacao = :cod_lotacao
         order by cv.matricula
     into :matricula do
     begin
       /* Total de proventos que incidem previdência dos Funcionários da 
Lotação */
       select sum(v.valor)
       from variavel v
         join funcionario x on (x.codigo = v.matricula and x.previdencia 
= 1)
         join provento p on (p.codigo = v.provento and p.previdencia = 
'S' and p.codigo <= 499)
       where v.mes       = :mes
         and v.ano       = :ano
         and v.sequencia = :sequencia
         and v.matricula = :matricula into :total_proventos_inss;
       if (:total_proventos_inss is null) then
         total_proventos_inss = 0.00;
       /* Total de descontos que incidem previdência dos Funcionários da 
Lotação */
       select sum(v.valor)
       from variavel v
         join funcionario x on (x.codigo = v.matricula and x.previdencia 
=1)
         join provento p on (p.codigo = v.provento and p.previdencia = 
'S' and p.codigo >= 500)
       where v.mes       = :mes
         and v.ano       = :ano
         and v.sequencia = :sequencia
         and v.matricula = :matricula into :total_descontos_inss;
       if (:total_descontos_inss is null) then
         total_descontos_inss = 0.00;

       bc_inss = :total_proventos_inss - :total_descontos_inss;
       base_calc_inss = :base_calc_inss + :bc_inss;
     end
     --execute procedure sp_trunc((:base_calc_inss * 
(:perc_inss_empresa/100)), 2)            returning_values :vlr_inss;
     --execute procedure sp_trunc((:base_calc_inss * 
((:aliquota_sat*:aliquota_fap)/100)), 2) returning_values :vlr_rat;

     vlr_inss = :base_calc_inss * (:perc_inss_empresa/100);
     vlr_rat  = :base_calc_inss * ((:aliquota_sat*:aliquota_fap)/100);
     valor_inss_empresa = :valor_inss_empresa + :vlr_inss;
     valor_rat = :vlr_rat;
     /* Valor total do INSS dos Funcionários da Lotação */
     select sum(v.valor)
     from variavel v
       join capa_variavel cv on (cv.matricula = v.matricula
                             and cv.mes = v.mes
                             and cv.ano = v.ano
                             and cv.sequencia = v.sequencia)
       join funcionario x on (x.codigo = v.matricula and x.previdencia = 1)
     where v.mes            = :mes
       and v.ano            = :ano
       and v.sequencia      = :sequencia
       and cv.codigo_lotacao= :cod_lotacao
       and v.provento       = :cod_inss into :valor_inss_funcionario;
     if (:valor_inss_funcionario is null) then
       valor_inss_funcionario = 0.00;
     /* Valor do Salário Família dos Funcionários da Lotação */
     select sum(v.valor)
     from variavel v
       join capa_variavel cv on (cv.matricula = v.matricula
                             and cv.mes = v.mes
                             and cv.ano = v.ano
                             and cv.sequencia = v.sequencia)
       join funcionario x on (x.codigo = v.matricula and x.previdencia = 1)
     where v.mes            = :mes
       and v.ano            = :ano
       and v.sequencia      = :sequencia
       and cv.codigo_lotacao = :cod_lotacao
       and v.provento       = :codigo_sf into :valor_salario_familia;
     if (:valor_salario_familia is null) then
       valor_salario_familia = 0.00;
     /* Valor do Salário Maternidade dos Funcionários da Lotação */
     select sum(v.valor)
     from variavel v
       join capa_variavel cv on (cv.matricula = v.matricula
                             and cv.mes = v.mes
                             and cv.ano = v.ano
                             and cv.sequencia = v.sequencia)
       join funcionario x on (x.codigo = v.matricula and x.previdencia = 1)
     where v.mes            = :mes
       and v.ano            = :ano
       and v.sequencia      = :sequencia
       and cv.codigo_lotacao= :cod_lotacao
       and v.provento       = :codigo_sm into :valor_salario_maternidade;
     if (:valor_salario_maternidade is null) then
       valor_salario_maternidade = 0.00;
     /* Calculo do INSS */

     valor_inss_recolher = (:valor_inss_empresa + :valor_rat + 
:valor_inss_funcionario) -
                           (:valor_salario_familia + 
:valor_salario_maternidade);
     suspend;
   end
end





Mais detalhes sobre a lista de discussão lista