Você está na página 1de 39

A U L A

Desenvolvendo um Projeto Prático


24 Parte 2
Controle de Estoque, Vendas, Compras e Financeiro.

Construindo o cadastro de Produtos

Assim como o cadastro de clientes e fornecedores o cadastro de produtos é peça


fundamental para a funcionalidade do sistema. Através do cadastro de produtos é que
controlamos o estoque. Este é um cadastro relativamente simples. É composto por dois
formulários. O primeiro formulário é o de navegação e o segundo o do cadastro
propriamente dito.

Crie primeira o formulário de navegação para produtos, baseado na classe navegacao.


Para isso você pode usar o comando:
CREATE FORM forms\lstProdutos As navegacao ;
FROM "c:\cursovfp\classes\formularios.vcx"

Defina as seguintes propriedades para o formulário:

Figura 24.1 – Propriedades do formulário navegação de produtos


A U L A

24
Agora que o formulário está criado e suas principais propriedades estão configuradas,
vamos trabalhar o ambiente de dados, incluindo a tabela de produtos.

4. No menu View, escolha Data Environment para exibir o ambiente de dados.

5. Ao aparecer o ambiente de dados, clique duplamente com o mouse sobre o seu


fundo para abrir o editor de comandos e adicione o seguinte código ao evento
BeforeOpenTables, conforem mostra a figura 24.2:

Figura 24.2 – estabelecendo a conexão com a origem de dados

6. Após adicionar o código acima, feche a janela de edição de código e clique com o
botão direito no fundo do ambiente de dados e escolha Add CursorAdapter... O
builder de CursorAdapter será acionado. Informe as seguintes propriedades na
primeira parte do builder:

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados


A U L A

24

Figura 24.3 – propriedades do CursorAdapter Produtos

7. Observe na figura acima os itens que estão contornados e os defina conforme


estão.

8. Clique na aba 2 do builder e defina as propriedades conforme a figura 24.4:

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados


A U L A

24

Figura 24.4 – propriedades de acesso a dados do CursorAdapter produtos

9. Ao definir as propriedades como as exibidas acima, clique em OK. O cursor estará


pronto para ser utilizado.

10. Para finalizar, você ainda deve substituir o código do evento init do cursoradapter
produtos pelo seguinte código:
local llReturn
do case
case not pemstatus(This, '__VFPSetup', 5)
This.AddProperty('__VFPSetup', 0)
case This.__VFPSetup = 2
This.__VFPSetup = 0
return
endcase
llReturn = dodefault()

* Define que o tipo de acesso será por ADO


this.DataSourceType = "ADO"

* Atribui objeto ADODB.RecordSet ao DataSource do cursor

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados


A U L A

24
this.DataSource = CREATEOBJECT("ADODB.RecordSet")
* 3, AdUseClient
this.DataSource.CursorLocation = 3
* 3, adLockOptmistic
this.DataSource.LockType = 3
This.DataSource.ActiveConnection = This.Parent.oConnection

* Adiciona o objeto ADODB.Command


this.AddProperty("oCommand",CREATEOBJECT("ADODB.Command"))
this.oCommand.ActiveConnection = this.Parent.oConnection

if This.__VFPSetup = 1
This.__VFPSetup = 2
endif
return llReturn

11. Finalmente o cursor está configurado. Podes fechar o ambiente de dados.

12. O próximo passo agora é configurar a tabela do formulário (Grid) para exibir as
colunas formatadas da forma como queremos. Primeriamente clique no objeto
grdLista e defina a propriedade ColumnCount = 5. Isso fará com que a grade fique
ajustada para 5 colunas.

13. Agora devemos ajustar cada coluna individualmente. Para tal, segure a tecla CTRL
e clique sobre a grade. Depois, clique sobre o cabeçalho da coluna, defina o texto
descritivo para cada cabeçalho conforme tabela abaixo:
Coluna Título do Cabeçalho
1 Cód. Produto
2 Descrição do Produto
3 Estoque
4 Unidade
5 Valor Unitário

14. Agora defina as demais propriedades de cada coluna conforme a próxima tabela.
Para definir as propriedades da coluna (não do cabeçalho) você clica com o mouse
em cima do controle interno, na primeira linha abaixo do cabeçalho.
Coluna Propriedades a alterar
1 ControlSource = produtos.id_produto
Width = 87
2 ControlSource = produtos.descricao_produto
Width = 331
3 ControlSource = produtos.qtd_estoque
InputMask
Width = 106
4 ControlSource = produtos.unidade
Width = 83
5 ControlSource = produtos.valor_unitario
InputMask = 99,999.99
Width = 106

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados


A U L A

24
15. Definidas todas as propriedades, o formulário de navegação para produtos estará
pronto, conforme a figura a seguir:

Figura 24.5 – formulário para navegação na tabela de produtos

A primeira etapa para o cadastro de produtos está realizada. O próximo passo é criar o
formulário para inclusão e edição de produtos. Para tal, siga os passos:

1. Crie o formulário baseado na classe edicao da biblioteca de classes conforme


comando abaixo:

CREATE FORM produtos AS edicao FROM


c:\cursovfp\classes\formularios.vcx

2. Assim que a janela Form Designer estiver aberta com o novo formulário criado,
defina as seguintes propriedades:
Propriedade Valor
Caption Cadastro de Produto
Height 362
Name Produtos
Width 553
Campo_sequencial Id_produto

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados


A U L A

24
Comandoprimeirofoco thisform.txtDescricao_produto.SetFocus()

3. Definidas as propriedades básicas do formulário, passemos então a configurar o


acesso a dados do mesmo, abrindo o ambiente de dados. Para abrir o ambiente de
dados, clique no menu View / Data Environment.

4. Ao abrir o ambiente de dados, clique duplo no seu fundo para que seja aberto o
editor de programas. Adicione o código a seguir ao evento BeforeOpenTables():
SET MULTILOCKS ON

* Define que o tipo de acesso será por ADO


this.DataSourceType = "ADO"

* Cria objeto de conexão ADODB.Connection


This.AddProperty("oConnection",CREATEOBJECT("ADODB.Connection"))
* recebe a string de conexão com o banco de dados
This.oConnection.ConnectionString = pStringConexao

* Estabelece a conexão
This.oConnection.Open()

5. O código acima já é nosso velho conhecido e dispensa qualquer comentário. Feche


o editor de códigos.

6. Adicione um novo CursorAdapter e defina as suas propriedades conforme a figura a


seguir:

Figura 24.6 – propriedades do cursoradapter produtos

7. Em seguida, defina as propriedades da aba 2 conforme a próxima figura:

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados


A U L A

24

Figura 24.7 – propriedades de acesso a dados do cursordapter produtos

8. Até aqui não há nenhuma exigência em especial. A próxima tarefa é a mais


importante e deve ser feita com cautela para não correr o risco de dar erros na hora
da gravação dos dados ou dos dados não serem gravados. Sempre que estamos
usando CursorAdapter, quando queremos que os dados que forem inclusos ou
editados sejam persistidos no banco de dados, devemos configurar as próximas
propriedades com bastante cuidado, não esquecendo de informar a chave primária,
os campos que são editáveis, enfim, tudo deve ser especificado corretamente.

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados


A U L A

24

Figura 24.8 – Propriedades de atualização do cursordapter produtos

9. Ao definir todas as propriedades, clique OK. Agora precisamos ajustar o código do


evento Init do cursoradapter produtos. Substitua o código gerado pelo seguinte
código:
LOCAL llReturn
DO CASE
CASE NOT PEMSTATUS(THIS, '__VFPSetup', 5)
THIS.ADDPROPERTY('__VFPSetup', 0)
CASE THIS.__VFPSetup = 2
THIS.__VFPSetup = 0
RETURN
ENDCASE
llReturn = DODEFAULT()

* Define que o tipo de acesso será por ADO


THIS.DATASOURCETYPE = "ADO"

* Atribui objeto ADODB.RecordSet ao DataSource do cursor


THIS.DATASOURCE = CREATEOBJECT("ADODB.RecordSet")

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados


A U L A

24
* 3, AdUseClient
THIS.DATASOURCE.CursorLocation = 3
* 3, adLockOptmistic
THIS.DATASOURCE.LockType = 3
THIS.DATASOURCE.ActiveConnection = THIS.PARENT.oConnection

* Adiciona o objeto ADODB.Command


THIS.ADDPROPERTY("oCommand",CREATEOBJECT("ADODB.Command"))
THIS.oCommand.ActiveConnection = THIS.PARENT.oConnection

*** Setup code: DO NOT REMOVE


***<SelectCmd>
TEXT to This.SelectCmd noshow
select produtos.id_produto, produtos.descricao_produto, produtos.unidade,
produtos.qtd_estoque, produtos.valor_unitario, produtos.minimo_estoque,
produtos.maximo_estoque, produtos.aparecer from produtos
ENDTEXT
***</SelectCmd>
***<KeyFieldList>
TEXT to This.KeyFieldList noshow
ID_PRODUTO
ENDTEXT
***</KeyFieldList>
***<UpdateNameList>
TEXT to This.UpdateNameList noshow
ID_PRODUTO produtos.ID_PRODUTO, DESCRICAO_PRODUTO
produtos.DESCRICAO_PRODUTO, UNIDADE produtos.UNIDADE, QTD_ESTOQUE
produtos.QTD_ESTOQUE, VALOR_UNITARIO produtos.VALOR_UNITARIO,
MINIMO_ESTOQUE produtos.MINIMO_ESTOQUE, MAXIMO_ESTOQUE
produtos.MAXIMO_ESTOQUE, APARECER produtos.APARECER
ENDTEXT
***</UpdateNameList>
***<UpdatableFieldList>
TEXT to This.UpdatableFieldList noshow
ID_PRODUTO, DESCRICAO_PRODUTO, UNIDADE, QTD_ESTOQUE, VALOR_UNITARIO,
MINIMO_ESTOQUE, MAXIMO_ESTOQUE, APARECER
ENDTEXT
***</UpdatableFieldList>
*** End of Setup code: DO NOT REMOVE
IF THIS.__VFPSetup = 1
THIS.__VFPSetup = 2
ENDIF

RETURN llReturn

10. Agora que o acesso a dados está completamente configurado, chega a hora de
posicionarmos os controles no formulário. Para poupar trabalho na associação dos
controles com os campos da tabela, você pode simplesmente arras os campos do
ambiente de dados para a área de desenho do formulário. Você deve posicionar os
campos conforme mostra a próxima figura, sendo que, se necessário você deve
substituir alguns controles.

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados


A U L A

24

Figura 24.9 – layout do formulário de produtos

11. O retângulo que está em volta dos campos é um objeto Shape. Após inseri-lo você
deve enviá-lo para trás dos demais objetos, senão os objetos não recebem o foco
adequadamente. Para enviá-lo para trás, clique sobre o objeto Shape, vá no menu
Format / Send to back.

12. Após o posicionamento dos campos em seus devidos locais, faz-se necessário
também a definição da ordem de tabulação dos mesmos, para que fique agradável
de se trabalhar. Para definir a ordem de tabulação, clique no menu View / Tab
order.

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados


A U L A

24

Figura 24.10 – ordem de tabulação dos controles

13. Observando na figura acima, você pode notar que o campo id_produto encontra-se
em uma cor diferente. Isto se deve ao fato de que o mesmo está desabilitado para
edição. É apenas leitura e sua propriedade Enabled está com o valor .F.. Sempre
defina os campos que o usuário não deve mexer com a propriedade Enabled = .F..

14. Para finalizar o formulário de produtos, devemos fazer a crítica geral para os dados
informados no formulário. Para tal, vamos inserir o seguinte código no método
Criticar() do formulário:
SELECT (thisform.cTabela)

WITH thisform

IF VAZIO(descricao_produto)
MESSAGEBOX("Informe a descrição do produto!";
,0+48,_Screen.Caption)
.txtDescricao_produto.SetFocus()
RETURN .F.
ENDIF

IF VAZIO(unidade)
MESSAGEBOX("Informe a unidade do produto!";
,0+48,_Screen.Caption)
.cboUnidade.SetFocus()
RETURN .F.
ENDIF

IF VAZIO(valor_unitario)
MESSAGEBOX("Informe o valor unitário do produto!";
,0+48,_Screen.Caption)
.txtValor_unitario.SetFocus()
RETURN .F.
ENDIF

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados


A U L A

24
ENDWITH

* Executa o código padrão do método


DODEFAULT()

15. Podemos dizer que a grosso modo nosso formulário está funcional.

Considero de extrema importância lembrar que o objetivo deste curso não é ensinar
a desenvolver um sistema de controle de estoques ou financeiro, mas sim de
ensinar técnicas de desenvolvimento em Visual FoxPro. Por este motivo, não entramos em
detalhes peculiares ao sistema, mas nos atemos aos recursos da linguagem para a
execução de tarefas que estão envolvidas nesse tipo de sistema, mostrando-lhe o caminho
a seguir. Cabe a você como desenvolvedor e artista que é, usar tudo o que for necessário
e que estiver no seu conhecimento para criar aplicações concisas e agradáveis aos olhos
dos usuários. Mais importante que uma interface bonita é uma interface que funcione. No
entanto, se for possível unir as duas, então será perfeito. Use sempre as máscaras de
formatação nos campos, induzindo sempre o usuário a acertar. Critique sempre que
houver necessidade a fim de não deixar que uma informação necessária seja deixada sem
preencher.

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados


A U L A

24
Construindo o formulário de navegação de Compras

Como você já percebeu, para cada tabela que queremos editar/incluir dados, de acordo
com nossas classes projetadas, precisamos criar primeiramente um formulário de
navegação. A partir deste formulário é que lançamos o formulário de edição.

Vamos então construir nesse momento o formulário para navegação de Entrada de


Produtos (Compras). Siga os passos:

1. Crie um novo formulário baseado na classe navegacao, emitindo o comando:


CREATE FORM forms\lstCompras As navegacao ;
FROM "c:\cursovfp\classes\formularios.vcx"

2. Abra o ambiente de dados (Data Environment) do formulário e então adicione um


novo objeto CursorAdapter.

3. Inicie o Builder do CursorAdapter clicando com o botão direito do mouse sobre o


novo objeto CursorAdapter criado.

4. Na primeira aba do Builder, você deve informar apenas as informações contidas na


próxima figura:

Figura 24.11 – propriedades do CursorAdapter Compras

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados


A U L A

24
5. Vá para a aba de número 2. Data Access e defina os campos do cursor, digitando a
expressão a seguir no Select Command:
SELECT compras.id_compra, compras.data_registro,
compras.data_nf, compras.numero_nf,
cliente_fornecedor.nome_razao AS nome_fornecedor
FROM compras
LEFT JOIN cliente_fornecedor
ON compras.id_fornecedor = cliente_fornecedor.codigo

6. Você pode digitar o comando Select acima sem se preocupar com a formatação,
atentando apenas para a grafia correta dos nomes dos campos e tabelas. O
comando acima possui uma sintaxe um pouco diferente do que já vimos até o
momento, pois nele fazemos uma junção (JOIN) das tabelas Compras e
Cliente_fornecedor. LEFT JOIN cliente_fornecedor quer dizer, junte-se à tabela da
esquerda da expressão de relacionamento, a tabela cliente_fornecedor. A
expressão de relacionamento é:
ON compras.id_fornecedor = cliente_fornecedor.codigo

7. onde ON estabelece o relacionamento entre a primeira tabela compras (tabela da


esquerda) à segunda tabela (tabela da direita) cliente_fornecedor. Note que são
usados os campos chaves, onde id_fornecedor é a chave estrangeira da tabela
compras que identifica o fornecedor e codigo é a expressão de chave primária da
tabela cliente_fornecedor.

8. Sempre que você desejar que campos de uma ou mais tabelas apareçam em uma
consulta e houver uma expressão de relacionamento entre as tabelas você pode
usar JOIN para estabelecer um relacionamento. Para maiores detalhes consulte o
tópico Join Conditions for Tables, Queries, and Views no help do Visual FoxPro.

9. Ok, uma vez definido o comando Select, clique no botão Build imediatamente acima
da caixa de texto Schema, a fim de que seja construída a expressão do
CursorSchema.

10. Defina as demais propriedades do CursorAdapter e então clique OK. Veja a figura
23.24:

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados


A U L A

24

Figura 24.12 – Propriedades do CursorAdapter – Acesso a Dados

11. Ao clicar OK, clique duplamente no objeto CursorAdapter compras e adicione o


código abaixo no evento Init do mesmo, logo após o comando llReturn = dodefault():
* Define que o tipo de acesso será por ADO
this.DataSourceType = "ADO"

* Atribui objeto ADODB.RecordSet ao DataSource do cursor


this.DataSource = CREATEOBJECT("ADODB.RecordSet")
* 3, AdUseClient
this.DataSource.CursorLocation = 3
* 3, adLockOptmistic
this.DataSource.LockType = 3
This.DataSource.ActiveConnection = This.Parent.oConnection

* Adiciona o objeto ADODB.Command


this.AddProperty("oCommand",CREATEOBJECT("ADODB.Command"))

this.oCommand.ActiveConnection = this.Parent.oConnection

12. Agora feche a janela de código e clique duplamente na área do ambiente de dados
para adicionarmos o seguinte código ao evento BeforeOpenTables():
SET MULTILOCKS ON

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados


A U L A

24
* Define que o tipo de acesso será por ADO
this.DataSourceType = "ADO"

* Cria objeto de conexão ADODB.Connection


This.AddProperty("oConnection",CREATEOBJECT("ADODB.Connection"))
* recebe a string de conexão com o banco de dados
This.oConnection.ConnectionString = pStringConexao

* Estabelece a conexão
This.oConnection.Open()

13. Como você já sabe, os dois códigos acima estabelecem a conexão com o banco de
dados e faz o seu compartilhamento. Muito bem, agora que os dados estão
definidos, já podemos formatar nosso grid. Feche o ambiente de dados.

14. Defina a propriedade do Grid: ColumnCount = 5

15. Associe a tabela Compras ao Grid, definindo a propriedade RecordSource =


compras.

16. Agora associe cada coluna do grid com seu respectivo campo na ordem que eles
aparecem na tabela.

17. Mude a propriedade name do formulário para lstCompras

18. Defina as propriedades a seguir com seus respectivos valores:

cCampo = id_compra
cTabela = compras
formularioedicao = compras

19. Ao final, o formulário deverá ter uma aparência mais ou menos assim:

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados


A U L A

24

Figura 24.13 – Formulário de navegação de Compras

Construindo um formulário com o uso de pesquisa estrangeira

Os formulários que construímos até o presente momento usam tabelas solitárias solitários,
ou seja, estão desconectados de quaisquer outras tabelas que não seja a tabela principal
em edição. Entretanto, muito comumente necessitamos de criar formulários de uma
complexidade relativamente maior onde várias tabelas precisam ser envolvidas e de
alguma forma relacionam-se entre si.

Quando usamos uma tabela relacionada a outra, geralmente determinamos o nome de


tabela estrangeira à tabela secundária onde geralmente iremos apenas consultar alguma
informação e tabela filha àquela que será usada para agregar informações detalhadas co-
relacionadas com a tabela principal.

Num cenário básico onde estaremos construindo um formulário para a entrada de produtos
(compra), envolveremos a tabela principal compras, a tabela filha compra_itens, e as
tabelas estrangeiras produtos e cliente_fornecedores.

Existem diversas técnicas para pesquisa de informações numa tabela estrangeira. Em


nosso caso específico, a fim de implementar um cenário com uma abordagem bem

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados


A U L A

24
próxima da arquitetura cliente/servidor, desenvolvemos um formulário específico que será
responsável por pesquisar dados em qualquer tabela estrangeira, e um controle disparador
que acoplaremos em nossos formulários, preencheremos algumas propriedades e pronto!
Nosso formulário de pesquisa estrangeira saberá lidar com qualquer tabela.

Construindo formulários de edição especializados

Uma coisa é certa, desenvolver aplicativos em Visual FoxPro é uma tarefa um tanto
empolgante e bastante produtivo quando aplicamos os conceitos de programação
orientada a objetos que até o momento estamos empregando. Um belo exemplo disto são
os formulários de navegação e de edição onde seria possível criar dezenas deles num
único dia, e sem muita exaustão.

Embora a classe esteja pronta para a maioria dos tipos de cadastros algumas vezes
precisaremos especializar mais ainda o formulário incluindo novos métodos, propriedades
adicionais e talvez até incluir outros controles como botões de comandos, chamar
formulários adicionais, etc.

Em nosso aplicativo financeiro e de controle de estoques facilmente criamos os formulários


de navegação e edição para clientes, fornecedores e produtos.

Chega então o momento em que teremos que criar formulários para a entrada (compra) e
saída (venda) de produtos. Nesse tipo de formulário há certa complexidade devido ao fato
que envolve várias tabelas. Por exemplo, num processo de compra de produtos, teríamos
no mínimo as tabelas de compras, compra_itens, produtos, cliente_fornecedores
envolvidas no processo onde as três primeiras estariam sendo usadas para incluir/alterar
registros e a quarta apenas para consulta.

À medida que precisamos realizar movimentações ou processos dentro de um


determinado formulário, geralmente, para facilitar a compreensão do código, tendemos a
criar novos métodos no formulário. Geralmente um método para cada processo, como por
exemplo, um método AtualizarEstoque(), outro GerarContasPagar() e assim
sucessivamente, à medida que necessitarmos, no entanto às vezes escrevemos o código
diretamente na ação de algum outro método já existente. Cabe a você decidir o momento
certo para criar novos métodos.

O processo de especialização de um formulário baseado na nossa classe de edição é


relativamente simples. Talvez sejam necessárias pequenas alterações na classe principal
para melhor acoplar as novas funcionalidades especializadas, contudo, sem comprometer
aquelas já existentes.

Quando chegar o momento oportuno, faremos pequenas modificações em nossa classe


edicao, a fim de permitirmos uma melhor especialização. Você pode até pensar, porque eu
já não codifiquei a classe de forma que não precisasse mexer mais, e então a resposta
seria simples: você precisa aprender a lidar com as situações mais inusitadas. Há
momentos que você projetou, re-projetou, codificou e está tudo testado e funcionando.
Então, de repente surge uma nova regra no negócio obrigando você a mexer na classe

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados


A U L A

24
principal para permitir que a nova regra seja codificada com eficiência. Acredite-me, tais
situações são bem mais freqüentes do que gostaríamos.

Construindo o formulário de edição/inclusão de compras

O formulário de inclusão/edição de compras lhe mostrará como realizar operações sobre


diversas tabelas simultaneamente em um mesmo formulário. Até o momento, só tivemos o
trabalho de realizar tarefas em uma única tabela.

Para muitos programadores iniciantes é nesse ponto que se perdem, ou seja, não
conseguem manter o elo das informações e acabam produzindo softwares inconsistentes.
No Visual FoxPro tudo é muito tranqüilo. Podemos manipular dezenas de tabelas sem que
o ponteiro se perca e venha causar confusão como em certas linguagens xBase.

É importante lembrar que para obter o melhor resultado de programação sobre as tabelas
envolvidas e não ter nenhum problema com falha na gravação dos dados, devemos tomar
o cuidado de definir muito bem os atributos dos CursorAdapter’s envolvidos de maneira
que, aqueles que vão ter informações inseridas ou atualizadas estejam devidamente
configurados para enviar as atualizações, bem como os pares de campos atualizáveis, etc.

Vamos agora à criação do nosso formulário.

1. Primeiramente, crie um novo formulário baseado na classe edição. Você poderá


fazê-lo a partir da janela de comandos:

2. CREATE FORM compras AS edicao FROM


c:\cursovfp\classes\formularios.vcx

3. Defina as seguintes propriedades gerais para o formulário:


Propriedades gerais do formulário compras
Caption Compra de Produtos
Height 426
Name Compras
Width 769
Campo_sequencial Id_compra
Chave_antecipada .T.
Comandoprimeirofoco thisform.cntFornecedor.SetFocus()
Nome_sequencia Compras

4. Agora defina os cursores adapters conforme as propriedades indicadas na tabela


abaixo:

Tabela de Compras
Name Compras
Alias Compras
Data Source Type ADO

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados


A U L A

24
Select Command select compras.id_compra, compras.data_registro,
compras.id_fornecedor, compras.data_nf,
compras.numero_nf from compras
Schema ID_COMPRA N(7, 0), DATA_REGISTRO D, ID_FORNECEDOR
N(7, 0), DATA_NF D, NUMERO_NF C(10)
Number of tecords All
to tetch at a time
Maximum number All
of records to fetch
Buffer mode Optmistic row buffering
override
Send Updates Marcar (sim)
Auto update Marcar (sim)
Tables Compras
KeyField ID_COMPRA
Campos Todos
Atualizáveis
SQL WHERE Key fields only
Clause
Tabela de Compras_itens
Name Compras_itens
Alias Compras_itens
Data Source Type ADO
Select Command select compras_itens.id_produto,
produtos.descricao_produto, compras_itens.quantidade,
compras_itens.valor_unitario,
compras_itens.valor_total_item,
compras_itens.id_compra, compras_itens.id_temp from
compras_itens inner join produtos on
compras_itens.id_produto=produtos.id_produto
Schema ID_PRODUTO N(7, 0), DESCRICAO_PRODUTO C(40),
QUANTIDADE N(8, 3), VALOR_UNITARIO N(8, 2),
VALOR_TOTAL_ITEM N(11, 2), ID_COMPRA N(7, 0), ID_TEMP
C(10)
Number of tecords All
to tetch at a time
Maximum number All
of records to fetch
Buffer mode Optmistic row buffering
override
Send Updates Marcar (sim)
Auto update Marcar (sim)
Tables Compras_itens
KeyField ID_TEMP
Campos Todos, exceto DESCRICAO_PRODUTO
Atualizáveis
SQL WHERE Key fields only
Clause

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados


A U L A

24
Tabela de Fornecedores
Name Fornecedores
Alias Fornecedores
Data Source Type ADO
Select Command select cliente_fornecedor.codigo,
cliente_fornecedor.nome_razao from cliente_fornecedor
Schema CODIGO N(7, 0), NOME_RAZAO C(40)
Number of tecords All
to tetch at a time
Maximum number All
of records to fetch
Buffer mode Optmistic row buffering
override
Send Updates Desmarcado
Auto update Desmarcado
Tables
KeyField
Campos Nenhum
Atualizáveis
SQL WHERE Key fields only
Clause
Tabela de Produtos
Name Produtos
Alias Produtos
Data Source Type ADO
Select Command select produtos.id_produto,
produtos.descricao_produto, produtos.valor_unitario,
produtos.qtd_estoque from produtos
Schema ID_PRODUTO N(7, 0), DESCRICAO_PRODUTO C(40),
VALOR_UNITARIO N(11, 2), QTD_ESTOQUE N(11, 3)
Number of tecords All
to tetch at a time
Maximum number All
of records to fetch
Buffer mode Optmistic row buffering
override
Send Updates Marcado
Auto update Marcado
Tables Produtos
KeyField ID_PRODUTO
Campos QDT_ESTOQUE
Atualizáveis
SQL WHERE Key fields only
Clause

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados


A U L A

24
4. Não se esqueça que o código do evento BeforeOpenTables() do ambiente de dados
e do evento Init() de cada CursorAdapter é obrigatório de se acrescentar, caso
contrário o cursor não será preenchido. Como já repetimos esta tarefa por várias
vezes anteriormente, julgo que você já seja capaz de executá-la sem que eu a
descreva nesse momento.

5. Após definidos todos os objetos CursorAdapter, formate o desenho do formulário


para se parecer com o mostrado na figura a seguir. Lembre-se de arrastar os
campos a partir do ambiente de dados. Dessa forma, você poupa tempo na
associação dos campos aos controles.

Figura 24.14 – Formulário de inclusão/edição de compras

6. A tabela a seguir lhe traz a lista das propriedades mais importantes para cada
controle do formulário acima.
Propriedades dos controles contidos no formulário

Controle: lblID_compra Caption = ID Compra


Classe: _label Height = 17
Left = 36
Name = lblID_compra
Top = 35
Width = 61

Controle: txtId_compra ControlSource = compras.id_compra


Classe: _textbox DisabledBackColor = 249,248,242

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados


A U L A

24
DisabledForeColor = 0,0,0
Enabled = .F.
Height = 23
Left = 36
Name = txtId_compra
TabIndex = 10
Top = 54
Width = 84

Controle: lblData_registro Caption = Data


Classe: _label Height = 17
Left = 132
Name = lblData_registro
Top = 35
Width = 77

Controle: txtData_registro ControlSource = compras.data_registro


Classe: _textbox DisabledBackColor = 249,248,242
DisabledForeColor = 0,0,0
Enabled = .F.
Height = 23
Left = 132
Name = txtData_registro
TabIndex = 12
Top = 54
Value = Date()
Width = 84

Controle: cntFornecedor BackStyle = 0 – Transparent


Classe: _pe Height = 47
Left = 216
Name = cntFornecedor
TabIndex = 1
Top = 32
Width = 94
Campoacapturar = codigo
Tabela = cliente_fornecedor
Tabela_local = fornecedores
Titulo = Pesquisando Fornecedores
(deve-se ligar o controle txtPe ao campo
compras.id_fornecedor)

Controle: txtNomeFornecedor ControlSource = fornecedores.nome_razao


Classe: _textbox DisabledBackColor = 249,248,242
DisabledForeColor = 0,0,0

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados


A U L A

24
Enabled = .F.
Height = 23
Left = 314
Name = txtNomeFornecedor
TabIndex = 17
Top = 54
Width = 245

Controle: lblData_nf Caption = Data NF


Classe: _label Height = 17
Left = 570
Name = lblData_nf
Top = 35

Width = 45

Controle: txtData_nf ControlSource = compras.data_nf


Classe: _textbox Height = 23
Left = 570
Name = txtData_nf
TabIndex = 2
Top = 54
Width = 73

Controle: lblNumero_nf Caption = Nº NF


Classe: _label Height = 17
Left = 654
Name = lblNumero_nf
Top = 35
Width = 64

Controle: txtNumero_nf ControlSource = compras.numero_nf


Classe: _textbox Height = 23
Left = 654
Name = txtNumero_nf
TabIndex = 3
Top = 54
Width = 78

Controle: shp1 BackStype = 0 – Transparent


Classe: _shape Height = 272
Left = 36
Name = shp1
SpecialEffect = 0 – 3D
Top = 90
Width = 697

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados


A U L A

24

Controle: lblTituloGrid Caption = Itens da Nota Fiscal/Pedido de Compra


Classe: _label Height = 17
Left = 275
Name = lblTituloGrid
Top = 95
Width = 218

Controle: grdCompras_itens AllowCellSelection = .F.


ColumnCount = 5
DeleteMark = 5
GridLines = 2 – vertical
Height = 200
HighlightStyle = 2
Left = 36
Name = grdCompras_itens
RecordSource = compras_itens
RecordSourceType = 1 – Alias
TabIndex = 8
Top = 114
Width = 697

Controle: lblValorTotal Caption = Valor Total da Compra


Classe: _label Height = 17
Left = 462
Name = lblValorTotal
Top = 300
Width = 126

Controle: txtValor_Total DisabledBackColor = 249,248,242


Classe: _textbox DisabledForeColor = 0,0,0
Enabled = .F.
Height = 23
InputMask = 999,999.99
Left = 594
Name = txtValor_total
Top = 327
Width = 117

Controle: cmdIncluir Caption = Incluir Item


Classe: _commandbutton Height = 41
Left = 43
Name = cmdIncluir
Picture = c:\cursovfp\imagens\text.ico
PicturePosition = 1
TabIndex = 4

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados


A U L A

24
Top = 316
Width = 106

Controle: cmdAlterar Caption = Alterar Item


Classe: _commandbutton Height = 41
Left = 156
Name = cmdAlterar
Picture = c:\cursovfp\imagens\write.ico
PicturePosition = 1
TabIndex = 6
Top = 316

Width = 106

Controle: cmdExcluir Caption = Excluir Item


Classe: _commandbutton Height = 41
Left = 269
Name = cmdExcluir
Picture = c:\cursovfp\imagens\trash full.ico
PicturePosition = 1
TabIndex = 7
Top = 316
Width = 106

7. A próxima tabela mostra as propriedades das colunas do controle


grdCompras_itens:
Propriedades das colunas do controle grdCompras_itens

Coluna 1 Header1:
Caption = Código

Column1:
ControlSource = compras_itens.id_produto
Width = 84

Coluna 2 Header1:
Caption: Descrição do Produto

Column2:
ControlSource = compras_itens.descricao_produto
Width = 290

Coluna 3 Header1:
Caption: Quantidade

Column3:
ControlSource = compras_itens.quantidade

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados


A U L A

24
Width = 73

Coluna 4 Header1:
Caption: Valor Unitário

Column4:
ControlSource = compras_itens.valor_unitario
InputMask = 999,999.99
Width = 92

Coluna 5 Header1:
Caption: Total do Item

Column5:
ControlSource = compras_itens.valor_total_item
InputMask = 999,999.99
Width = 92

8. O Controle Fornecedor trata-se de um controle baseado na classe de Pesquisa


Estrangeira. Defina o seguinte código no evento Init:

DIMENSION this.aCampos[2,5]
this.aCampos[1,1] = "Nome do Fornecedor"
this.aCampos[1,2] = "nome_razao"
this.aCampos[1,3] = 50
this.aCampos[1,4] = "!"
this.aCampos[1,5] = ""
this.aCampos[2,1] = "Código Fornecedor"
this.aCampos[2,2] = "codigo"
this.aCampos[2,3] = 6
this.aCampos[2,4] = "L"
this.aCampos[2,5] = "999999"

9. Assim que os controles estiverem posicionados, meio caminho terá sido percorrido.
Vem então a hora da verdade onde temos que inserir códigos para dar vida aos
controles. Vamos começar adiciona o código dos botões Incluir Item, Alterar item e
Excluir Item. A tabela abaixo lista o código de cada um:

Código do evento click do botão Incluir Item: cmdIncluir


* Verifica se é um registro novo
IF thisform.cOperacao = "NOVO"
IF NOT thisform.AnteciparChave()
MESSAGEBOX("Não foi possível iniciar a inserção de
itens."+;
" Verifique se preencheu todos os dados da compra!";
,0+48,_screen.Caption)
RETURN .F.

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados


A U L A

24
ENDIF
ENDIF

* define tipo de operação


thisform.operacao_item = "NOVO"

* Zera o conteúdo dos controles


thisform.cntEditarItem.cntProduto.txtPe.Value = 0
thisform.cntEditarItem.txtDescricao_produto.Value = ""
thisform.cntEditarItem.txtQuantidade.Value = 0.000
thisform.cntEditarItem.txtValor_unitario.Value = 0.00
thisform.cntEditarItem.txtValor_total_item.Value = 0.000

* Posiciona o controle de edição dos itens no local correto


thisform.cntEditarItem.Top = 313
thisform.cntEditarItem.Left = 36

* Exibe o controle de inclusão/edição de itens


thisform.cntEditarItem.Visible = .T.
thisform.cntEditarItem.cntProduto.txtPe.SetFocus()

Código do evento click do botão Alterar Item: cmdAlterar


* Verifica se há dados no cursor de itens
SELECT compras_itens
IF RECCOUNT("compras_itens") > 0

* define tipo de operação


thisform.operacao_item = "EDITAR"

* Transfere o conteúdo da tabela para os controles

thisform.cntEditarItem.cntProduto.txtPe.Value = ;
compras_itens.id_produto
thisform.cntEditarItem.txtDescricao_produto.Value = ;
compras_itens.descricao_produto
thisform.cntEditarItem.txtQuantidade.Value = ;
compras_itens.quantidade
thisform.cntEditarItem.txtValor_unitario.Value = ;
compras_itens.valor_unitario
thisform.cntEditarItem.txtValor_total_item.Value = ;
compras_itens.valor_total_item

* Posiciona o controle de edição dos itens no local correto


thisform.cntEditarItem.Top = 313
thisform.cntEditarItem.Left = 36

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados


A U L A

24
* Exibe o controle de inclusão/edição de itens
thisform.cntEditarItem.Visible = .T.
thisform.cntEditarItem.cntProduto.txtPe.SetFocus()

ENDIF

Código do evento click do botão Excluir Item: cmdExcluir


SELECT compras_itens
IF RECCOUNT("compras_itens")>0
IF MESSAGEBOX("Tem certeza que deseja excluir o item
"+CHR(13)+;
ALLTRIM(compras_itens.descricao_produto)+"?";
,4+32,"Confirma exclusão?") = 6

* Apaga o item
DELETE
TABLEUPDATE(.T.,.T.,"compras_itens")
* Atualiza os itens
thisform.dataenvironment.compras_itens.CursorRefresh()
ENDIF
ELSE
MESSAGEBOX("Não existem itens a excluir";
,0+48,_Screen.Caption)
ENDIF

10. O código do evento click de cada botão de comando para incluir e alterar itens faz
referência a um controle que ainda não existe no formulário, sendo este
cntEditarItem. Trata-se de um objeto container que hospedará dentro de si alguns
outros controles, conforme vimos na figura a seguir:

Figura 24.15 – container para edição dos itens da compra

11. Observe na figura acima que há alguns controles contidos no objeto cntEditarItem.
São alguns objetos Label, TextBox e CommandButton. Talvez você esteja se
perguntando porque em vez de criar um container não criamos um outro formulário
para abrigar estes elementos. Bem, particularmente prefiro esse tipo de edição para
registros filhos pois torna-se mais fácil o gerenciamento de sessões de dados no
Visual FoxPro. Como trabalhamos na maioria das vezes com sessões privadas de
dados, se editássemos em uma nova janela quando incluíssemos o registro o Visual
FoxPro automaticamente finaliza a transação para a sessão de formulário que está

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados


A U L A

24
sendo fechada, tornando mais difícil o gerenciamento de transações no banco de
dados, fazendo-se necessárias algumas gambiarras para garantir que não fiquem
registros órfãos nas tabelas filhas.

12. Nosso próximo passo então é adicionar o container cntEditarItem e os demais


controles dentro do mesmo. A partir da Toolbox, arraste a classe _container para o
formulário e defina suas propriedades conforme as descritas a seguir:
Propriedades do controle cntEditarItem

Controle: cntEditarItem BorderWidth = 1


Classe: _container Height = 96
Left = 36
Name = cntEditarItem
SpecialEffect = 1 – Sunken
Top = 316
Visible = .F.
Width = 698

13. Definidas as propriedades do controle cntEditarItem, clique sobre o mesmo


enquanto segura a tecla CTRL ativar o modo de edição do controle. Dessa forma
você poderá inserir os demais controles conforme lista a tabela de propriedades a
seguir:
Propriedades dos controles contidos em cntEditarItem

Controle: cntProduto BackStyle = 0 – Transparent


Classe: _pe Height = 47
Left = 16
Name = cntProduto
TabIndex = 1
Top = 12
Width = 94
Campoacapturar = id_produto
Tabela = produtos
Tabela_local = produtos
Titulo = Pesquisando Produtos
(deve-se ligar o controle txtPe ao campo
compras.id_fornecedor)

Controle: Caption = Descrição do produto


lblDescricao_produto Height = 17
Classe: _label Left = 113
Name = lblDescricao_produto
Top = 12
Width = 156

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados


A U L A

24

Controle: DisabledBackColor = 249,248,242


txtDescricao_produto DisabledForeColor = 0,0,0
Classe: _textbox Enabled = .F.
Height = 23
Left = 113
Name = txtDescricao_produto
Top = 30
Width = 271

Controle: lblQuantidade Caption = Quantidade


Classe: _label Height = 17
Left = 396
Name = lblQuantidade
Top = 12
Width = 66

Controle: txtQuantidade Height = 23


Classe: _textbox Left = 396
Name = txtQuantidade
Top = 30
Width = 64

Controle: lblValor_unitario Caption = Valor Unitário


Classe: _label Height = 17
Left = 481
Name = lblValor_unitario
Top = 12
Width = 78

Controle: txtValor_unitario Height = 23


Classe: _textbox InputMask = 999,999.99
Left = 481
Name = txtValor_unitario
Top = 30
Width = 78

Controle: lblValor_total_item Caption = Valor Total


Classe: _label Height = 17
Left = 581
Name = lblValor_total_item
Top = 12
Width = 91

Controle: txtValor_total_item DisabledBackColor = 249,248,242


Classe: _textbox DisabledForeColor = 0,0,0

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados


A U L A

24
Enabled = .F.
Height = 23
IntputMask = 999,999.99
Left = 581
Name = txtValor_unitario_item
Top = 30
Width = 92

Controle: cmdGravar Caption = “Gra\<var Item”


Classe: _commandbutton Left = 495
Name = cmdGravar
TabIndex = 4
Top = 60

Controle: cmdCancelar Cancel = .T.


Classe: _commandbutton Caption = “\<Cancelar”
Left = 590
Name = cmdCancelar
TabIndex = 11
Top = 60

14. Após inserir todos os controles, edite o controle cntProduto e adicione o seguinte
código ao evento LostFocus do :

Código do evento Init() do controle cntProduto


DIMENSION this.aCampos[4,5]

this.aCampos[1,1] = "Nome do Produto"


this.aCampos[1,2] = "descricao_produto"
this.aCampos[1,3] = 50
this.aCampos[1,4] = "!"
this.aCampos[1,5] = ""
this.aCampos[2,1] = "Código Produto"
this.aCampos[2,2] = "id_produto"
this.aCampos[2,3] = 6
this.aCampos[2,4] = "L"
this.aCampos[2,5] = "999999"
this.aCampos[3,1] = "Valor Unitário"
this.aCampos[3,2] = "valor_unitario"
this.aCampos[3,3] = 10
this.aCampos[3,4] = ""
this.aCampos[3,5] = "999,999.99"
this.aCampos[4,1] = "Estoque"
this.aCampos[4,2] = "qtd_estoque"
this.aCampos[4,3] = 10
this.aCampos[4,4] = ""

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados


A U L A

24
this.aCampos[4,5] = "999,999.999"

15. Adicione ainda ao controle txtPe contido no controle cntProduto o seguinte código
ao seu evento LostFocus():

Código do evento Init() do controle cntProduto


* Executa o código padrão da classe
DODEFAULT()

LOCAL lcCursor
lcCursor = this.Parent.tabela_local

IF USED(lcCursor)
IF RECCOUNT(lcCursor) > 0
this.parent.Parent.txtValor_unitario.Value ;
= &lcCursor..valor_unitario
this.Parent.Parent.txtDescricao_produto.Value ;
= &lcCursor..descricao_produto
ENDIF
ENDIF

16. Adicione o código a seguir ao evento Valid do controle txtQuantidade:

Código do evento Valid() do controle txtQuantidade


thisform.TotalizarItem()

17. Repita ainda o mesmo código no evento Valid do controle txtValor_unitario

Código do evento Valid() do controle txtValor_unitario


thisform.TotalizarItem()

18. Agora temos um código um pouco maior que é usado no evento Click() botão
Gravar Item:

Código do evento Click() do controle cmdGravar


LOCAL lnQuantidade_anterior, lnNova_quantidade, lnDiferenca
LOCAL m.id_produto, m.quantidade, m.valor_unitario
LOCAL m.valor_total_item, id_temp, id_compra
LOCAL lcSelect

IF VAZIO(this.Parent.cntProduto.txtPe.Value)
MESSAGEBOX("Informe o código do produto!";
,0+48,_screen.Caption)
this.Parent.cntProduto.txtPe.SetFocus()
RETURN
ENDIF
IF VAZIO(this.Parent.txtQuantidade.Value)
MESSAGEBOX("Informe a quantidade do produto!";
,0+48,_screen.Caption)
this.Parent.txtQuantidade.SetFocus()
RETURN

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados


A U L A

24
ENDIF
IF VAZIO(this.Parent.txtValor_unitario.Value)
MESSAGEBOX("Informe o valor unitário do produto!";
,0+48,_screen.Caption)
this.Parent.txtValor_unitario.SetFocus()
RETURN
ENDIF

* Pega o valor anterior do campo quantidade


lnQuantidade_anterior = OLDVAL("quantidade","compras_itens")

* Armazena o valor dos controles


m.id_produto = this.Parent.cntProduto.txtPe.Value
m.quantidade = this.Parent.txtQuantidade.Value
m.valor_unitario= this.Parent.txtValor_unitario.Value
m.valor_total_item=this.Parent.txtValor_total_item.Value
m.id_temp = thisform.id_temp
m.id_compra = thisform.txtId_compra.Value

SELECT compras_itens
IF thisform.operacao_item = "NOVO"
APPEND BLANK
GATHER MEMVAR
IF TABLEUPDATE(.T.,.T.,"compras_itens")

* Pesquisa na tabela de produtos para encontrar o produto


* que está sendo inserido
lcSelect = "SELECT produtos.id_produto, produtos.descricao_produto, "+;
"produtos.valor_unitario, produtos.qtd_estoque FROM produtos "+;
"WHERE id_produto = "+ALLTRIM(TRANSFORM(m.id_produto))

thisform.DataEnvironment.produtos.SelectCmd = lcSelect

IF thisform.DataEnvironment.produtos.CursorFill(.t.,.f.)

* Realiza processamento no estoque, inserindo a


* quantidade de itens da compra

SELECT produtos
* Calcula estoque
lnNova_quantidade = produtos.qtd_estoque + m.quantidade

* grava quantidade em estoque


REPLACE produtos.qtd_estoque WITH lnNova_quantidade
TABLEUPDATE(.t.,.t.,"produtos")

ENDIF

ENDIF
ENDIF

IF thisform.operacao_item = "EDITAR"
GATHER MEMVAR
IF TABLEUPDATE(.T.,.T.,"compras_itens")

* Pesquisa na tabela de produtos para encontrar o produto


* que está sendo inserido
lcSelect = "SELECT produtos.id_produto, produtos.descricao_produto, "+;
"produtos.valor_unitario, produtos.qtd_estoque FROM produtos "+;
"WHERE id_produto = "+ALLTRIM(TRANSFORM(m.id_produto))

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados


A U L A

24
thisform.DataEnvironment.produtos.SelectCmd = lcSelect

IF thisform.DataEnvironment.produtos.CursorFill(.t.,.f.)

* Verifica se houve alguma alteração na quantidade


* Se houve, diminui ou aumenta a diferença no estoque

IF m.quantidade <> lnQuantidade_anterior

* Calcula quantos itens adicionados ou removidos


lnDiferenca = (m.quantidade - lnQuantidade_anterior)

SELECT produtos
* Calcula estoque
lnNova_quantidade = produtos.qtd_estoque + lnDiferenca

* grava quantidade em estoque


REPLACE produtos.qtd_estoque WITH lnNova_quantidade
TABLEUPDATE(.t.,.t.,"produtos")

ENDIF
ENDIF
ENDIF
ENDIF

* Zera o conteúdo dos controles


this.Parent.cntProduto.txtPe.Value = 0
this.Parent.txtDescricao_produto.Value = ""
this.Parent.txtQuantidade.Value = 0.000
this.Parent.txtValor_unitario.Value = 0.00
this.Parent.txtValor_total_item.Value = 0.00

* Oculta o controle de inclusão/edição de itens


this.Parent.Visible = .F.

* Atualiza os dados do Grid


thisform.AtualizarItens()

19. O código acima faz duas tarefas distintas. Uma delas é a de ler os valores contidos
em cada um dos controles, criticá-los e gravá-los na tabela de itens da compra. A
segunda tarefa é a de atualizar o estoque de produtos. Ou seja, se foi incluído um
produto com X quantidades, ele vai lá no estoque e incrementa a quantidade X para
aquele produto. Se houver alteração na quantidade, ele verifica e processa o
estoque também. Outro fato importante a notar no procedimento que adotamos para
a inclusão/edição de itens da compra é que os controles não estão ligados à tabela.
Nós apenas os utilizamos para fazer a leitura e depois os gravamos manualmente
na tabela. Esta é outra técnica muito usada e com certeza você fará uso dela por
muitas vezes em outros sistemas.

20. Insira também o código evento Click() do botão cmdCancelar:

Código do evento Click() do controle cmdCancelar


* Zera o conteúdo dos controles
this.Parent.cntProduto.txtPe.Value = 0
this.Parent.txtDescricao_produto.Value = ""

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados


A U L A

24
this.Parent.txtQuantidade.Value = 0.000
this.Parent.txtValor_unitario.Value = 0.00
this.Parent.txtValor_total_item.Value = 0.00

* Oculta o controle de inclusão/edição de itens


this.Parent.Visible = .F.

21. Nosso formulário já possui forma e algumas funcionalidades. Vamos então finalizá-
lo acrescentando mais dois métodos novos e escrevendo código em um já
existente. Vamos começar criando um novo método chamado AtualizarItens(). Para
tal, vá no menu Form e escolha New Method. Informe como nome AtualizarItens e
clique em OK. Após, localize o novo método criado na janela de propriedades e
adicione o código ao mesmo:

Código do método AtualizarItens() do formulário compras


*
LOCAL lcSelect, lcAlias, lcTalk, lcConsole

lcSelect = [select compras_itens.id_produto,


produtos.descricao_produto, ]+;
[ compras_itens.quantidade,
compras_itens.valor_unitario, ]+;
[ compras_itens.valor_total_item, ]+;
[ compras_itens.id_compra, compras_itens.id_temp ]+;
[ from compras_itens inner join produtos ]+;
[ on compras_itens.id_produto=produtos.id_produto ]+;
[ WHERE compras_itens.id_compra = ]+;
ALLTRIM(TRANSFORM(thisform.txtId_compra.Value))

thisform.grdCompras_itens.RecordSource = ""

WITH thisform.dataenvironment.compras_itens

.SelectCmd = lcSelect
* Executa a consulta
.CursorFill(.T.,.F.)

ENDWITH

IF USED("compras_itens")

* Soma o total dos itens


SELECT compras_itens

* Guarda o Status anterior

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados


A U L A

24
lcTalk = SET("Talk")
lcConsole = SET("Console")

* Define status para não apresentar resultados na tela


SET TALK OFF
SET CONSOLE OFF

CALCULATE SUM(compras_itens.valor_total_item) ;
ALL TO thisform.txtVAlor_total.Value

GO TOP
* Associa o cursor gerado com o grid de itens da compra
thisform.grdCompras_itens.RecordSource = "compras_itens"

* Restaura o status anterior


SET TALK &lcTalk.
SET CONSOLE &lcConsole.

SELECT (thisform.cTabela)
ENDIF

22. O código acima garante que o grid de itens esteja exibindo as informações corretas
sobre os itens da compra. Este é um típico relacionamento do tipo um-para-n em
aplicações cliente/servidor, sendo que o lado um do relacionamento é a tabela
compras e o lado n é a tabela compras_itens.

23. Adicione ainda um novo método ao formulário nomeando-o de TotalizarItem e em


seguida adicione o seguinte código ao mesmo:

Código do método TotalizarItem() do formulário compras


LOCAL lnTotal

lnTotal = (thisform.cntEditarItem.txtQuantidade.Value * ;
thisform.cntEditarItem.txtValor_unitario.Value)

thisform.cntEditarItem.txtValor_total_item.Value = lnTotal

thisform.Refresh

24. O método acima é usado apenas para calcular o valor total do item quando este
está em edição/inclusão.

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados


A U L A

24
25. Agora localize o método ConfigurarRelacionamentos() do formulário compras e
adicione o código a seguir ao mesmo, que será responsável por definir o
relacionamento entre compras e fornecedores:

Código do método ConfigurarRelacionamentos() do formulário compras


DIMENSION this.aRelacoes[1,2]
this.aRelacoes[1,1] = ;
[thisform.cntFornecedor.txtPe.Value] && controle
this.aRelacoes[1,2] = ;
[fornecedores.codigo] && campo da tabela

26. E finalmente, para fechar com chave de ouro, adicione o seguite código ao método
RealizarOperacao() do formulário compras:

Código do método ReaçozarOperacao() do formulário compras


* Executa o código padrão da classe
DODEFAULT()

* Executa o método AtualizarItens()


thisform.AtualizarItens()

27. O código acima simplesmente executa o código padrão da classe usando


DODEFAULT() e em seguida faz chamada ao método AtualizarItens(). Essa
chamada é realizada uma vez quando o formulário é carregado, garantido assim
que os itens da compra sejam carregados também na inicialização.

Muito bem, agora é com você. Faça os testes, tire suas próprias conclusões e altere à
vontade para entender o mecanismo.

Copyright © 2004-2014 – Fox Total Network – Todos os direitos reservados

Você também pode gostar