Aplicação Multicamadas
Pessoal,
vou começar uma nova aplicação que deverá ser multicamadas e estou com algumas dúvidas.
1) Quero utilizar o mínimo possível de recursos do banco de dados para evitar o acoplamento da aplicação com o banco, mas ainda não aprendi a fazer certas operações via aplicação servidora. Exemplo: Ao realizar uma venda é necessário que faça automaticamente um lançamento de saída na tabela de movimentações de estoque. Atualmente faço isso através de trigger, porém isso cria um vínculo muito forte entre a aplicação e o banco, o que dificulta uma possível migração de um banco para outro. Nos testes que estou fazendo criei um DataModule (descendente de TDSServerModule) no servidor e nele ficará tudo que é relativo a vendas. Nele tenho alguns SQLDataSet's, dentre os quais sdsVenda, sdsVendaItens. Na aplicação cliente, na tela de vendas, tenho os ClientDataSet's para venda e itens da venda. O que não sei fazer é que ao salvar uma venda na aplicação cliente através do ClientDataSet o servidor deverá disparar um método que verifique a disponibilidade de estoque dos itens vendidos, caso haja disponibilidade a venda será confirmada e salva, caso não haja disponibilidade a venda não poderá ser salva e deverá ser emitido um aviso para o usuário. Alguém sabe como fazer esse tipo procedimento?
2) Em relação às regras de negócio, como separar o que deve ficar no lado servidor e o que deve ficar no lado cliente? Exemplo, o cálculo de total do ítem da venda (quantidade * unitario), a validação de CPF/CNPJ deverá ficar em qual aplicação?
Rogerio Corgozinho
Curtidas 0
Respostas
Marco Salles
26/08/2011
1)
O que não sei fazer é que ao salvar uma venda na aplicação cliente através do ClientDataSet o servidor deverá disparar um método que verifique a disponibilidade de estoque dos itens vendidos, caso haja disponibilidade a venda será confirmada e salva, caso não haja disponibilidade a venda não poderá ser salva e deverá ser emitido um aviso para o usuário. Alguém sabe como fazer esse tipo procedimento?
Codifique o evento BeforeUpdateRecor do TDataSetProvider , e gere uma exceção quando este valor for negativo
A codificação vai depender da normalização de seu banco de dados . Saldo esta e qual tabela , tabela Produtos , tabela Venda , tabela Item da Vendas ??? .. Enfim , vc pode analogicamente ao que vc faz na trigues utilizando oldValue e NewValue efetuar
a Regra de negocio..
Vc tem ainda a possibilidade de utilizar o evento onUpdateRecord onde vc recebe o Delta que contem todos os dados
Alterados e Não alterados
Sugiro olhar com carinho este dois eventos seus parametros e partir para esta linha de raciocineo que ha meu ver é a mais indicada neste tipo de arquitetura.
2) Em relação às regras de negócio, como separar o que deve ficar no lado servidor e o que deve ficar no lado cliente? Exemplo, o cálculo de total do ítem da venda (quantidade * unitario), a validação de CPF/CNPJ deverá ficar em qual aplicação?
O que fica no lado do servidor é algo que pode varia com o tempo , e algo sucessivel a mudança. Validar Cnpj , Validar CPF a regra de negocio é fixa , nunca ou dificilemente modificara. para que ocupar o Servidor com estes tipo de calculos ?? ( alem de que são calculos simples que qualquer cliente Magro tem plena condiçoes de fazer ). O mesmo valoe para cálculo de total do ítem da venda (quantidade * unitario), será sempre assim e pode ser feito num campo InternalCalc no lado cliente
GOSTEI 0
Rogerio Corgozinho
26/08/2011
Marco Antonio, obrigado pelas dicas, já estou trabalhando em meu projeto. Agora estou com um pequeno problema, se puder me ajudar.
É o seguinte, preciso salvar no campo CHAVE da tabela de usuários uma combinação de valores que garantirá a autenticidade do mesmo. Para isso coloquei na aplicação servidora o método abaixo, que é disparado sempre que se cadastre ou altere um usuário pela aplicação cliente. O problema é que quando é uma alteração de registro a propriedade NewValue somente é preenchida se houver alterações no respectivo campo. No meu caso, preciso pegar o valor que está no registro afetado pelo ClientDataSet, independentemente de ter sido alterado ou não. Tentei usar Value, AsString e outros mais, porém se o campo não foi alterado todas estas propriedades vem como null.
procedure TsmCadastros.dspUsuariosBeforeUpdateRecord(Sender: TObject;
SourceDS: TDataSet; DeltaDS: TCustomClientDataSet; UpdateKind: TUpdateKind;
var Applied: Boolean);
var Chave : String;
begin
Chave := DeltaDS.FieldByName('LOGIN').NewValue
+ DeltaDS.FieldByName('SENHA').NewValue
+ DeltaDS.FieldByName('BLOQUEADO').NewValue
+ IntToStr(DeltaDS.FieldByName('TIPO').NewValue);
Chave := Chave + DigitoVerificador (Chave);
DeltaDS.FieldByName('CHAVE').NewValue := dmPrincipal.Criptografia.EncodeString(uConsts.ChaveUsuario, chave);
end;
Sabe como posso fazer isso?
É o seguinte, preciso salvar no campo CHAVE da tabela de usuários uma combinação de valores que garantirá a autenticidade do mesmo. Para isso coloquei na aplicação servidora o método abaixo, que é disparado sempre que se cadastre ou altere um usuário pela aplicação cliente. O problema é que quando é uma alteração de registro a propriedade NewValue somente é preenchida se houver alterações no respectivo campo. No meu caso, preciso pegar o valor que está no registro afetado pelo ClientDataSet, independentemente de ter sido alterado ou não. Tentei usar Value, AsString e outros mais, porém se o campo não foi alterado todas estas propriedades vem como null.
procedure TsmCadastros.dspUsuariosBeforeUpdateRecord(Sender: TObject;
SourceDS: TDataSet; DeltaDS: TCustomClientDataSet; UpdateKind: TUpdateKind;
var Applied: Boolean);
var Chave : String;
begin
Chave := DeltaDS.FieldByName('LOGIN').NewValue
+ DeltaDS.FieldByName('SENHA').NewValue
+ DeltaDS.FieldByName('BLOQUEADO').NewValue
+ IntToStr(DeltaDS.FieldByName('TIPO').NewValue);
Chave := Chave + DigitoVerificador (Chave);
DeltaDS.FieldByName('CHAVE').NewValue := dmPrincipal.Criptografia.EncodeString(uConsts.ChaveUsuario, chave);
end;
Sabe como posso fazer isso?
GOSTEI 0
Marco Salles
26/08/2011
Antes de prosseguir , acreidito que esta regra de negocio deve ser testada no Client ..
Finalmente ao comoparar com o digito Verificador , se tudo ocorrer de acordo com a sua lógica proseguir
Afinal essas combinações com Digito Verificador , não são alterados e modificados a Vera
Finalmente ao comoparar com o digito Verificador , se tudo ocorrer de acordo com a sua lógica proseguir
Afinal essas combinações com Digito Verificador , não são alterados e modificados a Vera
GOSTEI 0
Rogerio Corgozinho
26/08/2011
Neste caso acho que a regra pode ficar no servidor, pois o usuário não fará nada com ela e deverá ser gerada automaticamente de acordo com as informações de seu cadastro. Este código que postei é para gerar esta chave que deverá ser testada no momento em que for feito o login, caso o sistema encontre alguma inconsistência não permitirá que o usuário prossiga.
Ainda assim, caso esta regra fique no cliente preciso aprender a recuperar os valores do registro corrente (independentemente de terem sido alterados) para usar em outros regras de negócios que obrigatoriamente ficarão no servidor.
Obrigado pela atenção
Ainda assim, caso esta regra fique no cliente preciso aprender a recuperar os valores do registro corrente (independentemente de terem sido alterados) para usar em outros regras de negócios que obrigatoriamente ficarão no servidor.
Obrigado pela atenção
GOSTEI 0
Marco Salles
26/08/2011
Bem, vc diz:
" O problema é que quando é uma alteração de registro a propriedade NewValue somente é preenchida se houver alterações"
Teste a propriedade UpdateKind , caso se trate de uma alteração de registro a utilize o oldValue , caso se trate de uma inserção
utilize a propriedade NewValue
" O problema é que quando é uma alteração de registro a propriedade NewValue somente é preenchida se houver alterações"
Teste a propriedade UpdateKind , caso se trate de uma alteração de registro a utilize o oldValue , caso se trate de uma inserção
utilize a propriedade NewValue
GOSTEI 0