Ir para conteúdo
Fórum Script Brasil
  • 0

Problemas com InternalCalc


SCIENTIST

Pergunta

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 ?

Editado por SCIENTIST
Link para o comentário
Compartilhar em outros sites

21 respostass a esta questão

Posts Recomendados

  • 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 para o comentário
Compartilhar em outros 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 para o comentário
Compartilhar em outros 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 para o comentário
Compartilhar em outros 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).

Editado por SCIENTIST
Link para o comentário
Compartilhar em outros 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 para o comentário
Compartilhar em outros 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 para o comentário
Compartilhar em outros 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 para o comentário
Compartilhar em outros 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 para o comentário
Compartilhar em outros 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 para o comentário
Compartilhar em outros 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 para o comentário
Compartilhar em outros 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 para o comentário
Compartilhar em outros 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 para o comentário
Compartilhar em outros 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 para o comentário
Compartilhar em outros 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 para o comentário
Compartilhar em outros sites

Participe da discussão

Você pode postar agora e se registrar depois. Se você já tem uma conta, acesse agora para postar com sua conta.

Visitante
Responder esta pergunta...

×   Você colou conteúdo com formatação.   Remover formatação

  Apenas 75 emoticons são permitidos.

×   Seu link foi incorporado automaticamente.   Exibir como um link em vez disso

×   Seu conteúdo anterior foi restaurado.   Limpar Editor

×   Você não pode colar imagens diretamente. Carregar ou inserir imagens do URL.



  • Estatísticas dos Fóruns

    • Tópicos
      152,1k
    • Posts
      651,8k
×
×
  • Criar Novo...