diff --git a/backend-challenge/.gitignore b/backend-challenge/.gitignore
new file mode 100644
index 0000000..153c933
--- /dev/null
+++ b/backend-challenge/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/backend-challenge/README.md b/backend-challenge/README.md
new file mode 100644
index 0000000..d6c05fe
--- /dev/null
+++ b/backend-challenge/README.md
@@ -0,0 +1,19 @@
+Backend Challenge BIT - SP
+
+Esse projeto foi construído usando uma versão simplificada da Clean Architecture (http://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html).
+
+Utilizamos o Spring Boot como facilitador, na sua última versão disponível (2.1.3).
+
+Para construir a aplicação, utilize o comando:
+
+mvn clean package
+
+Desta forma, no diretório "target" será gerado o jar "backend-challenge-0.0.1-SNAPSHOT.jar", que pode ser executado com o comando:
+
+java -jar target\backend-challenge-0.0.1-SNAPSHOT.jar
+
+Ou, utilizando o plugin do maven do Spring Boot, sem precisar pré construir a aplicação:
+
+mvn spring-boot:run
+
+
\ No newline at end of file
diff --git a/backend-challenge/pom.xml b/backend-challenge/pom.xml
new file mode 100644
index 0000000..7c8fb37
--- /dev/null
+++ b/backend-challenge/pom.xml
@@ -0,0 +1,48 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.1.3.RELEASE
+
+
+ br.com.bonaldo
+ backend-challenge
+ 0.0.1-SNAPSHOT
+ backend-challenge
+ backend-challenge
+
+
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/BackendChallengeApplication.java b/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/BackendChallengeApplication.java
new file mode 100644
index 0000000..be0d760
--- /dev/null
+++ b/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/BackendChallengeApplication.java
@@ -0,0 +1,11 @@
+package br.com.bonaldo.backendchallenge;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class BackendChallengeApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(BackendChallengeApplication.class, args);
+ }
+}
\ No newline at end of file
diff --git a/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/config/RestTemplateConfig.java b/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/config/RestTemplateConfig.java
new file mode 100644
index 0000000..9ac0b30
--- /dev/null
+++ b/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/config/RestTemplateConfig.java
@@ -0,0 +1,14 @@
+package br.com.bonaldo.backendchallenge.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.client.RestTemplate;
+
+@Configuration
+public class RestTemplateConfig {
+
+ @Bean
+ public RestTemplate restTemplate() {
+ return new RestTemplate();
+ }
+}
diff --git a/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/domains/Dimension.java b/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/domains/Dimension.java
new file mode 100644
index 0000000..396dda0
--- /dev/null
+++ b/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/domains/Dimension.java
@@ -0,0 +1,23 @@
+package br.com.bonaldo.backendchallenge.domains;
+
+import br.com.bonaldo.backendchallenge.gateways.http.json.DimensionResponse;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+@AllArgsConstructor
+public class Dimension {
+ private BigDecimal weight;
+ private BigDecimal height;
+ private BigDecimal width;
+ private BigDecimal length;
+
+ public Dimension(final DimensionResponse dimensionResponse) {
+ this.weight = dimensionResponse.getWeight();
+ this.height = dimensionResponse.getHeight();
+ this.length = dimensionResponse.getLength();
+ this.width = dimensionResponse.getWidth();
+ }
+}
\ No newline at end of file
diff --git a/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/domains/OrderItem.java b/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/domains/OrderItem.java
new file mode 100644
index 0000000..31205d2
--- /dev/null
+++ b/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/domains/OrderItem.java
@@ -0,0 +1,21 @@
+package br.com.bonaldo.backendchallenge.domains;
+
+import br.com.bonaldo.backendchallenge.gateways.http.json.OrderItemResponse;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Data
+public class OrderItem {
+ private String name;
+ private String code;
+ private LocalDateTime date;
+ private Dimension dimension;
+
+ public OrderItem(final OrderItemResponse orderItemResponse) {
+ this.name = orderItemResponse.getName();
+ this.code = orderItemResponse.getCode();
+ this.date = orderItemResponse.getDate();
+ this.dimension = new Dimension(orderItemResponse.getDimension());
+ }
+}
diff --git a/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/gateways/OrderGateway.java b/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/gateways/OrderGateway.java
new file mode 100644
index 0000000..651cec6
--- /dev/null
+++ b/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/gateways/OrderGateway.java
@@ -0,0 +1,9 @@
+package br.com.bonaldo.backendchallenge.gateways;
+
+import br.com.bonaldo.backendchallenge.gateways.http.json.OrderItemResponse;
+
+import java.util.List;
+
+public interface OrderGateway {
+ List getOrderItems();
+}
diff --git a/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/gateways/controllers/ItemController.java b/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/gateways/controllers/ItemController.java
new file mode 100644
index 0000000..d3e5f05
--- /dev/null
+++ b/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/gateways/controllers/ItemController.java
@@ -0,0 +1,46 @@
+package br.com.bonaldo.backendchallenge.gateways.controllers;
+
+import br.com.bonaldo.backendchallenge.gateways.controllers.json.ItemResponse;
+import br.com.bonaldo.backendchallenge.usecases.FilterOrderItems;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Slf4j
+@RestController
+@RequestMapping("/item")
+@RequiredArgsConstructor
+public class ItemController {
+
+ private final FilterOrderItems filterOrderItems;
+
+ @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
+ public List findItems(
+ @RequestParam(value = "begindate") final String beginDate,
+ @RequestParam(value = "finaldate") final String finalDate) {
+
+ log.info("Searching for items with date between {} and {}", beginDate, finalDate);
+
+ LocalDate startDate = parseStringDate(beginDate);
+ LocalDate endDate = parseStringDate(finalDate);
+
+ return filterOrderItems.execute(startDate, endDate)
+ .stream()
+ .map(ItemResponse::new)
+ .collect(Collectors.toList());
+ }
+
+ private LocalDate parseStringDate(final String stringDate) {
+ DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd-MM-yyyy");
+ return LocalDate.from(dtf.parse(stringDate));
+ }
+}
\ No newline at end of file
diff --git a/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/gateways/controllers/json/DimensionResponse.java b/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/gateways/controllers/json/DimensionResponse.java
new file mode 100644
index 0000000..8273baf
--- /dev/null
+++ b/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/gateways/controllers/json/DimensionResponse.java
@@ -0,0 +1,22 @@
+package br.com.bonaldo.backendchallenge.gateways.controllers.json;
+
+import br.com.bonaldo.backendchallenge.domains.Dimension;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+@Data
+public class DimensionResponse implements Serializable {
+ private BigDecimal weight;
+ private BigDecimal height;
+ private BigDecimal width;
+ private BigDecimal length;
+
+ public DimensionResponse(final Dimension dimension) {
+ this.weight = dimension.getWeight();
+ this.height = dimension.getHeight();
+ this.width = dimension.getWidth();
+ this.length = dimension.getLength();
+ }
+}
\ No newline at end of file
diff --git a/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/gateways/controllers/json/ItemResponse.java b/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/gateways/controllers/json/ItemResponse.java
new file mode 100644
index 0000000..8875a87
--- /dev/null
+++ b/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/gateways/controllers/json/ItemResponse.java
@@ -0,0 +1,22 @@
+package br.com.bonaldo.backendchallenge.gateways.controllers.json;
+
+import br.com.bonaldo.backendchallenge.domains.OrderItem;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+@Data
+public class ItemResponse implements Serializable {
+ private String name;
+ private String code;
+ private LocalDateTime date;
+ private DimensionResponse dimension;
+
+ public ItemResponse(final OrderItem orderItem) {
+ this.name = orderItem.getName();
+ this.code = orderItem.getCode();
+ this.date = orderItem.getDate();
+ this.dimension = new DimensionResponse(orderItem.getDimension());
+ }
+}
diff --git a/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/gateways/http/CustomExceptionHandler.java b/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/gateways/http/CustomExceptionHandler.java
new file mode 100644
index 0000000..5af824e
--- /dev/null
+++ b/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/gateways/http/CustomExceptionHandler.java
@@ -0,0 +1,25 @@
+package br.com.bonaldo.backendchallenge.gateways.http;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+import javax.servlet.http.HttpServletRequest;
+import java.time.DateTimeException;
+
+@Slf4j
+@ControllerAdvice
+public class CustomExceptionHandler {
+
+ @ExceptionHandler(DateTimeException.class)
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ @ResponseBody
+ public ResponseEntity handleInvalidDateException(HttpServletRequest req, Exception ex) {
+ log.info("Invalid date format on request: {}, with params: {}, exception: {}", req.getRequestURI(), req.getQueryString(), ex.getMessage());
+ return ResponseEntity.badRequest().body("Invalid date format");
+ }
+}
\ No newline at end of file
diff --git a/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/gateways/http/OrderGatewayAPI.java b/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/gateways/http/OrderGatewayAPI.java
new file mode 100644
index 0000000..94b2e4d
--- /dev/null
+++ b/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/gateways/http/OrderGatewayAPI.java
@@ -0,0 +1,30 @@
+package br.com.bonaldo.backendchallenge.gateways.http;
+
+import br.com.bonaldo.backendchallenge.gateways.OrderGateway;
+import br.com.bonaldo.backendchallenge.gateways.http.json.OrderItemResponse;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.List;
+
+@Component
+@RequiredArgsConstructor
+public class OrderGatewayAPI implements OrderGateway {
+
+ @Value("${integration.order-api.url}")
+ private String API_URL;
+
+ private final RestTemplate restTemplate;
+
+ @Override
+ public List getOrderItems() {
+ ResponseEntity> response = restTemplate
+ .exchange(API_URL, HttpMethod.GET, null, new ParameterizedTypeReference>() {});
+ return response.getBody();
+ }
+}
\ No newline at end of file
diff --git a/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/gateways/http/json/DimensionResponse.java b/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/gateways/http/json/DimensionResponse.java
new file mode 100644
index 0000000..0f70e32
--- /dev/null
+++ b/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/gateways/http/json/DimensionResponse.java
@@ -0,0 +1,16 @@
+package br.com.bonaldo.backendchallenge.gateways.http.json;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+@Data
+@NoArgsConstructor
+public class DimensionResponse implements Serializable {
+ private BigDecimal weight;
+ private BigDecimal height;
+ private BigDecimal width;
+ private BigDecimal length;
+}
diff --git a/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/gateways/http/json/OrderItemResponse.java b/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/gateways/http/json/OrderItemResponse.java
new file mode 100644
index 0000000..bdb6145
--- /dev/null
+++ b/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/gateways/http/json/OrderItemResponse.java
@@ -0,0 +1,20 @@
+package br.com.bonaldo.backendchallenge.gateways.http.json;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class OrderItemResponse implements Serializable {
+ private String name;
+ private String code;
+ private LocalDateTime date;
+ private DimensionResponse dimension;
+}
diff --git a/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/usecases/FilterOrderItems.java b/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/usecases/FilterOrderItems.java
new file mode 100644
index 0000000..b040618
--- /dev/null
+++ b/backend-challenge/src/main/java/br/com/bonaldo/backendchallenge/usecases/FilterOrderItems.java
@@ -0,0 +1,39 @@
+package br.com.bonaldo.backendchallenge.usecases;
+
+import br.com.bonaldo.backendchallenge.domains.OrderItem;
+import br.com.bonaldo.backendchallenge.gateways.OrderGateway;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDate;
+import java.time.LocalTime;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Service
+@RequiredArgsConstructor
+public class FilterOrderItems {
+
+ private final OrderGateway orderGateway;
+
+ public List execute(final LocalDate startDate, final LocalDate finalDate) {
+ final List orders = fetchOrderItemsFromAPI();
+ return filterOrderItemsByDate(startDate, finalDate, orders);
+ }
+
+ private List fetchOrderItemsFromAPI() {
+ return orderGateway
+ .getOrderItems()
+ .stream()
+ .map(OrderItem::new)
+ .collect(Collectors.toList());
+ }
+
+ private List filterOrderItemsByDate(final LocalDate startDate, final LocalDate finalDate, final List orders) {
+ return orders
+ .stream()
+ .filter(orderItem -> orderItem.getDate().isAfter(startDate.atStartOfDay()))
+ .filter(orderItem -> orderItem.getDate().isBefore(finalDate.atTime(LocalTime.MAX)))
+ .collect(Collectors.toList());
+ }
+}
\ No newline at end of file
diff --git a/backend-challenge/src/main/resources/application.yml b/backend-challenge/src/main/resources/application.yml
new file mode 100644
index 0000000..f8b8787
--- /dev/null
+++ b/backend-challenge/src/main/resources/application.yml
@@ -0,0 +1,7 @@
+server:
+ servlet:
+ context-path: /challenge-backend
+
+integration:
+ order-api:
+ url: http://www.mocky.io/v2/5817803a1000007d01cc7fc9
\ No newline at end of file
diff --git a/backend-challenge/src/test/java/br/com/bonaldo/backendchallenge/usecases/FilterOrderItemsTest.java b/backend-challenge/src/test/java/br/com/bonaldo/backendchallenge/usecases/FilterOrderItemsTest.java
new file mode 100644
index 0000000..104c492
--- /dev/null
+++ b/backend-challenge/src/test/java/br/com/bonaldo/backendchallenge/usecases/FilterOrderItemsTest.java
@@ -0,0 +1,65 @@
+package br.com.bonaldo.backendchallenge.usecases;
+
+import br.com.bonaldo.backendchallenge.domains.OrderItem;
+import br.com.bonaldo.backendchallenge.gateways.OrderGateway;
+import br.com.bonaldo.backendchallenge.gateways.http.json.DimensionResponse;
+import br.com.bonaldo.backendchallenge.gateways.http.json.OrderItemResponse;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+@SpringBootTest
+@RunWith(SpringRunner.class)
+public class FilterOrderItemsTest {
+
+ public static final String ITEM_DE_HOJE = "Today";
+
+ @InjectMocks
+ private FilterOrderItems filterOrderItems;
+
+ @Mock
+ private OrderGateway orderGateway;
+
+ @Test
+ public void FilterOrderItemsShouldReturnWithOnlyOneItemWithinDateRange() {
+ OrderItemResponse expectedItem = OrderItemResponse.builder()
+ .date(LocalDateTime.now())
+ .name(ITEM_DE_HOJE)
+ .dimension(new DimensionResponse())
+ .build();
+
+ OrderItemResponse futureItem = OrderItemResponse.builder()
+ .date(LocalDateTime.now().minusDays(1))
+ .name("Tomorrow")
+ .dimension(new DimensionResponse())
+ .build();
+
+ OrderItemResponse pastItem = OrderItemResponse.builder()
+ .date(LocalDateTime.now().plusDays(1))
+ .name("Yesterday")
+ .dimension(new DimensionResponse())
+ .build();
+
+ List response = new ArrayList<>();
+ Collections.addAll(response, expectedItem, futureItem, pastItem);
+
+ Mockito.when(orderGateway.getOrderItems()).thenReturn(response);
+
+ List result = filterOrderItems.execute(LocalDate.now(), LocalDate.now());
+
+ Assert.assertEquals(1, result.size());
+ Assert.assertNotNull(result.get(0));
+ Assert.assertEquals(result.get(0).getName(), ITEM_DE_HOJE);
+ }
+}
\ No newline at end of file
diff --git a/task2/query_events.sql b/task2/query_events.sql
new file mode 100644
index 0000000..b2aa061
--- /dev/null
+++ b/task2/query_events.sql
@@ -0,0 +1,16 @@
+-- Os resultados da planilha nao estao em conformidade com a proposta do exercicio
+-- Por exemplo, na base teste2, os dois registros mais antigos de event_type = 2 sao
+-- 2015-05-09 12:42:00 com value = 5 e 2015-05-09 12:54:39 com value = 7,
+-- ou seja, a diferenca e 7-5 = 2, e nao -3. Este cenario se repete nas outras bases
+
+select ev.event_type as EVENT_TYPE,
+ (select penultimate.value
+ from events penultimate
+ where penultimate.event_type = ev.event_type
+ order by time asc
+ limit 1 offset 1)
+ -
+ (select last.value from events last where last.event_type = ev.event_type order by time asc limit 1) as VALUE
+from events ev
+group by ev.event_type
+having count(ev.event_type) > 1;
\ No newline at end of file