Neste artigo falaremos sobre como utilizar o componente AcBr para trabalhar com emissão de boletos. No que sabemos, um dos meios mais utilizados para este controle de emissão de boletos é através do uso de DLL de terceiros, porém depende de licença para uso. Sendo assim, criamos este pequeno tutorial mostrando de forma simples como utilizar o componente AcBrBoleto.
Para exemplificar, criamos um pequeno banco de dados no Firebird 2.5, com apenas três tabelas básicas para o nosso controle. São elas Contas (Listagem 1), Banco (Listagem 2) e Config (Listagem 3).
CREATE SEQUENCE CONTAS_ID;
CREATE TABLE CONTAS (
ID INTEGER NOT NULL,
NUMCONTA VARCHAR(10),
SERIE CHAR(3),
DATA_CONTA DATE,
DATA_VENC DATE,
VALOR_CONTA DOUBLE PRECISION,
VALOR_DESCONTO DOUBLE PRECISION,
VALOR_ACRESCIMO DOUBLE PRECISION,
JUROS DOUBLE PRECISION,
MULTA DOUBLE PRECISION,
DATA_QUIT DATE,
VALOR_QUITATO DOUBLE PRECISION,
CLIENTE VARCHAR(50),
ENDERECO VARCHAR(50),
NUMERO VARCHAR(10),
COMPLEMENTO VARCHAR(10),
BAIRRO VARCHAR(20),
CIDADE VARCHAR(20),
CEP VARCHAR(10),
UF CHAR(2),
CNPJ_CPF VARCHAR(14),
INSCRICAO_RG VARCHAR(14),
NOSSO_NUMERO VARCHAR(30),
BOLETO_IMPRESSO CHAR(3)
);
ALTER TABLE CONTAS ADD CONSTRAINT PK_CONTAS PRIMARY KEY (ID);
CREATE SEQUENCE BANCO_ID;
CREATE TABLE BANCO (
ID INTEGER NOT NULL,
NUMERO_BANCO VARCHAR(5),
DIGITO_NUMERO_BANCO CHAR(1),
NOME_BANCO VARCHAR(50),
NOME_AGENCIA VARCHAR(50),
NUMERO_AGENCIA VARCHAR(10),
DIGITO_AGENCIA CHAR(1),
NUMERO_CONTA VARCHAR(20),
DIGITO_CONTA CHAR(1),
CIADE_AGENCIA VARCHAR(20),
UF_AGENCIA CHAR(2),
NOSSO_NUMERO INTEGER,
CEDENTE VARCHAR(50),
COD_CEDENTE VARCHAR(20)
);
ALTER TABLE BANCO ADD CONSTRAINT PK_BANCO PRIMARY KEY (ID);
CREATE SEQUENCE CONFIG_ID;
CREATE TABLE CONFIG (
ID INTEGER NOT NULL,
PATH_REMESSA VARCHAR(100),
PATH_RETORNO VARCHAR(100),
PATH_LOGOTIPO VARCHAR(100),
PATH_GERARPDF VARCHAR(100),
MENSAGEM VARCHAR(250),
DIAS_PROTESTO INTEGER,
ESPECIE VARCHAR(3),
MOEDA VARCHAR(3),
ACEITE CHAR(3),
CARTEIRA CHAR(3),
LOCAL_PAGTO VARCHAR(100),
INSTRUCAO_1 VARCHAR(100),
INSTRUCAO_2 VARCHAR(100),
CONT_REMESSA INTEGER
);
ALTER TABLE CONFIG ADD CONSTRAINT PK_CONFIG PRIMARY KEY (ID);
Com estas tabelas criadas no banco de dados, vamos ao projeto. Partindo do ponto de vista que esteja com o componente AcBrBoleto devidamente instalado, abra um novo projeto no Delphi e adicione os componentes de conexão com o banco de dados e respectivos componentes para acessar as tabelas criadas anteriormente. Preferimos trabalhar com os componentes da paleta dbExpress e Data Acess, mas fique a vontade para usar o que lhe parecer melhor.
Adicione também um componente ACBrBoleto1 e um ACBrBoletoFCQuick1. Observe que o AcBr disponibiliza algumas opções para imprimir o boleto. Dentre elas estão os componentes para Rave Report, Fortes Report e Quick Report. No caso usamos o Quick Report, mas para usar qualquer um dos outros, basta ter o componente do tipo instalado e efetivar a ligação com o componente ACBrBoleto1.
Veja como ficou a tela que montada na Figura 1.
No botão direcionado para “Localizar” as contas adicione o código da Listagem 4.
// fecha os componentes de acesso a tabela
CdsContas.Close;
CdsContas.Params.Clear;
SQLContas.Close;
SQLContas.SQL.Clear;
// passa a SQL para captura das contas em aberto e sem emissão do boleto
SQLContas.SQL.Add('select * from contas');
SQLContas.SQL.Add('where contas.data_conta >= :pDatai');
SQLContas.SQL.Add('and contas.data_conta <= :pDataf');
SQLContas.SQL.Add('and contas.boleto_impresso = '+QuotedStr('NAO'));
SQLContas.SQL.Add('and contas.data_quit is null');
// passa os paramentos de consulta para os componentes
CdsContas.FetchParams;
CdsContas.Params.ParamByName('pDatai').AsDate := DataInicio.Date;
CdsContas.Params.ParamByName('pDataf').AsDate := DataFim.Date;
CdsContas.Open;
// se não foram encontrado dados na consulta informa ao usuário
if CdsContas.IsEmpty then
begin
MessageDlg('Não foram encontradas contas no periodo informado!!!',
mtInformation, [mbOK], 0);
DataInicio.SetFocus;
end
else
DBGrid1.SetFocus;
O botão indicado para adicionar conta será usado para incluir os dados da conta selecionada numa lista do componente para posteriormente ser gerado o arquivo de remessa para o banco e a impressão dos boletos. O código para isso é mostrado na Listagem 5.
var Titulo : TACBrTitulo;
begin
if CdsContasNOSSO_NUMERO.IsNull then
begin
Inc(xNossoNumero);
Titulo := ACBrBoleto1.CriarTituloNaLista;
with Titulo do
begin
Vencimento := CdsContasDATA_VENC.AsDateTime;
DataDocumento := CdsContasDATA_CONTA.AsDateTime;
NumeroDocumento := CdsContasNUMCONTA.AsString;
EspecieDoc := CdsConfigESPECIE.AsString;
if CdsConfigACEITE.AsString = 'SIM' then
Aceite := atSim
else
Aceite := atNao;
DataProcessamento := Now;
NossoNumero := IntToStrZero(xNossoNumero,10);
Carteira := CdsConfigCARTEIRA.AsString;
ValorDocumento := CdsContasVALOR_CONTA.AsFloat;
Sacado.NomeSacado := CdsContasCLIENTE.AsString;
Sacado.CNPJCPF := CdsContasCNPJ_CPF.AsString;
Sacado.Logradouro := CdsContasENDERECO.AsString;
Sacado.Numero := CdsContasNUMERO.AsString;
Sacado.Bairro := CdsContasBAIRRO.AsString;
Sacado.Cidade := CdsContasCIDADE.AsString;
Sacado.UF := CdsContasUF.AsString;
Sacado.CEP := CdsContasCEP.AsString;
ValorAbatimento := 0;
LocalPagamento := CdsConfigLOCAL_PAGTO.AsString;
ValorMoraJuros := 0;
ValorDesconto := 0;
ValorAbatimento := 0;
DataMoraJuros := 0;
DataDesconto := 0;
DataAbatimento := 0;
DataProtesto := CdsContasDATA_VENC.AsDateTime +
CdsConfigDIAS_PROTESTO.AsInteger;
PercentualMulta := 0;
Mensagem.Text := CdsConfigMENSAGEM.AsString;
OcorrenciaOriginal.Tipo := toRemessaBaixar;
Instrucao1 := padL(trim(CdsConfigINSTRUCAO_1.AsString),2,'0');
Instrucao2 := padL(trim(CdsConfigINSTRUCAO_2.AsString),2,'0');
Parcela := 1;
end;
// grava o nosso numero na conta
SQLAux.Close;
SQLAux.SQL.Clear;
SQLAux.SQL.Add('update contas set contas.nosso_numero = :pNossoNum');
SQLAux.SQL.Add('where contas.id = :pIDConta');
SQLAux.Params.ParamByName('pNossoNum').AsInteger := xNossoNumero;
SQLAux.Params.ParamByName('pIDCOnta').AsInteger := CdsContasID.AsInteger;
SQLAux.ExecSQL(False);
// Atualiza a consulta
BtnLocalizarClick(Sender);
end;
Outra rotina importante é a de configuração do componente com os dados necessários. Para isso vamos adicionar no evento OnClick do Combo usado para selecionar o banco em uso para o qual serão emitidos os boletos e adicionar o código da Listagem 6.
xNossoNumero := CdsBancosNOSSO_NUMERO.AsInteger;
ConfiguraComponenteAcBr;
Na Listagem 7 temos o código da procedure ConfiguraComponenteAcBr.
procedure TForm1.ConfiguraComponenteAcBr;
begin
if not CdsConfig.IsEmpty then
begin
ACBrBoleto1.ACBrBoletoFC.DirLogo := CdsConfigPATH_LOGOTIPO.AsString;
ACBrBoleto1.ACBrBoletoFC.Filtro := fiNenhum;
ACBrBoleto1.ACBrBoletoFC.LayOut := lPadrao;
ACBrBoleto1.Banco.Digito := CdsBancosDIGITO_NUMERO_BANCO.AsInteger;
ACBrBoleto1.Banco.Numero := CdsBancosNUMERO_BANCO.AsInteger;
ACBrBoleto1.Cedente.Nome := CdsBancosCEDENTE.AsString;
ACBrBoleto1.Cedente.CodigoCedente := CdsBancosCOD_CEDENTE.AsString;
ACBrBoleto1.Cedente.Agencia := CdsBancosNUMERO_AGENCIA.AsString;
ACBrBoleto1.Cedente.AgenciaDigito := CdsBancosDIGITO_AGENCIA.AsString;
ACBrBoleto1.Cedente.Conta := CdsBancosNUMERO_CONTA.AsString;
ACBrBoleto1.Cedente.ContaDigito := CdsBancosDIGITO_CONTA.AsString;
ACBrBoleto1.Cedente.UF := CdsBancosUF_AGENCIA.AsString;
ACBrBoleto1.NomeArqRemessa :=
CdsConfigPATH_REMESSA.AsString+FormatDateTime('DDMMYYYYHHMMSS',Now)+'.TXT';;
end;
end;
Agora finalizando o nosso projeto para emissão de boletos vamos apenas inserir os códigos referentes aos botões indicados para imprimir os boletos (Listagem 8), gerar o arquivo de remessa (Listagem 9) e processar arquivo de retorno (Listagem 10).
try
ACBrBoleto1.Imprimir;
except
MessageDlg('Erro ao imprimir os boletos. Verifique!',mtWarning,[mbOK],0);
end;
var ContadorRemessa : Integer;
begin
try
// captura o contador de remessa e gera a mesma
ContadorRemessa := CdsConfigCONT_REMESSA.AsInteger;
Inc(ContadorRemessa);
ACBrBoleto1.GerarRemessa(ContadorRemessa);
// Atualiza a nosso numero no cadastro do banco
SQLAux.Close;
SQLAux.SQL.Clear;
SQLAux.SQL.Add('update banco set banco.nosso_numero = :pNossoNum');
SQLAux.SQL.Add('where banco.id = :pID');
SQLAux.Params.ParamByName('pNossoNum').AsInteger := xNossoNumero;
SQLAux.Params.ParamByName('pID').AsInteger := CdsBancosID.AsInteger;
SQLAux.ExecSQL(False);
// Atualiza o contador de remesa na tabela de configuração
SQLAux.Close;
SQLAux.SQL.Clear;
SQLAux.SQL.Add('update config set config.cont_remessa = :pContador');
SQLAux.SQL.Add('where config.id = :pID');
SQLAux.Params.ParamByName('pContador').AsInteger := ContadorRemessa;
SQLAux.Params.ParamByName('pID').AsInteger := CdsConfigID.AsInteger;
SQLAux.ExecSQL(False);
except
MessageDlg('Erro ao gerar arquivo de remessa. Verifique!',mtWarning,[mbOK],0);
end;
var i : Integer;
begin
if OpenDialog1.Execute then
begin
//Configurar banco
ConfiguraComponenteAcBr;
//
ACBrBoleto1.NomeArqRetorno := OpenDialog1.FileName;
ACBrBoleto1.LerRetorno;
for i := 0 to ACBrBoleto1.ListadeBoletos.Count-1 do
begin
if ACBrBoleto1.ListadeBoletos.Objects[i].ValorRecebido > 0 then
begin
// Grava a Quitação da conta
SQLAux.Close;
SQLAux.SQL.Clear;
SQLAux.SQL.Add('update contas set');
SQLAux.SQL.Add('contas.data_quit = :pData,');
SQLAux.SQL.Add('contas.valor_quitato = :pValor');
SQLAux.SQL.Add('where contas.nosso_numero = :pNossoNum');
SQLAux.Params.ParamByName('pData').AsDate
:= ACBrBoleto1.ListadeBoletos.Objects[i].DataBaixa;
SQLAux.Params.ParamByName('pValor').AsFloat
:= ACBrBoleto1.ListadeBoletos.Objects[i].ValorRecebido;
SQLAux.Params.ParamByName('pNossoNum').AsInteger
:= StrToInt(ACBrBoleto1.ListadeBoletos.Objects[i].NossoNumero);
SQLAux.ExecSQL(False);
end;
end;
end;