Página 1 de 1
Boletos
Enviado: 04 Out 2023 17:41
por JoséQuintas
Nada mudou, ao mesmo tempo que mudou, vão concordar.
Espécie do documento, número e sigla.
Pensem comigo: Isso é negociado com o banco, pra que ficar perdendo tempo criando tabela na classe ?
O banco passa pro cliente, o cliente preenche, fim.
E tudo pronto pra qualquer situação, sem ter que atualizar tabelas.
Este daqui, muito legal, vão ver que em outras classes está complicado.
Código: Selecionar todos
cCampoLivre := Substr( ::cBarras, 20 )
::cDigitavel := Substr( ::cBarras, 1, 4 ) + Substr( cCampoLivre, 1, 5 )
::cDigitavel += ::Modulo10_All( ::cDigitavel )
::cDigitavel += Substr( cCampoLivre, 6, 10 ) + ::Modulo10_All( Substr( cCampoLivre, 6, 10 ) )
::cDigitavel += Substr( cCampoLivre, 16, 10 ) + ::Modulo10_All( Substr( cCampoLivre, 16, 10 ) )
::cDigitavel += Substr( ::cBarras, 5, 1 )
::cDigitavel += Substr( ::cBarras, 6, 19 )
A linha digitável é o código de barras em outra ordem, acrescentado dos dígitos de controle.
Então.... continua tudo igual.
Mas.... tá resolvido espécie e linha digitável pra qualquer banco.
Importante:
Estou com 3 situações de Bradesco diferentes, e 2 situações de Itaú diferentes.
Isso significa que por mais que funcione pra um banco, não significa que esteja resolvido.
Então, apenas estou seguindo com meus bancos e minhas situações.
Boletos
Enviado: 04 Out 2023 18:24
por JoséQuintas

Código: Selecionar todos
REQUEST HB_CODEPAGE_PTISO
#include "inkey.ch"
#include "set.ch"
#include "directry.ch"
PROCEDURE Main
LOCAL nCont, a, b, cNumero, nTotal := 10000000, nKey
SetMode( 40, 100 )
Set( _SET_CODEPAGE, "PTISO" )
CLS
GrafTempo("calculando")
FOR nCont = 1 TO nTotal
GrafTempo( nCont, nTotal )
cNumero := Ltrim( Str( nCont ) )
A := Modulo11_All( cNumero )
B := Modulo11_033Barras( cNumero )
IF A != B
? A, B
ENDIF
nKey := Inkey()
IF nKey == K_ESC
EXIT
ENDIF
NEXT
? "fim"
Inkey(0)
RETURN
FUNCTION AppVersaoExe(); RETURN ""
//FUNCTION AppUserName(); RETURN ""
// genérico, usado no código de barras
FUNCTION Modulo11_All( cNumero )
LOCAL nFator := 2, nSoma := 0, nResto, cDigito
FOR EACH cDigito IN cNumero DESCEND
nSoma += ( Val( cDigito ) * nFator )
nFator := iif( nFator == 9, 2, nFator + 1 )
NEXT
nResto := 11 - Mod( nSoma, 11 )
nResto := iif( nResto == 0 .OR. nResto > 9, 1, nResto )
cDigito := Str( nResto, 1 )
RETURN cDigito
// Santander 033 Barras - esquisito ser diferente
FUNCTION Modulo11_033Barras( cNumero )
LOCAL nFator := 2, nSoma := 0, cDigito
FOR EACH cDigito IN cNumero DESCEND
nSoma += ( Val( cDigito ) * nFator )
nFator := iif( nFator == 9, 2, nFator + 1 )
NEXT
nSoma := Mod( nSoma * 10, 11 )
nSoma := iif( nSoma == 0 .OR. nSoma > 9, 1, nSoma )
cDigito := Str( nSoma, 1 )
RETURN cDigito
Não entenderam ?
É o carvalho da ponte que caiu.
A rotina de dígito de controle do Santander é diferente..... mas por incrível que pareça.... é diferente mas dá o mesmo resultado.
Pelo menos pra 10 milhões de números ficou igual.
Pois é... e essa merd. vai se espalhando por diversas rotinas de boletos kkkkk
Logo vi que não era possível só o Santander ser diferente....
Mais uma coisa resolvida pra todos os bancos de uma vez.
Aí pergunto: pressa pra que ? pra amontoar tranqueira igual os outros ? kkkkk
Pois é... a inteligência artificial tá vindo pra resolver a bagunça que criaram kkkk
Boletos
Enviado: 16 Out 2023 17:46
por JoséQuintas
Acho que o Bradesco colocou IA no envio.
Pela mensagem, talvez seja rejeitado, não é certeza kkkkk
Entrando mais um SAFRA
Pois é.... agora são 3 em andamento:
BRADESCO
SANTANDER
SAFRA
Parece combinado, estão entrando em ordem alfabética kkkkk
Boletos
Enviado: 16 Out 2023 18:49
por JoséQuintas
A propósito:
pesquisem na internet sobre como achar dígito de controle da agência do Bradesco.
É engraçado, eles inventam de colocar isso NO BOLETO (PDF), mas não entra em nenhum outro lugar, então é meio desconhecido.
Por enquanto é a única diferença entre os dois casos de Bradesco que tenho aqui.
O que está em uso há mais de 10 anos não tem isso no PDF, e lembro que também foi homologado antes do uso.
Boletos
Enviado: 17 Out 2023 18:09
por JoséQuintas
Safra vai entrar em testes.
Vamos ver se vai demorar igual aos outros.
Achei fácil até demais fazer pro Safra.
Mais fácil fazer do zero do que pegar rotinas malucas por aí.
Tapa buraco de banco:
Código: Selecionar todos
STATIC FUNCTION ze_Calculo000( Self )
::cBancoDigito := "ERRO"
::cLocalPagto := "INVALIDO"
::cBarras := Replicate( "0", 43 )
::cBolNumero := "INVALIDO"
::cBolConta := "INVALIDO"
RETURN Nil
É só isso que vai precisar pra qualquer banco, PARA O BOLETO.
O Cnab é outra história, precisa completo.
Cada vez mais acho que o pessoal só complica isso.
Boletos
Enviado: 17 Out 2023 22:10
por JoséQuintas
Tá ficando moleza.
Código: Selecionar todos
/*
Safra
Manual do banco em outubro/2023
*/
FUNCTION ze_Calculo422( SELF )
LOCAL cBarras1, cBarras2
::cBancoDigito := "422-7"
::cLocalPagto := "ATÉ O VENCIMENTO PAGUE EM QUALQUER BANCO"
::cBolNumero := StrZero( ::nBancario, 9 )
::cBolConta := StrZero( ::nAgencia, 5 ) + " / " + StrZero( ::nIdEmpresa, 9 )
cBarras1 := StrZero( ::nBanco, 3 ) + "9" + StrZero( ::nFatorVen, 4 ) + ;
StrZero( ::nValor * 100, 10 )
cBarras2 := StrZero( ::nAgencia, 5 ) + StrZero( ::nConta, 9 ) + ;
StrZero( ::nBancario, 9 )
::cBarras := cBarras1 + ::Modulo10_All( cBarras1 ) + cBarras2 + ::Modulo10_All( cBarras2 )
RETURN Nil
FUNCTION ze_Cnab422( aBoletoList )
LOCAL cTxt := "", nSequencial := 1
LOCAL oBoleto, nTotal := 0
IF Empty( aBoletoList )
RETURN Nil
ENDIF
IF ValType( aBoletoList ) != "A"
aBoletoList := { aBoletoList }
ENDIF
oBoleto := aBoletoList[1]
WITH OBJECT oBoleto
/* header */
/* 001-001 */ cTxt := "0"
/* 002-002 */ cTxt += "1"
/* 003-009 */ cTxt += "REMESSA"
/* 010-011 */ cTxt += "01"
/* 012-019 */ cTxt += "COBRANCA"
/* 020-026 */ cTxt += Space(7)
/* 027-040 */ cTxt += StrZero( :nAgencia, 5 ) + StrZero( :nConta, 9 )
/* 041-046 */ cTxt += Space(6)
/* 047-076 */ cTxt += Pad( :cEmpNome, 30 )
/* 077-079 */ cTxt += "422"
/* 080-090 */ cTxt += Pad( "BANCO SAFRA", 11 )
/* 091-094 */ cTxt += Space(4)
/* 095-100 */ cTxt += hb_Dtoc( Date(), "DDMMYY" )
/* 101-394 */ cTxt += Space(291)
/* 392-394 */ cTxt += StrZero( :nRemessa, 3 )
/* 395-400 */ cTxt += StrZero( nSequencial++, 6 )
cTxt += hb_Eol()
ENDWITH
FOR EACH oBoleto IN aBoletoList
WITH OBJECT oBoleto
/* Detalhe 1 */
/* 001-001 */ cTxt += "1"
/* 002-003 */ cTxt += iif( IsCnpj( :cEmpCnpj ), "02", "01" )
/* 004-017 */ cTxt += StrZero( Val( SoNumeros( :cEmpCnpj ) ), 14 )
/* 018-031 */ cTxt += StrZero( :nAgencia, 5 ) + StrZero( :nConta, 9 )
/* 032-037 */ cTxt += Space(6)
/* 038-062 */ cTxt += Space(25)
/* 063-071 */ cTxt += StrZero( :nBancario, 9 )
/* 072-101 */ cTxt += Space(30)
/* 102-102 */ cTxt += "0"
/* 103-104 */ cTxt += "00"
/* 105-105 */ cTxt += Space(1)
/* 106-107 */ cTxt += StrZero(0,2)
/* 108-108 */ cTxt += "1" // ou 2 pra vinculada
/* 109-110 */ cTxt += StrZero(1,2)
/* 111-120 */ cTxt += StrZero( Val( :cNumDoc ), 10 )
/* 121-126 */ cTxt += hb_Dtoc( :dDatVen, "DDMMYY" )
/* 127-139 */ cTxt += StrZero( :nValor * 100, 13 )
/* 140-142 */ cTxt += "422"
/* 143-147 */ cTxt += StrZero(0,5)
/* 148-149 */ cTxt += StrZero( :nEspecie, 2 )
/* 150-150 */ cTxt += "A"
/* 151-156 */ cTxt += hb_Dtoc( :dDatEmi, "DDMMYY" )
/* 157-158 */ cTxt += iif( :nJuros != 0, "01", "02" )
/* 159-160 */ cTxt += StrZero(0,2)
/* 161-173 */ cTxt += StrZero( :nValor * :nJuros / 30, 13 )
/* 174-179 */ cTxt += StrZero(0,6)
/* 180-192 */ cTxt += StrZero(0,13)
/* 193-205 */ cTxt += StrZero(0,13)
IF :nMulta == 0
/* 206-218 */ cTxt += StrZero(0,13)
ELSE
/* 206-211 */ cTxt += hb_Dtoc( :dEmissao + 30, "DDMMYY" )
/* 212-215 */ cTxt += StrZero( :nMulta * 100, 4 )
/* 216-218 */ cTxt += "000"
ENDIF
/* 219-220 */ cTxt += iif( IsCnpj( :cCliCnpj ), "02","01" )
/* 221-234 */ cTxt += StrZero( Val( SoNumeros( :cCliCnpj ) ), 14 )
/* 235-274 */ cTxt += Pad( :cCliNome, 40 )
/* 275-314 */ cTxt += Pad( :cCliEnd, 40 )
/* 315-324 */ cTxt += Pad( :cCliBairro, 10 )
/* 325-326 */ cTxt += Space(1)
/* 327-334 */ cTxt += StrZero( Val( SoNumeros( :cCliCep ) ), 8 )
/* 325-349 */ cTxt += Pad( :cCliCidade, 25 )
/* 350-351 */ cTxt += Pad( :cCliUF, 2 )
/* 352-381 */ cTxt += Pad( :cAvalNome, 30 )
/* 382-388 */ cTxt += Space(7)
/* 389-391 */ cTxt += "422"
/* 392-394 */ cTxt += StrZero( :nRemessa, 3 )
/* 395-400 */ cTxt += StrZero( nSequencial++, 6 )
nTotal += :nValor
ENDWITH
cTxt += hb_Eol()
NEXT
oBoleto := aBoletoList[1]
WITH OBJECT oBoleto
/* trailer */
/* 001-001 */ cTxt += "9"
/* 002-368 */ cTxt += Space(367)
/* 369-376 */ cTxt += StrZero( nSequencial - 2, 8 )
/* 377-391 */ cTxt += StrZero( nTotal * 100, 15)
/* 392-394 */ cTxt += StrZero( :nRemessa, 3 )
/* 394-400 */ cTxt += StrZero( nSequencial, 6 )
cTxt += hb_Eol()
ENDWITH
RETURN cTxt
Boletos
Enviado: 19 Out 2023 13:34
por JoséQuintas
Adicionado nEspecial pra tratar exceções, ou ítens não resolvidos de outra forma.
Considerei o Bradesco como sendo a primeira exceção, por estar tratando o dígito P para um cliente e outro não.
O tratamento do P é a exceção 1
Até encontrei rotina pra cálculo de dígito de agência e conta, mas nem assim uma rotina atende os dois clientes, sem colocar exceção.
Também pensei na possibilidade do código de barras não aceitar o P por isso troca por zero, mas também não atende os dois.
Então que fique na exceção e pronto.
Já imagino que, além da exceção de conta com P, pode ter agência com P, e as duas juntas com P.
Então o que seria uma diferença pra gambiarra, passou a ser esse ::nEspecial, e segue tudo normalmente.
Boletos
Enviado: 23 Out 2023 18:51
por JoséQuintas
Pronto, acho que agora não vai mudar tanto.
Centralizei tudo em zepack, antigo sefazclass.
Não estou a fim de ficar criando e fazendo manutenção em trocentos repositórios no github, assim é salvar tudo de uma vez.
https://github.com/JoseQuintas/zepack
Boletos
Enviado: 24 Out 2023 12:57
por JoséQuintas
Considerações gerais da classe:
- Gostei de poder gerar a linha digitável a partir do código de barras, isso encerra o assunto pra qualquer banco.
- Gostei das rotinas padrão de dígito de controle, são usadas para código de barras e digitável pra qualquer banco
- Gostei do PDF padrão, atende qualquer banco, pela classe ou fora dela
- Gostei do parâmetro nFormato (antes nEspecial) pra definir situações diferentes que possam aparecer
- Fator de vencimento preparado para até o fim da vida, vai durar mais do que nós
O boleto é padrão. Se o banco precisa preencher diferente, é mexer na rotina de banco, e não no PDF.
Rotinas de dígito de controle: testar cada uma nova pra ver se não é a que já existe com maquiagem, tem muito mais disso do que se pensa.
A rotina do Bradesco, por exemplo, é a mesma pra número bancário, calcular dígito de agência e de conta do Bradesco.
Se procurarem pela internet, vão ver várias rotinas ligeiramente diferentes, todas acabam com mesmo resultado.
Ficar colocando esse tipo de rotina na classe, é só complicar.
Ao implantar, vi que facilita fazer tudo por intermédio da classe principal, pra não ter que colocar IFs nos fontes de trabalho.
Se tem rotina pra cada banco, tudo bem, mas chamando pela classe principal fica mais flexível.
Quem quiser colaborar com outros bancos, fique à vontade.
NOVAMENTE:
Mesmo dentro de um banco não é padrão.
No momento duas situações diferentes do Bradesco.
A princípio pareceu o caso do dígito P, esse dígito existe no Bradesco, mas código de barras só aceita números, e o P é trocado por zero.
Apenas pareceu isso, porque a princípio trocou por zero, mas não é, então entrou no nFormato=1
No MEU aplicativo facilitou criar duas classes: oBolSetup e oBoleto.
Crio a classe oBolSetup com a configuração, e vou copiando pra cada boleto. Dá até pra colocar os dados da empresa nesse oBolSetup, já que os dados da empresa vão ser fixos em todos os boletos.
E uso oBolSetup pra ler/gravar configuração default do portador, através de uma função padrão, o que enxugou todos os fontes que tratam isso.
Considerações gerais sobre boleto:
Número bancário
É igual pra todos os bancos. O que o banco não aceita é NÚMERO REPETIDO EM ABERTO. Uma vez pago, o número é liberado.
Daria pra reiniciar esse número todo ano, e se grava no financeiro pra controle, é limpar os antigos liquidados.
Número de transmissão
Não sei ao certo, apenas imagino que siga a regra do número bancário, não pode repetir enquanto existir outro pendente.
Número de lote
É interno do CNAB, pode ser sempre lote 1.
Tem banco que pede um código de cliente na remessa
Tem banco que dá um código pro cliente, esse código é usado em vários lugares como se fosse a conta, ou uma conta de cobrança.
Com os bancos atuais foi isso que percebi.
Quando entrarem mais bancos verifico o que mais existe.
No momento: Itaú, Bradesco, Santander, e Safra.
Tirando Itaú, os demais considero ainda em fase de implantação, porque o Bradesco em uso está sendo trocado totalmente pra classe.
Todos sendo tratados diretamente com o banco, e só usando rotinas minhas mesmo, ou que já tinha, ou criadas do zero.
NÃO pretendo copiar rotina nenhuma de banco nenhum.
Como cada banco tem suas próprias exceções, copiar rotina não significa que esteja resolvido, e pode trazer complicações inúteis.
Quem tiver banco EM USO e quiser colaborar alterando e fazendo testes, à vontade.
Aqui ocupado implantando todos esses, e tem mais o CTE 4.00 pra fazer.
O que dá pra fazer, que continuo fazendo para os meus casos de boleto:
oBoleto é uma classe com variáveis.
É ir trocando nas rotinas pra usar essas variáveis no lugar das outras, e atualizando diretamente nos clientes, deixando possíveis erro sob controle.
O resultado vai ser um só: classe única pra tudo, configuração padrão pra tudo, sem mais rotinas duplicadas pra fazer a mesma coisa.
Boletos
Enviado: 06 Nov 2023 11:20
por JoséQuintas
Banco Safra tem uma ocorrência curiosa:
A agência é 56, mas é pra considerar em boleto e cnab como 5600.
O engraçado é que a validação diz que o dígito de código de barras e digitável está errado.
Mas errada é a agência, e não os cálculos, porque o banco usou 5600 nos cálculos.
Estou só tentando confirmar o porquê de agência 56 virar 5600, se é normal ou se é exceção.
A própria validação do banco, no título da listagem, mostra agência como 5600.
Das duas uma: ou multiplico agência por 100, ou digo para o usuário cadastrar agência como 5600 e não como 56.
Porque? porque sei lá se isso é normal ou é exceção.
Pelo que percebi, tem banco que comprou outro banco, mas internamente é como se fossem dois bancos ainda, com boletos e cnabs diferentes.
Então, exceções sempre vão existir.
Boletos
Enviado: 29 Jan 2024 10:38
por JoséQuintas
Rejeição no Itaú hoje que nunca aconteceu.
08/03 nome do pagador não informado ou deslocado
Tantos anos transmitindo boleto Itaú, só aconteceu isso desta vez.
Por enquanto a possibilidade que vejo é mais de um espaço em branco no nome.
Só vou ter certeza no retorno da nova transmissão.
Boletos
Enviado: 09 Fev 2024 11:17
por JoséQuintas
Situação atual:
- boletos Santander homologado
- boletos Bradesco homologado
- boletos Banco Real homologado
- boletos Itaú comuns homologado
- Boletos Itaú layout personalizado, enviados pelo correio e pelo banco, homologado há anos
- Boletos Itaú layout personalizado, enviados por email e pelo banco, VOLTOU À ESTACA ZERO, estavam tratando como boleto comum, a mudança maior é do lado do banco.
Boletos
Enviado: 16 Fev 2024 12:39
por JoséQuintas
Então, pra quem acha que é só pegar rotina pronta pra boleto e sair usando....
Já se vão alguns meses tratando isso no Itaú.
Parece piada mas....
Hoje o técnico enviou o link pra olhar o manual CNAB 400, do que pode ser feito.
Respondi pra ele, pra ele olhar o link de baixo, que é o layout usado pela empresa.
Pois é... é mostrar pro profissional de cobrança do banco o manual que ele não conhece, que está lá junto com o outro.
E tem mais esta:
A empresa já usa, é só olhar lá no Itaú o que está em uso.
A única diferença é que está sendo usada a opção por correio, e agora será usada TAMBÉM a opção por email.
Boleto é fácil.... mas não é fácil....
Demora pra colocar em prática, mesmo com tudo pronto.
É bom entender direito sobre boleto, pra poder ensinar pro banco kkkk
Tem até que ensinar pra quem fornece o manual, sobre aonde está o manual kkkk
Boletos
Enviado: 20 Fev 2024 21:27
por JoséQuintas
Pois é, em pleno 2024 ainda tem dessas coisas....
O Itaú não permite a opção de correio e email ao mesmo tempo, para o layout especial.
A única opção é ter duas contas correntes, uma pra cada.
Boletos
Enviado: 15 Mai 2024 13:09
por JoséQuintas
Layout: Itaú - Cob. com Registro - CNAB 400
Registro: detalhe
Linha: 2
Posição 034 - Campo: Código Instrução/Alegação a ser Cancelada - Conteúdo não é igual a zeros. (em branco)
Posição 157 - Campo: 1ª Instrução de Cobrança - Conteúdo do campo fora do conjunto permitido. (em branco)
Posição 159 - Campo: 2ª Instrução de Cobrança - Conteúdo do campo fora do conjunto permitido. (em branco)
Posição 174 - Campo: Data limite para concessão de desconto - Data inválida. (em branco)
Layout: Itaú - Cob. com Registro - CNAB 400
Linha: 3
Posição 034 - Campo: Código Instrução/Alegação a ser Cancelada - Conteúdo não é igual a zeros. (em branco)
Posição 157 - Campo: 1ª Instrução de Cobrança - Conteúdo do campo fora do conjunto permitido. (em branco)
Posição 159 - Campo: 2ª Instrução de Cobrança - Conteúdo do campo fora do conjunto permitido. (em branco)
Posição 174 - Campo: Data limite para concessão de desconto - Data inválida. (em branco)
Layout: Itaú - Cob. com Registro - CNAB 400
Situação nova..... devido à situação.
Num determinado cliente está acusando esses erros na remessa do ITAÚ, começou neste mês o erro.
Olhando o manual.... NÃO é pra deixar em branco é pra preencher com ZEROS
Tá.... então mudou o layout....
Mas só acontece nesse cliente !!!!!
Porque nos outros clientes continua aceitando em branco ?
Será que atualizando vai dar erro nos outros clientes ?
Sei lá....