Ultimo problema para finalizar meu primeiro Sistema

@RoinujNosde

Metodo adiciona produto

txtProdutos.setWidth("370px");
		txtProdutos.setLabel("Produtos");
		List<Produto> listaDeProdutos = produtoRepository.findAll();
		txtProdutos.setItemLabelGenerator(Produto::getNome);
		txtProdutos.setItems(listaDeProdutos);
		txtProdutos.addValueChangeListener(event -> {
			venda.addProduto(txtProdutos.getValue()); // LINHA 437
			NumberFormat formatter = NumberFormat.getCurrencyInstance(new Locale("pt", "BR"));
			try {

				txtValorUnitario.setValue(formatter.format(event.getValue().getValor()));

			} catch (Exception e) {
				e.printStackTrace();
			}

		});

		// ==========================================================================================================================

		txtQuantidade.setHasControls(true);
		txtQuantidade.setValue(null);
		txtQuantidade.setMin(1);

		txtQuantidade.addValueChangeListener(event -> {

			NumberFormat formatter = NumberFormat.getCurrencyInstance(new Locale("pt", "BR"));
			double valorTotal = 0;

			try {
				valorTotal = formatter.parse(txtValorUnitario.getValue()).doubleValue() * txtQuantidade.getValue();
			} catch (ParseException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			txtValorTotalItem.setValue(formatter.format(valorTotal));

			double soma = 0;// interna
			for (TextField tf : valores) {
				try {
					soma += formatter.parse(tf.getValue()).doubleValue();

				} catch (ParseException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}

			campoSomaValores.setValue(formatter.format(soma));// externa

		});

		adicionarProdutos = new HorizontalLayout();
		adicionarProdutos.add(txtProdutos, txtQuantidade, txtValorUnitario, txtValorTotalItem);
		centro.add(adicionarProdutos);
		valores.add(txtValorTotalItem);

	}

resultado:

mas pq não trouxe a descrição do produto?

Você escreveu alguma lógica pra isso?

1 curtida

Clonei seu projeto e rodei aqui. Da forma como vc está manipulando os produtos na venda, realmente, vai ser muito difícil para vc persistir eles.

Basicamente vc está apenas trabalhando com elementos de tela e esquecendo dos objetos de domínio (no caso, a venda e os produtos).

Pelo que testei, qdo o botão +Item é acionado, ele cria os elementos na tela para poder escolher as características do produto, e só. Depois disso, não há uma forma de concretizar essa inclusão na venda. Isso poderia ser feito com algum botão de confirmar, ou se vc recuperar todas as informações dos produtos adicionados no momento em que vc salvar a venda, é possível fazer isso através do componente adicionarProdutos (nome estranho, mas é o componente de layout HorizontalLayout).

Veja:

image

Com o código:

adicionarProdutos.getChildren().collect(Collectors.toList())

vc consegue recuperar os elementos adicionados onde vc vai conseguir recuperar os dados de cada produto adicionado e adicionar na venda (convertendo para a entidade ProdutoVendido).

Porém, acho que essa não é a melhor forma de fazer isso, pois, pelo que vi, se vc adicionar mais de um produto, vc terá dificuldades de recuperar os dados de todos esses produtos. Talvez uma melhor forma seja alguma modal para adicionar esses produtos ou algo para confirmar a ação.

1 curtida

@Lucas_Camara

vc então poderia me ajudar a criar tudo para que funcione o sistema? Eu entendi o que vc disse, mas gostaria de ter alguém me orientando “passo a passo”. Caso seja possível me ajudar, qual o primeiro passo para resolver a questão? Posso mudar tudo, não estou preso a nada…podemos excluir classes, criar classes, métodos, funções…o que for necessário

Para vc não ter que mudar muito seu código (até pq acho que falta pouco para fazer funcionar), acho que tu pode abrir uma modal qdo o botão +Item fosse acionado. Nessa modal, teria os campos com os dados do produto e, ao confirmar, vc adicionaria o produto à venda.

1 curtida

@Lucas_Camara

Ok, mas como faço esse modal?

Tu já fez uma modal lah no sistema. Acho que tu consegue fazer outra em cima dessa que já existe.

1 curtida

@RoinujNosde

Aqui eu consegui salvar os 4 objetos(por enquanto somente a descricao), mas ele está meio “apagado”

Como você mostrava um produto na tela antes e como mostra agora? Compare.

1 curtida

@RoinujNosde
Então, lembra que antes não mostrava nada? Antes eu apenas conseguia adicionar os produtos, mas eles não eram salvos. Agora está sendo salvo, mas está meio apagado.

código para “mostrar”

private void montarListaProdutos(List<ProdutoVendido> produtosVendidos) {
		HorizontalLayout adicionarProdutos = new HorizontalLayout();

		for (ProdutoVendido pv : produtosVendidos) {
			adicionarProdutos.add(new HorizontalLayout(new TextField("Produtos:", (pv.getProduto().getNome()))));
			adicionarProdutos.add(new HorizontalLayout(new TextField("Quantidade:", String.valueOf(pv.getQuantidade()))));
			adicionarProdutos.add(new HorizontalLayout(new TextField("Valor Unitário:", String.valueOf(pv.getValorUnitario()))));
			adicionarProdutos.add(new HorizontalLayout(new TextField("Valor Total Item:", String.valueOf(pv.getValorTotalItem()))));
			
		}
		adicionarProdutos.getChildren().collect(Collectors.toList());
		centro.add(adicionarProdutos);
	}

duplo click na grid:

grdVenda.addItemDoubleClickListener(event -> {
			if (venda != null) {
				binderVenda.readBean(venda);
				dlgJanela.open();
				montarListaProdutos(venda.getProdutos());

			}
		});

	}

Quando está criando uma Venda, fica apagado tbm? Não, né? É esse código que tô perguntando.

Está ficando apagando quando tenta editar uma Venda já salva, não é?

1 curtida

@RoinujNosde

Não…este duplo clique não é para Editar/Alterar nada…é apenas para visualizar

Quando estou criando a venda não, não fica apagado neste caso o código que vc se refere é este:

private void adicionaProduto() {

		ComboBox<Produto> txtProdutos = new ComboBox<>();

		IntegerField txtQuantidade = new IntegerField("Quantidade");

		TextField txtValorUnitario = new TextField("Valor Unitário");

		TextField txtValorTotalItem = new TextField("Valor Total Item");

		txtProdutos.setWidth("370px");
		txtProdutos.setLabel("Produtos");
		List<Produto> listaDeProdutos = produtoRepository.findAll();
		txtProdutos.setItemLabelGenerator(Produto::getNome);
		txtProdutos.setItems(listaDeProdutos);
		txtProdutos.addValueChangeListener(event -> {
			venda.addProduto(txtProdutos.getValue()); // LINHA 437
			NumberFormat formatter = NumberFormat.getCurrencyInstance(new Locale("pt", "BR"));
			try {

				txtValorUnitario.setValue(formatter.format(event.getValue().getValor()));

			} catch (Exception e) {
				e.printStackTrace();
			}

		});

		// ==========================================================================================================================

		txtQuantidade.setHasControls(true);
		txtQuantidade.setValue(null);
		txtQuantidade.setMin(1);

		txtQuantidade.addValueChangeListener(event -> {
			
			NumberFormat formatter = NumberFormat.getCurrencyInstance(new Locale("pt", "BR"));
			double valorTotal = 0;

			try {
				valorTotal = formatter.parse(txtValorUnitario.getValue()).doubleValue() * txtQuantidade.getValue();
			} catch (ParseException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			txtValorTotalItem.setValue(formatter.format(valorTotal));

			double soma = 0;// interna
			for (TextField tf : valores) {
				try {
					soma += formatter.parse(tf.getValue()).doubleValue();

				} catch (ParseException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}

			campoSomaValores.setValue(formatter.format(soma));// externa

		});

		adicionarProdutos = new HorizontalLayout();
		adicionarProdutos.add(txtProdutos, txtQuantidade, txtValorUnitario, txtValorTotalItem);
		centro.add(adicionarProdutos);
		valores.add(txtValorTotalItem);

	}

Ah, certo. Confundi.

Será que tá apagado porque não são campos editáveis?

1 curtida

@RoinujNosde

pode ser que seja mesmo…obg por sua ajuda até aqui!!!

@Lucas_Camara

a vc tbm, muito obg por sua ajuda!!!

1 curtida

@RoinujNosde e @Lucas_Camara

Eu fiz algumas modificações no código, mas não sei se irá facilitar as coisas, gostaria da opinião de vcs.

Fiz o seguinte:

Deletei a classe ProdutoVendido, só para vcs lembrarem esta ERA a classe ProdutoVendido:

package br.com.fjsistemas.backend;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@AllArgsConstructor
@NoArgsConstructor
@Data
@Getter
@Setter
@Entity
public class ProdutoVendido {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;
	
	@ManyToOne
	private Venda venda;
	
	@ManyToOne
	private Produto produto;
	
	private int quantidade;
	private Double valorUnitario;
	private Double valorTotalItem;
}

Na classe Venda(Entidade), antes estava assim:

package br.com.fjsistemas.backend;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@Data
@Entity
public class Venda {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;

	private LocalDate dataVenda = LocalDate.now();

	@ManyToOne
	private Cliente cliente;

	@ManyToOne
	private FormaDePagamento formaDePagamento;

	@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
	private List<ProdutoVendido> produtos = new ArrayList<>();

	public void addProduto(Produto produto) {
		ProdutoVendido produtoVenda = new ProdutoVendido(id, this, produto, 0, null, null);																			
		produtos.add(produtoVenda);
	}

	private String valorTotalVenda;

} 

AGORA a classe Venda ESTÁ assim:

package br.com.fjsistemas.backend;

import java.time.LocalDate;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@Data
@Entity
public class Venda {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;

	private LocalDate dataVenda = LocalDate.now();

	@ManyToOne
	private Cliente cliente;

	@ManyToOne
	private FormaDePagamento formaDePagamento;

	private String valorTotalVenda;
	private String descricao;
	private String quantidade;
	private Double valorUnitario;
	private Double valorTotalItem;
}

E por fim na classe VendaView eu tirei aquela Div enorme que recebia os produtos para venda, em seu lugar coloquei uma grid:

Aqui eu pensei em fazer da seguinte forma:

Para adicionar Produtos, Quantidade, Valor Unitário e total do item, basta o usuario clicar no botão Add Produtos, mas em vez de abrir uma janela, pensei em atribuir os dados diretamente na grid, eu vi no site Vaandin que tem alguns exemplos:

Mas nestes exemplos só falam como adicionar dados fornecidos pelo sistema e não pelo usuario.

Será que há alguma forma de atribuir dados na grid, onde o usuario passe as informações?

minha ideia(visualmente falando) é essa:

O que acham destas mudanças?

1 curtida

+1 por ter colocado uma tabela no lugar do HorizontalLayout que estava.

Mas isso te deixa com o mesmo problema. Qdo um produto for adicionado, como vc vai relacionar o produto à venda? E é exatamente o que a classe ProdutoVendido fazia (junto com o método addProduto que tinha na venda).

Pense bem, num sistema de vendas, o relacionamento entre um produto e uma venda, geralmente, é feita por uma tabela intermediária, pois um mesmo produto pode ser vendido várias vezes, e uma venda pode ser usada para vender mais de um produto.

Venda --> ProdutoVendido <-- Produto

Nesse exemplo, a tabela ProdutoVendido servirá de vínculo, não tem como vc não ter algo assim.

O problema que vc tem é na sua tela. Na forma como vc “amarra” a usabilidade da tela com as classes do domínio (que são Venda, Produto e ProdutoVendido).

1 curtida

@Lucas_Camara

Vc tem sido um cara muito prestativo, mas vou te confessar uma coisa…quando eu leio o que vc posta, parece que vc está falando grego…kkk…o problema não é vc, longe disso, sou eu…tenho muita dificuldade em entender, apenas lendo…

Se vc puder, se vc quiser, poderia me ajudar codificando tudo, passo a passo? Pois toda vez que vejo o código, ai sim eu consigo entender o que foi feito, o pq foi feito, as vantagens e desvantagens…etc etc. Como eu disse antes, podemos mudar tudo o que vc achar necessário

1 curtida

Hehe, tranquilo. Sei como é essa dificuldade.

Nesse print que vc mandou:

No oitavo passo que vc descreveu:

Após salvar, os produtos ficam expostos e salvos na grid.

Vc não pode focar apenas na tela. Está muito preocupado em que o produto apareça na tela e esquecendo do motor do sistema. A modelagem das classes Venda, ProdutoVendido e Produto é mais importante do que a tela.

Se vc conseguir fazer salvar os produtos da venda (esquece tela por enquanto), vc vai conseguir resolver o problema da tela depois com mais facilidade.

1 curtida

@Lucas_Camara

Ok, vamos esquecer a tela neste primeiro momento…o que devo fazer para obter os comportamentos necessários para rodar o programa?

Qdo o botão de salvar for acionado, vc deve ter um objeto Venda preenchido com uma lista de produtos vendidos (igual estava antes).

DICA: Para testar, tu pode até mesmo criar de forma fixa:

private void salvarClick() {
	venda = binderVenda.getBean();
	
	// faça isso fixo soh para ver se vai gravar no banco de dados mesmo
	// isso irá validar se o mapeamento das classes está correto
	venda.addProduto(new Produto(/* aqui vc passa uns valores fixo soh para testar */));
	venda.addProduto(new Produto(/* aqui vc passa uns valores fixo soh para testar */));
	venda.addProduto(new Produto(/* aqui vc passa uns valores fixo soh para testar */));
	venda.addProduto(new Produto(/* aqui vc passa uns valores fixo soh para testar */));
	
	boolean adicionarLista = venda.getId() == null ? true : false;
	vendaService.create(venda);
	
	if (adicionarLista) {
		listaVendas.add(venda);
	}
	
	atualizaGrdVenda();
	novaVenda();
	txtNomeCliente.focus();
	
	binderVenda.setBean(venda);
	
	if (adicionarLista) {
		dlgJanela.close();
	}
}
1 curtida