Bom dia a todos, estou precisando de alguém que esteja disposto a me ensinar como fazer para que uma Venda tenha VARIOS produtos salvos no mysql. Já tentei varias coisas que algumas pessoas do fórum tentaram me passar, mas nada deu certo. Desde já peço para que tenham paciência, pois sou novo neste mundo da programação.
Meu sistema neste momento, está quase pronto, tenho as telas de cadastros(produto, almoxarifado, cliente, fornecedor, funcionários, formas de pagamento) nestas telas tudo está funcionando perfeitamente, desde o lançamento de dados ao salvamento.
Tenho tbm telas de relatorios de vendas e compras, e tbm está funcionando perfeitamente.
Meu problema está nas Vendas e nas Compras, em ambos os casos não consigo salvar uma venda com VARIOS produtos, e tbm não consigo salvar uma Compra com VARIOS produtos. Eu consegui salvar a venda e a compra mas sem produto algum(somente com dados do comprador / fornecedor).
Minhas Classes até aqui:
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.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@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;
}
Classe Produto
package br.com.fjsistemas.backend;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
public class Produto {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String nome;
private String marca;
private String modelo;
private Double valor;
}
Classe Venda View(tela de vendas)
package br.com.fjsistemas.compraVenda;
import java.text.NumberFormat;
import java.text.ParseException;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.vaadin.textfieldformatter.CustomStringBlockFormatter;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.component.datepicker.DatePicker;
import com.vaadin.flow.component.dialog.Dialog;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.grid.GridVariant;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.NumberField;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.data.binder.Binder;
import com.vaadin.flow.data.binder.PropertyId;
import com.vaadin.flow.data.renderer.LocalDateRenderer;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import br.com.fjsistemas.backend.Cliente;
import br.com.fjsistemas.backend.FormaDePagamento;
import br.com.fjsistemas.backend.Produto;
import br.com.fjsistemas.backend.Venda;
import br.com.fjsistemas.main.MainView;
import br.com.fjsistemas.repository.ClienteRepository;
import br.com.fjsistemas.repository.FormaDePagamentoRepository;
import br.com.fjsistemas.repository.ProdutoRepository;
import br.com.fjsistemas.service.VendaService;
@Route(value = "venda-view", layout = MainView.class)
@PageTitle("Lançamento de Vendas")
public class VendaView extends VerticalLayout {
private static final long serialVersionUID = 1L;
private HorizontalLayout hltVenda = new HorizontalLayout();
Grid<Venda> grdVenda = new Grid<>(Venda.class, false);
private HorizontalLayout hltBarraBotoes = new HorizontalLayout();
Button btnNovo = new Button("Novo");
Button btnAlterar = new Button("Alterar");
Button btnExcluir = new Button("Excluir");
private Dialog dlgJanela = new Dialog();
Div superior = new Div();
Div centro = new Div();
Div inferior = new Div();
HorizontalLayout primeiraLinhaDivSuperior = new HorizontalLayout();
HorizontalLayout segundaLinhaDivSuperior = new HorizontalLayout();
HorizontalLayout adicionarProdutos = new HorizontalLayout();
@PropertyId("dataVenda")
private DatePicker txtDataVenda = new DatePicker("Data Venda");
@PropertyId("cliente")
private ComboBox<Cliente> txtNomeCliente = new ComboBox<>("Cliente");
@PropertyId("telefone")
private TextField txtTelefone = new TextField("Telefone");
@PropertyId("celular")
private TextField txtCelular = new TextField("Celular");
@PropertyId("endereco")
private TextField txtEndereco = new TextField("Endereço");
@PropertyId("numero")
private TextField txtNumero = new TextField("Nº");
@PropertyId("bairro")
private TextField txtBairro = new TextField("Bairro");
@PropertyId("cidade")
TextField txtCidade = new TextField("Cidade");
@PropertyId("estado")
TextField txtEstado = new TextField("Estado");
@PropertyId("formaDePagamento")
private ComboBox<FormaDePagamento> txtFormasPagamento = new ComboBox<>("Formas de Pagamento");
@PropertyId("valorTotalVenda")
private TextField campoSomaValores = new TextField();
private HorizontalLayout htlDlgBarraBotoes = new HorizontalLayout();
private Button btnSalvar = new Button("Salvar");
private Button btnFechar = new Button("Fechar");
private Button btnAdicionarItem = new Button("+ Item");
@Autowired
VendaService vendaService;
@Autowired
ClienteRepository clienteRepository;
@Autowired
FormaDePagamentoRepository formaDePagamentoRepository;
@Autowired
ProdutoRepository produtoRepository;
private List<Venda> listaVendas;
private List<TextField> valores = new ArrayList<>();
private Venda venda;
Binder<Venda> binderVenda = new Binder<>(Venda.class);
public VendaView() {
}
@PostConstruct
public void init() {
configuraTela();
}
private void configuraTela() {
setMargin(false);
setPadding(false);
configuraHltVenda();
configuraFltBarraBotoes();
configuraDlgJanela();
populaGrdVenda();
configuraBinder();
add(hltVenda, hltBarraBotoes);
}
private void configuraFltBarraBotoes() {
btnNovo.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
btnNovo.addClickListener(e -> {
novoClick();
});
btnAlterar.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
btnAlterar.addClickListener(e -> {
alterarClick();
});
btnExcluir.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
btnExcluir.addClickListener(e -> {
excluirClick();
});
hltBarraBotoes.add(btnNovo, btnAlterar, btnExcluir);
}
private void excluirClick() {
if (venda != null) {
listaVendas.remove(venda);
vendaService.delete(venda);
atualizaGrdVenda();
}
}
private void configuraHltVenda() {
hltVenda.setWidthFull();
configuraGrdVenda();
hltVenda.add(grdVenda);
}
private void configuraGrdVenda() {
grdVenda.setHeight("820px");
grdVenda.setWidthFull();
grdVenda.addColumn(Venda::getId).setHeader("ID:").setAutoWidth(true);
grdVenda.addColumn(new LocalDateRenderer<>(Venda::getDataVenda, DateTimeFormatter.ofPattern("dd/MM/yyy")))
.setHeader("Data Venda").setAutoWidth(true);
grdVenda.addColumn(venda -> venda.getCliente().getNome()).setHeader("Nome:").setAutoWidth(true)
.setKey("cliente.nome");
grdVenda.addColumn(Venda::getValorTotalVenda).setHeader("Valor Total:").setAutoWidth(true)
.setKey("valorTotalVenda");
grdVenda.addColumn(venda -> venda.getFormaDePagamento().getFormaDePagamento()).setHeader("Forma de Pagamento")
.setAutoWidth(true).setKey("formaDePagamento");
grdVenda.addThemeVariants(GridVariant.LUMO_COMPACT, GridVariant.LUMO_COLUMN_BORDERS);
grdVenda.getColumns().forEach(col -> col.setAutoWidth(true).setSortable(true).setResizable(true));
grdVenda.addItemClickListener(e -> {
venda = e.getItem();
});
grdVenda.addItemDoubleClickListener(event -> {
if (venda != null) {
binderVenda.readBean(venda);
dlgJanela.open();
}
});
}
private void configuraDlgJanela() {
dlgJanela.setHeightFull();
dlgJanela.setWidthFull();
dlgJanela.setCloseOnEsc(false);
dlgJanela.setCloseOnOutsideClick(false);
superior.setHeight("170px");
superior.setWidthFull();
txtNomeCliente.setWidth("350px");
txtNomeCliente.setLabel("Nome Cliente");
txtNomeCliente.setItemLabelGenerator(cliente -> {
if (cliente == null || cliente.getNome() == null) {
return " ";
} else {
return cliente.getNome();
}
});
List<Cliente> listaDeClientes = clienteRepository.findAll();
txtNomeCliente.setItems(listaDeClientes);
txtNomeCliente.addValueChangeListener(event -> {
if (event.getValue() == null || event.getValue().getFone() == null) {
txtTelefone.setValue(" ");
} else {
txtTelefone.setValue(event.getValue().getFone());
}
if (event.getValue() == null || event.getValue().getCelular() == null) {
txtCelular.setValue(" ");
} else {
txtCelular.setValue(event.getValue().getCelular());
}
if (event.getValue() == null || event.getValue().getEndereco() == null) {
txtEndereco.setValue(" ");
} else {
txtEndereco.setValue(event.getValue().getEndereco());
}
if (event.getValue() == null || event.getValue().getNumero() == null) {
txtNumero.setValue(" ");
} else {
txtNumero.setValue(event.getValue().getNumero());
}
if (event.getValue() == null || event.getValue().getBairro() == null) {
txtBairro.setValue(" ");
} else {
txtBairro.setValue(event.getValue().getBairro());
}
if (event.getValue() == null || event.getValue().getCidade() == null) {
txtCidade.setValue(" ");
} else {
txtCidade.setValue(event.getValue().getCidade());
}
if (event.getValue() == null || event.getValue().getEstado() == null) {
txtEstado.setValue(" ");
} else {
txtEstado.setValue(event.getValue().getEstado());
}
});
new CustomStringBlockFormatter.Builder().blocks(0, 2, 4, 4).delimiters("(", ")", "-").numeric().build()
.extend(txtTelefone);
new CustomStringBlockFormatter.Builder().blocks(0, 2, 5, 4).delimiters("(", ")", "-").numeric().build()
.extend(txtCelular);
primeiraLinhaDivSuperior.add(txtDataVenda, txtNomeCliente, txtTelefone, txtCelular, txtEndereco, txtNumero,
txtBairro, txtCidade);
txtNumero.setWidth("140px");
txtFormasPagamento.setLabel("Formas de Pagamento");
List<FormaDePagamento> listaPagamento = formaDePagamentoRepository.findAll();
txtFormasPagamento.setItemLabelGenerator(FormaDePagamento::getFormaDePagamento);
txtFormasPagamento.setItems(listaPagamento);
segundaLinhaDivSuperior.add(txtEstado, txtFormasPagamento);
superior.add(primeiraLinhaDivSuperior, segundaLinhaDivSuperior);
centro.setHeight("660px");
centro.getStyle().set("border-style", "ridge");
centro.getStyle().set("overflow-y", "scroll");
centro.setWidthFull();
btnSalvar.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
btnSalvar.getStyle().set("margin-top", "0em");
btnSalvar.getStyle().set("margin-left", "1em");
btnSalvar.addClickListener(e -> {
salvarClick();
});
btnFechar.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
btnFechar.getStyle().set("margin-top", "0em");
btnFechar.addClickListener(e -> {
dlgJanela.close();
limparCampos();
});
btnAdicionarItem.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
btnAdicionarItem.getStyle().set("margin-top", "0em");
btnAdicionarItem.addClickListener(e -> {
adicionaProduto();
});
Label text = new Label("Valor Total");
text.getElement().getStyle().set("fontWeight", "bold");
text.getStyle().set("margin-top", "0.8em");
text.getStyle().set("margin-left", "2em");
text.getStyle().set("text-align", "center");
campoSomaValores.getStyle().set("margin-top", "0em");
campoSomaValores.getStyle().set("margin-right", "0.2em");
campoSomaValores.setWidth("30em");
htlDlgBarraBotoes.add(btnSalvar, btnFechar, btnAdicionarItem, text, campoSomaValores);
inferior.getStyle().set("margin-top", "0px");
inferior.setHeight("45px");
inferior.setWidthFull();
inferior.add(htlDlgBarraBotoes);
dlgJanela.add(superior, centro, inferior);
}
private void salvarClick() {
venda = binderVenda.getBean();
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();
}
}
private void populaGrdVenda() {
listaVendas = vendaService.read();
atualizaGrdVenda();
}
private void atualizaGrdVenda() {
grdVenda.setItems(listaVendas);
}
private void configuraBinder() {
binderVenda.bindInstanceFields(this);
}
private void novoClick() {
novaVenda();
binderVenda.setBean(venda);
dlgJanela.open();
txtNomeCliente.focus();
}
private void alterarClick() {
if (venda != null) {
binderVenda.setBean(venda);
dlgJanela.open();
}
}
private void adicionaProduto() {
ComboBox<Produto> txtProdutos = new ComboBox<>();
NumberField txtQuantidade = new NumberField("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 -> {
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);
}
private void limparCampos() {
centro.removeAll();
}
private void novaVenda() {
venda = new Venda();
venda.setCliente(null);
venda.setFormaDePagamento(null);
dlgJanela.close();
}
}