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

A cada post uma evolução em nossa série, e neste post estarei mostrando agora a criação do command para a NFe.

Vamos deixar de muito papo e vamos logo ao que interessa.

Mas antes de criarmos esse command para NFe, iremos criar o command para o destinatário, se você está acompanhado essa série de post de boas práticas, onde no post anterior eu criei o command para o produto, mas no Demo do ACBr antes do produto existia o destinatário, então vamos criar esse command.

Antes de declararmos o Produto no Invoker deveremos colocarmos o destinatário, então iremos adicionar uma nova unit que iremos chamá-la de Blog.Model.Fiscal.NFe.Command.Dest.

...
function TModelFiscalNFeCommandDest.Execute: iCommand;
begin
   Result := Self;
   FParent.Component.NotaFiscal.NFe.Dest.CNPJCPF := '05481336000137';
   FParent.Component.NotaFiscal.NFe.Dest.IE := '687138770110';
   FParent.Component.NotaFiscal.NFe.Dest.ISUF := '';
   FParent.Component.NotaFiscal.NFe.Dest.xNome := 'D.J. COM. E LOCAÇÃO DE SOFTWARES LTDA - ME';
   FParent.Component.NotaFiscal.NFe.Dest.EnderDest.Fone := '1532599600';
   FParent.Component.NotaFiscal.NFe.Dest.EnderDest.CEP  := 18270170;
   FParent.Component.NotaFiscal.NFe.Dest.EnderDest.xLgr := 'Rua Coronel Aureliano de Camargo';
   FParent.Component.NotaFiscal.NFe.Dest.EnderDest.nro := '973';
   FParent.Component.NotaFiscal.NFe.Dest.EnderDest.xCpl := '';
   FParent.Component.NotaFiscal.NFe.Dest.EnderDest.xBairro := 'Centro';
   FParent.Component.NotaFiscal.NFe.Dest.EnderDest.cMun := 3554003;
   FParent.Component.NotaFiscal.NFe.Dest.EnderDest.xMun := 'Tatui';
   FParent.Component.NotaFiscal.NFe.Dest.EnderDest.UF := 'SP';
   FParent.Component.NotaFiscal.NFe.Dest.EnderDest.cPais := 1058;
   FParent.Component.NotaFiscal.NFe.Dest.EnderDest.xPais := 'BRASIL';
end;
...

No método Execute do nosso command de Destinatário ficará da forma do código acima, lembrando que essas informações podem ser extraídas diretamente do banco de dados.

E agora vamos em nosso Invoker e adicionar esse nosso comando Dest, antes claro do comando de Prod.

...
   TModelFiscalNFeInvoker.New
      .Add(TModelFiscalNFeCommandGeral.New(Self))
      .Add(TModelFiscalNFeCommandIde.New(Self))
      .Add(TModelFiscalNFeCommandEmit.New(Self))
      .Add(TModelFiscalNFeCommandDest.New(Self))
      .Add(TModelFiscalNFeCommandProd.New(Self))
   .Execute;
...

Agora em diante teremos mais trabalho, mas como você que está acompanhando nossa série, já sabe o que está sendo feito dentro da classe, por exemplo, a classe de destinatário, é somente a classe, o método execute que pega o Parent do componente por injeção de dependência, e está preenchendo o componente do ACBr, estamos fazendo o processo que preenche os dados da nota fiscal.

Agora vamos novamente para o Demo do ACBr, e logo após o destinatário vem o produto, e depois de produto tem o total da NF-e.

...
NotaF.NFe.Total.ICMSTot.vBC := 100;
NotaF.NFe.Total.ICMSTot.vICMS := 18;
NotaF.NFe.Total.ICMSTot.vBCST := 0;
NotaF.NFe.Total.ICMSTot.vST := 0;
NotaF.NFe.Total.ICMSTot.vProd := 100;
NotaF.NFe.Total.ICMSTot.vFrete := 0;
NotaF.NFe.Total.ICMSTot.vSeg := 0;
NotaF.NFe.Total.ICMSTot.vDesc := 0;
NotaF.NFe.Total.ICMSTot.vII := 0;
NotaF.NFe.Total.ICMSTot.vIPI := 0;
NotaF.NFe.Total.ICMSTot.vPIS := 0;
NotaF.NFe.Total.ICMSTot.vCOFINS := 0;
NotaF.NFe.Total.ICMSTot.vOutro := 0;
NotaF.NFe.Total.ICMSTot.vNF := 100;
...

Então iremos criar o nosso comando para o total da NF-e, como você já está familiarizado com essa criação não irei explicar muito…

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

implementation

{ TModelFiscalNFeCommandTotal }

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

destructor TModelFiscalNFeCommandTotal.Destroy;
begin
   inherited;
end;

function TModelFiscalNFeCommandTotal.Execute: iCommand;
begin
   Result := Self;
   FParent.Component.NotaFiscal.NFe.Total.ICMSTot.vBC := 100;
   FParent.Component.NotaFiscal.NFe.Total.ICMSTot.vICMS := 18;
   FParent.Component.NotaFiscal.NFe.Total.ICMSTot.vBCST := 0;
   FParent.Component.NotaFiscal.NFe.Total.ICMSTot.vST := 0;
   FParent.Component.NotaFiscal.NFe.Total.ICMSTot.vProd := 100;
   FParent.Component.NotaFiscal.NFe.Total.ICMSTot.vFrete := 0;
   FParent.Component.NotaFiscal.NFe.Total.ICMSTot.vSeg := 0;
   FParent.Component.NotaFiscal.NFe.Total.ICMSTot.vDesc := 0;
   FParent.Component.NotaFiscal.NFe.Total.ICMSTot.vII := 0;
   FParent.Component.NotaFiscal.NFe.Total.ICMSTot.vIPI := 0;
   FParent.Component.NotaFiscal.NFe.Total.ICMSTot.vPIS := 0;
   FParent.Component.NotaFiscal.NFe.Total.ICMSTot.vCOFINS := 0;
   FParent.Component.NotaFiscal.NFe.Total.ICMSTot.vOutro := 0;
   FParent.Component.NotaFiscal.NFe.Total.ICMSTot.vNF := 100;
     // lei da transparencia de impostos
   FParent.Component.NotaFiscal.NFe.Total.ICMSTot.vTotTrib := 0;
    // partilha do icms e fundo de probreza
   FParent.Component.NotaFiscal.NFe.Total.ICMSTot.vFCPUFDest := 0.00;
   FParent.Component.NotaFiscal.NFe.Total.ICMSTot.vICMSUFDest := 0.00;
   FParent.Component.NotaFiscal.NFe.Total.ICMSTot.vICMSUFRemet := 0.00;
end;

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

E lá no nosso Invoker iremos adicionar esse nosso comando.

...
   TModelFiscalNFeInvoker.New
      .Add(TModelFiscalNFeCommandGeral.New(Self))
      .Add(TModelFiscalNFeCommandIde.New(Self))
      .Add(TModelFiscalNFeCommandEmit.New(Self))
      .Add(TModelFiscalNFeCommandDest.New(Self))
      .Add(TModelFiscalNFeCommandProd.New(Self))
      .Add(TModelFiscalNFeCommandTotal.New(self))
   .Execute;
...

Acabamos de colocar o total dentro do nosso Invoker, e no Demo do ACBr logo depois do total temos o transporte.

...
   NotaF.NFe.Transp.modFrete := mfContaEmitente;
   NotaF.NFe.Transp.Transporta.CNPJCPF := '';
   NotaF.NFe.Transp.Transporta.xNome := '';
   NotaF.NFe.Transp.Transporta.IE := '';
   NotaF.NFe.Transp.Transporta.xEnder := '';
   NotaF.NFe.Transp.Transporta.xMun := '';
   NotaF.NFe.Transp.Transporta.UF := '';
...

Agora iremos criar um comando para o transporte também.

type
   TModelFiscalNFeCommandTransp = 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

{ TModelFiscalNFeCommandTransp }

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

destructor TModelFiscalNFeCommandTransp.Destroy;
begin
   inherited;
end;

function TModelFiscalNFeCommandTransp.Execute: iCommand;
begin
   Result := Self;
   FParent.Component.NotaFiscal.NFe.Transp.modFrete := mfContaEmitente;
   FParent.Component.NotaFiscal.NFe.Transp.Transporta.CNPJCPF  := '';
   FParent.Component.NotaFiscal.NFe.Transp.Transporta.xNome := '';
   FParent.Component.NotaFiscal.NFe.Transp.Transporta.IE := '';
   FParent.Component.NotaFiscal.NFe.Transp.Transporta.xEnder := '';
   FParent.Component.NotaFiscal.NFe.Transp.Transporta.xMun := '';
   FParent.Component.NotaFiscal.NFe.Transp.Transporta.UF := '';
   FParent.Component.NotaFiscal.NFe.Transp.veicTransp.placa := '';
   FParent.Component.NotaFiscal.NFe.Transp.veicTransp.UF := '';
   FParent.Component.NotaFiscal.NFe.Transp.veicTransp.RNTC := '';
end;

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

E claro, iremos adicionar no nosso Invoker.

...
   TModelFiscalNFeInvoker.New
      .Add(TModelFiscalNFeCommandGeral.New(Self))
      .Add(TModelFiscalNFeCommandIde.New(Self))
      .Add(TModelFiscalNFeCommandEmit.New(Self))
      .Add(TModelFiscalNFeCommandDest.New(Self))
      .Add(TModelFiscalNFeCommandProd.New(Self))
      .Add(TModelFiscalNFeCommandTotal.New(self))
      .Add(TModelFiscalNFeCommandTransp.New(Self))
   .Execute;
...

Observe que todos esses comandos são as tags da nota fiscal.

Irei colocar todos os comandos que iremos precisar nesse primeiro momentos, para adiantar um pouco as coisas…rsrs

Agora temos todas as tags adicionadas no nosso projeto.

Vamos novamente no exemplo do ACBr, onde iremos ver que na hora da criação da NF-e ele cria uma duplicata.

...
   Duplicata := NotaF.NFe.Cobr.Dup.New;
   Duplicata.nDup := '1234';
   Duplicata.dVenc := now+10;
   Duplicata.vDup := 50;
   Duplicata := NotaF.NFe.Cobr.Dup.New;
   Duplicata.nDup := '1235';
   Duplicata.dVenc := now+10;
   Duplicata.vDup := 50;
...

Desta forma iremos precisar criar essa variável dentro do nosso componente.

...
   iModelFiscalNFeCompoentes<T> = interface
      ['{A652704B-022A-4467-B881-C791F95D62D8}']
      function _This : T;
      function AddNotaFiscal : NotaFiscal;
      function NotaFiscal : NotaFiscal;
      function AddProduto : TDetCollectionItem;
      function Produto : TDetCollectionItem;
      function AddDuplicata : TDupCollectionItem;
      function Duplicata : TDupCollectionItem;
   end;
...

Observe que da mesma forma que criamos a nota fiscal e o produto, fizemos com a duplicata.

...
   private
...
      FDuplicata : TDupCollectionItem;
...
function TdmACBrNFe.AddDuplicata: TDupCollectionItem;
begin
   FDuplicata := FNotaFiscal.NFe.Cobr.Dup.New;
   Result := FDuplicata;
end;
...
function TdmACBrNFe.Duplicata: TDupCollectionItem;
begin
   Result := FDuplicata;
end;

Desta forma já temos a nossa duplicata funcionando em nosso componente.

Agora precisamos adicionar as observações complementares que o exemplo do ACBr solicita, em nosso componente, e será a mesma coisa que fizemos com a duplicata..

...
   ObsComplementar := NotaF.NFe.InfAdic.obsCont.New;
   ObsComplementar.xCampo := 'ObsCont';
   ObsComplementar.xTexto := 'Texto';
...

Adicionamos na interface do componente, e implementamos na classe dela.

...
   iModelFiscalNFeCompoentes<T> = interface
      ['{A652704B-022A-4467-B881-C791F95D62D8}']
...
      function AddObsComp : TobsContCollectionItem;
      function ObsComp : TobsContCollectionItem;
   end;
...

Na classe do componente.

...
private
...
   FObsCompo : TobsContCollectionItem;
...
function TdmACBrNFe.AddObsComp: TobsContCollectionItem;
begin
   FObsCompo := FNotaFiscal.NFe.InfAdic.obsCont.New;
   Result := FObsCompo;
end;
...
function TdmACBrNFe.ObsComp: TobsContCollectionItem;
begin
   Result := FObsCompo;
end;
...

Da mesma forma que a duplica, nas observações complementares iremos também adicionar as observações do fisco, lembrando que estamos seguindo o exemplo do ACBrNFe, onde estamos implementado usando as boas práticas, fazendo assim, claro que teremos grande trabalho na implementação, muito Ctrl+C e Ctrl+V, mas após tudo isso feito e bem estruturada, as novas implementações não levaram dias exaustivos, mas em implementações simples do objetivas.

...
   ObsFisco := NotaF.NFe.InfAdic.obsFisco.New;
   ObsFisco.xCampo := 'ObsFisco';
   ObsFisco.xTexto := 'Texto';
...

Iremos fazer a mesma coisa que fizemos com os demais comando, iremos adicionar em nossa interface e em sua classe que a implementa.

Assim também com o pagamento, onde podemos adicionar diversas formas de pagamentos na nota fiscal.

...
   InfoPgto := NotaF.NFe.pag.New;
   InfoPgto.indPag := ipVista;
   InfoPgto.tPag := fpDinheiro;
   InfoPgto.vPag := 100;
...

Observe agora como ficou a nossa classe de componente com todos esses comando para geração da NF-e do ACBrNFe.

type
   TdmACBrNFe = class(TDataModule, iModelFiscalNFeCompoentes<TACBrNFe>)
      ACBrNFe1: TACBrNFe;
   private
      { Private declarations }
      FNotaFiscal : NotaFiscal;
      FProduto :TDetCollectionItem;
      FDuplicata : TDupCollectionItem;
      FObsCompo : TobsContCollectionItem;
      FObsFisco : TobsFiscoCollectionItem;
      FPagamento : TpagCollectionItem;
      FTranspVol : TVolCollectionItem;
   public
      function _This : TACBrNFe;
      class function New : iModelFiscalNFeCompoentes<TACBrNFe>;
      function AddNotaFiscal : NotaFiscal;
      function NotaFiscal : NotaFiscal;
      function AddProduto : TDetCollectionItem;
      function Produto : TDetCollectionItem;
      function AddDuplicata : TDupCollectionItem;
      function Duplicata : TDupCollectionItem;
      function AddObsComp : TobsContCollectionItem;
      function ObsComp : TobsContCollectionItem;
      function AddObsFisco : TobsFiscoCollectionItem;
      function ObsFisco : TobsFiscoCollectionItem;
      function AddPagamento : TpagCollectionItem;
      function Pagamento : TpagCollectionItem;
      function AddTranspVol : TVolCollectionItem;
      function TranspVol : TVolCollectionItem;
  end;

implementation

{%CLASSGROUP 'Vcl.Controls.TControl'}

{$R *.dfm}

{ TdmACBrNFe }

function TdmACBrNFe.AddDuplicata: TDupCollectionItem;
begin
   FDuplicata := FNotaFiscal.NFe.Cobr.Dup.New;
   Result := FDuplicata;
end;

function TdmACBrNFe.AddNotaFiscal: NotaFiscal;
begin
   FNotaFiscal := ACBrNFe1.NotasFiscais.Add;
   Result := FNotaFiscal;
end;

function TdmACBrNFe.AddObsComp: TobsContCollectionItem;
begin
   FObsCompo := FNotaFiscal.NFe.InfAdic.obsCont.New;
   Result := FObsCompo;
end;

function TdmACBrNFe.AddObsFisco: TobsFiscoCollectionItem;
begin
   FObsFisco := FNotaFiscal.NFe.InfAdic.obsFisco.New;
   Result := FObsFisco;
end;

function TdmACBrNFe.AddPagamento: TpagCollectionItem;
begin
   FPagamento := FNotaFiscal.NFe.pag.New;
   Result := FPagamento;
end;

function TdmACBrNFe.AddProduto: TDetCollectionItem;
begin
   FProduto := FNotaFiscal.NFe.Det.New;
   Result := FProduto;
end;

function TdmACBrNFe.AddTranspVol: TVolCollectionItem;
begin
   FTranspVol := FNotaFiscal.NFe.Transp.Vol.New;
   Result := FTranspVol;
end;

function TdmACBrNFe.Duplicata: TDupCollectionItem;
begin
   Result := FDuplicata;
end;

class function TdmACBrNFe.New: iModelFiscalNFeCompoentes<TACBrNFe>;
begin
   Result := Self.Create(Nil);
end;

function TdmACBrNFe.NotaFiscal: NotaFiscal;
begin
   Result := FNotaFiscal;
end;

function TdmACBrNFe.ObsComp: TobsContCollectionItem;
begin
   Result := FObsCompo;
end;

function TdmACBrNFe.ObsFisco: TobsFiscoCollectionItem;
begin
   Result := FObsFisco;
end;

function TdmACBrNFe.Pagamento: TpagCollectionItem;
begin
   Result := FPagamento;
end;

function TdmACBrNFe.Produto: TDetCollectionItem;
begin
   Result := FProduto;
end;

function TdmACBrNFe.TranspVol: TVolCollectionItem;
begin
   Result := FTranspVol;
end;
 
function TdmACBrNFe._This: TACBrNFe;
begin
   Result := ACBrNFe1;
end;

Agora dentro do nosso Invoker iremos chamar todos esse comandos, observe como ficou nosso Invoker.

...
   TModelFiscalNFeInvoker.New
      .Add(TModelFiscalNFeCommandGeral.New(Self))
      .Add(TModelFiscalNFeCommandIde.New(Self))
      .Add(TModelFiscalNFeCommandEmit.New(Self))
      .Add(TModelFiscalNFeCommandDest.New(Self))
      .Add(TModelFiscalNFeCommandProd.New(Self))
      .Add(TModelFiscalNFeCommandTotal.New(self))
      .Add(TModelFiscalNFeCommandTransp.New(Self))
      .Add(TModelFiscalNfeCommandTranspVol.New(Self))
      .Add(TModelFiscalNfeCommandCobrFat.New(Self))
      .Add(TModelFiscalNfeCommandCobrDup.New(Self))
      .Add(TModelFiscalNfeCommandInfAdic.New(Self))
      .Add(TModelFiscalNfeCommandInfAdicObsComp.New(Self))
      .Add(TModelFiscalNfeCommandInfAdicObsFisco.New(Self))
      .Add(TModelFiscalNfeCommandExporta.New(Self))
      .Add(TModelFiscalNfeCommandCompra.New(Self))
      .Add(TModelFiscalNfeCommandPagamento.New(Self))
      .Add(TModelFiscalNfeCommandGerarNFe.New(Self))
   .Execute;
...

Se você for no exemplo do ACBrNFe, ele executa esses comandos da mesma ordem que foi feito em nosso Invoker.

Tudo que nós precisamos preencher no ACBr para botar na nota fiscal, está nesse Invoker.

O legal disso tudo é que agora não está centralizado num lugar só, está tudo bem dividido e estruturado.

Os comando você consegue ver as ordens que estão sendo gerados, e por exemplo, você quer que no final da geração da nota fiscal envie a nota para o cliente por e-mail.

Você irá criar o comando de enviar e-mail e adicioná-lo logo após o GerarNfe.

Em todo lugar em seu software que mexe com nota fiscal irá enviar o e-mail depois de ser gerado.

Dessa forma você está centralizando tudo, bem dividido.

Se vier ocorrer um erro no cálculo do transporte, basta você ir no comando que é responsável por esse cálculo, dessa for você só irá mexer em um único lugar.

Essas implementações só fazemos uma vez e não precisamos ter que refazer tudo ou até mesmo sofrer com as mudanças na geração da NF-e, fazendo assim você já estará pronto.

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