Controlar Transação de Informações Client DataSet
Amigos, tenho um sistema de controle de estoque que irei utilizar em rede, utilizo para acesso ao banco os componentes: SqlDataSet, ClientDataSet e DataSetProvider, minha dúvida é o seguinte (ex): na minha tela de saída de itens a medida que estou adicionando os itens (produtos), ao adicionar, antes de dar um post na tabela itens, localizo o produto na tabela produto pego o campo estoque(campo da tabela Produto) e subtraio a quantidade de saída e em seguida efetuo um post nas tabelas produtos e itemsaída. Depois que termino de lançar os itens é que confirmo com o ApplyUpdates(0), para a tabela itens e a tabela produtos.
Daí vem um problema, e se outro usuário estiver editando a tabela produto ou até mesmo dando saída no estoque e efetuar um ApplyUpdates(0) na tabela produto antes que eu, daí se eu cancelar a saída vai dar “BO” no estoque né.. já que o applyUpdates na tabela produto foi efetuado por outra pessoa.
QUAL A MELHOR FORMA DE SE TRABALHAR COM ESSA SITUAÇÃO.
Pensei em trabalhar com a tabela produto apenas na confirmação, ou seja dar baixa no estoque só depois de lançar os itens e confirmar através de um evento (botão), mas daí vem a questão, e se após eu ter confirmado (ApplyUpdates(0)), eu querer editar um item ? que devo fazer.
Obrigado..
Antonio Neto
Curtidas 0
Respostas
Emerson Nascimento
04/02/2010
se você trabalha com SGBDR, faça a movimentação de estoque através triggers - e stored procedures, se necessário.
GOSTEI 0
Antonio Neto
04/02/2010
caro EMERSON, uso sim SGBDR estou utilizando o firebird, é uma boa sim essa sua idéia, (triggers - e stored procedures), só me responde uma coisa... em que momento eu devo chamar esse procedimento, quando estiver adicionando o item? obrigado.
ps. se possível fico grato por uma orientação sua.
Neto
ps. se possível fico grato por uma orientação sua.
Neto
GOSTEI 0
Emerson Nascimento
04/02/2010
use triggers (gatilhos) que deverão ser disparadas quando você grava um item (seja por inclusão ou por alteração).
não sei em que ramo de negócio você atua, mas não é normal haver alteração numa saída de produto.
geralmente cancela-se o item e cria-se um novo; no caso de pedidos de venda que depois geram notas fiscais, o processo de movimentação do estoque ocorre no momento da geração da nota fiscal.
de qualquer forma, no caso de alteração, basta você fazer uma continha para que o resultado dê certo:
- obtenha a quantidade do item ANTES da alteração.
- ao gravar, calcule a diferença entre a quantidade anterior e a nova quantidade
qtdmov = qtdatual - qtdanterior
- e, finalmente, faça a retirada do estoque
estoque = estoque - qtdmov
lembrando que triggers são disparados automaticamente. você deve definir o momento do disparo (ao incluir, ao alterar, ao excluir) quando criar o trigger.
não sei em que ramo de negócio você atua, mas não é normal haver alteração numa saída de produto.
geralmente cancela-se o item e cria-se um novo; no caso de pedidos de venda que depois geram notas fiscais, o processo de movimentação do estoque ocorre no momento da geração da nota fiscal.
de qualquer forma, no caso de alteração, basta você fazer uma continha para que o resultado dê certo:
- obtenha a quantidade do item ANTES da alteração.
- ao gravar, calcule a diferença entre a quantidade anterior e a nova quantidade
qtdmov = qtdatual - qtdanterior
- e, finalmente, faça a retirada do estoque
estoque = estoque - qtdmov
lembrando que triggers são disparados automaticamente. você deve definir o momento do disparo (ao incluir, ao alterar, ao excluir) quando criar o trigger.
GOSTEI 0
Antonio Neto
04/02/2010
Grande Emerson valeu pelas diacas, o sistema é um controle de estoque interno sem rotinas para vendas etc, apenas possui funções para saída, entrada e retorno (o material saíu do estoque mas pode retornar), utilizavamos ele em apenas um micro que ficava no almoxarifado (funcionava que uma maravilha), agora preciso utiliza-lo em rede, e programei daquela forma que falei no primeiro tópico, daí observei que daria pau no estoque. Ja trabelhei com procedimentos direto no banco, mas em rotinas simples como em um cadastro normal, sem depender de relacionamentos (master detalhe..). eu até entendi a suas dicas, mas me responde uma coisa, Se todas as vezes que estou lançando um item a trigger vai se encarregar de dar baixa no estoque e atualizar sem a necessidade de forçar um ApplyUpdates(0) isso num deixa o sistema mais lento, ou não? ja que todos os itens q forem lançados ja vão ser atualizados no momento do lançamento?
ah!!! e no caso da alteração a "continha" tem que ser efetuada no banco tbm?
Obrigado novamente.
ah!!! e no caso da alteração a "continha" tem que ser efetuada no banco tbm?
Obrigado novamente.
GOSTEI 0
Emerson Nascimento
04/02/2010
o trigger será disparado após o ApplyUpdates.
a conta deverá ser feita no trigger, para que seja gravado o valor correto no saldo do produto.
a conta deverá ser feita no trigger, para que seja gravado o valor correto no saldo do produto.
GOSTEI 0
Antonio Neto
04/02/2010
Grande Emerson, fiz as modificações e estou testando o sistema na
mesma maquina, abrindo ele duas vezes o programa. E Cadastros duas movimentações simultâneas.
Com as mesmas informações de item, (o mesmo produto nos dois cadastro). Quando mando
gravar, somente um cadastro dar baixa no
estoque (o que foi chamado primeiro), o outro não dar baixa no estoque. Mas se
cadastro com itens diferente n tem problema funciona legal para os dois
cadastro.
Será que eu utilizando na rede esse problema não vai
existir?
Obrigado
Neto.
GOSTEI 0
Perivaldo Martins
04/02/2010
Creio que vc deveria pesquisar sobre nivel de isolamento, já que pretende rodar seu sistema em rede.
Boa sorte e bons códigos.
GOSTEI 0
Marco Salles
04/02/2010
Citação de Neto"Quando mando gravar, somente um cadastro dar baixa no estoque (o que foi chamado primeiro), o outro não dar baixa no estoque. Mas se cadastro com itens diferente n tem problema funciona legal para os dois cadastro.
Será que eu utilizando na rede esse problema não vai existir? "
Configuração do Provider Flags Não ??????
como é citação neste editor ??????
GOSTEI 0
Emerson Nascimento
04/02/2010
se vc fez via trigger não tem como dar erro. a menos que o trigger esteja errado.
GOSTEI 0
Marco Salles
04/02/2010
Ola Emersom tudo bem.
Talves eu não tenha entendido por não acompanhar o tópico do inicio ,
mas acredito que configurando de modo equivocado o provider Flags não se
executa um applayUpdates e portando não se executa a Triger . Se fosse problema
de codificação da triger ele não conseguiria ter resultado nenhum . E ele relata somente
qns se esta modificando , alteranso o mesmo registro . Nesta situação acredito que um erro
esta sendo propagado e arriscaria nas configurações do Provider
Peço para colocar o evento ReconcileError do clientDataSet , para obeservar a mensagem lançada
a partir desta teremos opiniões mais precissas acerca do problema . Mas arrisco no ProviderFlags
GOSTEI 0
Emerson Nascimento
04/02/2010
tudo beleza, MARCO SALLES?
realmente, se houve algum equivoco na configuração dos providerflag's, poderá ocasionar algum erro na gravação do registro. mas creio que não houve qualquer alteração e, portanto, todos os campos serão usados na montagem das queries. sendo assim, pode não haver erro na gravação, pois ele não acusa erro na gravação do registro, e sim na alteração do saldo na tabela produto (a gravação ocorre numa tabela de itens de venda).
realmente, se houve algum equivoco na configuração dos providerflag's, poderá ocasionar algum erro na gravação do registro. mas creio que não houve qualquer alteração e, portanto, todos os campos serão usados na montagem das queries. sendo assim, pode não haver erro na gravação, pois ele não acusa erro na gravação do registro, e sim na alteração do saldo na tabela produto (a gravação ocorre numa tabela de itens de venda).
GOSTEI 0
Marco Salles
04/02/2010
Sim , mas leia novamente o Relato dele
Citação
"Com as mesmas informações de item, (o mesmo produto nos dois cadastro). "
Isto é , ele esta simulando um ambiente de Rede , aonde se abre o mesmo Registro
Vai um e altera dar o applayUpdates a Triger entra em ação e Atualiza ( faz o que tem que fazer)
Porém para o segundo usário na hora do TDataSetProvider do resolving , teremos valores
difentes na montagem desta queries , exatamente pela razão citada por vc:
Citação de Emerson
"todos os campos serão usados na montagem das queries."
Provavelmente ele esta configurando os Provider Flas com [pfInUpdate,pfInWhere] e o
TDataSetProvider a propriedade UpdateMode em upWhereAll
Esta é a minha sugestão....
GOSTEI 0
Emerson Nascimento
04/02/2010
não, MARCOS. ele não abre o mesmo registro.
ele está fazendo duas vendas, uma em cada instância do sistema, utilizando o mesmo produto, para simular o ambiente de rede.
isso me dá a entender que ele grava as duas vendas (tabela itens de venda), porém apenas uma delas movimenta o estoque (tabela produtos). se as duas vendas foram gravadas, não há problema de providerflags.
pelo menos foi isso que eu entendi.
ele está fazendo duas vendas, uma em cada instância do sistema, utilizando o mesmo produto, para simular o ambiente de rede.
isso me dá a entender que ele grava as duas vendas (tabela itens de venda), porém apenas uma delas movimenta o estoque (tabela produtos). se as duas vendas foram gravadas, não há problema de providerflags.
pelo menos foi isso que eu entendi.
GOSTEI 0
Emerson Nascimento
04/02/2010
desculpe, MARCO, grafei seu nome errado.
GOSTEI 0
Antonio Neto
04/02/2010
Amigos.. obrigado a todos pela ajuda. Não sei se estar correto, mas como utilizo o clientDataSet, e ele quando "aberto" buscas os registros e deixa em memória, percebi que ele estava buscando o valor do estoque na memoria, e quando eu adicionama o mesmo item em dois lançamentos ao mesmo tempo, e como o estoque que estava em memória era igual para todos os lançamentos o sistema dava baixa igualmente para as duas movimentações, porém os cálculos eram o mesmo, ja que o estoque em memória eram os mesmos para as dois lançamentos.(tabela ficava desatualizada) Deu pra etender?. Percebendo isso utilize o RefreshRecord na tabela produto e funcionou, Deixe em aberto este chamado para discurção, SERÁ QUE ESTE MÉTODO DE REFRESHRECORD está correto..
Obrigado a Todos novamente.
Obrigado a Todos novamente.
GOSTEI 0
Emerson Nascimento
04/02/2010
por essas e outras que o melhor é fazer com trigger. porque a informação será fiel, pois trará os dados diretamente do BD, não de um dataset em memória.
mais uma vez recomendo: utilize trigger e pare de se preocupar com o dataset aberto no programa. deixe tudo a cargo do banco de dados.
mais uma vez recomendo: utilize trigger e pare de se preocupar com o dataset aberto no programa. deixe tudo a cargo do banco de dados.
GOSTEI 0
Antonio Neto
04/02/2010
Então caro Emerson, pensei sim em usar trigger, porém caí na seguinte. E se um dia eu quiser mudar de banco tipo uso hj. o firebird 2.0 daí quero uma mudança para o Oracle, vou ter que refazer tbm todas as trigger, no banco. o que n acontece com o código no sistema.. tem os prós e os contras... mas vou sim testar sua dica usar trigger. O porem que o sistema é muito cheio de regras com entradas, saídas e retorno de mercadoria, daí vou ter que estudar bem a questão dessas trigger..
brigado pelas dicas.
brigado pelas dicas.
GOSTEI 0
Emerson Nascimento
04/02/2010
outra forma de obter o resultado correto é fazer a atualização do estoque sem qualquer preocupação com o valor anterior.
assim:
update PRODUTO set ESTOQUE = ESTOQUE - :quantidadevendida where CODIGO = :produtovendido
dessa forma, a quantidade vendida será subtraída do saldo em estoque, independente de quanto havia ali.
da forma como você faz é um tanto insegura, justamente por ter o saldo previamente lido.
assim:
update PRODUTO set ESTOQUE = ESTOQUE - :quantidadevendida where CODIGO = :produtovendido
dessa forma, a quantidade vendida será subtraída do saldo em estoque, independente de quanto havia ali.
da forma como você faz é um tanto insegura, justamente por ter o saldo previamente lido.
GOSTEI 0
Alison Bissoli
04/02/2010
Costumo armazenar todo o detalhamento em xml de um clientdataset sem ligação à SGBDR, para depois que o usuário criar todos os registros eu poder gravar um por um passando-os para o cds ligado ao banco. Somente pego número sequencial ao gravar, nunca ao clicar em incluir a nota, porque dessa forma "impede" que o sistema tente gravar duas notas com o mesmo número. Quanto à triggers são uma boa mesmo, desde que bem escritas, uma trigger errada pode dar muita dor de cabeça.
GOSTEI 0