Consegui entender a situação do nosso amigo Leonardo e faz muito sentido a implementação dele
Realmente, está correto o que o banco Sicoob informou, que nada muda (em partes)
Partimos do principio que nos fontes atuais, o acbrBoleto sempre calcula o digito verificado do nosso numero.
O que acontece é que quando é gerado CNAB 240, nós geramos o nosso numero, e o AcbrBoleto calcula o digito verificador do nosso numero, e enviamos para o sicoob através do arquivo CNAB, registra no banco e o processo está correto.
Quando é por API, sobre o nosso numero há duas possibilidades
1) Nós informar o nosso numero + digito verificador, igualmente é feito no CNAB240, e que o boleto é registrado no Sicoob exatamente como é enviado.
2) Nós informar '' no campo nosso numero, neste cenário, após o registro no banco, o mesmo retorna o nosso numero, este é o cenário que eles implementaram, não há digito verificador para este caso, apenas o nosso numero, e neste caso não deve calcular o digito verificador, porque se calcular estará errado
Fiz uma implementação, e fiz essa validação com boletos de alguns clientes (API e CNAB240) e agora ficou correto.
criei a property
fpGerarDV no TACBrBancoClass
e essa modificação ao gerar o digito verificador
function TACBrBancoSicoob.CalcularDigitoVerificador(const ACBrTitulo: TACBrTitulo ): String;
var
Num, Res :String;
i, base, digito : Integer;
const
indice = '319731973197319731973';
begin
Result := '';
if (not GerarDV) then
Exit;
Result := '0';
Num := PadLeft(ACBrTitulo.ACBrBoleto.Cedente.Agencia, 4, '0') +
PadLeft(ACBrTitulo.ACBrBoleto.Cedente.CodigoCedente, 10, '0') +
PadLeft(trim(ACBrTitulo.NossoNumero), 7, '0');
base := 0;
for i := 1 to Length(Num) do
base := base + ( StrToInt(copy(Num,i,1)) * StrToInt(copy(indice,i,1)) );
digito := 11-(( base )-( trunc(base/11) * 11));
//(Se o Resto for igual a 0 ou 1 então o DV é igual a 0)
if (digito > 9) then
digito := 0;
Res := IntToStr(digito);
Result := Res;
{ Para o cálculo do dígito verificador do nosso número, deverá ser utilizada
a fórmula abaixo:
Número da Cooperativa 9(4) – 3009
Código do Cliente 9(10) – cedente
Nosso Número 9(7) – Iniciado contagem em 1
Constante para cálculo = 3197
a) Concatenar na seqüência completando com zero à esquerda.
Ex.: Número da Cooperativa = 0001
Número do Cliente(cedente) = 1-9
Nosso Número = 21
000100000000190000021
b) Alinhar a constante com a seqüência repetindo de traz para frente.
Ex.: 000100000000190000021
319731973197319731973
c) Multiplicar cada componente da seqüência com o seu correspondente da
constante e somar os resultados.
Ex.: 1*7 + 1*3 + 9*1 + 2*7 + 1*3 = 36
d) Calcular o Resto através do Módulo 11.
Ex.: 36/11 = 3, resto = 3
e) O resto da divisão deverá ser subtraído de 11 achando assim o DV
(Se o Resto for igual a 0 ou 1 então o DV é igual a 0).
Ex.: 11 – 3 = 8, então Nosso Número + DV = 21-8
Memória de Cálculo
Coop.(4)|Cliente(10) |Nosso Número(7)
3 0 0 9 0 0 0 0 1 3 6 3 5 2 5 9 3 1 1 5 1
3 1 9 7 3 1 9 7 3 1 9 7 3 1 9 7 3 1 9 7 3
9 0 0 63 0 0 0 0 3 3 54 21 15 2 45 63 9 1 9 35 3 = soma = 335
digito = 11-(( soma )-( resto inteiro (trunc) da divisao da soma por 11 * 11))
digito = 11-(( 335 )-(30*11))
digito = 6 }
end;
no meu caso isso resolveu para todos os cenários, controlo conforme a property no momento da geração, se é CNAB240 ou API
ACBrBoleto.pas
ACBrBancoSicoob.pas