unit DataModulo_NFe;

interface

uses
  SysUtils, Classes, ACBrNFe, ACBrNFeDANFEClass,
  IB_Components,Rotinas, Dialogs, Windows, system.UItypes, IB_Access, ShellApi,pmdfeConversaoMDFe, pcnConversao,Forms,
  ACBrMDFe, ACBrMDFeDAMDFeClass, ACBrCTe, ACBrBase,pcnConversaoNFe,
  ACBrDFe, ACBrMail, ACBrMDFeDAMDFEFR,
  ACBrNFeDANFEFRDM, ACBrNFeDANFEFR, blcksock, ACBrDFeDANFeReport, ACBrDFeReport, ACBrDFeUtil;
type
  TDMNFE = class(TDataModule)
    NFe: TACBrNFe;
    CTe: TACBrCTe;
    qrNF: TIB_Query;
    OpenDialog1: TOpenDialog;
    dlgSalvar: TSaveDialog;
    qrManifesto: TIB_Query;
    qrMDFe_NFs: TIB_Query;
    qryVencimentos: TIB_Query;
    qryItens: TIB_Query;
    Mail: TACBrMail;
    qrManifestoPercurso: TIB_Query;
    ImpressaoMDFe: TACBrMDFeDAMDFEFR;
    MDFe: TACBrMDFe;
    qrCartaCorrecao: TIB_Query;
    ImpressaoNFe: TACBrNFeDANFEFR;
    procedure NFe_GerarXml(numero: Integer);
    procedure NFe_ValidarXml;
    Procedure NFe_Assinar;
    procedure NFe_Transmitir(numero: Integer);
    function NFe_Consulta_Protocolo(numero: Integer;var protocolo:String):Boolean;
    procedure NFe_CopiarXml(numero: Integer);
    procedure NFe_Consultar_Status_WebService_Nacional;
    procedure NFe_Consultar_Status_WebService_MG;
    procedure MDFe_Consultar_Status_WebService;
    procedure NFeStatusChange(Sender: TObject);
    procedure LeConfiguracoesNFe;
    procedure DataModuleCreate(Sender: TObject);
    function NFe_Cancelar(numero,cod_filial: Integer;
      justificativa: WideString): Boolean;
    procedure NFe_Imprimir_Individual(numero: Integer);
    procedure NFe_Enviar_Email(Email_Destinatarios: string; numero: integer; var Erro : string; Mostra_Msg_Erro : Boolean = True );
  private
    procedure ArquivarXML(arquivo: String);
    function CarregarXml(numero: Integer): Boolean;
    procedure NFe_Gerar(numero: Integer);
    procedure NFe_Gravar_Protocolo_Transmissao(numero: Integer);
    procedure NFe_ApagarXml(chaveNFe: string);
    function MDNFe_CarregarXml(cod_manifesto, cod_filial: Integer): Boolean;
    procedure MDNFe_ArquivarXML(arquivo:String);
    procedure MDNFe_Gravar_Protocolo_Transmissao(cod_manifesto, cod_filial: Integer);
    procedure MDNFe_Gravar_Protocolo_Encerramento(cod_manifesto, cod_filial: Integer);
    procedure MDNFe_Gravar_Protocolo_Cancelamento(cod_manifesto, cod_filial: Integer; motivo : string);
    procedure MDNFe_Imprimir_Individual(cod_manifesto, cod_filial: Integer);
    { Private declarations }
  public
    procedure MDNFe_Gerar(cod_manifesto , cod_filial : Integer);
    procedure MDNFe_Cancelar(cod_manifesto, cod_filial: Integer; Motivo : string);
    procedure MDNFe_Encerramento(cod_manifesto, cod_filial: Integer);
    procedure MDNFe_Gerar_XML(cod_manifesto, cod_filial: Integer);
    procedure MDNFe_ValidarXml;
    procedure MDNFe_Transmitir (cod_manifesto, cod_filial: Integer);
    procedure MDNFe_Consulta_Protocolo(cod_manifesto, cod_filial: Integer);
    procedure NFe_CartaCorrecaoEletronica(cod_nf, cod_filial_nf, cod_carta_correcao, cod_filial_carta_correcao : Integer);
    { Public declarations }
  end;

var
  DMNFE: TDMNFE;
  DIFAL:Boolean;

implementation

uses DataModulo, ConfigacaoSistema, ufrmStatus, pmdfeMDFe,
  ACBrMDFeConfiguracoes, Justificativa;

{$R *.dfm}

procedure TDMNFE.NFe_Gerar(numero: Integer);
var i,PrazoMedio,Parcelas,DiasPrazo:Integer;
  PrimeiraParcela,ValorParcela,Valor_Duplicata,TotalPagar:Real;
  Letra_Duplicata,CFOP_Impressao:String;
  Vencimento_Duplicata:TDateTime;

  Numero_item : integer;
begin

  qrNF.Close;
  qrNF.ParamByName('numero').Value := numero;
  qrNF.Open;

   qryItens.Close;
   qryItens.ParamByName('VARNF').Value:=qrNF.FieldByName('NUMERO').Value;
   qryItens.Open;

  if dados.qryParametro_NF.FieldByName('FORMA_EMISSAO').AsString = 'CONTINGÊNCIA' then
    DMNFE.NFe.Configuracoes.Geral.FormaEmissao := teContingencia
  else
  if dados.qryParametro_NF.FieldByName('FORMA_EMISSAO').AsString = 'SCAN' then
    DMNFE.NFe.Configuracoes.Geral.FormaEmissao := teSCAN
  else
  if dados.qryParametro_NF.FieldByName('FORMA_EMISSAO').AsString = 'SVCAN' then
    DMNFE.NFe.Configuracoes.Geral.FormaEmissao := teSVCAN
  else
  if dados.qryParametro_NF.FieldByName('FORMA_EMISSAO').AsString = 'SVCRS' then
    DMNFE.NFe.Configuracoes.Geral.FormaEmissao := teSVCRS
  else
    DMNFE.NFe.Configuracoes.Geral.FormaEmissao := teNormal;

  DMNFE.NFe.NotasFiscais.Clear;

  with DMNFE.NFe.NotasFiscais.Add.NFe do
  begin
    if dados.qryParametro_NF.FieldByName('IMPRIMIR_CFOP').AsString = 'DESCRIÇÃO' then
      CFOP_Impressao:=qrNF.fieldByName('CFOP_DESCRICAO').AsString
    else
    if dados.qryParametro_NF.FieldByName('IMPRIMIR_CFOP').AsString = 'CFOP' then
      CFOP_Impressao:=qrNF.fieldByName('COD_CFOP').AsString
    else
      CFOP_Impressao:=qrNF.fieldByName('COD_CFOP').AsString +'-'+qrNF.fieldByName('CFOP_DESCRICAO').AsString;

  {Veja que o Manual de Integração - Pág. 152 você encontra para finNFe 3 opções:
  29 - B25 - finNFe - Finalidade de emissão da NF-e
  1 - NF-e normal // fnNormal
  2 - NF-e complementar // fnComplementar
  3 - NF-e de ajuste // fnAjuste
  4 - NF-e Devolução // fnDevolucao }

    if qrNF.FIeldByName('FINALIDADE_EMISSAO').AsString = 'COMPLEMENTAR' then
      ide.finNFe    := fnComplementar
    else
    if qrNF.FIeldByName('FINALIDADE_EMISSAO').AsString = 'AJUSTE' then
      ide.finNFe    := fnAjuste
    else
    if qrNF.FIeldByName('FINALIDADE_EMISSAO').AsString = 'DEVOLUÇÃO' then
      ide.finNFe    := fnDevolucao
    else
      ide.finNFe    := fnNormal;

    if ide.finNFe <> fnNormal then
    begin
      Ide.NFref.Add;
      Ide.NFref[0].refNFe := qrNF.FieldByName('REFERENCIA_NFE').AsString;
   end;

    Ide.tpImp     := tiRetrato;
    Ide.natOp     := Copy(CFOP_Impressao,1,60);
    Ide.nNF       := StrToInt(qrNF.FieldByName('NUMERO').AsString);
    //Ide.cNF       := StrToInt(qrNF.FieldByName('NUMERO').AsString);

    if qrNF.FieldByName('CNF').asInteger = 0 then
       Ide.cNF       :=  GerarCodigoDFe(StrToInt(qrNF.FieldByName('NUMERO').AsString))
    else
      Ide.cNF       :=  qrNF.FieldByName('CNF').asinteger;

    Ide.modelo    := StrToinT(dados.qryParametro_NF.FieldByName('MODELO_NF').AsString);
    Ide.serie     := qrNF.FIeldByName('SERIE').AsInteger;
    Ide.dEmi      := qrNF.FieldByName('DATA_EMISSAO').AsDate;
    Ide.dSaiEnt   := qrNF.FieldByName('DATA_SAIDA').AsDate+qrNF.FieldByName('HORA_SAIDA').AsDateTime;
    Ide.hSaiEnt   := Now;


    if qrNF.FieldByName('ENTRADA_SAIDA').AsString = 'E' then
      Ide.tpNF      := tnEntrada
    else
    if qrNF.FieldByName('ENTRADA_SAIDA').AsString = 'S' then
      Ide.tpNF      := tnSaida;

  //===== Condição de Pagamento À VISTA deve ser sempre código 1
      {(ipVista, ipPrazo, ipOutras, ipNenhum);}

      if qrNF.FieldByName('COD_CONDICAO_PAGAMENTO').AsInteger = 0 then
      begin
        ide.indPag:= ipOutras;
      end
      else
      if qrNF.FieldByName('COD_CONDICAO_PAGAMENTO').AsInteger = 1 then
      begin
        ide.indPag := ipVista;
      end
      else
      begin
        ide.indPag:= ipPrazo;
      end;


      with pag.Add do
      begin
        if qrNF.FieldByName('COD_CONDICAO_PAGAMENTO').AsInteger = 1 then // Se for à vista pagamento em dinheiro à prazo duplicata mercantil
          tPag := fpDinheiro
        else
          tPag := fpDuplicataMercantil;

        vPag := qrNF.FieldByName('TOTAL_NF').AsFloat;

        if qrNF.FIeldByName('FINALIDADE_EMISSAO').AsString = 'DEVOLUÇÃO' then
        begin
           //ide.indPag := ipNenhum;
           tPag := fpSemPagamento;
           vPag := 0;
        end;

      end;

     //=========== notas de devolucao nao tem informação de pagamento e neim de parcelas: Daniel 2018/08/16
     if qrNF.FIeldByName('FINALIDADE_EMISSAO').AsString <> 'DEVOLUÇÃO' then
       //if qrNF.FieldByName('COD_CONDICAO_PAGAMENTO').AsInteger <> 1 then // Gerar grupo faturamento apenas quando for à prazo
     begin
        with Cobr.Fat do
         begin
           nFat  := qrNF.FieldByName('NUMERO').AsString;
           vOrig := qrNF.FieldByName('TOTAL_NF').AsFloat;
           vDesc := 0;
           vLiq  := qrNF.FieldByName('TOTAL_NF').AsFloat;
         end;

        PrazoMedio:=qrNF.FieldBYName('PRAZOMEDIO').AsInteger;
        Parcelas  :=qrNF.FieldBYName('PARCELAS').AsInteger;

        qryVencimentos.Close;
        qryVencimentos.ParamByName('VARCONDICAO').Value:=qrNF.FieldByName('COD_CONDICAO_PAGAMENTO').AsInteger;
        qryVencimentos.Open;


        TotalPagar:=qrNF.FieldByName('TOTAL_NF').AsFloat;

        if parcelas > 0 then
          ValorParcela:= TotalPagar / Parcelas
        else
          ValorParcela:= TotalPagar;

        ArredondaParcelas(Parcelas,ValorParcela,TotalPagar,PrimeiraParcela);

        qryVencimentos.First;
        if not qryVencimentos.IsEmpty then  //Adcionado por daniel: 10/08/2018 EX: Qdo o tipo de pagamento = Outros nao existe parcelas e esava dando erro pq qryVencimentos estava vazia
        begin
           i:=0;
           repeat
           begin
             inc(i);
              //========= Os numeros das duplicatas devem ser Numerico com 3 caracteres: Daniel Azevedo 2018/09/03
             if i =1 then
               Letra_Duplicata  := '001'; //'[A]';
             if i =2 then
               Letra_Duplicata  := '002'; //'[B]';
             if i =3 then
               Letra_Duplicata  := '003'; //'[C]';
             if i =4 then
               Letra_Duplicata  := '004'; //'[D]';
             if i =5 then
               Letra_Duplicata  := '005'; //'[E]';
             if i =6 then
               Letra_Duplicata  := '006'; //'[F]';

             DiasPrazo           := qryVencimentos.FieldBYName('PRAZO').AsInteger;
             Vencimento_Duplicata:= AcrescentaDias(qrNF.FieldBYName('DATA_SAIDA').Value,DiasPrazo-1);

             if i = 1 then
                Valor_Duplicata    := PrimeiraParcela
             else Valor_Duplicata  := ValorParcela;

             with Cobr.Dup.Add do
              begin
                nDup  := Letra_Duplicata;
                dVenc := Vencimento_Duplicata;
                vDup  := Valor_Duplicata;
              end;

             qryVencimentos.Next;
           end;
           until i = parcelas;
        end;


     end;




    Ide.verProc   := PegaVersao;

    if Dados.qrRegistro.FieldByName('COD_UF').IsNull then
    begin
      MessageDlg('Informe a UF na tabela de Registro do sistema', mtError, [mbOK], 0);
      Exit;
    end;

    Dados.qrUF.Open;
    //=============== Atualiza os UF  ================
    if not Dados.qrUF.Locate('COD_UF' , Dados.qrRegistro.FieldByName('COD_UF').Value  , [] ) then
    begin
      if  NOT Dados.qrUF.Bof then
      begin
         Dados.qrUF.First;
         Dados.qrUF.Prior;
      end;
    end;

    Ide.cUF    := StrToIntDef(Copy(Dados.qrRegistro.FieldByName('COD_CIDADE_IBGE').AsString, 1, 2), 0);
    Ide.cMunFG := StrToIntDef(Dados.qrRegistro.FieldByName('COD_CIDADE_IBGE').AsString, 0);

    Ide.tpAmb    := DMNFE.NFe.Configuracoes.WebServices.Ambiente;

    if dados.qryParametro_NF.FieldByName('FORMA_EMISSAO').AsString <> 'NORMAL' then
    begin
       Ide.dhCont := date;
       Ide.xJust  := 'SEFAZ INDISPONÍVEL NO ESTADO DE '+Dados.qrUF.FieldByName('DESCRICAO').AsString;
    end;

    Emit.CNPJCPF           := Dados.qrRegistro.FieldByName('CNPJ').AsString;
    Emit.IE                := Dados.qrRegistro.FieldByName('INSCRICAO').AsString;
    Emit.xNome             := Dados.qrRegistro.FieldByName('RAZAO_SOCIAL').AsString;
    Emit.xFant             := Dados.qrRegistro.FieldByName('APELIDO').AsString;
    Emit.EnderEmit.fone    := Dados.qrRegistro.FieldByName('TELEFONE1').AsString;
    Emit.EnderEmit.CEP     := Dados.qrRegistro.FieldByName('CEP').AsInteger;
    Emit.EnderEmit.xLgr    := Dados.qrRegistro.FieldByName('LOGRADOURO').AsString;
    Emit.EnderEmit.nro     := Dados.qrRegistro.FieldByName('NUMERO').AsString;
    Emit.EnderEmit.xCpl    := Dados.qrRegistro.FieldByName('COMPLEMENTO').AsString;
    Emit.EnderEmit.xBairro := Dados.qrRegistro.FieldByName('BAIRRO').AsString;
    Emit.EnderEmit.cMun    := Dados.qrRegistro.FieldByName('COD_CIDADE_IBGE').AsInteger;
    Emit.EnderEmit.xMun    := Dados.qrRegistro.FieldByName('CIDADE').AsString;
    Emit.EnderEmit.UF      := Dados.qrUF.FieldByName('DESCRICAO').AsString;
    Emit.enderEmit.cPais   := 1058;
    Emit.enderEmit.xPais   := 'BRASIL';
    Emit.IEST              := qrNF.FieldByName('INSCRICAO_SUBSTITUICAO').AsString;
    Emit.CNAE              := Dados.qrRegistro.FieldByName('CNAE').AsString;

    case Dados.qrRegistro.FieldByName('CODIGO_REGIME_TRIBUTACAO').AsInteger of
       1 : Emit.CRT := crtSimplesNacional;
       2 : Emit.CRT := crtSimplesExcessoReceita;
       3 : Emit.CRT := crtRegimeNormal;
    end;

    Dest.CNPJCPF           := qrNF.FieldByName('CLIENTE_CNPJ').AsString;
    Dest.EnderDest.CEP     := qrNF.FieldByName('CLIENTE_ENDERECO_CEP').AsInteger;
    Dest.EnderDest.xLgr    := qrNF.FieldByName('CLIENTE_ENDERECO_LOGRADOURO').AsString;
    Dest.EnderDest.nro     := qrNF.FieldByName('CLIENTE_ENDERECO_NUMERO').AsString;
    Dest.EnderDest.xCpl    := qrNF.FieldByName('CLIENTE_ENDERECO_COMPLEMENTO').AsString;
    Dest.EnderDest.xBairro := qrNF.FieldByName('CLIENTE_ENDERECO_BAIRRO').AsString;
    Dest.EnderDest.cMun    := qrNF.FieldByName('CLIENTE_ENDERECO_COD_CIDADE').AsInteger;
    Dest.EnderDest.xMun    := qrNF.FieldByName('CLIENTE_ENDERECO_CIDADE').AsString;
    Dest.EnderDest.UF      := qrNF.FieldByName('CLIENTE_ENDERECO_UF').AsString;
    Dest.EnderDest.Fone    := qrNF.FieldByName('CLIENTE_TELEFONE1').AsString;
    if qrNF.FieldByName('CLIENTE_INSCRICAO').AsString = 'ISENTO' then
    begin
       Dest.indIEDest := inIsento;
       ide.indFinal := cfConsumidorFinal;
    end
    else
    if qrNF.FieldByName('CLIENTE_INSCRICAO').AsString = 'NÃO CONTRIBUINTE' then
    begin
       Dest.indIEDest := inNaoContribuinte;
       ide.indFinal := cfConsumidorFinal;
    end
    else
    begin
      Dest.indIEDest := inContribuinte;
      Dest.IE        := qrNF.FieldByName('CLIENTE_INSCRICAO').AsString;
      ide.indFinal   := cfNao;
    end;
    Dest.xNome             := qrNF.FieldByName('CLIENTE_RAZAO_SOCIAL').AsString;
    Dest.EnderDest.cPais   := 1058;
    Dest.EnderDest.xPais   := 'BRASIL';

    // TpcnDestinoOperacao = (doInterna, doInterestadual, doExterior);
   if Dest.EnderDest.UF = 'EX' then
    ide.idDest := doExterior
   else
   if Dest.EnderDest.UF = Emit.EnderEmit.UF then
   begin
     if Dest.CNPJCPF  = Emit.CNPJCPF  then // Pode haver necessidade de gerar uma NF de entrada então terei que olhar para o primeiro digito do CFOP para determinar se é dentro ou fora do estado
     begin
       if (Copy(qrNF.fieldByName('COD_CFOP').AsString,1,1) = '6') or (Copy(qrNF.fieldByName('COD_CFOP').AsString,1,1) = '2') then
         ide.idDest := doInterestadual
       else
         ide.idDest := doInterna;
     end
     else
     ide.idDest := doInterna
   end
   else
    ide.idDest := doInterestadual;

    qryItens.First;
    Numero_item := 0;
    while NOT qryItens.Eof do
    begin
    with Det.Add do
    begin
      //======== os itens tem q ficar na sequencia 1..2..3.. no xml ; Daniel Azevedo 04/09/19
      //Prod.nItem    := qryItens.FieldByName('ITEM').AsInteger;
      Numero_item   := Numero_item + 1;
      Prod.nItem    := Numero_item ;
      Prod.cProd    := qryItens.FieldByName('COD_PRODUTO').AsString;
      Prod.xProd    := qryItens.FieldByName('NOME_PRODUTO').AsString;
      Prod.cEAN     := qryItens.FieldByName('CODIGO_BARRAS').AsString;
      Prod.NCM      := qryItens.FieldByName('CLASSIFICACAO_FISCAL').AsString;
      Prod.CFOP     := qryItens.FieldByName('COD_CFOP').AsString;
      Prod.uCom     := qryItens.FieldByName('UNIDADE').AsString;
      Prod.qCom     := qryItens.FieldByName('QTE').AsFloat;
      Prod.vUnCom   := qryItens.FieldByName('VALOR_UNITARIO').AsFloat;
      Prod.vProd    := qryItens.FieldByName('VALOR_TOTAL').AsFloat;
      Prod.qTrib    := qryItens.FieldByName('QTE').AsFloat;
      Prod.vUnTrib  := qryItens.FieldByName('VALOR_UNITARIO').AsFloat;
      Prod.uTrib    := qryItens.FieldByName('UNIDADE').AsString;

      if trim(qryItens.FieldByName('CODIGO_BARRAS').AsString) = '' then
         Prod.cEANTrib := 'SEM GTIN'
      else
         Prod.cEANTrib := qryItens.FieldByName('CODIGO_BARRAS').AsString;

      Prod.vDesc    := qryItens.FieldByName('DESCONTO_VALOR').AsFloat;
      Prod.vOutro   := qryItens.FieldByName('OUTROS').AsFloat;
      Prod.vFrete   := qryItens.FieldByName('VALOR_FRETE').AsFloat;
      Prod.vSeg     := 0;

      infAdProd     := qryItens.FieldByName('INFORMACAO_ADICIONAL').AsString;



      with Imposto do
      begin
        vTotTrib:=qryItens.FieldByName('VALOR_ICMS').AsFloat;

        with ICMS do
        begin
         orig    := oeNacional;
         if Emit.CRT = crtSimplesNacional then // Ajuste SINIEF nº 3, de 09.07.2010 – DOU 1 de 13.07.2010

         begin
             case qryItens.FieldByName('COD_CSOSN').AsInteger of
             101:
             begin
               CSOSN       := csosn101;
               vBC         := qryItens.FieldByName('BASE_CALCULO').AsFloat;
               pICMS       := qryItens.FieldByName('ALIQUOTA').AsFloat;
               vICMS       := qryItens.FieldByName('VALOR_ICMS').AsFloat;
               pCredSN     := dados.qryParametro_NF.fieldByName('ALIQUOTA_CREDITO').AsFloat;
               vCredICMSSN := (qryItens.FieldByName('VALOR_TOTAL').AsFloat - qryItens.FieldByName('DESCONTO_VALOR').AsFloat) * (dados.qryParametro_NF.fieldByName('ALIQUOTA_CREDITO').AsFloat / 100);
             end;
             102:
             begin
               CSOSN       := csosn102;
               vBC         := qryItens.FieldByName('BASE_CALCULO').AsFloat;
               pICMS       := qryItens.FieldByName('ALIQUOTA').AsFloat;
               vICMS       := qryItens.FieldByName('VALOR_ICMS').AsFloat;
             end;

             103:
             begin
               CSOSN       := csosn103;
               vBC         := qryItens.FieldByName('BASE_CALCULO').AsFloat;
               pICMS       := qryItens.FieldByName('ALIQUOTA').AsFloat;
               vICMS       := qryItens.FieldByName('VALOR_ICMS').AsFloat;

             end;
             201:
             begin
               CSOSN       := csosn201;
               vBCST       := qryItens.FieldByName('BASE_ICMS_SUBSTITUICAO').AsFloat;
               pICMSST     := qryItens.FieldByName('ALIQUOTA_ICMS_SUBSTITUICAO').AsFloat;
               vICMSST     := qryItens.FieldByName('ICMS_SUBSTITUICAO').AsFloat;
               pRedBCST    := qryItens.FieldByName('PERCENTUAL_REDUCAO_BASE_CALCULO').AsFloat;
               modBCST     := dbisMargemValorAgregado;
             end;
             400:
             begin
               CSOSN       := csosn400;
               vBCST       := qryItens.FieldByName('BASE_ICMS_SUBSTITUICAO').AsFloat;
               pICMSST     := qryItens.FieldByName('ALIQUOTA_ICMS_SUBSTITUICAO').AsFloat;
               vICMSST     := qryItens.FieldByName('ICMS_SUBSTITUICAO').AsFloat;
               pRedBCST    := qryItens.FieldByName('PERCENTUAL_REDUCAO_BASE_CALCULO').AsFloat;
               modBCST     := dbisMargemValorAgregado;
             end;
             900:
             begin
               CSOSN     := csosn900;
               vBC       := qryItens.FieldByName('BASE_CALCULO').AsFloat;
               pICMS     := qryItens.FieldByName('ALIQUOTA').AsFloat;
               vICMS     := qryItens.FieldByName('VALOR_ICMS').AsFloat;
             end;
           end
         end
         else
         begin
           if qryItens.FieldByName('COD_CST').AsString = '000' then
              CST  := cst00
           else
           if qryItens.FieldByName('COD_CST').AsString = '010' then
              CST  := cst10
           else
           if qryItens.FieldByName('COD_CST').AsString = '020' then
              CST  := cst20
           else
           if qryItens.FieldByName('COD_CST').AsString = '030' then
              CST  := cst30
           else
           if qryItens.FieldByName('COD_CST').AsString = '040' then
              CST  := cst40
           else
           if qryItens.FieldByName('COD_CST').AsString = '041' then
              CST  := cst41
           else
           if qryItens.FieldByName('COD_CST').AsString = '050' then
              CST  := cst50
           else
           if qryItens.FieldByName('COD_CST').AsString = '051' then
              CST  := cst51
           else
           if qryItens.FieldByName('COD_CST').AsString = '060' then
              CST  := cst60
           else
           if qryItens.FieldByName('COD_CST').AsString = '070' then
              CST  := cst70
           else
           if qryItens.FieldByName('COD_CST').AsString = '090' then
              CST  := cst90;
         end;


         modBC   := dbiPrecoTabelado;
         pICMS   := qryItens.FieldByName('ALIQUOTA').AsFloat;
         vICMS   := qryItens.FieldByName('VALOR_ICMS').AsFloat;
         vBC     := qryItens.FieldByName('BASE_CALCULO').AsFloat;
         if qryItens.FieldByName('BASE_ICMS_SUBSTITUICAO').AsFloat > 0 then
           vBCST   := qryItens.FieldByName('BASE_ICMS_SUBSTITUICAO').AsFloat;
         if qryItens.FieldByName('ALIQUOTA_ICMS_SUBSTITUICAO').AsFloat > 0 then
           pICMSST := qryItens.FieldByName('ALIQUOTA_ICMS_SUBSTITUICAO').AsFloat;
         if qryItens.FieldByName('ICMS_SUBSTITUICAO').AsFloat > 0 then
           vICMSST := qryItens.FieldByName('ICMS_SUBSTITUICAO').AsFloat;
         pRedBC  := qryItens.FieldByName('PERCENTUAL_REDUCAO_BASE_CALCULO').AsFloat;


        end;

        if DIFAL then
        begin
          with ICMSUFDest do
          begin
            vBCUFDest     :=qryItens.FieldByName('DIFAL_BASE_UF_DESTINO').AsFloat;
            pFCPUFDest    :=qryItens.FieldByName('DIFAL_PERCENTUAL_FCP_DESTINO').AsFloat;
            pICMSUFDest   :=qryItens.FieldByName('DIFAL_ALIQ_INTERNA_DESTINO').AsFloat;
            pICMSInter    :=qryItens.FieldByName('DIFAL_ALIQ_INTERESTADUAL').AsFloat;
            pICMSInterPart:=qryItens.FieldByName('DIFAL_PERCENTUAL_PARTILHA').AsFloat;
            vFCPUFDest    :=qryItens.FieldByName('DIFAL_VALOR_FCP_DESTINO').AsFloat;
            vICMSUFDest   :=qryItens.FieldByName('DIFAL_VALOR_INTERESTADUAL_DEST').AsFloat;
            vICMSUFRemet  :=qryItens.FieldByName('DIFAL_VALOR_INTERESTADUAL_REME').AsFloat;
          end;
        end;

        IPI.CST := ipi99;
        if qryItens.FieldByName('VALOR_IPI').AsFloat > 0 then
        begin
           IPI.vBC    := qryItens.FieldByName('BASE_CALCULO').AsFloat;
           IPI.pIPI   := qryItens.FieldByName('ALIQUOTA_IPI').AsFloat;
           IPI.vIPI   := qryItens.FieldByName('VALOR_IPI').AsFloat;
        end;
        PIS.CST := pis99;
        COFINS.CST := cof99;

      end;
    end;
    qryItens.Next;
    end;

    if qrNF.FieldByName('CIF_FOB').Value = 'C' then
      Transp.modFrete := mfContaEmitente
    else
    if qrNF.FieldByName('CIF_FOB').Value = 'F' then
      Transp.modFrete := mfContaDestinatario;

    Transp.Transporta.CNPJCPF  := qrNF.FieldByName('TRANSPORTADOR_CNPJ').AsString;
    Transp.Transporta.xNome    := qrNF.FieldByName('TRANSPORTADOR_RAZAO_SOCIAL').AsString;
    Transp.Transporta.IE       := qrNF.FieldByName('TRANSPORTADOR_INSCRICAO').AsString;
    Transp.Transporta.xEnder   := qrNF.FieldByName('TRANSP_END_LOGRADOURO').AsString+' '+qrNF.FieldByName('TRANSP_END_NUMERO').AsString+' '+qrNF.FieldByName('TRANSP_END_COMPLEMENTO').AsString+' - '+qrNF.FieldByName('TRANSP_END_BAIRRO').AsString;
    Transp.Transporta.xMun     := qrNF.FieldByName('TRANSP_END_CIDADE').AsString;
    Transp.Transporta.UF       := qrNF.FieldByName('TRANSP_END_UF').AsString;
//    Transp.veicTransp.placa    := qrNF.FieldByName('VEICULO_PLACA').AsString;
//    Transp.veicTransp.UF       := qrNF.FieldByName('VEICULO_UF').AsString;
//    Transp.veicTransp.RNTC     := qrNF.FieldByName('RNTC').AsString;


    with Transp.Vol.Add do
     begin
       qVol  := qrNF.fieldByName('VOLUMES').AsInteger;
       esp   := qrNF.FieldByName('ESPECIE_MERCADORIA').AsString;
       marca := qrNF.fieldByName('MARCA').AsString;
       nVol  := qrNF.fieldByName('NUMERACAO_VOLUME').AsString;
       pesoL := qrNF.fieldByName('PESO_LIQUIDO').AsFloat;
       pesoB := qrNF.fieldByName('PESO_BRUTO').AsFloat;
     end;

    Total.ICMSTot.vBC         := qrNF.FieldByName('BASE_CALCULO').AsFloat;
    Total.ICMSTot.vICMS       := qrNF.FieldByName('VALOR_ICMS').AsFloat;
    Total.ICMSTot.vNF         := qrNF.FieldByName('TOTAL_NF').AsFloat;
    Total.ICMSTot.vProd       := qrNF.FieldByName('TOTAL_PRODUTOS').AsFloat;
    Total.ICMSTot.vTotTrib    := qrNF.FieldByName('VALOR_ICMS').AsFloat;

    if qrNF.FieldByName('BASE_ICMS_SUBSTITUICAO').AsFloat > 0 then
      Total.ICMSTot.vBCST       := qrNF.FieldByName('BASE_ICMS_SUBSTITUICAO').AsFloat;

    Total.ICMSTot.vST         := qrNF.FieldByName('ICMS_SUBSTITUICAO').AsFloat;
    Total.ICMSTot.vFrete      := qrNF.FieldByName('VALOR_FRETE').AsFloat;
    Total.ICMSTot.vSeg        := qrNF.FieldByName('VALOR_SEGURO').AsFloat;
    Total.ICMSTot.vDesc       := qrNF.FieldByName('DESCONTO_VALOR').AsFloat;
    Total.ICMSTot.vOutro      := qrNF.FieldByName('OUTRAS_DESPESAS').AsFloat;
    Total.ICMSTot.vIPI        := qrNF.FieldByName('TOTAL_IPI').AsFloat;

    if DIFAL then
    begin
      Total.ICMSTot.vFCPUFDest  := qrNF.FieldByName('DIFAL_VALOR_FCP').AsFloat;
      Total.ICMSTot.vICMSUFDest := qrNF.FieldByName('DIFAL_VALOR_ICMS_UF_DESTINO').AsFloat;
      Total.ICMSTot.vICMSUFRemet:= qrNF.FieldByName('DIFAL_VALOR_ICMS_UF_REMETEN').AsFloat;
    end;

    InfAdic.infCpl            := qrNF.fieldBYName('OBSERVACAO').AsString;
    InfAdic.infAdFisco        := qrNF.fieldBYName('OBS_FISCO').AsString;

    if qrNF.fieldBYName('ORDEM_COMPRA').AsString <> '' then
    begin
      Compra.xPED := qrNF.fieldBYName('ORDEM_COMPRA').AsString;
    end;


{
    with InfAdic.obsCont.Add do
    begin
      xCampo := 'ObsCont';
      xTexto := qrNF.fieldBYName('OBSERVACAO').AsString;
    end;


    with InfAdic.obsFisco.Add do
    begin
      xCampo := 'ObsFisco';
      xTexto := qrNF.fieldBYName('OBS_FISCO').AsString;
    end;
}
  end;
end;

procedure TDMNFE.NFe_GerarXml(numero: Integer);
var NomeArquivoXML : string;
begin
  //================= Gera o xml do NFe Caso o xml exista ele carrega os dados ==============

   qrNF.Close;
   qrNF.ParamByName('numero').Value := numero;
   qrNF.Open;

   //================= Verifica se o xml existe na pasta Transmitidos ==============
   NomeArquivoXML := CaminhoEXE + 'NFe\Transmitidos\';
   NomeArquivoXML := NomeArquivoXML + qrNF.FieldByName('CHAVE_ACESSO').AsString + '-NFe.xml';

   if FileExists(NomeArquivoXML) then
   begin
      NFe.NotasFiscais.Clear;
      NFe.NotasFiscais.LoadFromFile(NomeArquivoXML);
      Exit;
   end;


   //================= Se nao existir na pasta transmitidos gera um xml na pasta gerados ==============
   NFe.NotasFiscais.Clear;

   NFe_Gerar(numero);

   NFe.NotasFiscais.Items[0].GravarXML();

   Dados.script.SQL.Clear;
   Dados.script.SQL.Add(' UPDATE NF SET NF.CHAVE_ACESSO ='+QuotedStr(Copy(NFe.NotasFiscais.Items[0].NFe.infNFe.ID, 4, 44)));
   Dados.script.SQL.Add('              , NF.CNF = ' + NFe.NotasFiscais.Items[0].NFe.Ide.cNF.ToString );
   Dados.script.SQL.Add(' WHERE NF.NUMERO = '+ IntToStr(numero));
   Dados.script.Execute;

end;

procedure TDMNFE.NFe_Assinar;
begin
   NFe.NotasFiscais.Assinar;
end;

procedure TDMNFE.NFe_Imprimir_Individual(numero: Integer);
begin
   //================= Faz a impressao da NF ==============

   if CarregarXml(numero) = False then
   begin
      MessageDlg('Atenção'+#13+#10+''+#13+#10+'O arquivo XML com as informações do NFe não foi encontrado na pasta '+#13+#10+'do sistema'+#13+#10+''+#13+#10+'Selecione o arquivo manualmente', mtWarning, [mbOK], 0);

      OpenDialog1.Title      := 'Selecione o NFe';
      OpenDialog1.DefaultExt := '*-NFe.xml';
      OpenDialog1.Filter     := 'Arquivos NFe (*-NFe.xml)|*-NFe.xml|Arquivos XML (*.xml)|*.xml|Todos os Arquivos (*.*)|*.*';

      if not OpenDialog1.Execute then
        Exit;

      NFe.NotasFiscais.Clear;
      NFe.NotasFiscais.LoadFromFile(OpenDialog1.FileName);
   end;

   NFe.NotasFiscais.Imprimir;

   DataModulo.Dados.script.SQL.Clear;
   DataModulo.Dados.script.SQL.Add(' update NF set NF.DATA_IMPRESSAO = CURRENT_DATE , NF.HORA_SAIDA = CURRENT_TIME ');
   DataModulo.Dados.script.SQL.Add(' WHERE NF.NUMERO= '+ IntToStr(numero) );
   DataModulo.Dados.script.Execute;

end;

procedure TDMNFE.NFe_ValidarXml;
begin
   //================= Faz a validação do arquivo xml ==============
   DMNFE.NFe.NotasFiscais.Validar;
end;

procedure TDMNFE.NFe_Transmitir (numero : Integer);
begin
   NFe.Enviar(1);
   if NFe.NotasFiscais.Items[0].Confirmada then
   begin
      NFe_Gravar_Protocolo_Transmissao(numero);

      ArquivarXML(DMNFE.NFe.NotasFiscais.Items[0].NomeArq);
   end;
end;

procedure TDMNFE.ArquivarXML(arquivo:String);
var NomeArquivo:String;
begin
   NomeArquivo := ExtractFileName(arquivo);
   NomeArquivo := ImpressaoNFe.PathPDF + NomeArquivo;

   if FileExists(NomeArquivo) then
     DeleteFile(PChar(NomeArquivo));

   MoveFile(pchar(arquivo), PChar(NomeArquivo));


   //================= Salva uma copia em pdf para enviar para o cliente por email no futuro (que pode ser amanha rss) ==============
   DMNFE.NFe.NotasFiscais.ImprimirPDF;
end;

procedure TDMNFE.NFe_Gravar_Protocolo_Transmissao(numero: Integer);
begin
   DataModulo.Dados.script.SQL.Clear;
   DataModulo.Dados.script.SQL.Add(' UPDATE NF SET NF.PROTOCOLO_AUTORIZACAO = '+QuotedStr(DMNFE.NFe.WebServices.Retorno.Protocolo));
   DataModulo.Dados.script.SQL.Add('               , NF.data_impressao = current_date ');
   DataModulo.Dados.script.SQL.Add(' WHERE NF.NUMERO = ' + IntToStr(numero) );
   DataModulo.Dados.script.Execute;

end;

procedure TDMNFE.LeConfiguracoesNFe;
begin
   NFe.Configuracoes.Geral.ModeloDF:=moNFe;
   if Dados.qryParametro_NF.fieldbyName('VERSAO_NFE').AsString = 've400' then
     NFe.Configuracoes.Geral.VersaoDF:=ve400
   else
   if Dados.qryParametro_NF.fieldbyName('VERSAO_NFE').AsString = 've310' then
     NFe.Configuracoes.Geral.VersaoDF:=ve310
   else
   if Dados.qryParametro_NF.fieldbyName('VERSAO_NFE').AsString = 've300' then
     NFe.Configuracoes.Geral.VersaoDF:=ve300
   else
   if Dados.qryParametro_NF.fieldbyName('VERSAO_NFE').AsString = 've200' then
     NFe.Configuracoes.Geral.VersaoDF:=ve200
   else
   begin
     MessageDlg('É necessário indicar a versão da NFe', mtError, [mbOK], 0);
     Exit;
   end;

   if Dados.qryParametro_NF.FieldByName('HAMBIENTE_NFE').AsString = 'Homologação' then
   begin
      NFe.Configuracoes.WebServices.Ambiente := taHomologacao;
   end
   else
   if Dados.qryParametro_NF.FieldByName('HAMBIENTE_NFE').AsString = 'Produção' then
   begin
      NFe.Configuracoes.WebServices.Ambiente := taProducao;
   end;

   if Dados.tbParametro_Manifesto.fieldbyName('VERSAO_MDFE').AsString = 've100' then
     MDFe.Configuracoes.Geral.VersaoDF := pmdfeConversaoMDFe.ve100
   else
   if Dados.tbParametro_Manifesto.fieldbyName('VERSAO_MDFE').AsString = 've300' then
     MDFe.Configuracoes.Geral.VersaoDF := pmdfeConversaoMDFe.ve300
   else
   begin
     MessageDlg('É necessário indicar a versão da MDFe', mtError, [mbOK], 0);
     Exit;
   end;

   if Dados.tbParametro_Manifesto.FieldByName('HAMBIENTE').AsString = 'Homologação' then
   begin
      MDFe.Configuracoes.WebServices.Ambiente := taHomologacao;
   end
   else
   if Dados.tbParametro_Manifesto.FieldByName('HAMBIENTE').AsString = 'Produção' then
   begin
      MDFe.Configuracoes.WebServices.Ambiente := taProducao;
   end;


   if Dados.qryParametro_NF.FieldByName('VISUALIZA_WEBSERVICE').AsBoolean or  Dados.qryParametro_NF.FieldByName('VISUALIZA_WEBSERVICE').IsNull then
   begin
      NFe.Configuracoes.WebServices.Visualizar := True;
      MDFe.Configuracoes.WebServices.Visualizar := True;
   end
   else
   begin
      NFe.Configuracoes.WebServices.Visualizar := False;
      MDFe.Configuracoes.WebServices.Visualizar := False;
   end;

   NFe.Configuracoes.Certificados.NumeroSerie := Dados.qrfilial.FieldByName('CERTIFICADO_DIGITAL').AsString;
   NFe.Configuracoes.WebServices.UF := Dados.qrfilial.FieldByName('UF').AsString;



   MDFe.Configuracoes.Certificados.NumeroSerie := Dados.qrfilial.FieldByName('CERTIFICADO_DIGITAL').AsString;
   MDFe.Configuracoes.WebServices.UF := Dados.qrfilial.FieldByName('UF').AsString;

   ForceDirectories( CaminhoEXE + 'NFe\Schemas\'+Dados.qryParametro_NF.fieldbyName('VERSAO_NFE').AsString+'\' );
   ForceDirectories( CaminhoEXE + 'NFe\GERADAS\' );
   ForceDirectories( CaminhoEXE + 'NFe\Transmitidas\' );

   NFe.Configuracoes.Arquivos.PathSchemas := CaminhoEXE + 'NFe\Schemas\'+Dados.qryParametro_NF.fieldbyName('VERSAO_NFE').AsString+'\';
   NFe.Configuracoes.Arquivos.PathSalvar  := CaminhoEXE + 'NFe\GERADAS\';

   MDFe.Configuracoes.Arquivos.PathSchemas := CaminhoEXE + 'MDFe\Schemas\'+Dados.tbParametro_Manifesto.fieldbyName('VERSAO_MDFE').AsString+'\';
   MDFe.Configuracoes.Arquivos.PathSalvar  := CaminhoEXE + 'MDFe\GERADOS\';

   ImpressaoNFe.PathPDF                := CaminhoEXE+'NFe\TRANSMITIDAS\';
   ImpressaoNFe.Sistema                := 'SYSHOP - ' + PegaVersao  + '  www.systemsgeraes.com.br';
   ImpressaoNFe.Logo                   := PegaCaminhodoArquivo(Dados.tbConfig.FieldByName('LOCAL_IMAGENS').AsString)+'logo.bmp';
   ImpressaoNFe.FastFile               := Dados.qryParametro_NF.FieldByName('MODELO_DANFE').AsString;

   Mail.Host                := Dados.qrConfigEmail.FieldByName('EMAIL_HOST').AsString;
   Mail.Port                := Dados.qrConfigEmail.FieldByName('EMAIL_PORTA').AsString;
   Mail.Username            := Dados.qrConfigEmail.FieldByName('EMAIL_LOGIN').AsString;
   Mail.Password            := Dados.qrConfigEmail.FieldByName('EMAIL_SENHA').AsString;
   Mail.FromName            := Dados.qrConfigEmail.FieldByName('EMAIL_REMETENTE_NOME').AsString;
   Mail.From                := Dados.qrConfigEmail.FieldByName('EMAIL_REMENTENTE_EMAIL').AsString;
   Mail.ReadingConfirmation := Dados.qrConfigEmail.FieldByName('EMAIL_CONFIRMACAO_LEITURA').AsBoolean;
   Mail.SetSSL              := Dados.qrConfigEmail.FieldByName('EMAIL_AUTENTICACAO_SEGURA').AsBoolean;
   Mail.SetTLS              := Dados.qrConfigEmail.FieldByName('EMAIL_CONEXAO_SEGURA').AsBoolean;

   DIFAL:=Dados.qryParametro_NF.fieldbyName('DIFAL').AsBoolean; // Difal Suspenso conforme informação Jalice email da enviado contabilidade para Jalice em 18/02/2016


end;

function TDMNFE.NFe_Cancelar(numero,cod_filial: Integer; justificativa : WideString) : Boolean;
var NomeArquivoXML : string;
begin
  //================= Faz o cancelamento do NFe ==============
   Result := False;

   qrNF.Close;
   qrNF.ParamByName('numero').Value := numero;
   qrNF.Open;

   //================= procura o xml para impressao na pasta de transmitidos ==============
   NomeArquivoXML := ImpressaoNFe.PathPDF;
   NomeArquivoXML := NomeArquivoXML + qrNF.FieldByName('CHAVE_ACESSO').AsString + '-NFe.xml';

   dados.qryPesquisa.Close;
   dados.qryPesquisa.SQL.Clear;
   dados.qryPesquisa.SQL.Add(' select count(nf_historico.cod_nf_historico) as qte ');
   dados.qryPesquisa.SQL.Add(' from nf_historico ');
   dados.qryPesquisa.SQL.Add(' where nf_historico.descricao like '+QuotedStr('%cancelou%')+'  and nf_historico.cod_nf = '+IntToStr(NUMERO));
   dados.qryPesquisa.open;

   if not FileExists(NomeArquivoXML) then
   begin
      MessageDlg('Não foi possível carregar o xml do NFe para realizar o cancelamento'+#13+#10+'Não encontrado na pasta do NFe\Transmitidas'+#13+#10+'ele pode ter sido movido ou removido', mtWarning, [mbOK], 0);
      Exit;
   end;

   DMNFE.NFe.NotasFiscais.LoadFromFile(NomeArquivoXML);
   if DMNFE.NFe.Cancelamento(justificativa,dados.qryPesquisa.FieldByName('qte').AsINteger) then
   begin
     Result := True;
     //================= Grava o protocolo de cancelamento ==============
     DataModulo.Dados.script.SQL.Clear;
     DataModulo.Dados.script.SQL.Add(' UPDATE NF SET NF.PROTOCOLO_CANCELAMENTO ='+QuotedStr(NFe.WebServices.EnvEvento.EventoRetorno.retEvento.Items[0].RetInfEvento.nProt));
     DataModulo.Dados.script.SQL.Add(' WHERE NF.NUMERO = ' + IntToStr(NUMERO));
     DataModulo.Dados.script.Execute;
   end
   else
     Result := False;
end;

procedure TDMNFE.NFe_Consultar_Status_WebService_Nacional;
var Url : string;
begin
   Url := 'http://www.nfe.fazenda.gov.br/portal/disponibilidade.aspx';
   ShellExecute(0, 'open', PChar(Url), '', '', 1);

end;

procedure TDMNFE.NFe_Consultar_Status_WebService_MG;
var Url : string;
begin
   Url := 'http://nfe.fazenda.mg.gov.br/portalnfe/sistema/consultaarg.xhtml';
   ShellExecute(0, 'open', PChar(Url), '', '', 1);

end;

procedure TDMNFE.MDFe_Consultar_Status_WebService;
var Url : string;
begin
   Url := 'https://mdfe-portal.sefaz.rs.gov.br/Site/Servicos';
   ShellExecute(0, 'open', PChar(Url), '', '', 1);
end;

procedure TDMNFE.NFe_CopiarXml(numero : Integer);
var NomeArquivoXML : string;
    Encontrado : Boolean;
begin
  //================= Copia o xml da pasta do sistema para outro lugar que o usuario deseje salvar ==============

   Encontrado := False;

   qrNF.Close;
   qrNF.ParamByName('numero').Value := numero;
   qrNF.Open;

   //================= procura o xml para impressao na pasta de transmitidos ==============
   NomeArquivoXML := ImpressaoNFe.PathPDF;
   NomeArquivoXML := NomeArquivoXML + qrNF.FieldByName('CHAVE_ACESSO').AsString + '-NFe.xml';

   if FileExists(NomeArquivoXML) then
   begin
      Encontrado := True;
   end;

   if Encontrado = False then
   begin
       //================= se nao encontou o xml na pasta transmitidos Procura o arquivo xml na pasta Gerados ==============
      NomeArquivoXML := CaminhoEXE + 'NFe\geradas\';
      NomeArquivoXML := NomeArquivoXML + qrNF.FieldByName('CHAVE_ACESSO').AsString + '-NFe.xml';

      if FileExists(NomeArquivoXML) then
      begin
         MessageDlg('Existe um arquivo Xml referente a Chave de Acesso informada'+#13+#10+'que esta na pasta Geradas e talvez não tenha sido autorizada pela Receita', mtWarning, [mbOK], 0);
         encontrado := True;
      end
   end;

   if Encontrado = False then
   begin
      MessageDlg('O arquivo xml não foi encontrado', mtWarning, [mbOK], 0);
      Exit;
   end;

   dlgSalvar.FileName := qrNF.FieldByName('CHAVE_ACESSO').AsString + '-NFe.xml';

   if dlgSalvar.Execute = False then
      Exit;

   CopyFile(PChar(NomeArquivoXML) , PChar(dlgSalvar.FileName) , true );

end;

procedure TDMNFE.NFe_Enviar_Email(Email_Destinatarios: string; numero: integer; var Erro : string; Mostra_Msg_Erro : Boolean = True );
var
 i : Integer;
 Para, assunto : String;
 CC, CorpoEmail, Anexos: Tstrings;

 ListaDeEmail : TStringList;

begin
   //==================== Envia o NFe em pdf e xml por email =============
   Erro := '' ;

   if Trim(Email_Destinatarios) = '' then
   begin
      Erro := 'Sem Informação de Email';
      Exit;
   end;

   if CarregarXml(numero) = False then
   begin
      Erro := 'O arquivo xml da NFe não foi encontrado';
      if Mostra_Msg_Erro = True then
      begin
         MessageDlg('O arquivo xml da NFe não foi encontrado', mtWarning, [mbOK], 0);
      end;
      Exit;
   end ;

   Para := Email_Destinatarios;

   if (Dados.qrConfigEmail.FieldByName('EMAIL_HOST').AsString  = '') or
      (Dados.qrConfigEmail.FieldByName('EMAIL_PORTA').AsString = '') or
      (Dados.qrConfigEmail.FieldByName('EMAIL_LOGIN').AsString = '') or
      (Dados.qrConfigEmail.FieldByName('EMAIL_SENHA').AsString = '') then
   begin
      MessageDlg('Não é possivel Enviar E-mails'+#13+#10+'Falta informar as configurações SMTP da conta'+#13+#10+'nas configurações da NF', mtWarning, [mbOK], 0);
      Exit;
   end;


   CC         := TstringList.Create;
   CC.Clear;


   CorpoEmail := TstringList.Create;

   assunto := 'NFe eletronica Nº: ' + qrNF.FieldByName('NUMERO').AsString + ' - ' +
              Dados.qrRegistro.FieldByName('RAZAO_SOCIAL').AsString;

   CorpoEmail.Add('À '+qrNF.FieldByName('CLIENTE_RAZAO_SOCIAL').AsString);
   CorpoEmail.Add('');

   CorpoEmail.Add('Em anexo, você está recebendo a NFe Eletrônica número '+ qrNF.FieldByName('NUMERO').AsString);
   CorpoEmail.Add('Série '       + qrNF.FieldByName('SERIE').AsString);
   CorpoEmail.Add('Emitida por ' + Dados.qrRegistro.FieldByName('RAZAO_SOCIAL').AsString);

   CorpoEmail.Add('');
   CorpoEmail.Add('');
   CorpoEmail.Add('Junto com a mercadoria você receberá também um DANFe (Documento Auxiliar de Nota Fiscal Eletrônica) correspondente a esta NFe');
   CorpoEmail.Add('');
   CorpoEmail.Add('');
   CorpoEmail.Add('A validade e autenticidade deste documento eletrônico pode ser verificada no site nacional do projeto (www.nfe.fazenda.gov.br)');
   CorpoEmail.Add('através da chave de acesso: ' + qrNF.FieldByName('CHAVE_ACESSO').AsString);

   CorpoEmail.Add('');
   CorpoEmail.Add('');
   CorpoEmail.Add('');
   CorpoEmail.Add('');
   CorpoEmail.Add('Data e Hora: '+ DateTimeToStr(Now));
   CorpoEmail.Add('Geração da NFe: '         + qrNF.FieldByName('NUMERO').AsString );
   CorpoEmail.Add('Chave de Identificação: ' + qrNF.FieldByName('CHAVE_ACESSO').AsString);
   CorpoEmail.Add('');
   CorpoEmail.Add('');
   CorpoEmail.Add('-----------------------------------------------------------------');
   CorpoEmail.Add('|                                                               |');
   CorpoEmail.Add('|                                                               |');
   CorpoEmail.Add('|  Por favor não responda este email                            |');
   CorpoEmail.Add('|  Em caso de dúvidas entre com contato com o setor responsável |');
   CorpoEmail.Add('|                                                               |');
   CorpoEmail.Add('|                                                               |');
   CorpoEmail.Add('----------------------------------------------------------------|');


   {==================================
      Se o email do rementente for igual ao email do destinatario é considerado um email de bkp
      estes emails sao para ficar armazenados como copia de seguranca no servidor de emails
   ===================================}


   //================= Se tive mais de um email para se enviado tem que colocar como copia e os emails devem ser separados por ( ; ) ==============

   ListaDeEmail := TStringList.Create;
   ListaDeEmail.Delimiter := ';';
   ListaDeEmail.DelimitedText := Email_Destinatarios;

   para := '';

   for i := 0 to ListaDeEmail.Count - 1 do
   begin
      if Para = '' then
         para := ListaDeEmail[i]
      else
      CC.Add(ListaDeEmail[i])
   end;

    //================= manda uma copia do email para o email do remetente ==============
   if Dados.qryParametro_NF.FieldByName('ENVIAR_COPIA_EMAIL_NF').AsString = 'T' then
    CC.Add(Dados.qrConfigEmail.fieldByName('EMAIL_LOGIN').AsString);

   NFe.NotasFiscais.Items[0].EnviarEmail(
                                              Para
                                            , assunto
                                            , CorpoEmail
                                            , True //Enviar PDF junto
                                            , CC //Lista com emails que serão enviado cópias - TStrings
                                            , Anexos // Lista de anexos - TStrings
                                            ); // Auto TLS
   CC.Free;
   CorpoEmail.Free;
end;


function TDMNFE.NFe_Consulta_Protocolo(numero: Integer;var protocolo:String):Boolean;
var NomeArquivoXML : string;
begin
  //================= Consulta e grava o numero do protocolo no xml ==============
   Result := False;
   Protocolo:='';
   if CarregarXml(numero) = False then
   begin
      MessageDlg('O arquivo xml do NFe não foi encontrado', mtWarning, [mbOK], 0);
      Exit;
   end;

   NFe.Consultar;
   protocolo:=DMNFE.NFe.WebServices.Consulta.Protocolo;
   if Trim(Protocolo) = '' then
   begin
      MessageDlg('Nº do protocolo não foi encontrado'+#13+#10+'Talvez esta NFe ainda não tenha sido transmitida', mtWarning, [mbOK], 0);
      Exit;
   end;
   DataModulo.Dados.script.SQL.Clear;
   DataModulo.Dados.script.SQL.Add(' UPDATE NF SET NF.PROTOCOLO_AUTORIZACAO = '+QuotedStr(protocolo));
   DataModulo.Dados.script.SQL.Add(' WHERE NF.NUMERO = ' + IntToStr(NUMERO) );
   DataModulo.Dados.script.Execute;

   DMNFE.NFe.NotasFiscais.Items[0].GravarXML();

   ArquivarXML(DMNFE.NFe.NotasFiscais.Items[0].NomeArq);

   Result:=True;

end;

function TDMNFE.CarregarXml(numero: Integer): Boolean;
var Carregou : Boolean;
    NomeArquivoXML : string;
begin
   //================= Carrega o arquvo xml no componente  ==============

   qrNF.Close;
   qrNF.ParamByName('numero').Value := numero;
   qrNF.Open;

   Carregou := False;

  //================= procura o xml para impressao na pasta de transmitidas ==============

   NomeArquivoXML := ImpressaoNFe.PathPDF;
   NomeArquivoXML := NomeArquivoXML + qrNF.FieldByName('CHAVE_ACESSO').AsString + '-NFe.xml';

   if FileExists(NomeArquivoXML) then
   begin
     DMNFE.NFe.NotasFiscais.Clear;
     DMNFE.NFe.NotasFiscais.LoadFromFile(NomeArquivoXML);
     Carregou := True;
   end
   else
   begin
       //================= se nao encontou o xml na pasta transmitidos Procura o arquivo xml na pasta Gerados ==============
      NomeArquivoXML := CaminhoEXE + 'NFe\GERADAS\';
      NomeArquivoXML := NomeArquivoXML + qrNF.FieldByName('CHAVE_ACESSO').AsString + '-NFe.xml';

      if FileExists(NomeArquivoXML) then
      begin
         NFe.NotasFiscais.Clear;
         NFe.NotasFiscais.LoadFromFile(NomeArquivoXML);
         Carregou := True;
      end
   end;

   Result := Carregou;
end;

procedure TDMNFE.NFeStatusChange(Sender: TObject);
begin
  case NFe.Status of
    stIdle :
    begin
      if ( frmStatus <> nil ) then
        frmStatus.Hide;
    end;
    stNFeStatusServico :
    begin
      if ( frmStatus = nil ) then
        frmStatus := TfrmStatus.Create(Application);
      frmStatus.lblStatus.Caption := 'Verificando Status do servico...';
      frmStatus.Show;
      frmStatus.BringToFront;
    end;
    stNFeRecepcao :
    begin
      if ( frmStatus = nil ) then
        frmStatus := TfrmStatus.Create(Application);
      frmStatus.lblStatus.Caption := 'Enviando dados da NFe...';
      frmStatus.Show;
      frmStatus.BringToFront;
    end;
    stNfeRetRecepcao :
    begin
      if ( frmStatus = nil ) then
        frmStatus := TfrmStatus.Create(Application);
      frmStatus.lblStatus.Caption := 'Recebendo dados da NFe...';
      frmStatus.Show;
      frmStatus.BringToFront;
    end;
    stNfeConsulta :
    begin
      if ( frmStatus = nil ) then
        frmStatus := TfrmStatus.Create(Application);
      frmStatus.lblStatus.Caption := 'Consultando NFe...';
      frmStatus.Show;
      frmStatus.BringToFront;
    end;
    stNfeCancelamento :
    begin
      if ( frmStatus = nil ) then
        frmStatus := TfrmStatus.Create(Application);
      frmStatus.lblStatus.Caption := 'Enviando cancelamento de NFe...';
      frmStatus.Show;
      frmStatus.BringToFront;
    end;
    stNfeInutilizacao :
    begin
      if ( frmStatus = nil ) then
        frmStatus := TfrmStatus.Create(Application);
      frmStatus.lblStatus.Caption := 'Enviando pedido de Inutilização...';
      frmStatus.Show;
      frmStatus.BringToFront;
    end;
    stNFeRecibo :
    begin
      if ( frmStatus = nil ) then
        frmStatus := TfrmStatus.Create(Application);
      frmStatus.lblStatus.Caption := 'Consultando Recibo de Lote...';
      frmStatus.Show;
      frmStatus.BringToFront;
    end;
    stNFeCadastro :
    begin
      if ( frmStatus = nil ) then
        frmStatus := TfrmStatus.Create(Application);
      frmStatus.lblStatus.Caption := 'Consultando Cadastro...';
      frmStatus.Show;
      frmStatus.BringToFront;
    end;
    stNFeEmail :
    begin
      if ( frmStatus = nil ) then
        frmStatus := TfrmStatus.Create(Application);
      frmStatus.lblStatus.Caption := 'Enviando Email...';
      frmStatus.Show;
      frmStatus.BringToFront;
    end;
  end;
  Application.ProcessMessages;
end;


procedure TDMNFE.NFe_ApagarXml(chaveNFe: string);
var PastaGerados, PastaTransmitidos,
    ArquivoXml, ArquivoPdf : string;
begin
  //======================= Apaga o xml da pasta gerados e transmitidos ======================

   PastaGerados := CaminhoEXE + 'nfe\GERADOS\';
   PastaTransmitidos:= CaminhoEXE + 'nfe\Transmitidos\';

   ArquivoXml := PastaGerados + chaveNFe + '-nfe.xml';
   ArquivoPdf := PastaGerados + chaveNFe + '.pdf';

   DeleteFile(PChar(ArquivoXml));
   DeleteFile(PChar(ArquivoPdf));

   ArquivoXml := PastaTransmitidos + chaveNFe + '-nfe.xml';
   ArquivoPdf := PastaTransmitidos + chaveNFe + '.pdf';

   DeleteFile(PChar(ArquivoXml));
   DeleteFile(PChar(ArquivoPdf));

end;

procedure TDMNFE.MDNFe_Gerar(cod_manifesto , cod_filial : Integer);
begin
  //================= Gera o xml do Manifesto Eletronico para ser transmitido ==============
  if (Dados.tbParametro_Manifesto.FieldByName('HAMBIENTE').AsString <> 'Homologação' ) and (Dados.tbParametro_Manifesto.FieldByName('HAMBIENTE').AsString <> 'Produção' ) then
  begin
     MessageDlg('Não foi definido o Hambiente'+#13+#10+'Homologação ou Produção'+#13+#10+'Verifique as configurações do Manifesto', mtWarning, [mbOK], 0);
     Exit;
  end;

   qrManifesto.Close;
   qrManifesto.ParamByName('codManifesto').Value := cod_manifesto;
   qrManifesto.ParamByName('CodFilial').Value    := cod_filial;
   qrManifesto.Open;

   with MDFe.Manifestos.Add.MDFe do
   begin
      //================= Dados de Identificação do MDF-e ==============

      Ide.cUF   := qrManifesto.FieldByName('TRANS_END_COD_UF').AsInteger;

      //================= TMDFeTpEmitente = ( teTransportadora, teTranspCargaPropria ) ==============
      Ide.tpEmit  := teTranspCargaPropria;
      Ide.modelo  := qrManifesto.FieldByName('MODELO').AsString ; //'58';
      Ide.serie   := qrManifesto.FieldByName('SERIE').AsInteger; //1;
      Ide.nMDF    := cod_manifesto;

      Ide.modal   := moRodoviario;
//      Ide.dhEmi   := Now; Mudei colocando a data de cadastro porque quando tenta retransmitir se estiver uma data diferente não consegue transmitir nem pegar o protocolo de tranmissao
      Ide.dhEmi   := qrManifesto.FieldByName('DATA_EMISSAO').AsDate;

       //================= TpcnTipoEmissao = (teNormal, teContingencia, teSCAN, teDPEC, teFSDA) ==============
      if qrManifesto.FieldByName('TIPO_EMISSAO').AsString = 'CONTINGENCIA' then
        Ide.tpEmis := teContingencia
      else
      if qrManifesto.FieldByName('TIPO_EMISSAO').AsString = 'SCAN' then
        Ide.tpEmis := teSCAN
      else
      if qrManifesto.FieldByName('TIPO_EMISSAO').AsString = 'DPEC' then
        Ide.tpEmis := teDPEC
      else
      if qrManifesto.FieldByName('TIPO_EMISSAO').AsString = 'FSDA' then
        Ide.tpEmis := teFSDA
      else
         Ide.tpEmis := teNormal;

      // TpcnProcessoEmissao = (peAplicativoContribuinte, peAvulsaFisco, peAvulsaContribuinte, peContribuinteAplicativoFisco);
      Ide.procEmi := peAplicativoContribuinte;
      Ide.verProc := PegaVersao;

      Ide.UFIni   := qrManifesto.FieldByName('UF_INICIO_DESCRICAO').AsString;
      Ide.UFFim   := qrManifesto.FieldByName('UF_FIM_DESCRICAO').AsString;

      with Ide.infMunCarrega.Add do
      begin
         cMunCarrega := qrManifesto.FieldByName('COD_MUNICIPIO_CARREGAMENTO').AsInteger;
         xMunCarrega := qrManifesto.FieldByName('NOME_MUNICIPIO_CARREGAMENTO').AsString;
      end;

     qrManifestoPercurso.Close;
     qrManifestoPercurso.ParamByName('cod_manifesto').Value  := cod_manifesto;
     qrManifestoPercurso.ParamByName('cod_filial').Value     := cod_filial;
     qrManifestoPercurso.ParamByName('modeloManifesto').Value:= qrManifesto.FieldByName('MODELO').AsString;
     qrManifestoPercurso.Open;

     while NOT qrManifestoPercurso.Eof do
     begin
        with Ide.infPercurso.Add do
        begin
            UFPer := qrManifestoPercurso.FieldByName('UF').AsString;
        end;
        qrManifestoPercurso.Next;
     end;


      //================= Dados do Emitente - Transportadora ==============

      Emit.CNPJCPF  := qrManifesto.FieldByName('TRANS_CNPJ').AsString;
      Emit.IE    := qrManifesto.FieldByName('TRANS_INSCR_ESTADUAL').AsString;
      Emit.xNome := qrManifesto.FieldByName('TRANS_NOME').AsString;
      Emit.xFant := qrManifesto.FieldByName('TRANS_FANTASIA').AsString;

      Emit.EnderEmit.xLgr    := qrManifesto.FieldByName('TRANS_END_LOGRADOURO').AsString;
      Emit.EnderEmit.nro     := qrManifesto.FieldByName('TRANS_END_NUMERO').AsString;
      Emit.EnderEmit.xCpl    := qrManifesto.FieldByName('TRANS_END_COMPLEMENTO').AsString;
      Emit.EnderEmit.xBairro := qrManifesto.FieldByName('TRANS_END_BAIRRO').AsString;
      Emit.EnderEmit.cMun    := qrManifesto.FieldByName('TRANS_END_COD_IBGE_CIDADE').AsInteger;
      Emit.EnderEmit.xMun    := qrManifesto.FieldByName('TRANS_END_CIDADE').AsString;
      Emit.EnderEmit.CEP     := qrManifesto.FieldByName('TRANS_END_CEP').AsInteger;
      Emit.EnderEmit.UF      := qrManifesto.FieldByName('TRANS_END_UF').AsString;
      Emit.EnderEmit.fone    := qrManifesto.FieldByName('TRANS_TELEFONE').AsString;
      Emit.enderEmit.email   := qrManifesto.FieldByName('TRANS_EMAIL').AsString;

      rodo.veicTracao.placa := qrManifesto.FieldByName('VEICULO_PRINCIPAL_PLACA').AsString;
      rodo.veicTracao.tara  := qrManifesto.FieldByName('VEICULO_PRINCIPAL_TARA').AsInteger;
      rodo.veicTracao.capKG := qrManifesto.FieldByName('VEICULO_PRINCIPAL_CAPACIDADE_KG').AsInteger;
      rodo.veicTracao.tpCar := tcNaoAplicavel;
      rodo.veicTracao.UF    := 'MG' ;
      rodo.veicTracao.tpRod := trToco;
{    // comentei o código abaixo porque ficava dando erro informando que se for carga própria não deve informar tipo transportador
      if qrManifesto.FieldByName('PROP_VEICULO_PRNCI_CPF').AsString <> qrManifesto.FieldByName('TRANS_CNPJ').AsString then
      begin
        rodo.veicTracao.prop.CNPJCPF :=  qrManifesto.FieldByName('PROP_VEICULO_PRNCI_CPF').AsString;
        rodo.veicTracao.prop.RNTRC   :=  qrManifesto.FieldByName('VEICULO_PRINCIPAL_RNTRC').AsString;
        rodo.veicTracao.prop.xNome   :=  qrManifesto.FieldByName('PROP_VEICULO_PRNCI_NOME').AsString;
        rodo.veicTracao.prop.IE      :=  'ISENTO';
        rodo.veicTracao.prop.UF      :=  qrManifesto.FieldByName('PROP_VEICULO_PRNCI_UF').AsString;
        rodo.veicTracao.prop.tpProp  :=  tpTACAgregado;
      end;
}
      with rodo.veicTracao.condutor.Add do
      begin
        xNome := qrManifesto.FieldByName('CONDUTOR_NOME').AsString;
        CPF   := qrManifesto.FieldByName('CONDUTOR_CPF').AsString;
      end;

      if qrManifesto.FieldByName('REBOQUE_PLACA').AsString <> '' then
      begin
         with rodo.veicReboque.Add do
         begin
            cInt  := qrManifesto.FieldByName('REBOQUE_CODIGO').AsString;
            placa := qrManifesto.FieldByName('REBOQUE_PLACA').AsString;
            tara  := qrManifesto.FieldByName('REBOQUE_TARA').AsInteger;
            capKG := qrManifesto.FieldByName('REBOQUE_CAPACIDADE_KG').AsInteger;
            UF    := qrManifesto.FieldByName('PROP_VEICULO_REBOQUE_UF').AsString;

            IF qrManifesto.FieldByName('PROP_VEICULO_REBOQUE_CPF').AsString <> qrManifesto.FieldByName('TRANS_CNPJ').AsString then
            begin
              prop.CNPJCPF :=  qrManifesto.FieldByName('PROP_VEICULO_REBOQUE_CPF').AsString;
              prop.RNTRC   :=  qrManifesto.FieldByName('REBOQUE_RNTRC').AsString;
              prop.xNome   :=  qrManifesto.FieldByName('PROP_VEICULO_REBOQUE_NOME').AsString;
              prop.UF      :=  qrManifesto.FieldByName('PROP_VEICULO_REBOQUE_UF').AsString;
              prop.IE      := 'ISENTO';
              prop.tpProp  :=  tpOutros;
            end;
         end;
      end;


      with infDoc.infMunDescarga.Add do
      begin
         cMunDescarga := qrManifesto.FieldByName('COD_MUNICIPIO_DESCARREGAMENTO').AsInteger;
         xMunDescarga := qrManifesto.FieldByName('NOME_MUNICIPIO_DESCARREGAMENTO').AsString;

         //================= Adciona os Nfe do manifesto ==============
         qrMDFe_NFs.Close;
         qrMDFe_NFs.ParamByName('codigo_manifesto').Value := cod_manifesto;
         qrMDFe_NFs.ParamByName('Filial_manifesto').Value := cod_filial;
         qrMDFe_NFs.Open;

         if not qrMDFe_NFs.IsEmpty then
            qrMDFe_NFs.First;

         while not qrMDFe_NFs.Eof do
         begin
            with infNFe.Add do
            begin
               chNFe := qrMDFe_NFs.FieldByName('CHAVE_ACESSO').AsString;

               //================= Informações das Unidades de Transporte (Carreta/Reboque/Vagão) ==============
               with infUnidTransp.Add do
               begin
                  //================= TpcnUnidTransp = ( utRodoTracao, utRodoReboque, utNavio, utBalsa, utAeronave, utVagao, utOutros ) ==============
                  tpUnidTransp := utRodoTracao;
                  idUnidTransp := qrManifesto.FieldByName('VEICULO_PRINCIPAL_PLACA').AsString;

                  //================= Informações das Unidades de carga (Containeres/ULD/Outros) ==============
                  with infUnidCarga.Add do
                  begin
                     //================= TpcnUnidCarga  = ( ucContainer, ucULD, ucPallet, ucOutros ) ==============
                     tpUnidCarga := ucOutros;
                     idUnidCarga := qrMDFe_NFs.FieldByName('NUMERO').AsString;

                     qtdRat := 1.0;
                  end;

                  qtdRat := 1.0;
               end;

              qrMDFe_NFs.Next;
            end;
         end;


      end;

      tot.qNfe  := qrManifesto.FieldByName('QTD_CTRC').AsInteger;
      tot.vCarga := qrManifesto.FieldByName('CARGA_VALOR_TOTAL').AsCurrency;

      //================= UnidMed = (uM3,uKG, uTON, uUNIDADE, uLITROS) ==============
      tot.cUnid  :=  uKG;
      tot.qCarga := qrManifesto.FieldByName('CARGA_PESO_TOTAL').AsCurrency;

      infAdic.infCpl     := 'Empresa optante pelo Simples Nacional.; Caminhao VW.';
      infAdic.infAdFisco := '';
   end;
 MDFe.Manifestos.GerarMDFe;
end;

procedure TDMNFE.MDNFe_Consulta_Protocolo(cod_manifesto, cod_filial: Integer);
begin
  //================= Consulta e grava o numero do protocolo no xml ==============

   if MDNFe_CarregarXml(cod_manifesto, cod_filial) = False then
   begin
      MessageDlg('O arquivo xml do MDFw não foi encontrado', mtWarning, [mbOK], 0);
      Exit;
   end;

   MDFe.Consultar;

   if Trim(MDFe.WebServices.Consulta.Protocolo) = '' then
   begin
      MessageDlg('Nº do protocolo não foi encontrado'+#13+#10+'Talvez este MDFe ainda não tenha sido transmitido', mtWarning, [mbOK], 0);
      Exit;
   end;

   MDFe.Manifestos.Items[0].GravarXML();

   MDNFe_ArquivarXML(MDFe.Manifestos.Items[0].NomeArq);

   DataModulo.Dados.script.SQL.Clear;
   DataModulo.Dados.script.SQL.Add(' UPDATE MANIFESTO SET MANIFESTO.PROTOCOLO_TRANSMISSAO = '+QuotedStr(MDFe.WebServices.Consulta.Protocolo));
   DataModulo.Dados.script.SQL.Add(' WHERE MANIFESTO.COD_MANIFESTO = ' + IntToStr(cod_manifesto) + ' AND MANIFESTO.COD_FILIAL_CADASTRO = '+  IntToStr(cod_filial));
   DataModulo.Dados.script.Execute;


end;

procedure TDMNFE.MDNFe_ValidarXml;
begin
   //================= Faz a validação do arquivo xml ==============
   MDFe.Manifestos.Validar;
end;

procedure TDMNFE.MDNFe_Gravar_Protocolo_Transmissao(cod_manifesto, cod_filial: Integer);
begin
   DataModulo.Dados.script.SQL.Clear;
   DataModulo.Dados.script.SQL.Add(' UPDATE MANIFESTO SET MANIFESTO.PROTOCOLO_TRANSMISSAO = '+ QuotedStr(DMNFE.MDFe.WebServices.Retorno.Protocolo));
   DataModulo.Dados.script.SQL.Add('               , MANIFESTO.data_impressao = current_date ');
   DataModulo.Dados.script.SQL.Add(' WHERE MANIFESTO.COD_MANIFESTO = ' + IntToStr(cod_manifesto) + ' AND MANIFESTO.COD_FILIAL_CADASTRO = '+  IntToStr(cod_filial));
   DataModulo.Dados.script.SQL.Add('    and MANIFESTO.MODELO > 0 ');
   DataModulo.Dados.script.Execute;
end;

procedure TDMNFE.MDNFe_Gravar_Protocolo_Encerramento(cod_manifesto, cod_filial: Integer);
begin
   DataModulo.Dados.script.SQL.Clear;
   DataModulo.Dados.script.SQL.Add(' UPDATE MANIFESTO SET MANIFESTO.PROTOCOLO_ENCERRAMENTO = '+ QuotedStr(MDFe.Manifestos.Items[0].MDFe.procMDFe.nProt));

   DataModulo.Dados.script.SQL.Add(' , MANIFESTO.COD_USUARIO_ENCERRAMENTO = ' + Dados.qrUsuario.FieldByName('cod_usuario').AsString );
   DataModulo.Dados.script.SQL.Add(' , MANIFESTO.HORA_ENCERRAMENTO = CURRENT_TIME ');
   DataModulo.Dados.script.SQL.Add(' , MANIFESTO.DATA_ENCERRAMENTO = current_date ');

   DataModulo.Dados.script.SQL.Add(' WHERE MANIFESTO.COD_MANIFESTO = ' + IntToStr(cod_manifesto) + ' AND MANIFESTO.COD_FILIAL_CADASTRO = '+  IntToStr(cod_filial));
   DataModulo.Dados.script.SQL.Add('    and MANIFESTO.MODELO > 0 ');
   DataModulo.Dados.script.Execute;
end;

procedure TDMNFE.MDNFe_Gravar_Protocolo_Cancelamento(cod_manifesto, cod_filial: Integer; motivo : string);
begin
   DataModulo.Dados.script.SQL.Clear;
   DataModulo.Dados.script.SQL.Add(' UPDATE MANIFESTO SET MANIFESTO.PROTOCOLO_CANCELAMENTO = '+ QuotedStr(MDFe.Manifestos.Items[0].MDFe.procMDFe.nProt));

   DataModulo.Dados.script.SQL.Add(' , MANIFESTO.COD_USUARIO_CANCELAMENTO = ' + Dados.qrUsuario.FieldByName('cod_usuario').AsString );
   DataModulo.Dados.script.SQL.Add(' , MANIFESTO.HORA_CANCELAMENTO = CURRENT_TIME ');
   DataModulo.Dados.script.SQL.Add(' , MANIFESTO.DATA_CANCELAMENTO = current_date ');
   DataModulo.Dados.script.SQL.Add(' , MANIFESTO.MOTIVO_CANCELAMENTO = ' + QuotedStr(motivo));

   DataModulo.Dados.script.SQL.Add(' WHERE MANIFESTO.COD_MANIFESTO = ' + IntToStr(cod_manifesto) + ' AND MANIFESTO.COD_FILIAL_CADASTRO = '+  IntToStr(cod_filial));
   DataModulo.Dados.script.SQL.Add('    and MANIFESTO.MODELO > 0 ');
   DataModulo.Dados.script.Execute;
end;

procedure TDMNFE.MDNFe_Transmitir (cod_manifesto, cod_filial: Integer);
begin
   MDFe.Enviar(1,False);
   if MDFe.Manifestos.Items[0].Confirmado then
   begin
      MDNFe_Gravar_Protocolo_Transmissao(cod_manifesto, cod_filial);

      MDFe.Manifestos.Items[0].GravarXML();

      MDNFe_ArquivarXML(MDFe.Manifestos.Items[0].NomeArq);
   end;
end;


function TDMNFE.MDNFe_CarregarXml(cod_manifesto, cod_filial: Integer): Boolean;
var Carregou : Boolean;
    NomeArquivoXML: string;
begin
   //================= Carrega o arquvo xml no componente  ==============

   qrManifesto.Close;
   qrManifesto.ParamByName('codManifesto').Value := cod_manifesto;
   qrManifesto.ParamByName('CodFilial').Value    := cod_filial;
   qrManifesto.Open;

   Carregou := False;

  //================= procura o xml para impressao na pasta de transmitidos ==============

   NomeArquivoXML := CaminhoEXE + 'mdfe\Transmitidos\';
   NomeArquivoXML := NomeArquivoXML + qrManifesto.FieldByName('CHAVE_ACESSO').AsString + '-mdfe.xml';

   if FileExists(NomeArquivoXML) then
   begin
     MDFe.Manifestos.Clear;
     MDFe.Manifestos.LoadFromFile(NomeArquivoXML);
     Carregou := True;
   end
   else
   begin
       //================= se nao encontou o xml na pasta transmitidos Procura o arquivo xml na pasta Gerados ==============
      NomeArquivoXML := CaminhoEXE + 'mdfe\gerados\';
      NomeArquivoXML := NomeArquivoXML + qrManifesto.FieldByName('CHAVE_ACESSO').AsString + '-mdfe.xml';

      if FileExists(NomeArquivoXML) then
      begin
         MDFe.Manifestos.Clear;
         MDFe.Manifestos.LoadFromFile(NomeArquivoXML);
         Carregou := True;
      end
   end;

   Result := Carregou;
end;

procedure TDMNFE.MDNFe_Gerar_XML(cod_manifesto, cod_filial: Integer);
var NomeArquivoXML : string;
begin
  //================= Gera o xml do Manifsto. Caso o xml exista ele carrega os dados ==============

   qrManifesto.Close;
   qrManifesto.ParamByName('codManifesto').Value := cod_manifesto;
   qrManifesto.ParamByName('CodFilial').Value    := cod_filial;
   qrManifesto.Open;

   //================= Verifica se o xml existe na pasta Transmitidos ==============
   NomeArquivoXML := CaminhoEXE + 'mdfe\Transmitidos\';
   NomeArquivoXML := NomeArquivoXML + qrManifesto.FieldByName('CHAVE_ACESSO').AsString + '-MDFe.xml';

   if FileExists(NomeArquivoXML) then
   begin
      MDFe.Manifestos.Clear;
      MDFe.Manifestos.LoadFromFile(NomeArquivoXML);
      Exit;
   end;


   //================= Se nao existir na pasta transmitidos gera um xml na pasta gerados ==============
   MDFe.Manifestos.Clear;
   MDFe.Configuracoes.Arquivos.PathSalvar := CaminhoEXE + 'mdfe\GERADOS\';

   MDNFe_Gerar(cod_manifesto , cod_filial);

   MDFe.Manifestos.Items[0].Assinar;
   MDFe.Manifestos.Items[0].GravarXML('','');

//   if qrManifesto.FieldByName('CHAVE_ACESSO').AsString = '' then
//   begin
     DataModulo.Dados.script.SQL.Clear;
     DataModulo.Dados.script.SQL.Add(' UPDATE MANIFESTO SET MANIFESTO.CHAVE_ACESSO ='+QuotedStr(Copy(MDFe.Manifestos.Items[0].MDFe.infMDFe.ID, 5, 44)));
     DataModulo.Dados.script.SQL.Add(' WHERE MANIFESTO.COD_MANIFESTO = '+ IntToStr(cod_manifesto) + ' AND MANIFESTO.COD_FILIAL_CADASTRO =' + IntToStr(cod_filial) );
     DataModulo.Dados.script.Execute;
//   end;
end;

procedure TDMNFE.MDNFe_ArquivarXML(arquivo:String);
var NomeArquivo:String;
begin
   NomeArquivo := ExtractFileName(arquivo);
   NomeArquivo := CaminhoEXE + 'mdfe\TRANSMITIDOS\' + NomeArquivo;

   DeleteFile( PChar(NomeArquivo));
   MoveFile(pchar(arquivo), PChar(NomeArquivo));

   //================= Salva uma copia em pdf para enviar para o cliente por email no futuro (que pode ser amanha rss) ==============
   MDFe.Manifestos.ImprimirPDF;

end;

procedure TDMNFE.MDNFe_Imprimir_Individual(cod_manifesto, cod_filial: Integer);
begin
   //================= Faz a impressao do ctrc ==============

   if MDNFe_CarregarXml(cod_manifesto, cod_filial) = False then
   begin
      MessageDlg('Atenção'+#13+#10+''+#13+#10+'O arquivo XML com as informações do MDFe não foi encontrado na pasta '+#13+#10+'do sistema'+#13+#10+''+#13+#10+'Selecione o arquivo manualmente', mtWarning, [mbOK], 0);

      OpenDialog1.Title      := 'Selecione o MDFe';
      OpenDialog1.DefaultExt := '*-MDFe.xml';
      OpenDialog1.Filter     := 'Arquivos MDFe (*-mdfe.xml)|*-mdfe.xml|Arquivos XML (*.xml)|*.xml|Todos os Arquivos (*.*)|*.*';
      OpenDialog1.InitialDir := MDFe.Configuracoes.Arquivos.PathSalvar;

      if not OpenDialog1.Execute then
        Exit;

      MDFe.Manifestos.Clear;
      MDFe.Manifestos.LoadFromFile(OpenDialog1.FileName);
   end;

   MDFe.Manifestos.Imprimir;


   DataModulo.Dados.script.SQL.Clear;
   DataModulo.Dados.script.SQL.Add(' update MANIFESTO set MANIFESTO.DATA_IMPRESSAO = CURRENT_DATE , MANIFESTO.HORA_IMPRESSAO = CURRENT_TIME ');
   DataModulo.Dados.script.SQL.Add(' WHERE MANIFESTO.COD_MANIFESTO= '+ IntToStr(cod_manifesto) + ' AND MANIFESTO.COD_FILIAL_CADASTRO =' + IntToStr(cod_filial) );
   DataModulo.Dados.script.Execute;

end;

procedure TDMNFE.MDNFe_Encerramento(cod_manifesto, cod_filial: Integer);
begin
   //================= Faz o encerramento do mdfe ==============

   MDFe.EventoMDFe.Evento.Clear;

   if MDNFe_CarregarXml(cod_manifesto, cod_filial) = False then
   begin
      MessageDlg('Atenção'+#13+#10+''+#13+#10+'O arquivo XML com as informações do MDFe não foi encontrado na pasta '+#13+#10+'do sistema'+#13+#10+''+#13+#10+'Selecione o arquivo manualmente', mtWarning, [mbOK], 0);

      OpenDialog1.Title      := 'Selecione o MDFe';
      OpenDialog1.DefaultExt := '*-MDFe.xml';
      OpenDialog1.Filter     := 'Arquivos MDFe (*-mdfe.xml)|*-mdfe.xml|Arquivos XML (*.xml)|*.xml|Todos os Arquivos (*.*)|*.*';
      OpenDialog1.InitialDir := MDFe.Configuracoes.Arquivos.PathSalvar;

      if not OpenDialog1.Execute then
        Exit;

      MDFe.Manifestos.Clear;
      MDFe.Manifestos.LoadFromFile(OpenDialog1.FileName);
   end;



   with MDFe.EventoMDFe.Evento.Add do
    begin
     infEvento.chMDFe   := Copy(MDFe.Manifestos.Items[0].MDFe.infMDFe.ID, 5, 44);
     infEvento.CNPJCPF  := Dados.qrFilial.FieldByName('cnpj').AsString;
     infEvento.dhEvento := now;

     infEvento.tpEvento   := teEncerramento;
     infEvento.nSeqEvento := 1;

     infEvento.detEvento.nProt := MDFe.Manifestos.Items[0].MDFe.procMDFe.nProt;
     infEvento.detEvento.dtEnc := Date;
     infEvento.detEvento.cUF   := StrToInt(Copy(IntToStr(MDFe.Manifestos.Items[0].MDFe.infDoc.infMunDescarga.Items[0].cMunDescarga),1,2));
     infEvento.detEvento.cMun  := MDFe.Manifestos.Items[0].MDFe.infDoc.infMunDescarga.Items[0].cMunDescarga;
    end;

   MDFe.EnviarEvento( 1 ); // 1 = Numero do Lote

   MDNFe_Gravar_Protocolo_Encerramento(cod_manifesto, cod_filial);

end;

procedure TDMNFE.MDNFe_Cancelar(cod_manifesto, cod_filial: Integer; Motivo : string);
begin
   //================= Faz o encerramento do mdfe ==============

   MDFe.EventoMDFe.Evento.Clear;

   if MDNFe_CarregarXml(cod_manifesto, cod_filial) = False then
   begin
      MessageDlg('Atenção'+#13+#10+''+#13+#10+'O arquivo XML com as informações do MDFe não foi encontrado na pasta '+#13+#10+'do sistema'+#13+#10+''+#13+#10+'Selecione o arquivo manualmente', mtWarning, [mbOK], 0);

      OpenDialog1.Title      := 'Selecione o MDFe';
      OpenDialog1.DefaultExt := '*-MDFe.xml';
      OpenDialog1.Filter     := 'Arquivos MDFe (*-mdfe.xml)|*-mdfe.xml|Arquivos XML (*.xml)|*.xml|Todos os Arquivos (*.*)|*.*';
      OpenDialog1.InitialDir := MDFe.Configuracoes.Arquivos.PathSalvar;

      if not OpenDialog1.Execute then
        Exit;

      MDFe.Manifestos.Clear;
      MDFe.Manifestos.LoadFromFile(OpenDialog1.FileName);
   end;

   with MDFe.EventoMDFe.Evento.Add do
    begin
       infEvento.chMDFe   := Copy(MDFe.Manifestos.Items[0].MDFe.infMDFe.ID, 5, 44);
       infEvento.CNPJCPF  := Dados.qrFilial.FieldByName('cnpj').AsString;
       infEvento.dhEvento := now;
       infEvento.tpEvento   := teCancelamento;
       infEvento.nSeqEvento := 1;

       infEvento.detEvento.nProt := MDFe.Manifestos.Items[0].MDFe.procMDFe.nProt;
       infEvento.detEvento.xJust := Motivo;
    end;

   MDFe.EnviarEvento( 1 ); // 1 = Numero do Lote

   MDNFe_Gravar_Protocolo_Cancelamento(cod_manifesto, cod_filial, Motivo);

end;

procedure TDMNFE.DataModuleCreate(Sender: TObject);
begin
  LeConfiguracoesNFe;
end;

procedure TDMNFE.NFe_CartaCorrecaoEletronica(cod_nf, cod_filial_nf, cod_carta_correcao, cod_filial_carta_correcao : Integer);
var iNumItem : Integer;

begin
   //======================= Gera a carta e correcao eletronica para a NFe ======================
   { É importante saber que a última carta de correção enviada substitui as anteriores,
     portanto a última deve sempre conter todas as correções, mesmo as já enviadas.              }

   qrCartaCorrecao.Close;
   qrCartaCorrecao.ParamByName('codCartaCorrecao').Value  := cod_carta_correcao;
   qrCartaCorrecao.ParamByName('codFilialCarta').Value    := cod_filial_carta_correcao;
   qrCartaCorrecao.Open;

   NFe.EventoNFe.Evento.Clear;

   CarregarXml(cod_nf);

   with NFe.EventoNFe.Evento.new do
   begin
      infevento.chNFe := Copy(NFe.NotasFiscais.Items[0].NFe.infNFe.Id, 4, 44);;
      infEvento.CNPJ  := Dados.qrFilial.FieldByName('cnpj').AsString;

      infEvento.dhEvento := now;
      infEvento.tpEvento := teCCe;
      infEvento.nSeqEvento := 1;

      //======================= Carrega a carta de correção e add os itens corrigidos no xml ======================

      iNumItem := 0;
      while not qrCartaCorrecao.Eof do
      begin

         if (Trim( qrCartaCorrecao.FieldByName('ALTERADO_PARA').AsString) = '') or
            (Trim( qrCartaCorrecao.FieldByName('XML_GRUPO').AsString) = '') or
            (Trim( qrCartaCorrecao.FieldByName('XML_CAMPO').AsString) = '') then
         begin
            qrCartaCorrecao.Next;
            Continue;
         end;

         NFe.EventoNFe.Evento.Items[0].InfEvento.detEvento.xCorrecao := qrCartaCorrecao.FieldByName('ALTERADO_PARA').AsString;

         qrCartaCorrecao.Next;
      end;

   end;

   Nfe.EnviarEvento(1);

   //================= Grava o protocolo de cancelamento ==============
   DataModulo.Dados.script.SQL.Clear;
   DataModulo.Dados.script.SQL.Add(' UPDATE CARTA_CORRECAO SET CARTA_CORRECAO.PROTOCOLO_TRANSMISSAO ='+QuotedStr(Nfe.WebServices.EnvEvento.EventoRetorno.retEvento.Items[0].RetInfEvento.nProt));
   DataModulo.Dados.script.SQL.Add('                         , CARTA_CORRECAO.DATA_TRANSMISSAO = CURRENT_DATE ');
   DataModulo.Dados.script.SQL.Add(' WHERE CARTA_CORRECAO.COD_CARTA_CORRECAO = ' + IntToStr(cod_carta_correcao) );
   DataModulo.Dados.script.SQL.Add('    AND CARTA_CORRECAO.COD_FILIAL_GERACAO = '+  IntToStr(cod_filial_carta_correcao));
   DataModulo.Dados.script.Execute;

end;

end.
