sexta-feira, 30 de março de 2012

Cálculo do Módulo11 para o Nosso Número


No exemplo anterior postado, eu mostro como fazer um cálculo do dígito verificador módulo10 do banco do brasil, e neste, mostro como é feito o cálculo usando o módulo11. Essas duas funções, referente aos chamados DV(Dígito Verificador), podem serem executadas sem nenhuma alteração, pois, elas não fazem referência as tabelas do banco de dados, são funções das quais chamo de "Genéricas".

CREATE OR REPLACE FUNCTION "TS_ParcelaBloquetoBancoBrasilModulo11"(xdocumento character varying)
  RETURNS character varying AS
$BODY$
declare
  XNumero     Varchar;
  XNumeroOrg  Varchar;
  XCont       Integer;
  XParcial    Integer;
  XDivisorM11 Integer;
  XResto      Integer;
  XDigVerM11  Integer;
  XMultiplo   Integer;
begin
  /*
   Função responsável por calcular o DV módulo 11
   Esta informação vai impressa no bloqueto
  */
  --Pegando somente os números do documentos
  XNumeroOrg = regexp_replace(XDocumento, '[^[:digit:]]', '', 'g');

  /*
  *** Calculando Módulo "11" ***
  */
  XDivisorM11 = 2;
  XParcial    = 0;
  XNumero     = trim(XNumeroOrg);
  XCont       = length(XNumero);
  loop
    --Pegando número a número e multiplicando por 2 a 9 e acumulando o resultado linha a linha
    if XDivisorM11 > 9 then
       XDivisorM11 = 2;
    end if;
    XParcial    = XParcial    + Cast(SubStr(trim(XNumero),XCont,1) as Integer) * XDivisorM11;
    XDivisorM11 = XDivisorM11 + 1;
    XCont       = XCont - 1;
    if XCont = 0 then
       Exit;
    end if;

  end loop;
  /*
  Tratando o resultado da multiplicação
  */
  XResto     = Cast(((XParcial-(trunc(Cast(XParcial as Numeric(15,2))/11))*11)) as Integer);
  XDigVerM11 = 11 - XResto;
  if XDigVerM11 = 0 or XDigVerM11 = 10 or XDigVerM11 = 11 then
     XDigVerM11 = 1;
  end if;

  Return XDigVerM11;
end;
$BODY$
  LANGUAGE 'plpgsql' VOLATILE;
ALTER FUNCTION "TS_ParcelaBloquetoBancoBrasilModulo11"(character varying) OWNER TO postgres;

*** Para executar esta função digite: ***
Select "TS_ParcelaBloquetoBancoBrasilModulo11"('12345678')



4 comentários:

  1. Calcula certinho o digito, parabéns.

    ResponderExcluir
  2. Muito bom! Fiz uma modificação para validar digitação:

    --DROP FUNCTION Modulo11(XDocumento Varchar)
    CREATE OR REPLACE FUNCTION public.modulo11(XDocumento Varchar)
    RETURNS boolean AS
    $BODY$
    declare
    XNumero Varchar;
    XCont Integer;
    XParcial Integer;
    XDivisorM11 Integer;
    XResto Integer;
    XDigVerM11 Integer;
    XMultiplo Integer;

    --Digito digitado para ser confrontado
    XDocDigito char(1);


    begin
    /*
    Função responsável por validar o DV módulo 11
    Pode ser utilizada para a maioria das contas bancarias, CPF, CNPJ e outros titulos que
    utilizam o artificio.

    */

    --Pegando somente a parte significativa para o calculo.
    --O último digito de XDocumento é o DV, propriamente dito
    XNumero = regexp_replace(SubStr(XDocumento, 1, length(XDocumento)-1), '[^[:digit:]]', '', 'g');

    --Captura o DV digitado para ser confrontado
    XDocDigito = SubStr(XDocumento, length(XDocumento),1);




    /*

    *** Calculando Módulo "11" ***
    */
    XDivisorM11 = 2;
    XParcial = 0;
    XCont = length(XNumero);


    loop
    --Pegando número a número e multiplicando por 2 a 9 e acumulando o resultado linha a linha
    if XDivisorM11 > 9 then
    XDivisorM11 = 2;
    end if;
    XParcial = XParcial + Cast(SubStr(trim(XNumero),XCont,1) as Integer) * XDivisorM11;
    XDivisorM11 = XDivisorM11 + 1;
    XCont = XCont - 1;
    if XCont = 0 then
    Exit;
    end if;

    end loop;
    /*
    Tratando o resultado da multiplicação
    */
    XResto = Cast(((XParcial-(trunc(Cast(XParcial as Numeric(15,2))/11))*11)) as Integer);
    XDigVerM11 = 11 - XResto;
    if XDigVerM11 = 0 or XDigVerM11 = 10 or XDigVerM11 = 11 then
    /*
    Para algumas entidades (Codigo de barras e alguns bancos) quando o resultado do calculo
    for 0, 10 ou 11 utilizar o confronto com exDV que será o valor para o tratamento.
    Por exemplo: Para calcular DV das contas do BB, quando o resultado for 10 ou 11, deve-se utilizar
    o DV 'X' em exDV
    */
    --XDigVerM11 = 1;
    Return true;
    else
    Return cast(XDigVerM11 as char) = XDocDigito;
    end if;


    end;
    $BODY$ LANGUAGE 'plpgsql' VOLATILE;



    ResponderExcluir
  3. Não funcionou no padrão febraban.
    Para o número 23 o dígito é 9 e não está ocorrendo isso.

    ResponderExcluir

Comente sempre por favor.