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);
Listagem 1. Tabela usada para armazenar as contas dos clientes (contas a receber)

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);
Listagem 2. Tabela usada para armazenar os dados bancários da empresa

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);
Listagem 3. Tabela usada para armazenar as configurações referentes a boletas

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.

figura 1
Figura 1. Tela montada

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;
Listagem 4. Botão localizar contas

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;
Listagem 5. Opções da conta

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;
Listagem 6. Configuração do componente

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;
Listagem 7. ConfiguraComponenteAcBr

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;
Listagem 8. Imprimir Boletos

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;
Listagem 9. Gerar Remessa

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;
Listagem 10. Processar NomeArqRetorno