Mudar uma função para uma Stored Procedure?

Firebird

25/04/2010

Pessoal, estou usando esta função aqui para gerar parcelas

function _Automaticamente_Receber._GerarRegistros(ANumParcelas,  ANumDias: Integer): Boolean;
var
  I, Dias, tot_parc, t_parcelas : Integer;
  nr_doc, client, cont_contab, nomecontacontab, Histor, str_TipoDevedor, strParcelas : String;
  dt_lanc, dt_doc : TDateTime;
  vl_total, vl_parcela : Real;
begin

  Result := False;
  with dm.contasreceber do  //Busca o dataset do datamodule
  begin
    try
      Dias             := 1;
      if trim(lbldtlcto.Caption) = '' then
         dt_lanc       := now
      else
         dt_lanc       := StrTodate(lbldtlcto.Caption);

      nr_doc           := lblnrdoc.Caption;

      if trim(lbldtdoc.Caption) = '' then
         dt_doc        := now
      else
         dt_doc        := StrToDate(lbldtdoc.Caption);

      client           := lblcliente.Caption;

      cont_contab      := lblcontacontabil.Caption;

      nomecontacontab  := lblnomecontabil.Caption;

      tot_parc         := StrToInt(lbltotalparcelas.Caption);

      vl_total         := StrToCurr(lblvltotal.Caption);

      //vl_parcela       := StrToCurr(lblvlparcelas.Caption);
      
      Histor           := lblhistorico.Text;

      {:Faço um laço aqui}
      t_parcelas := 0;
      {:variavel recebendo o valor do form frmCadContasaPagar}
      str_TipoDevedor := dm.contasreceberTIPO_DEVEDOR.AsString;

      for I := 1 to ANumParcelas do
      begin
         Dias := I * ANumDias;
         with qryLocal do // aqui estou usando uma query local em cache
         begin
           {:Gera + 1 a cada vez que passa no laço}
           t_parcelas  := t_parcelas + 1;
           strParcelas := IntToStr(t_parcelas);
           if qryLocal.Active = False then
              qryLocal.Active := true;
           Append;
           FieldByName('DTLANCAMENTO').AsDateTime      := dt_lanc;
           FieldByName('TIPO_DEVEDOR').asString        := str_TipoDevedor;
           FieldByName('NUMERO_DOCUMENTO').asString    := nr_doc+'/'+strParcelas;
           FieldByName('NUMERO_PARCELA').asString      := strParcelas;
           FieldByName('DTEMISSAO').AsDateTime         := dt_doc;
           FieldByName('IDCLIENTE').AsInteger          := DM.contasreceberIDCLIENTE.AsInteger; //TODO: aqui preciso verificar
           FieldByName('CLIENTE').AsString             := client;
           FieldByName('CONTA_CONTABIL').AsString      := cont_contab;
           FieldByName('NOMECONTACONTABIL').AsString   := nomecontacontab;
           FieldByName('TOTAL_PARCELAS').AsInteger     := tot_parc;
           FieldByName('VALOR_TOTAL').AsCurrency       := vl_total;
           //calculo da parcela
           vl_parcela := (vl_total / tot_parc) ; //O calculo é o total da fatura / pela quantidade de parcelas
           FieldByName('VALOR_DA_PARCELA').AsCurrency  := vl_parcela;
           FieldByName('HISTORICO').AsString           := histor;
           FieldByName('LIQUIDADO').AsString           := 'N';
           FieldByName('BLOQUEADO').AsString           := 'N';
           if cb1.Checked = True then
              FieldByName('DTVENCIMENTO').AsDateTime   := IncMonth(dt_doc, I)
           else
              FieldByName('DTVENCIMENTO').AsDateTime   := dt_doc + Dias;
           FieldByName('DATAUSER').AsDateTime          := Date;
           FieldByName('VALOR_PAGO').AsCurrency        := 0.00; //SOMENTE QUANDO PAGAR (BAIXA)
//           FieldByName('VALOR_DUPLICATA').asCurrency   := StrToCurr(lblvlparcelas.Caption);
           {ABAIXO FAÇO OS CALCULOS CFE SOLICITADO}
           FieldByName('CALCULA_JUROS').AsCurrency     := StrToCurr(JvSpinEdit1.Text);
           if trim(JvSpinEdit1.Text) = '' then
              FieldByName('VALOR_JUROS').AsCurrency    := 0.00
           else
              if RadioGroup1.ItemIndex = 0 then
                 FieldByName('VALOR_JUROS').AsCurrency    := (FieldByName('VALOR_TOTAL').AsCurrency * FieldByName('CALCULA_JUROS').AsCurrency /100)
              else if RadioGroup1.ItemIndex = 1 then
                 FieldByName('VALOR_JUROS').AsCurrency    := (FieldByName('VALOR_DA_PARCELA').AsCurrency * FieldByName('CALCULA_JUROS').AsCurrency /100);
           // CALCULO MORA
           FieldByName('CALCULA_MORA').AsCurrency      := StrToCurr(JvSpinEdit2.Text);
           if trim(JvSpinEdit2.Text) = '' then
              FieldByName('VALOR_MORA').AsCurrency     := 0.00
           else
              if RadioGroup1.ItemIndex = 0 then
                 FieldByName('VALOR_MORA').AsCurrency  := (FieldByName('VALOR_TOTAL').AsCurrency * FieldByName('CALCULA_MORA').AsCurrency /100)
              if RadioGroup1.ItemIndex = 1 then
                 FieldByName('VALOR_MORA').AsCurrency  := (FieldByName('VALOR_DA_PARCELA').AsCurrency * FieldByName('CALCULA_MORA').AsCurrency /100);
           // CALCULO DESCONTO
           FieldByName('CALCULA_DESCONTO').AsCurrency  := StrToCurr(JvSpinEdit3.Text);
           if trim(JvSpinEdit3.Text) = '' then
              FieldByName('VALOR_DESCONTO').AsCurrency:= 0.00
           else
              if RadioGroup1.ItemIndex = 0 then
                 FieldByName('VALOR_DESCONTO').AsCurrency  := (FieldByName('VALOR_TOTAL').AsCurrency * FieldByName('CALCULA_DESCONTO').AsCurrency /100)
              if RadioGroup1.ItemIndex = 1 then
                 FieldByName('VALOR_DESCONTO').AsCurrency  := (FieldByName('VALOR_DA_PARCELA').AsCurrency * FieldByName('CALCULA_DESCONTO').AsCurrency /100);

           if CheckBox1.Checked = true then
              FieldByName('CK_calcula_juros').AsString    := 'S';
           if CheckBox2.Checked = true then
              FieldByName('CK_calcula_mora').AsString     := 'S';
           if CheckBox3.Checked = true then
              FieldByName('CK_calcula_desconto').AsString := 'S';
           if CheckBox4.Checked = true then
              FieldByName('gerar_boleto').AsString        := 'S';
           if CheckBox5.Checked = true then
              FieldByName('gerar_duplicata').AsString     := 'S';

           FieldByName('idempresas').asinteger := StrToInt( frmprincipal.lblidempr.caption ); //grava a ID da empresa
           // GRAVA
           Post;
           ApplyUpdates(0);
           Close;
           Open;
         end;
      end;
      dm.connection.Commit;
      pt_MessageDlg('Processo efetuado com sucesso.', mtInformation, [mbOK], 0);
      Result := True;
    except
      on E: Exception do
      begin
        dm.connection.Rollback;
        pt_MessageDlg('Ocorreu um erro neste processo. ' +#13#13 +'Erro gerado: '+#13+
        E.Message + #13#13 + 'Todo o processo foi abortado!', mtError, [mbOk],0);
        Result := False;
      end;
    end;
  end;

end;
Mais esta muito lento quando preciso gerar umas 20 parcelas por exemplo, e gostaria de saber se tem como eu fazer isso tudo por uma Stored Procedure, e se tiver gostaria de um pequeno exemplo para eu poder começar a desenvolver ...

Muito obrigado...

Adriano Dolce

Adriano Dolce

Curtidas 0

Respostas

Emerson Nascimento

Emerson Nascimento

25/04/2010

claro que é possível fazer com stored procedure, mas tente modificar sua procedure de modo a ficar assim:

function _Automaticamente_Receber._GerarRegistros(ANumParcelas,  ANumDias: Integer): Boolean;
var
  I, Dias, tot_parc, t_parcelas : Integer;
  nr_doc, client, cont_contab, nomecontacontab, Histor, str_TipoDevedor, strParcelas: String;
  dt_lanc, dt_doc : TDateTime;
  vl_total, vl_parcela : Real;
begin
  Result := False;
  with dm.contasreceber do  //Busca o dataset do datamodule
  begin
    try
      Dias             := 1;
      if trim(lbldtlcto.Caption) = '' then
         dt_lanc       := now
      else
         dt_lanc       := StrTodate(lbldtlcto.Caption);

      nr_doc           := lblnrdoc.Caption;

      if trim(lbldtdoc.Caption) = '' then
         dt_doc        := now
      else
         dt_doc        := StrToDate(lbldtdoc.Caption);

      client           := lblcliente.Caption;

      cont_contab      := lblcontacontabil.Caption;

      nomecontacontab  := lblnomecontabil.Caption;

      tot_parc         := StrToInt(lbltotalparcelas.Caption);

      vl_total         := StrToCurr(lblvltotal.Caption);

      //vl_parcela       := StrToCurr(lblvlparcelas.Caption);
    
      Histor           := lblhistorico.Text;

      {:Faço um laço aqui}
      t_parcelas := 0;
      {:variavel recebendo o valor do form frmCadContasaPagar}
      str_TipoDevedor := dm.contasreceberTIPO_DEVEDOR.AsString;

      with qryLocal do // aqui estou usando uma query local em cache
      begin
        close;
        // qualquer instrução que não retorne registros
        sql := 'select * from tabelaparcelas where idcliente is null and valor_total is null';
        open;
      end;

      for I := 1 to ANumParcelas do
      begin
         Dias := I * ANumDias;
         with qryLocal do // aqui estou usando uma query local em cache
         begin
           {:Gera + 1 a cada vez que passa no laço}
           strParcelas := IntToStr( I );
           Append;
           FieldByName('DTLANCAMENTO').AsDateTime      := dt_lanc;
           FieldByName('TIPO_DEVEDOR').asString        := str_TipoDevedor;
           FieldByName('NUMERO_DOCUMENTO').asString    := nr_doc+'/'+strParcelas;
           FieldByName('NUMERO_PARCELA').asString      := strParcelas;
           FieldByName('DTEMISSAO').AsDateTime         := dt_doc;
           FieldByName('IDCLIENTE').AsInteger          := DM.contasreceberIDCLIENTE.AsInteger; //TODO: aqui preciso verificar
           FieldByName('CLIENTE').AsString             := client;
           FieldByName('CONTA_CONTABIL').AsString      := cont_contab;
           FieldByName('NOMECONTACONTABIL').AsString   := nomecontacontab;
           FieldByName('TOTAL_PARCELAS').AsInteger     := tot_parc;
           FieldByName('VALOR_TOTAL').AsCurrency       := vl_total;
           //calculo da parcela
           vl_parcela := (vl_total / tot_parc) ; //O calculo é o total da fatura / pela quantidade de parcelas
           FieldByName('VALOR_DA_PARCELA').AsCurrency  := vl_parcela;
           FieldByName('HISTORICO').AsString           := histor;
           FieldByName('LIQUIDADO').AsString           := 'N';
           FieldByName('BLOQUEADO').AsString           := 'N';
           if cb1.Checked then
              FieldByName('DTVENCIMENTO').AsDateTime   := IncMonth(dt_doc, I)
           else
              FieldByName('DTVENCIMENTO').AsDateTime   := dt_doc;
           FieldByName('DATAUSER').AsDateTime          := Date;
           FieldByName('VALOR_PAGO').AsCurrency        := 0.00; //SOMENTE QUANDO PAGAR (BAIXA)
//           FieldByName('VALOR_DUPLICATA').asCurrency   := StrToCurr(lblvlparcelas.Caption);
           {ABAIXO FAÇO OS CALCULOS CFE SOLICITADO}
           FieldByName('CALCULA_JUROS').AsCurrency     := StrToCurr(JvSpinEdit1.Text);
           if trim(JvSpinEdit1.Text) = '' then
              FieldByName('VALOR_JUROS').AsCurrency    := 0.00
           else
              if RadioGroup1.ItemIndex = 0 then
                 FieldByName('VALOR_JUROS').AsCurrency    := (vl_total * FieldByName('CALCULA_JUROS').AsCurrency /100)
              else if RadioGroup1.ItemIndex = 1 then
                 FieldByName('VALOR_JUROS').AsCurrency    := (vl_parcela * FieldByName('CALCULA_JUROS').AsCurrency /100);
           // CALCULO MORA
           FieldByName('CALCULA_MORA').AsCurrency      := StrToCurr(JvSpinEdit2.Text);
           if trim(JvSpinEdit2.Text) = '' then
              FieldByName('VALOR_MORA').AsCurrency     := 0.00
           else
              if RadioGroup1.ItemIndex = 0 then
                 FieldByName('VALOR_MORA').AsCurrency  := (vl_total * FieldByName('CALCULA_MORA').AsCurrency /100)
              if RadioGroup1.ItemIndex = 1 then
                 FieldByName('VALOR_MORA').AsCurrency  := (vl_parcela * FieldByName('CALCULA_MORA').AsCurrency /100);
           // CALCULO DESCONTO
           FieldByName('CALCULA_DESCONTO').AsCurrency  := StrToCurr(JvSpinEdit3.Text);
           if trim(JvSpinEdit3.Text) = '' then
              FieldByName('VALOR_DESCONTO').AsCurrency:= 0.00
           else
              if RadioGroup1.ItemIndex = 0 then
                 FieldByName('VALOR_DESCONTO').AsCurrency  := (vl_total * FieldByName('CALCULA_DESCONTO').AsCurrency /100)
              if RadioGroup1.ItemIndex = 1 then
                 FieldByName('VALOR_DESCONTO').AsCurrency  := (vl_parcela * FieldByName('CALCULA_DESCONTO').AsCurrency /100);

           if CheckBox1.Checked = true then
              FieldByName('CK_calcula_juros').AsString    := 'S';
           if CheckBox2.Checked = true then
              FieldByName('CK_calcula_mora').AsString     := 'S';
           if CheckBox3.Checked = true then
              FieldByName('CK_calcula_desconto').AsString := 'S';
           if CheckBox4.Checked = true then
              FieldByName('gerar_boleto').AsString        := 'S';
           if CheckBox5.Checked = true then
              FieldByName('gerar_duplicata').AsString     := 'S';

           FieldByName('idempresas').asinteger := StrToInt( frmprincipal.lblidempr.caption ); //grava a ID da empresa
           Post;
         end;
      end;
      qryLocal.ApplyUpdates(0);
      dm.connection.Commit;
      pt_MessageDlg('Processo efetuado com sucesso.', mtInformation, [mbOK], 0);
      Result := True;
    except
      on E: Exception do
      begin
        dm.connection.Rollback;
        pt_MessageDlg('Ocorreu um erro neste processo. ' +#13#13 +'Erro gerado: '+#13+
        E.Message + #13#13 + 'Todo o processo foi abortado!', mtError, [mbOk],0);
        Result := False;
      end;
    end;
    qryLocal.Close;
  end;

end;

note que a alteração consiste em abrir a tabela uma única vez e aplicar as alterações somente ao sair do loop, evitando vários fechamentos e aberturas da mesma tabela.
veja que o applyupdates é dado uma única vez e, depois de tudo, a tabela é fechada, evitando assim vários procedimentos desnecessários.
observe também que, onde eu pude, fiz uso das variáveis, pois economiza processamento, visto que o FieldByName() faz uma varredura na lista de campos em busca do campo solicitado para depois retornar o valor do campo. como a variável já está com o valor desejado em memória, a performance é melhor com a variável.
 
se ainda assim vc achar que ficou lentou ou preferir mesmo que seja com stored procedure, basta solicitar que ajudaremos.


GOSTEI 0
Adriano Dolce

Adriano Dolce

25/04/2010

Bom dia Emerson,

Melhorou bastante a performance, acho que vai ficar assim mesmo....

Mais uma vez muito obrigado....Aprendi mais uma
GOSTEI 0
POSTAR