Fala ai Radizeiros e Radizeiras, tudo bem com vocês?

Como nós que trabalhamos com as rotinas fiscais em nossos software usando o ACBr para facilitar as implementações, nos deparamos com inúmeras linhas de códigos, e as vezes isso nos atrapalha.

Nessa série de post que estou publicando aqui no blog, mostro como aplicar as boas práticas para essas rotinas fiscais, se você ainda não viu os posts anteriores clique aqui.

No post de hoje estaremos implementando o gerenciamento de processos da NF-e

Vamos lá então?

Agora que as coisas irão ficar mais estreitas, pois é agora que iremos implementar a parte de nota fiscal propriamente dita.

Esse post é parte integrada do curso de Boas Prática em Arquivos Fiscais com ACBr, e nele você irá aprender como aplicar todas essas técnicas para melhorar a sua rotina de implementações da geração e envio da NFe, e todo o conteúdo aplicado e seus fontes estão disponíveis dentro do treinamento para melhor fixação e entendimento do conteúdo aplicado.

No post anterior eu falei do método This, onde ao chamar esse método na instância da nossa Factory ele mostra todo os métodos do ACBrNFe.

O método This é um método que existe nativamente em outras linguagens de programação, como por exemplo, Java, C#, dentre outras.

Dentro de nossa Unit de interface temos uma interface chamada iModelFiscalNFeComponentes<T> onde possui um método chamado _This, o Delphi não possuímos este método nativo com nas outras linguagens.

O método _This, retorna apenas um objeto que implementa a interface.

type
    iModelFiscalNFeCompoentes<T> = interface  
        ['{A652704B-022A-4467-B881-C791F95D62D8}']
        function _This : T;
    end;

Observe no código acima que a interface é apenas uma casca, ela não funciona sozinha, ela precisa ter um objeto que vai implementar ela, como é o caso da nossa classe TdmACBrNFe, o nosso DataModule, ele é o cara que implementa essa nossa interface.

type
    TdmACBrNFe = class(TDataModule, iModelFiscalNFeCompoentes<TACBrNFe>)
        ACBrNFe1: TACBrNFe;
    private
      { Private declarations }
    public
      function _This : TACBrNFe;
      class function New : iModelFiscalNFeCompoentes<TACBrNFe>;
    end;

Observe que o método _This está apenas como genérico dando acesso ao objeto que está implementando a interface, se não, só teríamos acesso ao métodos que eu criar, seu eu não tivesse o método _This, para que eu possa acessar aos métodos do ACBr teria que replicar todos os métodos do ACBr dentro de nossa interface, então para que eu não precise fazer isso, como o ACBr não é interfaceado,  eu criei o método _This quebrando o galho para nós, onde criamos a nossa interface como genérica que retorna o _This, ou seja, retorna o objeto que está implementando essa interface, para que eu possa ter acesso aos métodos públicos dele, sem que precisemos ter que reescrever todo os métodos dele.

É isso que o método _This faz para nós, dando acesso a classe que está implementando a interface.

Agora com o componente funcionando, vamos criar a nossa classe mãe na NF-e, é a classe que irá gerenciar os processos de NF-e.

Iremos criar essa classe e salvá-la dentro da pasta NFe da nossa estrutura MVC.

Dentro da nossa estrutura de NFe iremos ter as Units: NFe.pas, NFe.Interfaces,pas, NFe.Invoker.pas, teremos essas 3 Units para que possamos gerenciar, quem quiser trabalhar com NFe dentro do nosso software, por exemplo, o financeiro precisa emitir uma nota, dentro do financeiro ele não irá ter que conhecer o ACBr, ele irá somente conhecer nossa NFe.pas, ou no caso uma Factory, ele só terá acesso a aquilo que está visível para ele.

Vamos criar uma nova Unit onde iremos chama-la de Blog.Model.Fiscal.NFe que iremos salvar na camada Model na pasta NFe.

Não iremos mexer nela agora, pois iremos criar uma nova UNIT chamada Blog.Model.Fiscal.NFe.Interfaces, porque nós iremos declarar a interface que ela irá implementar.

   iModelFiscalNFe = interface
       ['{754932DD-B6C7-4BC1-BACF-FC788CCD1D6A}']
       function Clear : iModelFiscalNFe;
       function Gerar : iModelFiscalNFe;
       function Component : iModelFiscalNFeCompoentes<TACBrNFe>;
   end;

Observe que criamos nossa interface e ela possui alguns métodos, onde os métodos Clear e Gerar retornam a interface iModelFiscalNFe, pois como eles não precisam ter um retorno eles retornam a interface, pois de forma fluente em nossa programação retornamos a própria interface.

E o método Component retorna a interface iModelFiscalNFeCompoentes<TACBrNFe>, como falei aqui anteriormente, iremos ter um acoplamento do componente do ACBr, mas acabamos minimizando ele ao máximo, para que não venhamos ter que reescrever tudo.

Dessa forma iremos ter um sistema de geração de NF-e bem sadio.

Quando alguém do mundo externo for ter acesso a nossa nota fiscal principal, quando digo mundo externo, fora a nossa camada de NFe, por exemplo, se alguém lá dentro do financeiro chamar nossa função de nota fiscal irá ter acesso ao método que acabamos de criar, ele não precisa conhecer todo componente, ele só irá precisar conhecer os métodos que estão nessa interface iModelFiscalNFe.

É na iModelFiscalNFe que tudo irá acontecer.

Vamos analisar o código do Demo do ACBrNFe para que você possa entender o porque eu coloquei esse métodos visíveis na minha interface.

Dentro do botão “Criar e Enviar” temos esse código abaixo.


procedure TForm1.btnCriarEnviarClick(Sender: TObject);
var
vAux, vNumLote : String;
begin
if not(InputQuery('WebServices Enviar', 'Numero da Nota', vAux)) then
exit;

if not(InputQuery('WebServices Enviar', 'Numero do Lote', vNumLote)) then
exit;

vNumLote := OnlyNumber(vNumLote);

if Trim(vNumLote) = '' then
begin
MessageDlg('Número do Lote inválido.',mtError,[mbok],0);
exit;
end;

ACBrNFe1.NotasFiscais.Clear;

ACBrNFe1.Configuracoes.Geral.ModeloDF := moNFe;
ACBrNFe1.Configuracoes.Geral.VersaoDF := TpcnVersaoDF(cbVersaoDF.ItemIndex);
GerarNFe(vAux);

ACBrNFe1.NotasFiscais.GerarNFe;

...

Observe no código acima que primeiro ele solicita o número da nota, pede o lote, e valida o número e o lote, e em seguida manda limpar,ele executa o método Clear.

Então vamos colocar esse método lá na nossa interface.

Logo depois ele manda gerar algumas informações, preenche toda a nota e manda GerarNFe, por este motivo estão esse métodos em nossa interface.

Então vamos implementar essa nossa interface dentro de nossa classe de NFe.

type
    TModelFiscalNFe = class (TInterfacedObject, iModelFiscalNFe)
    private
        FComponenteFactory : iModelFiscalNFeFactory;
        FComponente : iModelFiscalNFeCompoentes&amp;lt;TACBrNFe&amp;gt;;
    public
        constructor Create;
        destructor Destroy; override;
        class function New : iModelFiscalNFe;
        function Clear : iModelFiscalNFe;
        function Gerar : iModelFiscalNFe;
        function Component : iModelFiscalNFeCompoentes<TACBrNFe>;
    end;

implementation

{ TModelFiscalNFe }

function TModelFiscalNFe.Clear: iModelFiscalNFe;
begin
    Result := Self;
    FComponente._This.NotasFiscais.Clear;
end; 

function TModelFiscalNFe.Component: iModelFiscalNFeCompoentes<TACBrNFe>;
begin
    Result := FComponente;
end;

constructor TModelFiscalNFe.Create;
begin
    FComponenteFactory := TModelFiscalNFeComponentesFactory.New;
    FComponente := FComponenteFactory.ACBr;
end;

destructor TModelFiscalNFe.Destroy;
begin
    inherited;
end;

function TModelFiscalNFe.Gerar: iModelFiscalNFe;
begin
    Result := Self;
    FComponente._This.NotasFiscais.GerarNFe;
end;

class function TModelFiscalNFe.New: iModelFiscalNFe;
begin
    Result := Self.Create;
end;

Para que possamos trabalhar e emitir a nota, é necessário ter o componente do ACBr, sendo assim no código acima você pode observar que temos um objeto que implementa a interface do componente ACBr.

Devido o problema de gerenciamento de memória do DataModule precisamos guardar a instância da Factory, para que ele possa saber que foi criado e que não irei destruir enquanto essa nossa classe esteja criada, porque se eu não criar a variável, e simplesmente chamar a factory, ele irá destruir antes da hora, então não queremos isso.

Observe que instanciamos no Create o nosso objeto da factory, e logo em seguida o objeto de componente recebe o ACBr dessa nossa Factory.

Então, já estou guardando a instância que eu precisava, e tudo que eu for trabalhar com o ACBr, irei trabalhar com o meu objeto FComponente.

No método Clear  simplesmente chamamos nosso FComponente e logo em seguida o _This, fazendo assim conseguimos acessar todos os métodos do ACBr e chamar o Clear para a nota fiscal.

E em Gerar chamamos o GerarNFe do ACBr.

Agora a nossa classe que dará visibilidade as outras, está acessando o ACBr tranquilamente, mas o componente do ACBr está lá dentro do DataModule encapsulado e interfaceado, para que possamos seguir as boas práticas.

Agora está pronta a estrutura que precisávamos para começar a implementar a geração da NFe.

Viu como vamos melhorando todo nosso código para implementação do ACBrNFe, esse é apenas o primeiro post da nossa série de Boas práticas para geração de arquivos fiscais com ACBr, este post foi extraído de um dos meus treinamentos que ensino todas as técnicas de boas práticas com clean code para geração de arquivos fiscais.

Com as técnicas aplicadas nesse treinamento, alem de aprender a aplicar na criação e emissão da NF-e, você pode também aplicar facilmente para o SPED e o SINTEGRA, ou seja, o que é problema para você hoje, depois desse treinamento você irá enxergar como oportunidade.

CLIQUE AQUI PARA SABER MAIS SOBRE O TREINAMENTO BOAS PRÁTICAS PARA GERAÇÃO DE ARQUIVOS DISCAIS COM ACBr