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