From 94074910eb95b8cc292c34d9b73ce531b4adb0bf Mon Sep 17 00:00:00 2001 From: William Almeida Date: Wed, 28 Apr 2021 17:48:28 -0300 Subject: [PATCH] feat: cadastrar fotos para um produto --- .../william/ecommerce/produto/Produto.java | 31 +++++++++- .../caracteristica/ProdutoCaracteristica.java | 11 ++-- .../produto/imagem/ProdutoImagem.java | 29 +++++++++ .../imagem/ProdutoImagemController.java | 59 +++++++++++++++++++ .../produto/imagem/ProdutoImagemInputDto.java | 22 +++++++ .../produto/imagem/UploaderFake.java | 18 ++++++ .../william/ecommerce/usuario/Usuario.java | 14 +++-- src/main/resources/messages.properties | 6 +- 8 files changed, 180 insertions(+), 10 deletions(-) create mode 100644 src/main/java/br/com/zupacademy/william/ecommerce/produto/imagem/ProdutoImagem.java create mode 100644 src/main/java/br/com/zupacademy/william/ecommerce/produto/imagem/ProdutoImagemController.java create mode 100644 src/main/java/br/com/zupacademy/william/ecommerce/produto/imagem/ProdutoImagemInputDto.java create mode 100644 src/main/java/br/com/zupacademy/william/ecommerce/produto/imagem/UploaderFake.java diff --git a/src/main/java/br/com/zupacademy/william/ecommerce/produto/Produto.java b/src/main/java/br/com/zupacademy/william/ecommerce/produto/Produto.java index 4b36ad77..f113832e 100644 --- a/src/main/java/br/com/zupacademy/william/ecommerce/produto/Produto.java +++ b/src/main/java/br/com/zupacademy/william/ecommerce/produto/Produto.java @@ -2,6 +2,7 @@ import br.com.zupacademy.william.ecommerce.categoria.Categoria; import br.com.zupacademy.william.ecommerce.produto.caracteristica.ProdutoCaracteristica; +import br.com.zupacademy.william.ecommerce.produto.imagem.ProdutoImagem; import br.com.zupacademy.william.ecommerce.usuario.Usuario; import io.jsonwebtoken.lang.Assert; import org.hibernate.annotations.CreationTimestamp; @@ -9,7 +10,9 @@ import javax.persistence.*; import java.math.BigDecimal; import java.time.LocalDateTime; +import java.util.Objects; import java.util.Set; +import java.util.stream.Collectors; @Entity public class Produto { @@ -23,7 +26,7 @@ public class Produto { private int quantidadeDisponivel; private String descricao; - @OneToMany(cascade = CascadeType.ALL) + @OneToMany(cascade = CascadeType.ALL, mappedBy = "produto") private Set caracteristicas; @ManyToOne @@ -37,6 +40,9 @@ public class Produto { @CreationTimestamp private LocalDateTime instanteCriacao = LocalDateTime.now(); + @OneToMany(cascade = CascadeType.ALL, mappedBy = "produto") + private Set imagens; + public Produto(String nome, BigDecimal valor, int quantidadeDisponivel, String descricao, Set caracteristicas, Categoria categoria, Usuario donoDoProduto) { this.nome = nome; @@ -49,4 +55,27 @@ public Produto(String nome, BigDecimal valor, int quantidadeDisponivel, String d Assert.isTrue(this.caracteristicas.size() >= 3, "É necessário ao menos 3 características para um produto"); } + + @Deprecated + public Produto() { + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Produto produto = (Produto) o; + return Objects.equals(id, produto.id); + } + + @Override + public int hashCode() { + return Objects.hash(id, nome, valor, quantidadeDisponivel, descricao, caracteristicas, categoria, donoDoProduto, instanteCriacao, imagens); + } + + public void associarImagens(Set links) { + this.imagens.addAll(links.stream() + .map(link -> new ProdutoImagem(this, link)) + .collect(Collectors.toSet())); + } } diff --git a/src/main/java/br/com/zupacademy/william/ecommerce/produto/caracteristica/ProdutoCaracteristica.java b/src/main/java/br/com/zupacademy/william/ecommerce/produto/caracteristica/ProdutoCaracteristica.java index 360bdbc7..a50bac16 100644 --- a/src/main/java/br/com/zupacademy/william/ecommerce/produto/caracteristica/ProdutoCaracteristica.java +++ b/src/main/java/br/com/zupacademy/william/ecommerce/produto/caracteristica/ProdutoCaracteristica.java @@ -1,9 +1,8 @@ package br.com.zupacademy.william.ecommerce.produto.caracteristica; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; +import br.com.zupacademy.william.ecommerce.produto.Produto; + +import javax.persistence.*; import java.util.Objects; @Entity @@ -16,6 +15,10 @@ public class ProdutoCaracteristica { private String nome; private String descricao; + @ManyToOne + @JoinColumn(name = "id_produto") + private Produto produto; + public ProdutoCaracteristica(String nome, String descricao) { this.nome = nome; this.descricao = descricao; diff --git a/src/main/java/br/com/zupacademy/william/ecommerce/produto/imagem/ProdutoImagem.java b/src/main/java/br/com/zupacademy/william/ecommerce/produto/imagem/ProdutoImagem.java new file mode 100644 index 00000000..dfb43eed --- /dev/null +++ b/src/main/java/br/com/zupacademy/william/ecommerce/produto/imagem/ProdutoImagem.java @@ -0,0 +1,29 @@ +package br.com.zupacademy.william.ecommerce.produto.imagem; + +import br.com.zupacademy.william.ecommerce.produto.Produto; + +import javax.persistence.*; + +@Entity +public class ProdutoImagem { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String link; + + @ManyToOne + @JoinColumn(name = "id_produto") + private Produto produto; + + public ProdutoImagem(Produto produto, String link) { + this.produto = produto; + this.link = link; + } + + @Deprecated + public ProdutoImagem() { + + } +} diff --git a/src/main/java/br/com/zupacademy/william/ecommerce/produto/imagem/ProdutoImagemController.java b/src/main/java/br/com/zupacademy/william/ecommerce/produto/imagem/ProdutoImagemController.java new file mode 100644 index 00000000..176222a3 --- /dev/null +++ b/src/main/java/br/com/zupacademy/william/ecommerce/produto/imagem/ProdutoImagemController.java @@ -0,0 +1,59 @@ +package br.com.zupacademy.william.ecommerce.produto.imagem; + +import br.com.zupacademy.william.ecommerce.produto.Produto; +import br.com.zupacademy.william.ecommerce.produto.ProdutoRepository; +import br.com.zupacademy.william.ecommerce.usuario.Usuario; +import br.com.zupacademy.william.ecommerce.usuario.UsuarioRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.server.ResponseStatusException; + +import javax.transaction.Transactional; +import javax.validation.Valid; +import java.util.Optional; +import java.util.Set; + +@RestController +@RequestMapping("/produtos") +public class ProdutoImagemController { + + @Autowired + private UsuarioRepository usuarioRepository; + + @Autowired + private ProdutoRepository produtoRepository; + + @Autowired + private UploaderFake uploaderFake; + + @Transactional + @PostMapping("/{id}/imagens") + public ResponseEntity adicionaImagem(@PathVariable Long id, + @Valid ProdutoImagemInputDto produtoImagemInputDto, + @AuthenticationPrincipal Usuario usuarioLogado) { + Optional possivelProduto = produtoRepository.findById(id); + + if (possivelProduto.isEmpty()) { + throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Produto não encontrado"); + } + + Produto produto = possivelProduto.get(); + boolean eDonoDoProduto = usuarioLogado.eDonoDoProduto(produto); + + if (!eDonoDoProduto) { +// return ResponseEntity.status(HttpStatus.FORBIDDEN).body("Você nao é dono do produto"); + throw new ResponseStatusException(HttpStatus.FORBIDDEN, "Você não é dono do produto"); + } + + Set links = uploaderFake.envia(produtoImagemInputDto.getImagens()); + produto.associarImagens(links); + + return ResponseEntity.ok().build(); + } +} diff --git a/src/main/java/br/com/zupacademy/william/ecommerce/produto/imagem/ProdutoImagemInputDto.java b/src/main/java/br/com/zupacademy/william/ecommerce/produto/imagem/ProdutoImagemInputDto.java new file mode 100644 index 00000000..a52eaf5b --- /dev/null +++ b/src/main/java/br/com/zupacademy/william/ecommerce/produto/imagem/ProdutoImagemInputDto.java @@ -0,0 +1,22 @@ +package br.com.zupacademy.william.ecommerce.produto.imagem; + +import org.springframework.web.multipart.MultipartFile; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import java.util.List; + +public class ProdutoImagemInputDto { + + @Size(min = 1, max = 7) + @NotNull + private List imagens; + + public ProdutoImagemInputDto(List imagens) { + this.imagens = imagens; + } + + public List getImagens() { + return imagens; + } +} diff --git a/src/main/java/br/com/zupacademy/william/ecommerce/produto/imagem/UploaderFake.java b/src/main/java/br/com/zupacademy/william/ecommerce/produto/imagem/UploaderFake.java new file mode 100644 index 00000000..f2f88445 --- /dev/null +++ b/src/main/java/br/com/zupacademy/william/ecommerce/produto/imagem/UploaderFake.java @@ -0,0 +1,18 @@ +package br.com.zupacademy.william.ecommerce.produto.imagem; + +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +@Component +public class UploaderFake { + + public Set envia(List imagens) { + return imagens.stream() + .map(imagem -> "http://bucket.io/" + imagem.getOriginalFilename() + ".com") + .collect(Collectors.toSet()); + } +} diff --git a/src/main/java/br/com/zupacademy/william/ecommerce/usuario/Usuario.java b/src/main/java/br/com/zupacademy/william/ecommerce/usuario/Usuario.java index 9235e6df..db96a1a2 100644 --- a/src/main/java/br/com/zupacademy/william/ecommerce/usuario/Usuario.java +++ b/src/main/java/br/com/zupacademy/william/ecommerce/usuario/Usuario.java @@ -1,14 +1,13 @@ package br.com.zupacademy.william.ecommerce.usuario; +import br.com.zupacademy.william.ecommerce.produto.Produto; import org.hibernate.annotations.CreationTimestamp; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import javax.persistence.*; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; +import java.util.*; @Entity public class Usuario implements UserDetails { @@ -21,11 +20,14 @@ public class Usuario implements UserDetails { private String senha; @ManyToMany(fetch = FetchType.EAGER) - private List perfis = new ArrayList<>(); + private Set perfis = new HashSet<>(); @CreationTimestamp private LocalDateTime instanteCadastro = LocalDateTime.now(); + @OneToMany(mappedBy = "donoDoProduto", fetch = FetchType.EAGER) + private List produtos; + public Usuario(String login, SenhaLimpa senhaLimpa) { this.login = login; this.senha = senhaLimpa.hash(); @@ -35,6 +37,10 @@ public Usuario(String login, SenhaLimpa senhaLimpa) { public Usuario() { } + public boolean eDonoDoProduto(Produto produto) { + return this.produtos.contains(produto); + } + public Long getId() { return id; } diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index c4d0d016..c806727c 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -1,4 +1,5 @@ NotBlank={0} é obrigatório(a) +NotNull={0} é obrigatório(a) Email={0} deve ser um e-mail válido UniqueValue={0} já existe no banco de dados ExistsId={0} não existe no banco de dados @@ -28,4 +29,7 @@ produtoInputDto.idCategoria=Categoria do produto #ProdutoCaracteristicaInputDto produtoCaracteristicaInputDto.nome=Nome da característica -produtoCaracteristicaInputDto.descricao=Descrição da característica \ No newline at end of file +produtoCaracteristicaInputDto.descricao=Descrição da característica + +#FotoProdutoInputDto +produtoImagemInputDto[0-9].imagens=Imagem do produto \ No newline at end of file