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

Mais um post da nossa série de Boas Práticas em arquivos fiscais com ACBr, a cada post estamos evoluindo a geração da NF-e aqui em nosso blog.

Chega de você sofrer com rotinas constantes e desgastantes no desenvolvimento das rotinas fiscais do seu software.

Vamos lá seguir em nosso desenvolvimento?

Vamos voltar ao Demo do ACBr, e observe que ele limpa a nota, preenche as configurações da nota, e na hora que começa gerar, é pedido para adicionar uma nota.

...
   ACBrNFe1.NotasFiscais.Clear;
   ACBrNFe1.Configuracoes.Geral.ModeloDF := moNFe;
   ACBrNFe1.Configuracoes.Geral.VersaoDF := TpcnVersaoDF(cbVersaoDF.ItemIndex);
   GerarNFe(vAux);
...
   NotaF := ACBrNFe1.NotasFiscais.Add;
   NotaF.NFe.Ide.cNF := StrToInt(NumNFe); //Caso não seja preenchido será gerado um número aleatório pelo componente
   NotaF.NFe.Ide.natOp := 'VENDA PRODUCAO DO ESTAB.';
   NotaF.NFe.Ide.indPag := ipVista;
   NotaF.NFe.Ide.modelo := 55;
   NotaF.NFe.Ide.serie := 1;
   NotaF.NFe.Ide.nNF := StrToInt(NumNFe);
...

Observe que todos os outros comandos estão usando a variável NotaF, no nosso caso não iremos utilizar  a variável, iremos utilizar simplesmente o comando FComponente.NotaFiscal e chamar os métodos para rotina proposta.

...
   FComponente._This.NotasFiscais.Clear;
   FComponente.AddNotaFiscal;
   
   TModelFiscalNFeInvoker.New
     .Add(TModelFiscalNFeCommandGeral.New(Self))
   .Execute;
...

Você pode observar que só com esse comando estamos trabalhando a nota fiscal, onde em FComponente.AddNotaFiscal já é a nossa nota fiscal, que foi adicionada e já encontra-se salva no objeto, lá no nosso DataModule.

Observe que o comando geral já foi feito, e agora qual é o próximo comando que nós temos que fazer agora dentro do ACBr? É o de identificação da nota, que pode ser visto no código do Demo do ACBr logo acima.

Iremos criar uma Unit e irei salva-la com a nomenclatura Blog.Model.Fiscal.NFe.Command.Ide, e nossa classe irá ficar desta forma.

type
   TModelFiscalNFeCommandIde = class (TInterfacedObject, iCommand)
   private
     FParent : iModelFiscalNFe;
   public
     constructor Create(Parent : iModelFiscalNFe);
     destructor Destroy; override;
     class function New(Parent : iModelFiscalNFe) : iCommand;
     function Execute : iCommand;
   end;

implementation

uses
   System.SysUtils, pcnConversao, pcnConversaoNFe;

{ TModelFiscalNFeCommandIde }

constructor TModelFiscalNFeCommandIde.Create(Parent : iModelFiscalNFe);
begin
   FParent := Parent;
end;

destructor TModelFiscalNFeCommandIde.Destroy;
begin
   inherited;
end;

function TModelFiscalNFeCommandIde.Execute: iCommand;
begin
   Result := Self;
   FParent.Component.NotaFiscal.NFe.Ide.cNF := 0; //Caso não seja preenchido será gerado um número aleatório pelo componente 
   FParent.Component.NotaFiscal.NFe.Ide.natOp := 'VENDA PRODUCAO DO ESTAB.';
   FParent.Component.NotaFiscal.NFe.Ide.indPag := ipVista;
   FParent.Component.NotaFiscal.NFe.Ide.modelo := 55;
   FParent.Component.NotaFiscal.NFe.Ide.serie := 1;
   FParent.Component.NotaFiscal.NFe.Ide.nNF := 0;
   FParent.Component.NotaFiscal.NFe.Ide.dEmi := Date;
   FParent.Component.NotaFiscal.NFe.Ide.dSaiEnt := Date;
   FParent.Component.NotaFiscal.NFe.Ide.hSaiEnt := Now;
   FParent.Component.NotaFiscal.NFe.Ide.tpNF := tnSaida;
   FParent.Component.NotaFiscal.NFe.Ide.tpEmis := TpcnTipoEmissao(cbFormaEmissao.ItemIndex);
   FParent.Component.NotaFiscal.NFe.Ide.tpAmb := taHomologacao; //Lembre-se de trocar esta variável quando for para ambiente de produção
   FParent.Component.NotaFiscal.NFe.Ide.verProc := '1.0.0.0'; //Versão do seu sistema
   FParent.Component.NotaFiscal.NFe.Ide.cUF := UFtoCUF('RJ');
   FParent.Component.NotaFiscal.NFe.Ide.cMunFG := 0;
   FParent.Component.NotaFiscal.NFe.Ide.finNFe := fnNormal;
   if Assigned(FParent.Component._This.DANFE ) then
      FParent.Component.NotaFiscal.NFe.Ide.tpImp := FParent.Component._This.DANFE;
end;

class function TModelFiscalNFeCommandIde.New(Parent : iModelFiscalNFe) : iCommand;
begin
   Result := Self.Create(Parent)
end;

A única coisa que fizemos no comando acima foi traduzir o código do componente ACBr para esse nosso método, como mostrado anteriormente e outros posts desta nossa série.

Agora eu tenho um novo comando dentro da nossa camada Commands, falo sobre esse Padrão de Projeto em posts anteriores da nossa série, agora eu possuo dois comandos, o que gera a configuração e o que gera a identificação da nota.

Essa informações que colocamos dentro desse nosso comando, você poderia estar buscando dentro do seu banco de dados, mas para fins de didáticos irei deixar aqui em nossa classe engessado mesmo.

Agora tudo que é identificação da nota é feita dentro do comando de identificação da nota, se por algum motivo acontecer alguma coisa com relação e identificação da nota é nessa classe que você irá realizar a manutenção, viu como é fácil fazer manutenções usando as boas práticas?

Mas você já deve esta se perguntando, e as regras fiscais?

Vamos por parte, primeiro precisamos fazer todos os comandos, ai iremos conseguir implementar as regras fiscais.

Agora precisamos chamar esse nosso comando lá no Invoker, que está executando somente o comando Geral, e agora quero que execute também o Ide que acabamos de implementar.

...
FComponente._This.NotasFiscais.Clear;
FComponente.AddNotaFiscal;
TModelFiscalNFeInvoker.New
   .Add(TModelFiscalNFeCommandGeral.New(Self))
   .Add(TModelFiscalNFeCommandIde.New(Self))
.Execute;
FComponente._This.NotasFiscais.GerarNFe;
...

Agora quando eu mandar gerar a nota, ela irá limpar, adicionar uma nova nota,  preencher o Geral e a identificação da nota e executar, só que eu tenho mais comandos para ser executados, ai que é a parte mais burocrática.

Observando o Demo do ACBr, depois da identificação temos a parte do emitente, agora iremos criar a parte do emitente.

...
NotaF.NFe.Emit.CNPJCPF := edtEmitCNPJ.Text;
NotaF.NFe.Emit.IE := edtEmitIE.Text;
NotaF.NFe.Emit.xNome := edtEmitRazao.Text;
NotaF.NFe.Emit.xFant := edtEmitFantasia.Text;
...

Agora vamos criar nossa classe de comando para o Emitente.

type
   TModelFiscalNFeCommandEmit = class (TInterfacedObject, iCommand)
   private
      FParent : iModelFiscalNFe;
   public
      constructor Create(Parent : iModelFiscalNFe);
      destructor Destroy; override;
      class function New(Parent : iModelFiscalNFe) : iCommand;
      function Execute : iCommand;
   end;

implementation

uses
   pcnConversao;

{ TModelFiscalNFeCommandEmit }

constructor TModelFiscalNFeCommandEmit.Create(Parent : iModelFiscalNFe);
begin
   FParent := Parent;
end;

destructor TModelFiscalNFeCommandEmit.Destroy;
begin
   inherited;
end;

function TModelFiscalNFeCommandEmit.Execute: iCommand;
begin
   Result := Self;
   FParent.Component.NotaFiscal.NFe.Emit.CNPJCPF := '';
   FParent.Component.NotaFiscal.NFe.Emit.IE := '';
   FParent.Component.NotaFiscal.NFe.Emit.xNome := '';
   FParent.Component.NotaFiscal.NFe.Emit.xFant := '';
   FParent.Component.NotaFiscal.NFe.Emit.EnderEmit.fone := '';
   FParent.Component.NotaFiscal.NFe.Emit.EnderEmit.CEP := 0;
   FParent.Component.NotaFiscal.NFe.Emit.EnderEmit.xLgr := '';
   FParent.Component.NotaFiscal.NFe.Emit.EnderEmit.nro := '';
   FParent.Component.NotaFiscal.NFe.Emit.EnderEmit.xCpl := '';
   FParent.Component.NotaFiscal.NFe.Emit.EnderEmit.xBairro := '';
   FParent.Component.NotaFiscal.NFe.Emit.EnderEmit.cMun := 0;
   FParent.Component.NotaFiscal.NFe.Emit.EnderEmit.xMun := '';
   FParent.Component.NotaFiscal.NFe.Emit.EnderEmit.UF := '';
   FParent.Component.NotaFiscal.NFe.Emit.enderEmit.cPais := 1058;
   FParent.Component.NotaFiscal.NFe.Emit.enderEmit.xPais := 'BRASIL';
   FParent.Component.NotaFiscal.NFe.Emit.IEST := '';
   FParent.Component.NotaFiscal.NFe.Emit.IM := '2648800'; // Preencher no caso de existir serviços na nota
   FParent.Component.NotaFiscal.NFe.Emit.CNAE := '6201500'; // Verifique na cidade do emissor da NFe se é permitido
          // a inclusão de serviços na NFe
   FParent.Component.NotaFiscal.NFe.Emit.CRT := crtRegimeNormal;// (1-crtSimplesNacional, 2-crtSimplesExcessoReceita, 3-crtRegimeNormal)
end;

class function TModelFiscalNFeCommandEmit.New(Parent : iModelFiscalNFe) : iCommand;
begin
  Result := Self.Create(Parent);
end;

end.

Observe que simplesmente traduzimos todo o código do emitente para o nosso comando e chamamos nossa classe do componente,  simples assim.

A nota fiscal possui muitos campos para serem tratados, isso é a única coisa que dá trabalho para nós, por possuir muitos campos a serem tratados nós precisamos nos preocupar com esse trabalho todo que estamos fazendo na aplicação das boas práticas.

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