Erro método com BigDecimal

Uma pergunta… nas restrições ele diz assim na classe Produto:

/**
 * Classe que representa um produto que pode ser adicionado
 * como item ao carrinho de compras.
 *
 * Importante: Dois produtos são considerados iguais quando ambos possuem o mesmo 
 * código.
 */

e na função adicionarItem do CarrinhoCompras só fala para checar se o item já estiver ali, então fazer isso aqui:

**if (item.getProduto().getCodigo().equals(produto.getCodigo()))** {
            	
                existe = true;
               
                if (item.getValorUnitario() != valorUnitario) {
                	
                item.setValorUnitario(valorUnitario);
                
                }
                
                item.adicionarQuantidade(quantidade);
                
                break; 
            }
        }

não vai adicionar produtos com códigos iguais, certo? Vai adicionar só códigos diferentes… ou estou errado?

Se o produto já está na lista de itens, ele só atualiza a quantidade e valor do item.

Entendi. É que estava criando produtos assim:

Produto p1 = new Produto(1L, "Leite");
Produto p2 = new Produto(1L, "Leite em pó");

E estava cadastrando ambos mesmo com código igual (no caso esse Long 1L)… é que fui ver essa restrição do mesmo código agora. Dai na hora de puxar o getItens() tá lá os 2 produtos cadastrados

[Item [Produto=Leite, Código=1, Valor Unitario=19.99, Quantidade=4]
[Item [Produto=Leite em pó, Código=1, Valor Unitario=9.99, Quantidade=2]

e embora descrições diferentes (Leite e Leite em pó) no adicionarItem() se estiver adicionando DOIS PRODUTOS EXATEMENTE IGUAIS

c.adicionarItem(p2, v2, 1);//pão
c.adicionarItem(p2, v2, 1);//pão denovo

ele atualiza a quantidade e seta o valorUnitário do parâmetro, mas se for CÓDIGO IGUAL PRODUTO DIFERENTE


Produto p2 = new Produto(4L, "Pão");
Produto p2a = new Produto(4L, "Pão");//mesmo nome e código

c.adicionarItem(p2, v2, 3);
c.adicionarItem(p2a, v8, 2);//chama pão com mesmo código e descrição, valor e quant diferente

ele add os com códigos iguais

Item [Produto=Pão, Código=4, Valor Unitario=1.14, Quantidade=3]
Item [Produto=Pão, Código=4, Valor Unitario=14.99, Quantidade=2]//esse é o p2a

Mas se forem EXATAMENTE IGUAIS ele só atualiza. Obrigado.

Man… desculpe te importunar novamente… tô ficando loko aqui… mas tem como checar antes de adicionar o item na lista pela função adicionarItem() (ou por outro lugar) se tem códigos iguais? Porque eu fiz isso aqui na parte que vc organizou:

if (item.getProduto().getCodigo().equals(produto.getCodigo()))

e se tiver mesmo código, ele não adiciona, PORÉM ele seta o valor do item seguinte e aumenta a quantidade com a do item seguinte (como era pra fazer mesmo) gerando erro no valor total e quantidade. É possível ver se os códigos dos produtos são iguais e se forem não cadastrar se de fato o produto já estiver la, só arrumar valor e quantidade, mas esse ponto dos códigos iguais lançando a exceção dentro do if, tipo para tudo… obrigado por toda a ajuda.

Coloca o código completo do método e como vc está testando

Classe CarrinhoComprars.java

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

/**
 * Classe que representa o carrinho de compras de um cliente.
 */
public class CarrinhoCompras {
	
	private List<Item> itens;
	
	public CarrinhoCompras() {
		
		itens = new ArrayList<>();
		
	}

    /**
     * Permite a adição de um novo item no carrinho de compras.
     *
     * Caso o item já exista no carrinho para este mesmo produto, as seguintes regras deverão ser seguidas:
     * - A quantidade do item deverá ser a soma da quantidade atual com a quantidade passada como parâmetro.
     * - Se o valor unitário informado for diferente do valor unitário atual do item, o novo valor unitário do item deverá ser
     * o passado como parâmetro.
     *
     * Devem ser lançadas subclasses de RuntimeException caso não seja possível adicionar o item ao carrinho de compras.
     *
     * @param produto
     * @param valorUnitario
     * @param quantidade
     */
    public void adicionarItem(Produto produto, BigDecimal valorUnitario, int quantidade) {


    	if (produto == null) {
            throw new IllegalArgumentException("Produto não pode ser nulo");
        }
    	
        if (valorUnitario == null || valorUnitario.compareTo(BigDecimal.ZERO) <= 0) {
            throw new IllegalArgumentException("Valor unitário deve ser maior que zero");
        }
        if (quantidade <= 0) {
            throw new IllegalArgumentException("Quantidade deve ser maior que zero");
        }
        
    	boolean existe = false;
    	
        for (Item item : itens) {
        	
        	//if (item.getProduto().equals(produto)) {
            if (item.getProduto().getCodigo().equals(produto.getCodigo())) {
            	
                existe = true;
                               
                if (item.getValorUnitario() != valorUnitario) {
                	
                item.setValorUnitario(valorUnitario);
                
                }
                
                item.adicionarQuantidade(quantidade);
                
                break; 
            }
        }

        if (!existe) {
        	
        	itens.add(new Item(produto, valorUnitario, quantidade));
        }  

    }

    /**
     * Permite a remoção do item que representa este produto do carrinho de compras.
     *
     * @param produto
     * @return Retorna um boolean, tendo o valor true caso o produto exista no carrinho de compras e false
     * caso o produto não exista no carrinho.
     */
    public boolean removerItem(Produto produto) {
    	
    	Iterator<Item> it = itens.iterator();
    
    	while(it.hasNext()) {
    		
    		Produto p = it.next().getProduto();
    		
    		if(p.equals(produto)) {
    			
    			it.remove();
    			
    			return true;
    		}
    	}
    	return false;
    }

    /**
     * Permite a remoção do item de acordo com a posição.
     * Essa posição deve ser determinada pela ordem de inclusão do produto na 
     * coleção, em que zero representa o primeiro item.
     *
     * @param posicaoItem
     * @return Retorna um boolean, tendo o valor true caso o produto exista no carrinho de compras e false
     * caso o produto não exista no carrinho.
     */
    public boolean removerItem(int posicaoItem) {
    	
    	if(posicaoItem < 0 || posicaoItem >= itens.size()) {
    		
    		return false;
    		
    	}
    	
    	itens.remove(posicaoItem);
    	
    	return true;

    }

    /**
     * Retorna o valor total do carrinho de compras, que deve ser a soma dos valores totais
     * de todos os itens que compõem o carrinho.
     *
     * @return BigDecimal
     */
    public BigDecimal getValorTotal() {

    	BigDecimal total = BigDecimal.ZERO;
  	  
  	  	for(Item item: getItens()) {
  	  
  	  		total = total.add(item.getValorTotal());
  	  
  	  }
  	  
  	  return total;
    }

    /**
     * Retorna a lista de itens do carrinho de compras.
     *
     * @return itens
     */
    public Collection<Item> getItens() {

    	return itens;
    }
}

Main.java

import java.math.BigDecimal;

public class Main {

	public static void main(String[] args) {

		//cria a factory
		CarrinhoComprasFactory cf = new CarrinhoComprasFactory();

		//add carrinhos na factory
		CarrinhoCompras c = cf.criar("Alexandre");
		CarrinhoCompras c1 = cf.criar("Isabela");
		//criando novo carrinho com mesma identificação
		CarrinhoCompras c2 = cf.criar("Alexandre");
		
		if (c.equals(c2)) {
			
			System.out.println("Mesmo nome retorna null");
		} else {
			System.out.println("Erro ao criar carrinho");
		}
		
		//System.out.println(c2.getIdentificacaoCliente());
		if (c2 == null) {
			System.out.println("Carrinho já criado");
		} else {
			System.out.println("Criado");
		}
				
		BigDecimal v = new BigDecimal("4.12");
		BigDecimal v1 = new BigDecimal("8.24");
		BigDecimal v2 = new BigDecimal("1.14");
		
		BigDecimal v3 = new BigDecimal("3.12");
		BigDecimal v4 = new BigDecimal("5.24");
		BigDecimal v5 = new BigDecimal("2.50");
		BigDecimal v6 = new BigDecimal("6.51");
		BigDecimal v7 = new BigDecimal("19.99");
		BigDecimal v8 = new BigDecimal("14.99");
		
		
		Produto p = new Produto(1L, "Leite");//item 0
		Produto p1 = new Produto(2L, "Carne");//item 1
		Produto p2 = new Produto(3L, "Pão");//item 2
		Produto p2a = new Produto(3L, "Pão de Sal");//mesmo nome e código, mas poderia colocar só código iguais
		//p2 e p2a mesmo código 3L
		Produto p3 = new Produto(5L, "Arroz");
		Produto p4 = new Produto(6L, "Feijão");
		Produto p5 = new Produto(7L, "Água");
		Produto p6 = new Produto(8L, "Salsicha");
		Produto p7 = new Produto(9L, "Sabão em pó");
		
		//carrinho C
		c.adicionarItem(p, v, 2);//leite
		c.adicionarItem(p1, v1, 3);//carne v1=4.12
		c.adicionarItem(p1, v3, 3);//erro deve dar aqui - carne denovo v3=3.12 TEM QUE FICAR COM ESSE VALOR
		c.adicionarItem(p2, v2, 2);//pão
		c.adicionarItem(p2, v2, 2);//pão denovo
		c.adicionarItem(p2a, v8, 2);//chama pão de sal código igual do pão pra ver o erro
		c.adicionarItem(p7, v7, 2);//sabao em pó
		//c.removerItem(p3);

		
		//carrinho C1
		c1.adicionarItem(p3, v3, 2);//arroz
		c1.adicionarItem(p3, v3, 1);//mais um arroz com 2 + 1 = 3 quantidade
		c1.adicionarItem(p4, v4, 3);//feijao
		c1.adicionarItem(p4, v4, 2);//feijao indice 2
		c1.adicionarItem(p5, v5, 1);//agua
		c1.adicionarItem(p6, v6, 3);//salsicha
		
		
		//c.removerItem(3);
		//c1.removerItem(p6);
		
		//imprimir carrinho C
		
		System.out.println("Carrinho C");
		System.out.println("Quantidade de itens: " + c.getItens().size());
		System.out.println("Lista itens no carrinho: \n");
		System.out.println(c.getItens());
		
		c.removerItem(3);//removendo sabão em pó
		System.out.println("Lista itens no carrinho depois de removido um item: \n");
		System.out.println(c.getItens());
		//c.removerItem(p7);
		//System.out.println("Carrinho C");
		//System.out.println("Quantidade de itens depois de removido algum item: " + c.getItens().size());
		//System.out.println("Lista itens no carrinho: \n");
		//System.out.println(c.getItens());
		
		//imprimir carrinho C1
		System.out.println("Carrinho C1");
		System.out.println("Quantidade de itens: " + c1.getItens().size());
		System.out.println("Lista itens no carrinho: \n");
		System.out.println(c1.getItens());

		c1.removerItem(p6);//removendo salsicha
		System.out.println("Lista itens no carrinho depois de removido um item: \n");
		System.out.println(c1.getItens());
		//c.removerItem(3);
		
		
		System.out.println(" ");
		System.out.println("Valor total dos itens do carrinho C: R$ "+c.getValorTotal());
		System.out.println("Valor total dos itens do carrinho C1: R$ "+c1.getValorTotal());
		
		System.out.println("Valor ticket medio dos carrinhos: R$ " + cf.getValorTicketMedio());
		/*
		System.out.println(c.getItens().size() + " itens no carrinho antes de remover p7: \n");
		System.out.println(c.getItens());

		System.out.println("--------------------");
		if (c.removerItem(p7)) {
		    System.out.println(c.getItens().size() + " itens no carrinho depois de remover p7: \n");
		    System.out.println(c.getItens());
		} else {
		    System.out.printf("Produto Código %d (%s) não foi removido porque não estava no carrinho \n", p7.getCodigo(), p7.getDescricao());
		}
		
		System.out.println("Depois de removido itens, valor ticketMedio muda \n");
		System.out.println("Valor ticket medio dos carrinhos: R$ " + cf.getValorTicketMedio());*/
		
		
		if(cf.invalidar("Alexandre")) {
			System.out.println("Invalidado");
		} else {
			System.out.println("Não invalidado");
		}
		
		if(cf.invalidar("Isabela")) {
			System.out.println("invalido e removido");
		} else {
			System.out.println("Não removido");
		}
			
		if(cf.invalidar("A")) {
			System.out.println("Invalido e removido");
		} else {
			System.out.println("Não invalido e não removido");
		}
		
		if(cf.invalidar("b")) {
			System.out.println("Invalido e removido");
		} else {
			System.out.println("Não invalido e não removido");
		}
	}
}

Ta aí! Obrigado!

c.adicionarItem(p1, v3, 3);//erro deve dar aqui - carne denovo v3=3.12 TEM QUE FICAR COM ESSE VALOR

Depois dessa linha, o valor do produto é 3.12, como deveria ser. A descrição diz que é para atualizar o valor, e é isso que ele faz.

c.adicionarItem(p2a, v8, 2);//chama pão de sal código igual do pão pra ver o erro

Aqui também não dá erro. Como o código é o mesmo, ele atualizar o valor para 14.99 e adiciona a quantidade.

Não entendi qual o problema. Não tem erro nenhum.

Boa tarde… desculpe te incomodar novamente. Estou pensando num ponto aqui, gostaria de saber se é possível e se tem como vc me ajudar. Estava pensando num modo de quando for remover um produto pelo removerItem(Produto produto) ele percorrer todos os carrinhos instanciados e se encontrar um produto com mesmo código, remover de todos os carrinhos.Eu pensei nissaqui:

    public List<Produto> encontrarProdutosIguais(CarrinhoCompras carrinhoCompras) {
    	  
    	List<Produto> produtosIguais = new ArrayList<>();
    	  
    	for (Item item : carrinhoCompras.getItens()) {
    	  
    		Produto produtoAtual = item.getProduto();
    	   
    		boolean produtoJaEncontrado = false;
    	    
    		for (Produto produtoIgual : produtosIguais) {
    	     
    			if (produtoAtual.equals(produtoIgual)) {
    	     
    	    	  produtoJaEncontrado = true;
    	     
    	    	  break;
    	     
    			}
    	    }
    		
    	    if (!produtoJaEncontrado) {
    	     
    	    	produtosIguais.add(produtoAtual);
    	   
    	    }

Mas não ta indo. Adicionei esse método no CarrinhoCompras dentro do removerItem(Produto produto) mas só remove do carrinho que eu especifico, mais ou menos assim:

				CarrinhoComprasFactory cf = new CarrinhoComprasFactory();

				//add carrinhos na factory
				CarrinhoCompras c = cf.criar("Cliente1");
				CarrinhoCompras c1 = cf.criar("Cliente2");

				Produto p1 = new Produto(2L, "Carne");
				Produto p2 = new Produto(3L, "Pão");
                                Produto p3 = new Produto(3L, "Pão de Sal");

                c.adicionarItem(p2, v2, 2);
                c.adicionarItem(p7, v5, 2);

                c1.adicionarItem(p3, v6, 2);
                c1.adicionarItem(p7, v7, 2);

//e se eu chamo para c1.removerItem(p7)
//só remove do c1, e fica lá no carrinho c

é possível percorrer todos os carrinhos criados com o código acima, e remover produtos com o código igual de todos os carrinhos?

Obrigado.

Você pode modificar o seu método removerItem dessa forma:

public boolean removerItem(Produto produto) {
    List<Item> itensIguais = new ArrayList<>();
    for (Item item : itens) {
    	Produto p = item.getProduto();
    	if (p.equals(produto)) {
    		itensIguais.add(item);
    	}
    }
    itens.removeAll(itensIguais);
    return !itensIguais.isEmpty();
}

Aí crie um método estático na classe CarrinhoCompras que permita remover os itens de vários carrinhos de uma só vez:

public static void removerItem(Produto produto, CarrinhoCompras... carrinhos) {
    for (CarrinhoCompras carrinho : carrinhos) {
        carrinho.removerItem(produto);
    }
}

Então, no seu main você pode fazer assim:

CarrinhoComprasFactory cf = new CarrinhoComprasFactory();

CarrinhoCompras c1 = cf.criar("Cliente1");
CarrinhoCompras c2 = cf.criar("Cliente2");

Produto p1 = new Produto(2L, "Carne");
Produto p2 = new Produto(3L, "Pão");
Produto p3 = new Produto(3L, "Pão de Sal");

c1.adicionarItem(p2, v2, 2);
c1.adicionarItem(p7, v5, 2);

c2.adicionarItem(p3, v6, 2);
c2.adicionarItem(p7, v7, 2);

CarrinhoCompras.removerItem(p7, c1, c2);

Tenho uma pergunta: Porque você tem uma CarrinhoComprasFactory sendo que seu CarrinhoCompras possui um construtor padrão público e não implementa nenhuma interface?