From 1a67504938064890f6b00f14621568f77594643d Mon Sep 17 00:00:00 2001 From: Thiago Dotto Date: Sun, 18 Aug 2019 13:18:04 -0300 Subject: [PATCH 1/9] =?UTF-8?q?Teste=20De=20integracao=20de=20gastos=20por?= =?UTF-8?q?=20cart=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 57 ++++++++++++ .../santander/TestBackJavaApplication.java | 13 +++ src/main/java/com/santander/model/Gasto.java | 68 ++++++++++++++ .../santander/repository/GastoRepositoy.java | 12 +++ .../java/com/santander/repository/Gastos.java | 9 ++ .../com/santander/service/GastoService.java | 25 ++++++ .../com/santander/service/IGastoService.java | 11 +++ src/main/resources/application.properties | 12 +++ .../com/santander/IntegracaoGastosTest.java | 90 +++++++++++++++++++ .../TestBackJavaApplicationTests.java | 16 ++++ 10 files changed, 313 insertions(+) create mode 100644 pom.xml create mode 100644 src/main/java/com/santander/TestBackJavaApplication.java create mode 100644 src/main/java/com/santander/model/Gasto.java create mode 100644 src/main/java/com/santander/repository/GastoRepositoy.java create mode 100644 src/main/java/com/santander/repository/Gastos.java create mode 100644 src/main/java/com/santander/service/GastoService.java create mode 100644 src/main/java/com/santander/service/IGastoService.java create mode 100644 src/main/resources/application.properties create mode 100644 src/test/java/com/santander/IntegracaoGastosTest.java create mode 100644 src/test/java/com/santander/TestBackJavaApplicationTests.java diff --git a/pom.xml b/pom.xml new file mode 100644 index 00000000..5bc4da86 --- /dev/null +++ b/pom.xml @@ -0,0 +1,57 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.1.7.RELEASE + + + com.santander + TestBackJava + 0.0.1-SNAPSHOT + TestBackJava + Demo project for Spring Boot + + + 1.8 + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-web + + + + com.h2database + h2 + runtime + + + org.projectlombok + lombok + true + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/src/main/java/com/santander/TestBackJavaApplication.java b/src/main/java/com/santander/TestBackJavaApplication.java new file mode 100644 index 00000000..a669448c --- /dev/null +++ b/src/main/java/com/santander/TestBackJavaApplication.java @@ -0,0 +1,13 @@ +package com.santander; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class TestBackJavaApplication { + + public static void main(String[] args) { + SpringApplication.run(TestBackJavaApplication.class, args); + } + +} diff --git a/src/main/java/com/santander/model/Gasto.java b/src/main/java/com/santander/model/Gasto.java new file mode 100644 index 00000000..a60c070f --- /dev/null +++ b/src/main/java/com/santander/model/Gasto.java @@ -0,0 +1,68 @@ +package com.santander.model; + +import java.time.LocalDateTime; + +import javax.persistence.Entity; + +@Entity +public class Gasto implements Runnable{ + + private Long id; + + private String descricao; + + private Double valor; + + private int codigoUsuario; + + private LocalDateTime data; + + public void setDescricao(String descricao) { + this.descricao = descricao; + + } + + public Double getValor() { + return valor; + } + + public void setValor(Double valor) { + this.valor = valor; + } + + public int getCodigoUsuario() { + return codigoUsuario; + } + + public void setCodigoUsuario(int codigousuario) { + this.codigoUsuario = codigousuario; + } + + public LocalDateTime getData() { + return data; + } + + public void setData(LocalDateTime data) { + this.data = data; + } + + public String getDescricao() { + return descricao; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + @Override + public void run() { + + System.out.println("incluindo " ); + + } + +} diff --git a/src/main/java/com/santander/repository/GastoRepositoy.java b/src/main/java/com/santander/repository/GastoRepositoy.java new file mode 100644 index 00000000..a2c01be4 --- /dev/null +++ b/src/main/java/com/santander/repository/GastoRepositoy.java @@ -0,0 +1,12 @@ +package com.santander.repository; + +import com.santander.model.Gasto; + +public interface GastoRepositoy { + + public Gasto save(Gasto gasto); + + public Integer count(); + + +} diff --git a/src/main/java/com/santander/repository/Gastos.java b/src/main/java/com/santander/repository/Gastos.java new file mode 100644 index 00000000..d7e6f08d --- /dev/null +++ b/src/main/java/com/santander/repository/Gastos.java @@ -0,0 +1,9 @@ +package com.santander.repository; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.santander.model.Gasto; + +public interface Gastos extends JpaRepository { + +} diff --git a/src/main/java/com/santander/service/GastoService.java b/src/main/java/com/santander/service/GastoService.java new file mode 100644 index 00000000..5d7dc7cd --- /dev/null +++ b/src/main/java/com/santander/service/GastoService.java @@ -0,0 +1,25 @@ +package com.santander.service; + +import java.util.List; + +import com.santander.model.Gasto; +import com.santander.repository.GastoRepositoy; + +public class GastoService implements IGastoService { + + private GastoRepositoy gastosRepository; + + public GastoService(GastoRepositoy gastoRepository) { + this.gastosRepository = gastoRepository; + } + + @Override + public void salvar(List listGasto) { + + for (Gasto gasto : listGasto) { + gastosRepository.save(gasto); + } + + } + +} diff --git a/src/main/java/com/santander/service/IGastoService.java b/src/main/java/com/santander/service/IGastoService.java new file mode 100644 index 00000000..75b23fa5 --- /dev/null +++ b/src/main/java/com/santander/service/IGastoService.java @@ -0,0 +1,11 @@ +package com.santander.service; + +import java.util.List; + +import com.santander.model.Gasto; + +public interface IGastoService { + + public void salvar(List listGasto); + +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 00000000..46a6309d --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1,12 @@ +spring.datasource.url=jdbc:h2:mem:testdb +spring.datasource.driverClassName=org.h2.Driver +spring.datasource.username=sa +spring.datasource.password=12345 +spring.jpa.database-platform=org.hibernate.dialect.H2Dialect +spring.h2.console.enabled=true + +server.port=8000 +server.servlet.context-path= /gasto + +spring.jpa.show-sql=true +spring.jackson.deserialization.fail-on-unknown-properties= true diff --git a/src/test/java/com/santander/IntegracaoGastosTest.java b/src/test/java/com/santander/IntegracaoGastosTest.java new file mode 100644 index 00000000..b0947b23 --- /dev/null +++ b/src/test/java/com/santander/IntegracaoGastosTest.java @@ -0,0 +1,90 @@ +package com.santander; + +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.junit4.SpringRunner; + +import com.santander.model.Gasto; +import com.santander.repository.GastoRepositoy; +import com.santander.service.GastoService; +import com.santander.service.IGastoService; + +@RunWith(SpringRunner.class) +public class IntegracaoGastosTest { + + @MockBean + private GastoRepositoy gastoRepository; + + private IGastoService gastoService; + + private Gasto gasto; + private List listGasto; + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Before + public void setUp() { + listGasto = new ArrayList(); + + gasto = new Gasto(); + gasto.setDescricao("Primeiro Gsato"); + gasto.setValor(1.0); + gasto.setCodigoUsuario(1); + gasto.setData(LocalDateTime.now()); + + gastoService = new GastoService(gastoRepository); + } + + @Test + public void deveSalvarGastosNoRepositorio() { + + listGasto.add(gasto); + + gastoService.salvar(listGasto); + verify(gastoRepository).save(gasto); + } + + @Test + public void deveSalvar2GastosNoRepositorio() throws Exception { + + listGasto.add(gasto); + listGasto.add(gasto); + gastoService.salvar(listGasto); + + verify(gastoRepository, times(2)).save(gasto); + + } + + @Test + public void deveSalvarCemMilGastosPorSegundoNoRepositorio() { + + long inicio = System.currentTimeMillis(); + + for (int i = 0; i <= 100000 - 1; i++) { + listGasto.add(gasto); + } + + long fim = System.currentTimeMillis(); + long tempo = fim - inicio; + + gastoService.salvar(listGasto); + verify(gastoRepository, times(100000)).save(gasto); + + assertTrue(tempo <= 1000); + + } + +} diff --git a/src/test/java/com/santander/TestBackJavaApplicationTests.java b/src/test/java/com/santander/TestBackJavaApplicationTests.java new file mode 100644 index 00000000..d49dd237 --- /dev/null +++ b/src/test/java/com/santander/TestBackJavaApplicationTests.java @@ -0,0 +1,16 @@ +package com.santander; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class TestBackJavaApplicationTests { + + @Test + public void contextLoads() { + } + +} From 633e3f042715fa51f93ab17b6a45a06ee341846c Mon Sep 17 00:00:00 2001 From: Thiago Dotto Date: Tue, 20 Aug 2019 17:31:00 -0300 Subject: [PATCH 2/9] =?UTF-8?q?Salvando=20gastos=20por=20cart=C3=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/santander/model/Gasto.java | 88 +++++++++++++++---- .../com/santander/service/GastoService.java | 10 +-- .../com/santander/service/IGastoService.java | 4 +- src/main/resources/application.properties | 4 + .../com/santander/IntegracaoGastosTest.java | 33 ++++--- 5 files changed, 94 insertions(+), 45 deletions(-) diff --git a/src/main/java/com/santander/model/Gasto.java b/src/main/java/com/santander/model/Gasto.java index a60c070f..3b404f6f 100644 --- a/src/main/java/com/santander/model/Gasto.java +++ b/src/main/java/com/santander/model/Gasto.java @@ -1,32 +1,61 @@ package com.santander.model; +import java.math.BigDecimal; import java.time.LocalDateTime; +import javax.persistence.Column; import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; @Entity -public class Gasto implements Runnable{ +public class Gasto { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + @NotBlank + @Size(min = 3, max = 250) + @Column(name = "descricao") private String descricao; - private Double valor; + @Column(name = "valor") + private BigDecimal valor; + @Column(name = "codigoUsuario") private int codigoUsuario; + @Column(name = "data") private LocalDateTime data; + @Column(name = "categoria") + private String categoria; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getDescricao() { + return descricao; + } + public void setDescricao(String descricao) { this.descricao = descricao; - } - public Double getValor() { + public BigDecimal getValor() { return valor; } - public void setValor(Double valor) { + public void setValor(BigDecimal valor) { this.valor = valor; } @@ -34,8 +63,8 @@ public int getCodigoUsuario() { return codigoUsuario; } - public void setCodigoUsuario(int codigousuario) { - this.codigoUsuario = codigousuario; + public void setCodigoUsuario(int codigoUsuario) { + this.codigoUsuario = codigoUsuario; } public LocalDateTime getData() { @@ -46,23 +75,48 @@ public void setData(LocalDateTime data) { this.data = data; } - public String getDescricao() { - return descricao; + public boolean temCategoria() { + return false; + } - public Long getId() { - return id; + public String getCategoria() { + return categoria; } - public void setId(Long id) { - this.id = id; + public void setCategoria(String categoria) { + this.categoria = categoria; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((data == null) ? 0 : data.hashCode()); + result = prime * result + ((id == null) ? 0 : id.hashCode()); + return result; } @Override - public void run() { - - System.out.println("incluindo " ); - + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Gasto other = (Gasto) obj; + if (data == null) { + if (other.data != null) + return false; + } else if (!data.equals(other.data)) + return false; + if (id == null) { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + return true; } } diff --git a/src/main/java/com/santander/service/GastoService.java b/src/main/java/com/santander/service/GastoService.java index 5d7dc7cd..1cfed0d3 100644 --- a/src/main/java/com/santander/service/GastoService.java +++ b/src/main/java/com/santander/service/GastoService.java @@ -1,7 +1,5 @@ package com.santander.service; -import java.util.List; - import com.santander.model.Gasto; import com.santander.repository.GastoRepositoy; @@ -14,12 +12,8 @@ public GastoService(GastoRepositoy gastoRepository) { } @Override - public void salvar(List listGasto) { - - for (Gasto gasto : listGasto) { - gastosRepository.save(gasto); - } - + public Gasto salvar(Gasto gasto) { + return gastosRepository.save(gasto); } } diff --git a/src/main/java/com/santander/service/IGastoService.java b/src/main/java/com/santander/service/IGastoService.java index 75b23fa5..c29b5a86 100644 --- a/src/main/java/com/santander/service/IGastoService.java +++ b/src/main/java/com/santander/service/IGastoService.java @@ -1,11 +1,9 @@ package com.santander.service; -import java.util.List; - import com.santander.model.Gasto; public interface IGastoService { - public void salvar(List listGasto); + public Gasto salvar(Gasto gasto); } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 46a6309d..8af64327 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -9,4 +9,8 @@ server.port=8000 server.servlet.context-path= /gasto spring.jpa.show-sql=true + spring.jackson.deserialization.fail-on-unknown-properties= true +spring.jackson.serialization.write-dates-as-timestamps= false + +spring.jackson.date-format=yyyy-MM-dd diff --git a/src/test/java/com/santander/IntegracaoGastosTest.java b/src/test/java/com/santander/IntegracaoGastosTest.java index b0947b23..db85a092 100644 --- a/src/test/java/com/santander/IntegracaoGastosTest.java +++ b/src/test/java/com/santander/IntegracaoGastosTest.java @@ -4,9 +4,8 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import java.math.BigDecimal; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; import org.junit.Before; import org.junit.Rule; @@ -30,18 +29,17 @@ public class IntegracaoGastosTest { private IGastoService gastoService; private Gasto gasto; - private List listGasto; @Rule public ExpectedException expectedException = ExpectedException.none(); + @Before public void setUp() { - listGasto = new ArrayList(); gasto = new Gasto(); - gasto.setDescricao("Primeiro Gsato"); - gasto.setValor(1.0); + gasto.setDescricao("Primeiro Gasto"); + gasto.setValor(new BigDecimal(1.0)); gasto.setCodigoUsuario(1); gasto.setData(LocalDateTime.now()); @@ -50,39 +48,40 @@ public void setUp() { @Test public void deveSalvarGastosNoRepositorio() { - - listGasto.add(gasto); - - gastoService.salvar(listGasto); + gastoService.salvar(gasto); verify(gastoRepository).save(gasto); } @Test public void deveSalvar2GastosNoRepositorio() throws Exception { - listGasto.add(gasto); - listGasto.add(gasto); - gastoService.salvar(listGasto); + Gasto gasto2 = new Gasto(); + gasto2.setCategoria(null); + gasto2.setDescricao("Segundo Gsato"); + gasto2.setValor(new BigDecimal(10.00)); + gasto2.setCodigoUsuario(2); + gasto2.setData(LocalDateTime.now()); + gastoService.salvar(gasto); + gastoService.salvar(gasto2); + verify(gastoRepository, times(2)).save(gasto); } - + @Test public void deveSalvarCemMilGastosPorSegundoNoRepositorio() { long inicio = System.currentTimeMillis(); for (int i = 0; i <= 100000 - 1; i++) { - listGasto.add(gasto); + gastoService.salvar(gasto); } long fim = System.currentTimeMillis(); long tempo = fim - inicio; - gastoService.salvar(listGasto); verify(gastoRepository, times(100000)).save(gasto); - assertTrue(tempo <= 1000); } From ddc6d78b2dcd893daf4ad3f68f66ac5577f3a051 Mon Sep 17 00:00:00 2001 From: Thiago Dotto Date: Tue, 20 Aug 2019 17:40:09 -0300 Subject: [PATCH 3/9] =?UTF-8?q?Salvando=20gastos=20por=20cart=C3=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../santander/repository/GastoRepositoy.java | 11 +++--- .../com/santander/resource/GastoResouce.java | 36 +++++++++++++++++++ .../com/santander/service/GastoService.java | 5 +++ 3 files changed, 46 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/santander/resource/GastoResouce.java diff --git a/src/main/java/com/santander/repository/GastoRepositoy.java b/src/main/java/com/santander/repository/GastoRepositoy.java index a2c01be4..4549c628 100644 --- a/src/main/java/com/santander/repository/GastoRepositoy.java +++ b/src/main/java/com/santander/repository/GastoRepositoy.java @@ -1,12 +1,11 @@ package com.santander.repository; -import com.santander.model.Gasto; - -public interface GastoRepositoy { +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; - public Gasto save(Gasto gasto); - - public Integer count(); +import com.santander.model.Gasto; +@Repository +public interface GastoRepositoy extends JpaRepository { } diff --git a/src/main/java/com/santander/resource/GastoResouce.java b/src/main/java/com/santander/resource/GastoResouce.java new file mode 100644 index 00000000..7a0e12d8 --- /dev/null +++ b/src/main/java/com/santander/resource/GastoResouce.java @@ -0,0 +1,36 @@ +package com.santander.resource; + +import java.net.URI; + +import javax.validation.Valid; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; + +import com.santander.model.Gasto; +import com.santander.service.GastoService; + +@RestController +@RequestMapping("/") +public class GastoResouce { + + @Autowired + private GastoService gastoService; + + @PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity criarGasto(@Valid @RequestBody Gasto gasto) { + + Gasto gastoSalvo = gastoService.salvar(gasto); + + URI uri = ServletUriComponentsBuilder.fromCurrentRequestUri().path("/usuario/{codigoUsuario}") + .buildAndExpand(gastoSalvo.getCodigoUsuario()).toUri(); + + return ResponseEntity.created(uri).body(gastoSalvo); + } +} \ No newline at end of file diff --git a/src/main/java/com/santander/service/GastoService.java b/src/main/java/com/santander/service/GastoService.java index 1cfed0d3..2c9949f7 100644 --- a/src/main/java/com/santander/service/GastoService.java +++ b/src/main/java/com/santander/service/GastoService.java @@ -1,10 +1,15 @@ package com.santander.service; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + import com.santander.model.Gasto; import com.santander.repository.GastoRepositoy; +@Service public class GastoService implements IGastoService { + @Autowired private GastoRepositoy gastosRepository; public GastoService(GastoRepositoy gastoRepository) { From 3e8b18febfcbb02fadf30952e03c9fac98a0dac3 Mon Sep 17 00:00:00 2001 From: Thiago Dotto Date: Tue, 20 Aug 2019 17:53:28 -0300 Subject: [PATCH 4/9] Listagem de Gastos --- .../santander/repository/GastoRepositoy.java | 3 +- .../repository/filter/GastoFilter.java | 19 ++++++ .../repository/gasto/GastoRepositoyImpl.java | 63 +++++++++++++++++++ .../repository/gasto/GastoRepositoyQuery.java | 10 +++ .../com/santander/resource/GastoResouce.java | 10 +++ .../com/santander/service/GastoService.java | 8 +++ .../com/santander/service/IGastoService.java | 5 ++ .../com/santander/IntegracaoGastosTest.java | 20 +++++- 8 files changed, 134 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/santander/repository/filter/GastoFilter.java create mode 100644 src/main/java/com/santander/repository/gasto/GastoRepositoyImpl.java create mode 100644 src/main/java/com/santander/repository/gasto/GastoRepositoyQuery.java diff --git a/src/main/java/com/santander/repository/GastoRepositoy.java b/src/main/java/com/santander/repository/GastoRepositoy.java index 4549c628..8da0f5d9 100644 --- a/src/main/java/com/santander/repository/GastoRepositoy.java +++ b/src/main/java/com/santander/repository/GastoRepositoy.java @@ -4,8 +4,9 @@ import org.springframework.stereotype.Repository; import com.santander.model.Gasto; +import com.santander.repository.gasto.GastoRepositoyQuery; @Repository -public interface GastoRepositoy extends JpaRepository { +public interface GastoRepositoy extends JpaRepository, GastoRepositoyQuery { } diff --git a/src/main/java/com/santander/repository/filter/GastoFilter.java b/src/main/java/com/santander/repository/filter/GastoFilter.java new file mode 100644 index 00000000..94e7047f --- /dev/null +++ b/src/main/java/com/santander/repository/filter/GastoFilter.java @@ -0,0 +1,19 @@ +package com.santander.repository.filter; + +import java.time.LocalDate; + +import org.springframework.format.annotation.DateTimeFormat; + +public class GastoFilter { + @DateTimeFormat(pattern = "yyyy-MM-dd") + private LocalDate data; + + public LocalDate getData() { + return data; + } + + public void setData(LocalDate data) { + this.data = data; + } + +} diff --git a/src/main/java/com/santander/repository/gasto/GastoRepositoyImpl.java b/src/main/java/com/santander/repository/gasto/GastoRepositoyImpl.java new file mode 100644 index 00000000..ca6fee7c --- /dev/null +++ b/src/main/java/com/santander/repository/gasto/GastoRepositoyImpl.java @@ -0,0 +1,63 @@ +package com.santander.repository.gasto; + +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.ArrayList; +import java.util.List; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.TypedQuery; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; + +import org.springframework.util.StringUtils; + +import com.santander.model.Gasto; +import com.santander.repository.filter.GastoFilter; + +public class GastoRepositoyImpl implements GastoRepositoyQuery { + + @PersistenceContext + private EntityManager manager; + + @Override + public List filtrar(GastoFilter gastoFilter, int codigoUsuario) { + + CriteriaBuilder builder = manager.getCriteriaBuilder(); + CriteriaQuery criteria = builder.createQuery(Gasto.class); + Root root = criteria.from(Gasto.class); + + Predicate[] predicates = criarRestricoes(gastoFilter, codigoUsuario, builder, root); + criteria.where(predicates); + + TypedQuery query = manager.createQuery(criteria); + return query.getResultList(); + } + + private Predicate[] criarRestricoes(GastoFilter gastoFilter, int codigoUsuario, CriteriaBuilder builder, + Root root) { + + List predicates = new ArrayList<>(); + + if (gastoFilter.getData() != null) { + predicates.add(builder.greaterThanOrEqualTo(root.get("data"), gastoFilter.getData().atStartOfDay())); + predicates.add(builder.lessThanOrEqualTo(root.get("data"), gastoFilter.getData().atTime(LocalTime.MAX))); + } else { + LocalDateTime now = LocalDateTime.now(); + predicates.add(builder.lessThanOrEqualTo(root.get("data"), now)); + + LocalDateTime second = now.minusSeconds(5); + predicates.add(builder.greaterThanOrEqualTo(root.get("data"), second)); + } + + if (!StringUtils.isEmpty(codigoUsuario)) { + predicates.add(builder.equal(root.get("codigoUsuario"), codigoUsuario)); + } + return predicates.toArray(new Predicate[predicates.size()]); + } + + +} diff --git a/src/main/java/com/santander/repository/gasto/GastoRepositoyQuery.java b/src/main/java/com/santander/repository/gasto/GastoRepositoyQuery.java new file mode 100644 index 00000000..a4e24cbe --- /dev/null +++ b/src/main/java/com/santander/repository/gasto/GastoRepositoyQuery.java @@ -0,0 +1,10 @@ +package com.santander.repository.gasto; + +import java.util.List; + +import com.santander.model.Gasto; +import com.santander.repository.filter.GastoFilter; + +public interface GastoRepositoyQuery { + public List filtrar(GastoFilter gastoFilter, int codigoUsuario); +} diff --git a/src/main/java/com/santander/resource/GastoResouce.java b/src/main/java/com/santander/resource/GastoResouce.java index 7a0e12d8..4623de64 100644 --- a/src/main/java/com/santander/resource/GastoResouce.java +++ b/src/main/java/com/santander/resource/GastoResouce.java @@ -1,12 +1,15 @@ package com.santander.resource; import java.net.URI; +import java.util.List; import javax.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -14,6 +17,7 @@ import org.springframework.web.servlet.support.ServletUriComponentsBuilder; import com.santander.model.Gasto; +import com.santander.repository.filter.GastoFilter; import com.santander.service.GastoService; @RestController @@ -33,4 +37,10 @@ public ResponseEntity criarGasto(@Valid @RequestBody Gasto gasto) { return ResponseEntity.created(uri).body(gastoSalvo); } + + @GetMapping("/{codigoUsuario}/listagemGasto") + public ResponseEntity> buscarGastoPor(GastoFilter filter, @PathVariable int codigoUsuario) { + List gasto = gastoService.filtrar(filter, codigoUsuario); + return !gasto.isEmpty() ? ResponseEntity.ok(gasto) : ResponseEntity.notFound().build(); + } } \ No newline at end of file diff --git a/src/main/java/com/santander/service/GastoService.java b/src/main/java/com/santander/service/GastoService.java index 2c9949f7..1928b649 100644 --- a/src/main/java/com/santander/service/GastoService.java +++ b/src/main/java/com/santander/service/GastoService.java @@ -1,10 +1,13 @@ package com.santander.service; +import java.util.List; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.santander.model.Gasto; import com.santander.repository.GastoRepositoy; +import com.santander.repository.filter.GastoFilter; @Service public class GastoService implements IGastoService { @@ -20,5 +23,10 @@ public GastoService(GastoRepositoy gastoRepository) { public Gasto salvar(Gasto gasto) { return gastosRepository.save(gasto); } + + @Override + public List filtrar(GastoFilter filter, int codigoUsuario) { + return gastosRepository.filtrar(filter, codigoUsuario); + } } diff --git a/src/main/java/com/santander/service/IGastoService.java b/src/main/java/com/santander/service/IGastoService.java index c29b5a86..80f6946d 100644 --- a/src/main/java/com/santander/service/IGastoService.java +++ b/src/main/java/com/santander/service/IGastoService.java @@ -1,9 +1,14 @@ package com.santander.service; +import java.util.List; + import com.santander.model.Gasto; +import com.santander.repository.filter.GastoFilter; public interface IGastoService { public Gasto salvar(Gasto gasto); + public List filtrar(GastoFilter filter, int codigoUsuario); + } diff --git a/src/test/java/com/santander/IntegracaoGastosTest.java b/src/test/java/com/santander/IntegracaoGastosTest.java index db85a092..0d8d625a 100644 --- a/src/test/java/com/santander/IntegracaoGastosTest.java +++ b/src/test/java/com/santander/IntegracaoGastosTest.java @@ -3,9 +3,12 @@ import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import java.math.BigDecimal; +import java.time.LocalDate; import java.time.LocalDateTime; +import java.util.ArrayList; import org.junit.Before; import org.junit.Rule; @@ -17,6 +20,7 @@ import com.santander.model.Gasto; import com.santander.repository.GastoRepositoy; +import com.santander.repository.filter.GastoFilter; import com.santander.service.GastoService; import com.santander.service.IGastoService; @@ -33,7 +37,6 @@ public class IntegracaoGastosTest { @Rule public ExpectedException expectedException = ExpectedException.none(); - @Before public void setUp() { @@ -64,11 +67,11 @@ public void deveSalvar2GastosNoRepositorio() throws Exception { gastoService.salvar(gasto); gastoService.salvar(gasto2); - + verify(gastoRepository, times(2)).save(gasto); } - + @Test public void deveSalvarCemMilGastosPorSegundoNoRepositorio() { @@ -86,4 +89,15 @@ public void deveSalvarCemMilGastosPorSegundoNoRepositorio() { } + @Test + public void deveTrazerGastoParaDia() throws Exception { + GastoFilter filter = new GastoFilter(); + + filter.setData(LocalDate.of(2019, 9, 29)); + when(gastoRepository.filtrar(filter, gasto.getCodigoUsuario())).thenReturn(new ArrayList()); + gastoService.filtrar(filter, gasto.getCodigoUsuario()); + verify(gastoRepository).filtrar(filter, gasto.getCodigoUsuario()); + + } + } From b6e2ba7685e07dfa791e60a18bf74c427029268d Mon Sep 17 00:00:00 2001 From: Thiago Dotto Date: Tue, 20 Aug 2019 18:28:02 -0300 Subject: [PATCH 5/9] =?UTF-8?q?Categoriza=C3=A7=C3=A3o=20de=20gastos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../santander/repository/GastoRepositoy.java | 4 ++++ .../com/santander/resource/GastoResouce.java | 7 +++++++ .../com/santander/service/GastoService.java | 19 ++++++++++++++++++- .../com/santander/service/IGastoService.java | 2 ++ .../com/santander/IntegracaoGastosTest.java | 9 +++++---- 5 files changed, 36 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/santander/repository/GastoRepositoy.java b/src/main/java/com/santander/repository/GastoRepositoy.java index 8da0f5d9..f4680514 100644 --- a/src/main/java/com/santander/repository/GastoRepositoy.java +++ b/src/main/java/com/santander/repository/GastoRepositoy.java @@ -1,5 +1,7 @@ package com.santander.repository; +import java.util.Optional; + import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @@ -9,4 +11,6 @@ @Repository public interface GastoRepositoy extends JpaRepository, GastoRepositoyQuery { + Optional findByDescricao(String descricao); + } diff --git a/src/main/java/com/santander/resource/GastoResouce.java b/src/main/java/com/santander/resource/GastoResouce.java index 4623de64..44293827 100644 --- a/src/main/java/com/santander/resource/GastoResouce.java +++ b/src/main/java/com/santander/resource/GastoResouce.java @@ -11,6 +11,7 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -43,4 +44,10 @@ public ResponseEntity> buscarGastoPor(GastoFilter filter, @PathVaria List gasto = gastoService.filtrar(filter, codigoUsuario); return !gasto.isEmpty() ? ResponseEntity.ok(gasto) : ResponseEntity.notFound().build(); } + + @PutMapping("/{codigo}/categoria") + public void alterarCategoria(@PathVariable Long codigo, @RequestBody String categoria) { + gastoService.alterarCategoria(codigo, categoria); + } + } \ No newline at end of file diff --git a/src/main/java/com/santander/service/GastoService.java b/src/main/java/com/santander/service/GastoService.java index 1928b649..2e3ec37f 100644 --- a/src/main/java/com/santander/service/GastoService.java +++ b/src/main/java/com/santander/service/GastoService.java @@ -1,9 +1,12 @@ package com.santander.service; import java.util.List; +import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; import com.santander.model.Gasto; import com.santander.repository.GastoRepositoy; @@ -23,10 +26,24 @@ public GastoService(GastoRepositoy gastoRepository) { public Gasto salvar(Gasto gasto) { return gastosRepository.save(gasto); } - + @Override public List filtrar(GastoFilter filter, int codigoUsuario) { return gastosRepository.filtrar(filter, codigoUsuario); } + @Override + public Gasto alterarCategoria(Long idGasto, String categoria) { + + Gasto gastoSalvo = this.gastosRepository.findById(idGasto) + .orElseThrow(() -> new EmptyResultDataAccessException(1)); + + if (!StringUtils.isEmpty(gastoSalvo.getCategoria())) { + throw new IllegalArgumentException("voce nao pode alterar esse campo"); + } + + gastoSalvo.setCategoria(categoria); + return gastosRepository.save(gastoSalvo); + } + } diff --git a/src/main/java/com/santander/service/IGastoService.java b/src/main/java/com/santander/service/IGastoService.java index 80f6946d..8fd1c53e 100644 --- a/src/main/java/com/santander/service/IGastoService.java +++ b/src/main/java/com/santander/service/IGastoService.java @@ -11,4 +11,6 @@ public interface IGastoService { public List filtrar(GastoFilter filter, int codigoUsuario); + public Gasto alterarCategoria(Long idGasto, String categoria); + } diff --git a/src/test/java/com/santander/IntegracaoGastosTest.java b/src/test/java/com/santander/IntegracaoGastosTest.java index 0d8d625a..030a8e31 100644 --- a/src/test/java/com/santander/IntegracaoGastosTest.java +++ b/src/test/java/com/santander/IntegracaoGastosTest.java @@ -9,6 +9,8 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.util.ArrayList; +import java.util.List; +import java.util.Optional; import org.junit.Before; import org.junit.Rule; @@ -45,7 +47,7 @@ public void setUp() { gasto.setValor(new BigDecimal(1.0)); gasto.setCodigoUsuario(1); gasto.setData(LocalDateTime.now()); - + gasto.setCategoria("teste"); gastoService = new GastoService(gastoRepository); } @@ -66,8 +68,8 @@ public void deveSalvar2GastosNoRepositorio() throws Exception { gasto2.setData(LocalDateTime.now()); gastoService.salvar(gasto); - gastoService.salvar(gasto2); + gastoService.salvar(gasto2); verify(gastoRepository, times(2)).save(gasto); } @@ -93,11 +95,10 @@ public void deveSalvarCemMilGastosPorSegundoNoRepositorio() { public void deveTrazerGastoParaDia() throws Exception { GastoFilter filter = new GastoFilter(); - filter.setData(LocalDate.of(2019, 9, 29)); + filter.setData(LocalDate.now()); when(gastoRepository.filtrar(filter, gasto.getCodigoUsuario())).thenReturn(new ArrayList()); gastoService.filtrar(filter, gasto.getCodigoUsuario()); verify(gastoRepository).filtrar(filter, gasto.getCodigoUsuario()); - } } From baa63f0f349a1091249e4283ded9728d554a8105 Mon Sep 17 00:00:00 2001 From: Thiago Dotto Date: Tue, 20 Aug 2019 18:41:30 -0300 Subject: [PATCH 6/9] =?UTF-8?q?Sugest=C3=A3o=20de=20categoria?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/santander/model/dto/GastoDTO.java | 18 ++++ .../repository/gasto/GastoRepositoyImpl.java | 11 +++ .../repository/gasto/GastoRepositoyQuery.java | 3 + .../com/santander/resource/GastoResouce.java | 10 ++ .../exceptionhandler/ApiExceptionHandler.java | 96 +++++++++++++++++++ .../com/santander/service/GastoService.java | 1 - .../com/santander/IntegracaoGastosTest.java | 2 - 7 files changed, 138 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/santander/model/dto/GastoDTO.java create mode 100644 src/main/java/com/santander/resource/exceptionhandler/ApiExceptionHandler.java diff --git a/src/main/java/com/santander/model/dto/GastoDTO.java b/src/main/java/com/santander/model/dto/GastoDTO.java new file mode 100644 index 00000000..6eb2bc04 --- /dev/null +++ b/src/main/java/com/santander/model/dto/GastoDTO.java @@ -0,0 +1,18 @@ +package com.santander.model.dto; + +public class GastoDTO { + private String categoria; + + public GastoDTO(String categoria) { + this.setCategoria(categoria); + } + + public String getCategoria() { + return categoria; + } + + public void setCategoria(String categoria) { + this.categoria = categoria; + } + +} diff --git a/src/main/java/com/santander/repository/gasto/GastoRepositoyImpl.java b/src/main/java/com/santander/repository/gasto/GastoRepositoyImpl.java index ca6fee7c..e12da914 100644 --- a/src/main/java/com/santander/repository/gasto/GastoRepositoyImpl.java +++ b/src/main/java/com/santander/repository/gasto/GastoRepositoyImpl.java @@ -16,6 +16,7 @@ import org.springframework.util.StringUtils; import com.santander.model.Gasto; +import com.santander.model.dto.GastoDTO; import com.santander.repository.filter.GastoFilter; public class GastoRepositoyImpl implements GastoRepositoyQuery { @@ -59,5 +60,15 @@ private Predicate[] criarRestricoes(GastoFilter gastoFilter, int codigoUsuario, return predicates.toArray(new Predicate[predicates.size()]); } + @Override + public List buscarPorCategoria(String categoria) { + String jpql = "select new com.santander.model.dto.GastoDTO(categoria) " + + "from Gasto where lower(categoria) like lower(:categoria)"; + + List categoriasFiltradas = manager.createQuery(jpql, GastoDTO.class) + .setParameter("categoria", categoria + "%").getResultList(); + return categoriasFiltradas; + } + } diff --git a/src/main/java/com/santander/repository/gasto/GastoRepositoyQuery.java b/src/main/java/com/santander/repository/gasto/GastoRepositoyQuery.java index a4e24cbe..1d01c939 100644 --- a/src/main/java/com/santander/repository/gasto/GastoRepositoyQuery.java +++ b/src/main/java/com/santander/repository/gasto/GastoRepositoyQuery.java @@ -3,8 +3,11 @@ import java.util.List; import com.santander.model.Gasto; +import com.santander.model.dto.GastoDTO; import com.santander.repository.filter.GastoFilter; public interface GastoRepositoyQuery { public List filtrar(GastoFilter gastoFilter, int codigoUsuario); + + public List buscarPorCategoria(String categoria); } diff --git a/src/main/java/com/santander/resource/GastoResouce.java b/src/main/java/com/santander/resource/GastoResouce.java index 44293827..dad39a6f 100644 --- a/src/main/java/com/santander/resource/GastoResouce.java +++ b/src/main/java/com/santander/resource/GastoResouce.java @@ -14,10 +14,13 @@ import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.support.ServletUriComponentsBuilder; import com.santander.model.Gasto; +import com.santander.model.dto.GastoDTO; +import com.santander.repository.GastoRepositoy; import com.santander.repository.filter.GastoFilter; import com.santander.service.GastoService; @@ -27,6 +30,8 @@ public class GastoResouce { @Autowired private GastoService gastoService; + @Autowired + private GastoRepositoy gastoRepository; @PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity criarGasto(@Valid @RequestBody Gasto gasto) { @@ -50,4 +55,9 @@ public void alterarCategoria(@PathVariable Long codigo, @RequestBody String cate gastoService.alterarCategoria(codigo, categoria); } + @GetMapping("/categoria/filtro") + public @ResponseBody List pesquisarCategoria(String categoria) { + return gastoRepository.buscarPorCategoria(categoria); + } + } \ No newline at end of file diff --git a/src/main/java/com/santander/resource/exceptionhandler/ApiExceptionHandler.java b/src/main/java/com/santander/resource/exceptionhandler/ApiExceptionHandler.java new file mode 100644 index 00000000..39894b0c --- /dev/null +++ b/src/main/java/com/santander/resource/exceptionhandler/ApiExceptionHandler.java @@ -0,0 +1,96 @@ +package com.santander.resource.exceptionhandler; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.MessageSource; +import org.springframework.context.i18n.LocaleContextHolder; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindingResult; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.context.request.WebRequest; +import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; + +public class ApiExceptionHandler extends ResponseEntityExceptionHandler { + + @Autowired + private MessageSource messageSource; + + @Override + protected ResponseEntity handleHttpMessageNotReadable(HttpMessageNotReadableException ex, + HttpHeaders headers, HttpStatus status, WebRequest request) { + + String mensagemUsuario = messageSource.getMessage("mensagem.invalida", null, LocaleContextHolder.getLocale()); + String mensagemDesenvolvedor = ex.getCause().toString(); + return handleExceptionInternal(ex, new Erro(mensagemUsuario, mensagemDesenvolvedor), headers, + HttpStatus.BAD_REQUEST, request); + } + + @Override + protected ResponseEntity handleMethodArgumentNotValid(MethodArgumentNotValidException ex, + HttpHeaders headers, HttpStatus status, WebRequest request) { + + List erros = criarListaDeErros(ex.getBindingResult()); + return handleExceptionInternal(ex, erros, headers, HttpStatus.BAD_REQUEST, request); + } + + @ExceptionHandler({ EmptyResultDataAccessException.class }) + public ResponseEntity handleEmptyResultDataAccessException(EmptyResultDataAccessException ex, + WebRequest request) { + String mensagemUsuario = messageSource.getMessage("recurso.nao-encontrado", null, + LocaleContextHolder.getLocale()); + String mensagemDesenvolvedor = ex.toString(); + List erros = Arrays.asList(new Erro(mensagemUsuario, mensagemDesenvolvedor)); + return handleExceptionInternal(ex, erros, new HttpHeaders(), HttpStatus.NOT_FOUND, request); + } + + @ExceptionHandler({ IllegalArgumentException.class }) + public ResponseEntity handleIllegalArgumentException(IllegalArgumentException ex, WebRequest request) { + String mensagemUsuario = messageSource.getMessage("categoria.nao-pode-ser-alterada", null, + LocaleContextHolder.getLocale()); + String mensagemDesenvolvedor = ex.toString(); + List erros = Arrays.asList(new Erro(mensagemUsuario, mensagemDesenvolvedor)); + return handleExceptionInternal(ex, erros, new HttpHeaders(), HttpStatus.BAD_REQUEST, request); + } + + private List criarListaDeErros(BindingResult bindingResult) { + List erros = new ArrayList<>(); + + for (FieldError fieldError : bindingResult.getFieldErrors()) { + String mensagemUsuario = messageSource.getMessage(fieldError, LocaleContextHolder.getLocale()); + String mensagemDesenvolvedor = fieldError.toString(); + erros.add(new Erro(mensagemUsuario, mensagemDesenvolvedor)); + } + + return erros; + } + + public static class Erro { + + private String mensagemUsuario; + private String mensagemDesenvolvedor; + + public Erro(String mensagemUsuario, String mensagemDesenvolvedor) { + this.mensagemUsuario = mensagemUsuario; + this.mensagemDesenvolvedor = mensagemDesenvolvedor; + } + + public String getMensagemUsuario() { + return mensagemUsuario; + } + + public String getMensagemDesenvolvedor() { + return mensagemDesenvolvedor; + } + + } + +} \ No newline at end of file diff --git a/src/main/java/com/santander/service/GastoService.java b/src/main/java/com/santander/service/GastoService.java index 2e3ec37f..f9347e6f 100644 --- a/src/main/java/com/santander/service/GastoService.java +++ b/src/main/java/com/santander/service/GastoService.java @@ -1,7 +1,6 @@ package com.santander.service; import java.util.List; -import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.EmptyResultDataAccessException; diff --git a/src/test/java/com/santander/IntegracaoGastosTest.java b/src/test/java/com/santander/IntegracaoGastosTest.java index 030a8e31..6b9b269d 100644 --- a/src/test/java/com/santander/IntegracaoGastosTest.java +++ b/src/test/java/com/santander/IntegracaoGastosTest.java @@ -9,8 +9,6 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.util.ArrayList; -import java.util.List; -import java.util.Optional; import org.junit.Before; import org.junit.Rule; From caff52ec2b0fa47011143e3555f3fb9271975848 Mon Sep 17 00:00:00 2001 From: Thiago Dotto Date: Wed, 21 Aug 2019 00:49:19 -0300 Subject: [PATCH 7/9] =?UTF-8?q?Seguran=C3=A7a=20e=20ajustes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 6 +++ README.md | 26 +++++++++++ pom.xml | 24 ++++++++-- .../config/AuthorizationServerConfig.java | 46 +++++++++++++++++++ .../santander/config/OAuthSecurityConfig.java | 25 ++++++++++ .../config/ResourceServerConfig.java | 39 ++++++++++++++++ .../repository/gasto/GastoRepositoyImpl.java | 21 ++++----- .../com/santander/resource/GastoResouce.java | 8 ++-- .../com/santander/service/GastoService.java | 9 ++++ .../resources/ValidationMessages.properties | 3 ++ src/main/resources/messages.properties | 4 ++ 11 files changed, 193 insertions(+), 18 deletions(-) create mode 100644 .gitignore create mode 100644 src/main/java/com/santander/config/AuthorizationServerConfig.java create mode 100644 src/main/java/com/santander/config/OAuthSecurityConfig.java create mode 100644 src/main/java/com/santander/config/ResourceServerConfig.java create mode 100644 src/main/resources/ValidationMessages.properties create mode 100644 src/main/resources/messages.properties diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..5ecf1cf2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.settings +.DS_Store +.classpath +.factorypath +target/ +.project \ No newline at end of file diff --git a/README.md b/README.md index 15d8f685..0736621c 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,32 @@ ### # DESAFIO: +Instruções para rodar a Api. + +0- Primeiramente, ir na pasta raiz do projeto e compile com o maven + ```./mvnw clean install``` +1- Na pasta Targat Clique 2x no TestBackJava-1.jar +2- A api está usando segurança Oauth 2 + Então é necessario fazer um POST primeiro no endpoint: + ```http://localhost:8000/gasto/oauth/token``` + Como Authorization basic, deve-se passar o username e passaword que nesse caso é "cliente". + No Body da requisição deve se passar; + chave Valor + client cliente + username admin + password admin + grant_type password + na resposta existe um access_token o qual deve ser copiado e passado no header do http para as outras requisições. +3- A api responde os seguinte endPoonts; + ``` + POST http://localhost:8000/gasto/ --> Para a inclusão de gastos + GET http://localhost:8000/gasto/{idUsuario}/listagemGasto e http://localhost:8000/gasto/{idUsuario}/listagemGasto?data=2019-09-20 --> Para consulta de gastos + PUT http://localhost:8000/gasto/{idGasto}/categoria --> Altera uma categoria caso ela possa ser alterada + GET http://localhost:8000/gasto/categoria/filtro?categoria={caracter} --> lista categorias que iniciam com um caracter + ``` + +### # DESAFIO: + API REST para Gestão de Gastos! ``` diff --git a/pom.xml b/pom.xml index 5bc4da86..6300c62b 100644 --- a/pom.xml +++ b/pom.xml @@ -1,16 +1,17 @@ - 4.0.0 org.springframework.boot spring-boot-starter-parent 2.1.7.RELEASE - + com.santander TestBackJava - 0.0.1-SNAPSHOT + 1 TestBackJava Demo project for Spring Boot @@ -43,6 +44,23 @@ spring-boot-starter-test test + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + + + + org.springframework.security.oauth + spring-security-oauth2 + 2.3.5.RELEASE + + + + org.springframework.security + spring-security-jwt + 1.0.10.RELEASE + diff --git a/src/main/java/com/santander/config/AuthorizationServerConfig.java b/src/main/java/com/santander/config/AuthorizationServerConfig.java new file mode 100644 index 00000000..a9f14c47 --- /dev/null +++ b/src/main/java/com/santander/config/AuthorizationServerConfig.java @@ -0,0 +1,46 @@ +package com.santander.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; +import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; +import org.springframework.security.oauth2.provider.token.TokenStore; +import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; +import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; + +@Configuration +@EnableAuthorizationServer +public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { + + @Autowired + private AuthenticationManager authenticationManager; + + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + clients.inMemory().withClient("cliente").secret("cliente").scopes("read", "write") + .authorizedGrantTypes("password").accessTokenValiditySeconds(1800); + } + + @Override + public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { + endpoints.tokenStore(tokenStore()).accessTokenConverter(accessTokenConverter()) + .authenticationManager(authenticationManager); + } + + @Bean + public JwtAccessTokenConverter accessTokenConverter() { + JwtAccessTokenConverter accessTokenConverter = new JwtAccessTokenConverter(); + accessTokenConverter.setSigningKey("algaworks"); + return accessTokenConverter; + } + + @Bean + public TokenStore tokenStore() { + return new JwtTokenStore(accessTokenConverter()); + } + +} \ No newline at end of file diff --git a/src/main/java/com/santander/config/OAuthSecurityConfig.java b/src/main/java/com/santander/config/OAuthSecurityConfig.java new file mode 100644 index 00000000..70c5b66a --- /dev/null +++ b/src/main/java/com/santander/config/OAuthSecurityConfig.java @@ -0,0 +1,25 @@ +package com.santander.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.crypto.password.NoOpPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +@Configuration +@EnableWebSecurity +public class OAuthSecurityConfig extends WebSecurityConfigurerAdapter { + + @Bean + @Override + public AuthenticationManager authenticationManager() throws Exception { + return super.authenticationManager(); + } + + @Bean + public PasswordEncoder passwordEncoder() { + return NoOpPasswordEncoder.getInstance(); + } +} \ No newline at end of file diff --git a/src/main/java/com/santander/config/ResourceServerConfig.java b/src/main/java/com/santander/config/ResourceServerConfig.java new file mode 100644 index 00000000..7f82090b --- /dev/null +++ b/src/main/java/com/santander/config/ResourceServerConfig.java @@ -0,0 +1,39 @@ +package com.santander.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; +import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; +import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; + +@Configuration +@EnableWebSecurity +@EnableResourceServer +public class ResourceServerConfig extends ResourceServerConfigurerAdapter { + + @Autowired + public void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.inMemoryAuthentication() + .withUser("admin").password("admin").roles("ROLE"); + } + + @Override + public void configure(HttpSecurity http) throws Exception { + http.authorizeRequests() + .antMatchers("/categorias").permitAll() + .anyRequest().authenticated() + .and() + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() + .csrf().disable(); + } + + @Override + public void configure(ResourceServerSecurityConfigurer resources) throws Exception { + resources.stateless(true); + } + +} \ No newline at end of file diff --git a/src/main/java/com/santander/repository/gasto/GastoRepositoyImpl.java b/src/main/java/com/santander/repository/gasto/GastoRepositoyImpl.java index e12da914..5a45f394 100644 --- a/src/main/java/com/santander/repository/gasto/GastoRepositoyImpl.java +++ b/src/main/java/com/santander/repository/gasto/GastoRepositoyImpl.java @@ -38,6 +38,16 @@ public List filtrar(GastoFilter gastoFilter, int codigoUsuario) { return query.getResultList(); } + @Override + public List buscarPorCategoria(String categoria) { + String jpql = "select new com.santander.model.dto.GastoDTO(categoria) " + + "from Gasto where lower(categoria) like lower(:categoria)"; + + List categoriasFiltradas = manager.createQuery(jpql, GastoDTO.class) + .setParameter("categoria", categoria + "%").getResultList(); + return categoriasFiltradas; + } + private Predicate[] criarRestricoes(GastoFilter gastoFilter, int codigoUsuario, CriteriaBuilder builder, Root root) { @@ -60,15 +70,4 @@ private Predicate[] criarRestricoes(GastoFilter gastoFilter, int codigoUsuario, return predicates.toArray(new Predicate[predicates.size()]); } - @Override - public List buscarPorCategoria(String categoria) { - String jpql = "select new com.santander.model.dto.GastoDTO(categoria) " - + "from Gasto where lower(categoria) like lower(:categoria)"; - - List categoriasFiltradas = manager.createQuery(jpql, GastoDTO.class) - .setParameter("categoria", categoria + "%").getResultList(); - return categoriasFiltradas; - } - - } diff --git a/src/main/java/com/santander/resource/GastoResouce.java b/src/main/java/com/santander/resource/GastoResouce.java index dad39a6f..8a47409c 100644 --- a/src/main/java/com/santander/resource/GastoResouce.java +++ b/src/main/java/com/santander/resource/GastoResouce.java @@ -43,21 +43,21 @@ public ResponseEntity criarGasto(@Valid @RequestBody Gasto gasto) { return ResponseEntity.created(uri).body(gastoSalvo); } - + @GetMapping("/{codigoUsuario}/listagemGasto") public ResponseEntity> buscarGastoPor(GastoFilter filter, @PathVariable int codigoUsuario) { List gasto = gastoService.filtrar(filter, codigoUsuario); return !gasto.isEmpty() ? ResponseEntity.ok(gasto) : ResponseEntity.notFound().build(); } - + @PutMapping("/{codigo}/categoria") public void alterarCategoria(@PathVariable Long codigo, @RequestBody String categoria) { gastoService.alterarCategoria(codigo, categoria); } - + @GetMapping("/categoria/filtro") public @ResponseBody List pesquisarCategoria(String categoria) { return gastoRepository.buscarPorCategoria(categoria); } - + } \ No newline at end of file diff --git a/src/main/java/com/santander/service/GastoService.java b/src/main/java/com/santander/service/GastoService.java index f9347e6f..53a3a42e 100644 --- a/src/main/java/com/santander/service/GastoService.java +++ b/src/main/java/com/santander/service/GastoService.java @@ -1,6 +1,7 @@ package com.santander.service; import java.util.List; +import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.EmptyResultDataAccessException; @@ -23,6 +24,14 @@ public GastoService(GastoRepositoy gastoRepository) { @Override public Gasto salvar(Gasto gasto) { + + if (StringUtils.isEmpty(gasto.getCategoria())) { + Optional descricaoOptional = gastosRepository.findByDescricao(gasto.getDescricao()); + if (descricaoOptional.isPresent()) { + Gasto gastoSalvo = descricaoOptional.get(); + gasto.setCategoria(gastoSalvo.getCategoria()); + } + } return gastosRepository.save(gasto); } diff --git a/src/main/resources/ValidationMessages.properties b/src/main/resources/ValidationMessages.properties new file mode 100644 index 00000000..3db868cf --- /dev/null +++ b/src/main/resources/ValidationMessages.properties @@ -0,0 +1,3 @@ +javax.validation.constraints.NotNull.message={0} \u00e9 obrigat\u00f3rio(a) +javax.validation.constraints.Size.message={0} deve ter o tamanho entre {min} e {max} +javax.validation.constraints.NotBlank.message={0} não pode ser embranco \ No newline at end of file diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties new file mode 100644 index 00000000..7cc87108 --- /dev/null +++ b/src/main/resources/messages.properties @@ -0,0 +1,4 @@ +mensagem.invalida=Mensagem inv\u00E1lida +recurso.nao-encontrado=Recurso n\u00E3o encontrado + +categoria.nao-pode-ser-alterada= N\u00E3o pode alterar categora já cadastrada \ No newline at end of file From 5563eda2ec66ca30108f8eae3c627ee03a479a8e Mon Sep 17 00:00:00 2001 From: Thiago Dotto Date: Wed, 21 Aug 2019 01:01:18 -0300 Subject: [PATCH 8/9] Ajuste --- README.md | 50 +++++++++++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 0736621c..e42bede9 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,38 @@ # Show me the code -### # DESAFIO: +### # Instruções para rodar a Api. -Instruções para rodar a Api. +

1- Primeiramente, ir na pasta raiz do projeto e compile com o maven

+ ```./mvnw clean install``` +2- Na pasta Targat Clique 2x no TestBackJava-1.jar +3- A api está usando segurança Oauth 2 + Então é necessario fazer um POST primeiro no endpoint: + ```http://localhost:8000/gasto/oauth/token``` + Como Authorization basic, deve-se passar o username e passaword que nesse caso é "cliente". + No Body da requisição deve se passar; + chave Valor + client cliente + username admin + password admin + grant_type password + na resposta existe um access_token o qual deve ser copiado e passado no header do http para as outras requisições. +4- A api responde os seguinte endPoonts; -0- Primeiramente, ir na pasta raiz do projeto e compile com o maven - ```./mvnw clean install``` -1- Na pasta Targat Clique 2x no TestBackJava-1.jar -2- A api está usando segurança Oauth 2 - Então é necessario fazer um POST primeiro no endpoint: - ```http://localhost:8000/gasto/oauth/token``` - Como Authorization basic, deve-se passar o username e passaword que nesse caso é "cliente". - No Body da requisição deve se passar; - chave Valor - client cliente - username admin - password admin - grant_type password - na resposta existe um access_token o qual deve ser copiado e passado no header do http para as outras requisições. -3- A api responde os seguinte endPoonts; ``` - POST http://localhost:8000/gasto/ --> Para a inclusão de gastos - GET http://localhost:8000/gasto/{idUsuario}/listagemGasto e http://localhost:8000/gasto/{idUsuario}/listagemGasto?data=2019-09-20 --> Para consulta de gastos - PUT http://localhost:8000/gasto/{idGasto}/categoria --> Altera uma categoria caso ela possa ser alterada - GET http://localhost:8000/gasto/categoria/filtro?categoria={caracter} --> lista categorias que iniciam com um caracter + POST http://localhost:8000/gasto/ --> Para a inclusão de gastos, exemplo. + { + "descricao" : "teste", + "codigoUsuario" : 1, + "valor" : "200.00", + "data" : "2019-09-20T18:54:10", + "categoria": "" + } + GET http://localhost:8000/gasto/{idUsuario}/listagemGasto e http://localhost:8000/gasto/{idUsuario}/listagemGasto?data={2019-09-20} --> Para consulta de gastos + PUT http://localhost:8000/gasto/{idGasto}/categoria --> Altera uma categoria caso ela possa ser alterada + GET http://localhost:8000/gasto/categoria/filtro?categoria={caracter} --> lista categorias que iniciam com um caracter ``` +*O banco de Dados ultilizado foi o H2, um banco em memoria. + ### # DESAFIO: From e9fc247f5621da3fc2cbb626668a427fffbf8b37 Mon Sep 17 00:00:00 2001 From: Thiago Dotto Date: Wed, 21 Aug 2019 01:05:53 -0300 Subject: [PATCH 9/9] Ajuste Readme --- README.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index e42bede9..5f465b56 100644 --- a/README.md +++ b/README.md @@ -3,11 +3,15 @@ ### # Instruções para rodar a Api.

1- Primeiramente, ir na pasta raiz do projeto e compile com o maven

- ```./mvnw clean install``` -2- Na pasta Targat Clique 2x no TestBackJava-1.jar -3- A api está usando segurança Oauth 2 - Então é necessario fazer um POST primeiro no endpoint: - ```http://localhost:8000/gasto/oauth/token``` + + ./mvnw clean install + +

2- Na pasta Targat Clique 2x no TestBackJava-1.jar

+

3- A api está usando segurança Oauth 2 + Então é necessario fazer um POST primeiro no endpoint:

+ + http://localhost:8000/gasto/oauth/token + Como Authorization basic, deve-se passar o username e passaword que nesse caso é "cliente". No Body da requisição deve se passar; chave Valor