Jump to content
Fórum Script Brasil
  • 0

Problemas com InternalCalc


SCIENTIST

Question

Bom dia,

Tenho uma Tabela PROJETO (Master), SERVICOS (Detail), PRODUTOS (Detail), COMISSOES (Detail).

Nas Tabelas SERVICOS e PRODUTOS tenho em ambas 1 campo chamado TOTAL (aggregate). Na Tabela PROJETO tenho um InternalCalc chamado TOTAL_GERAL que soma TOTAL DE SERVICOS + TOTAL DE PRODUTOS.

Na Tabela COMISSOES tenho um campo InternalCalc VALOR_PERCENT que pega o TOTAL_GERAL da Tabela PROJETO e retira 10% deste. Aqui ocorre o problema: Identifiquei que os Campos Calculados do Detail são executados primeiro do que do Master, dessa forma eu não tenho como pegar o TOTAL_GERAL se ele ainda nem foi calculado.

Como resolver isso ?

Edited by SCIENTIST
Link to comment
Share on other sites

21 answers to this question

Recommended Posts

  • 0

se voce percebeu, voce deve colocar a coluna a ser calculada primeiro, mais a esquerda

exemplo

a coluna total sera a primeira a efetuar o calculo, em seguida será a de percent ... entendeu ?

quant ------preço--------total-------percent

abraço

Link to comment
Share on other sites

  • 0
Nas Tabelas SERVICOS e PRODUTOS tenho em ambas 1 campo chamado TOTAL (aggregate). Na Tabela PROJETO tenho um InternalCalc chamado TOTAL_GERAL que soma TOTAL DE SERVICOS + TOTAL DE PRODUTOS.

Podemos criar um valor agregado, agrupado, somando com uma expressão agregada de SQL, para isso voce pode usar SQL, SUM, AVG, MAX, MIN ... etc

ao usar a sentença slq, voce vai obter o valor do campo Total_Geral .. correto ?

entretanto, devo supor que suas tabelas entejam relacionadas atraves de um campo comum entre elas

então para que voce tenha o calculo do campo VALOR_PERCENT que esta em outra tabela, é o seu select que tera que definir a posição dos campos ( sequencia dos campos a aparecer em um dbgrid )

abraço

Link to comment
Share on other sites

  • 0

Jhonas, eu sei que posso calcular o TOTAL_GERAL e o VALOR_PERCENT pelo SQL, porém há um grande problema nisso. Se em tempo de execução, o usuário adicionar um SERVIÇO por exemplo, o TOTAL_GERAL não mudará, a não ser que eu de um REFRESH no CLIENTDATASET.

Olha, fiz uma modelagem rapida do meu problema (MER) de uma olhada por gentileza. http://s14.postimage.org/6ifpphef5/imagem_modelagem.png

Link to comment
Share on other sites

  • 0

experimente

The following AfterScroll event handler refreshes the current record every time the user moves to a new record, ensuring the most up-to-date value. Before refreshing a record, however, it checks the update status to avoid refreshing records that have been edited, which would potentially mask update errors.

procedure TForm1.ClientDataSet1AfterScroll(DataSet: TDataSet);
begin
  if ClientDataSet1.UpdateStatus = usUnModified then
    ClientDataSet1.RefreshRecord;
end;

abraço

Link to comment
Share on other sites

  • 0

Bom, deixa eu ver se entendi.

Tenho um determinado registro, se eu não o editar, posso usar o RefreshRecord ? QUal a utilidade disso ? Lembrando que eu preciso que ao adicionar um novo serviço ou produto o valor do TOTAL_GERAL (pego do SQL) seja atualizado automaticamente.

Tem mais uma coisa, o registro (no código acima) só será atualizado se eu mudar de registro (mudar a linha).

Edited by SCIENTIST
Link to comment
Share on other sites

  • 0

um registro ao ser inserido ou modificado deve ser atualizado no banco de dados, o RefreshRecord faz isso somente no registro corrente e não em toda a tabela

veja o help do delphi

Updates the base values of the current record to match the current values of the provider’s dataset.

procedure RefreshRecord;

Description

Call Refresh to change the base values of the current record to match the current value on the server. Refresh replaces the original values obtained from a provider, but leaves any changes in the change log intact.

Warning: RefreshRecord should be used with care. If the user has modified the current record, refreshing the original values may mask update conflicts. When the client application calls ApplyUpdates, no reconcile error will occur, even where this is appropriate.

Note: A similar method, Refresh, replaces the entire contents of the client dataset with the current values supplied by the provider. Unlike RefreshRecord, which leaves unapplied changes in the change log, Refresh raises an exception when the change log is not empty.

Atualiza os valores de base do registro atual para coincidir com os valores atuais de conjunto de dados do provedor.

procedimento RefreshRecord;


descrição

Chamada de atualização para mudar os valores de base do registro atual para coincidir com o valor atual do servidor. Atualizar substitui os valores originais obtidos a partir de um provedor, mas deixa quaisquer alterações no log de alterações intacta.

Aviso: RefreshRecord deve ser usado com cuidado. Se o usuário tenha modificado o registro atual, atualizar os valores originais podem mascarar conflitos de atualização. Quando o aplicativo cliente chama ApplyUpdates, sem conciliar, o erro irá ocorrer, mesmo quando isso é apropriado.

Nota: Um método semelhante, Refresh, substitui todo o conteúdo do conjunto de dados do cliente com os valores atuais fornecidos pelo prestador. Ao contrário RefreshRecord, o que deixa as alterações não aplicadas no log de alterações, Refresh gera uma exceção quando o log de alterações não está vazio.
OBS: Se voce estiver usando o interbase ou firebird pode usar
FMenu.IBTransaction1.Commit;
   FMenu.IBTransaction1.StartTransaction;

abraço

Link to comment
Share on other sites

  • 0

Bom, uso firebird 2.1

Na verdade eu ainda não entendi muito bem como fazer isso. O que eu entendi até agora foi que eu devo calcular o TOTAL_GERAL via SQL e não no InternalCalc, assim devo fazer com o VALOR_PERCENT, já pegar o mesmo calculado pelo SQL e não internalCalc. Porém não entendi onde aplicar o RefreshRecord.

Imagine, o usuário abre a tela de PROJETOS, lá em baixo tem TOTAL GERAL DO PROJETO, então ele adiciona um Serviço e nada acontece com o TOTAL GERAL que deveria mudar. Onde aplico o RefreshRecord para que este TOTAL GERAL que foi calculado pelo SQL mude conforme as alterações.

Se puderes, eu tenho TeamViewer em minha máquina, vocÊ poderia acessar rapidamente só para entender melhor a situação. Posso enviar via Mensagem o ID e SENHA de acesso, claro só se você puder.

Link to comment
Share on other sites

  • 0
Imagine, o usuário abre a tela de PROJETOS, lá em baixo tem TOTAL GERAL DO PROJETO, então ele adiciona um Serviço e nada acontece com o TOTAL GERAL que deveria mudar. Onde aplico o RefreshRecord para que este TOTAL GERAL que foi calculado pelo SQL mude conforme as alterações.

voce esta usando dbgrid ou dbedit para visualizar os campos ?

Link to comment
Share on other sites

  • 0

use o evento OnExit do componente

nesse caso voce pode:

1 - usar outra instrução SQL para efetuar o calculo do campo

2 - dar o refeshrecord na tabela em uso

3 - usar o Commit para atualizar as tabelas

4 - fechar e abrir a tabela novamente

abraço

Link to comment
Share on other sites

  • 0

não vai dar muito certo. Dentro da tela de projetos eu tenho outras telas, como a de adicao de servicos, se eu adiciono um novo servico não tem como fazer estes procedimentos.

Adicionar ou deletar servicos e produtos devem consequentemente alterar o total geral e isso não da pra ser feito no onexit.

Link to comment
Share on other sites

  • 0

acho que se voce seguiu o padrão de programação, voce deve ter um botão OK para salvar as alterações ou inclusões ..certo ?

então faça o calculo nesse botão quando for clicado ou faça o calculo quando exibir os dados no dbgrid ...( sempre que atualizar a tabela )

o seu problema está sendo a demora em atualizar os dados da tabela ?

Link to comment
Share on other sites

  • 0

Vamos la, supondo que eu queria calcular o total geral. então toda vez que eu clicar no botão ok eu deveria somar o total de produtos com o total de serviços. E toda vez que eu calcular o total geral eu devo calcular o valor da percentagem, não seria um processo trabalho e dsspendioso ou e a maneira certa de se trabalhar nesse caso?

Link to comment
Share on other sites

  • 0

ok ... veja que a utilização de campos calculados, voce só usa quando voce não quer que esses calculos fiquem na tabela... ou seja voce quer os calculos somente na memoria e que sejam apresentados ao usuario sempre que houver modificações. ( na verdade o usuario acha que esses calculos estão na tabela )

eu utilizo campos calculados de 2 maneiras:

o calculo é realizado a cada atualização da tabela e é mostrado no dbgrid ( ao fechar a tabela os valores são perdidos)

mas como os valores ainda estão na memoria , posso utilizados inclusive para gerar relatorios.

ou o calculo é efetuado e guardado em um campo da tabela , o que facilita tambem muito a manipulação dos dados

quant ------preço--------total-------percent

E toda vez que eu calcular o total geral eu devo calcular o valor da percentagem, não seria um processo trabalho e dsspendioso ou e a maneira certa de se trabalhar nesse caso?

voce tem que ver qual é a melhor opção para o seu uso ( quantidade de registros trabalhados ou tempo de resposta )

abraço

Link to comment
Share on other sites

  • 0

Bom, dar refresh na tabela resolve porém não acho que seja a solução, pois iremos trabalhar com uma grande quantidade de dados e isso iria deixar o sistema lento.

Não tem como usar o internalCAlc pois não posso calcular o valor da percentagem se eu não tenha o total geral, a única solução possível que me restaé calcular os campos em cada atualização do registro manualmente.

Porém onde eu iria armazenar esses valores? Em um campo calculado? Ou crio um campo internalcalc?

Ps: só para responder sua pergunta, eu prefiro trabalhar com o tempo de resposta, pois o cliente não deseja lentidão no sistema.lento

Link to comment
Share on other sites

  • 0
Bom, dar refresh na tabela resolve porém não acho que seja a solução, pois iremos trabalhar com uma grande quantidade de dados e isso iria deixar o sistema lento.
por isso falei para usar o refreshrecord ( apenas no registro em uso )

Não tem como usar o internalCAlc pois não posso calcular o valor da percentagem se eu não tenha o total geral, a única solução possível que me restaé calcular os campos em cada atualização do registro manualmente.

Porém onde eu iria armazenar esses valores? Em um campo calculado? Ou crio um campo internalcalc?

uma solução seria voce criar esse campo na tabela ... isso pode ser feito via programação, sem a necessidade de pegar o banco de dados do cliente ... coloca o codigo em um botão e o campo é adicionado a tabela ( veja alter table na net )

abraço

Link to comment
Share on other sites

  • 0

voce ainda não entendeu como proceder..

veja o exemplo

procedure TForm1.Button1Click(Sender: TObject);
begin

   // CLOCAR A  INSTRUÇÃO SQL PARA FILTRAR OS REGISTROS PARA CALCULO

   DBGrid1.Visible := false;
   if (CDS_Moviment.RecordCount <> 0) then
      begin
         CurrencyEdit1.Value := 0;
         for i := 1 to CDS_Moviment.RecordCount do
            begin
               CDS_Moviment.Edit;
               CDS_MovimentTOTAL.Value := CDS_MovimentQUANT.Value * CDS_MovimentPRECOV.Value;
               CDS_Moviment.Post;
               CDS_Moviment.ApplyUpdates(-1);

               // calcular o valor de 10 % sobre o valor total
               CDS_MovimentPERCENT.Value := CDS_MovimentTOTAL.Value * 10 / 100; 

               CDS_Moviment.Next;
            end;
         CDS_Moviment.First;
      end;
    DBGrid1.Visible := true;

end;

ai no codigo eu não coloquei, mas voce pode incluir uma instrução sql para filtrar os registros e depois aplicar o calculo

entendeu ?

abraço

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



  • Forum Statistics

    • Total Topics
      152.2k
    • Total Posts
      652.1k
×
×
  • Create New...