From 4bc256a65dc3ff7e27f60f4f757a1a202394b35d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Di=C3=AAgo=20de=20Barros?= Date: Sat, 28 Mar 2026 16:30:28 -0300 Subject: [PATCH 1/8] chore(docker): set up development environment with Docker Compose, PostgreSQL, RabbitMQ, and Spring Boot --- .idea/workspace.xml | 70 ++++++++++++++++- Dockerfile | 10 +++ docker-compose.yml | 77 +++++++++++++++++++ pom.xml | 4 +- src/main/resources/application.dev.properties | 15 ++++ src/main/resources/application.properties | 18 ++--- 6 files changed, 182 insertions(+), 12 deletions(-) create mode 100644 Dockerfile create mode 100644 docker-compose.yml create mode 100644 src/main/resources/application.dev.properties diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 1ac928b..5afaaf4 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -1,4 +1,72 @@ - {} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1774725312415 + + + \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..21a13e9 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,10 @@ +FROM eclipse-temurin:21-jdk-alpine + +WORKDIR /app + +COPY pom.xml . +RUN apk add --no-cache maven && mvn dependency:go-offline -B + +COPY src src + +CMD ["mvn", "spring-boot:run", "-Dspring-boot.run.profiles=docker"] \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..ef16da4 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,77 @@ +version: '3.8' + +services: + postgres: + image: postgres:15 + container_name: orderflow-postgres + environment: + POSTGRES_DB: orderflow + POSTGRES_USER: orderflow + POSTGRES_PASSWORD: orderflow123 + ports: + - "5432:5432" + volumes: + - postgres_data:/var/lib/postgresql/data + networks: + - orderflow-network + healthcheck: + test: ["CMD-SHELL", "pg_isready -U orderflow"] + interval: 10s + timeout: 5s + retries: 5 + + rabbitmq: + image: rabbitmq:3-management + container_name: orderflow-rabbitmq + environment: + RABBITMQ_DEFAULT_USER: orderflow + RABBITMQ_DEFAULT_PASS: orderflow123 + ports: + - "5672:5672" + - "15672:15672" + volumes: + - rabbitmq_data:/var/lib/rabbitmq + networks: + - orderflow-network + healthcheck: + test: ["CMD", "rabbitmq-diagnostics", "ping"] + interval: 10s + timeout: 5s + retries: 5 + + app: + build: + context: . + dockerfile: Dockerfile + container_name: orderflow-app + environment: + SPRING_PROFILES_ACTIVE: docker + SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/orderflow + SPRING_DATASOURCE_USERNAME: orderflow + SPRING_DATASOURCE_PASSWORD: orderflow123 + SPRING_RABBITMQ_HOST: rabbitmq + SPRING_RABBITMQ_PORT: 5672 + SPRING_RABBITMQ_USERNAME: orderflow + SPRING_RABBITMQ_PASSWORD: orderflow123 + ports: + - "8080:8080" + volumes: + - ./src:/app/src # <-- código fonte sincronizado + - ./pom.xml:/app/pom.xml # <-- pom sincronizado + - maven-repo:/root/.m2 # <-- cache das dependências + depends_on: + postgres: + condition: service_healthy + rabbitmq: + condition: service_healthy + networks: + - orderflow-network + +volumes: + postgres_data: + rabbitmq_data: + maven-repo: + +networks: + orderflow-network: + driver: bridge \ No newline at end of file diff --git a/pom.xml b/pom.xml index 064182a..f04a0d3 100644 --- a/pom.xml +++ b/pom.xml @@ -32,8 +32,8 @@ - com.h2database - h2 + org.postgresql + postgresql runtime diff --git a/src/main/resources/application.dev.properties b/src/main/resources/application.dev.properties new file mode 100644 index 0000000..57ded54 --- /dev/null +++ b/src/main/resources/application.dev.properties @@ -0,0 +1,15 @@ +spring.profiles.active=dev + +spring.datasource.url=jdbc:postgresql://postgres:5432/orderflow +spring.datasource.username=orderflow +spring.datasource.password=orderflow123 +spring.datasource.driver-class-name=org.postgresql.Driver + +spring.jpa.hibernate.ddl-auto=update +spring.jpa.show-sql=true +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect + +spring.rabbitmq.host=rabbitmq +spring.rabbitmq.port=5672 +spring.rabbitmq.username=orderflow +spring.rabbitmq.password=orderflow123 \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index f780901..b03a5ad 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,13 +1,13 @@ -# H2 Database -spring.datasource.url=jdbc:h2:mem:orderflowdb -spring.datasource.driverClassName=org.h2.Driver -spring.datasource.username=sa -spring.datasource.password= +spring.datasource.url=jdbc:postgresql://postgres:5432/orderflow +spring.datasource.username=orderflow +spring.datasource.password=orderflow123 +spring.datasource.driver-class-name=org.postgresql.Driver -# JPA -spring.jpa.database-platform=org.hibernate.dialect.H2Dialect spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect -spring.h2.console.enabled=true -spring.h2.console.path=/h2-console \ No newline at end of file +spring.rabbitmq.host=rabbitmq +spring.rabbitmq.port=5672 +spring.rabbitmq.username=orderflow +spring.rabbitmq.password=orderflow123 \ No newline at end of file From 8f84ff2e6162344c2b16ee93756919e0be9058ec Mon Sep 17 00:00:00 2001 From: gio448 Date: Sat, 28 Mar 2026 21:09:07 -0300 Subject: [PATCH 2/8] feat: add cart models and repositories for ecommerce flow --- .../ecommerce/controllers/CartController.java | 47 +++++++++++++++++++ .../orderflow/ecommerce/entities/Cart.java | 35 ++++++++++++++ .../ecommerce/entities/CartItem.java | 31 ++++++++++++ .../repositories/CartItemRepository.java | 9 ++++ .../repositories/CartRepository.java | 9 ++++ src/main/resources/application.properties | 4 +- 6 files changed, 133 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/orderflow/ecommerce/controllers/CartController.java create mode 100644 src/main/java/com/orderflow/ecommerce/entities/Cart.java create mode 100644 src/main/java/com/orderflow/ecommerce/entities/CartItem.java create mode 100644 src/main/java/com/orderflow/ecommerce/repositories/CartItemRepository.java create mode 100644 src/main/java/com/orderflow/ecommerce/repositories/CartRepository.java diff --git a/src/main/java/com/orderflow/ecommerce/controllers/CartController.java b/src/main/java/com/orderflow/ecommerce/controllers/CartController.java new file mode 100644 index 0000000..2e0a81b --- /dev/null +++ b/src/main/java/com/orderflow/ecommerce/controllers/CartController.java @@ -0,0 +1,47 @@ +package com.orderflow.ecommerce.controllers; + +import com.orderflow.ecommerce.entities.CartItem; +import com.orderflow.ecommerce.repositories.CartRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +import static org.springframework.data.jpa.domain.AbstractPersistable_.id; + +@RestController +@RequestMapping("/api/cart") +public class CartController { + + @Autowired + private CartRepository repository; + + @GetMapping + public List listCart() { + return repository.findAll(); + } + + @PostMapping + public CartItem addItem(@RequestBody CartItem item) { + return repository.save(item); + } + + @DeleteMapping("/{id}") + public void removeItem(@PathVariable Long id) { + repository.deleteById(id); + } + + @PutMapping("/{id}") + public CartItem updateItem(@PathVariable Long id, @RequestBody CartItem itemDetails) { + CartItem item = repository.findById(id) + .orElseThrow(() -> new RuntimeException("Item não encontrado com id: " + id)); + + item.setQuantity(itemDetails.getQuantity()); + return repository.save(item); + } + + @DeleteMapping("/clear") + public void clearCart() { + repository.deleteAll(); + } +} diff --git a/src/main/java/com/orderflow/ecommerce/entities/Cart.java b/src/main/java/com/orderflow/ecommerce/entities/Cart.java new file mode 100644 index 0000000..4ac60a4 --- /dev/null +++ b/src/main/java/com/orderflow/ecommerce/entities/Cart.java @@ -0,0 +1,35 @@ +package com.orderflow.ecommerce.entities; + +import jakarta.persistence.*; +import lombok.Getter; +import lombok.Setter; +import lombok.NoArgsConstructor; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import java.io.Serial; +import java.io.Serializable; +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +@Entity +@Table(name = "tb_cart") +@Getter @Setter +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(onlyExplicitlyIncluded = true) +public class Cart implements Serializable { + @Serial + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @EqualsAndHashCode.Include + private Long id; + + private Instant createdAt = Instant.now(); + + @OneToMany(mappedBy = "cart", cascade = CascadeType.ALL) + private List items = new ArrayList<>(); +} \ No newline at end of file diff --git a/src/main/java/com/orderflow/ecommerce/entities/CartItem.java b/src/main/java/com/orderflow/ecommerce/entities/CartItem.java new file mode 100644 index 0000000..9c0173a --- /dev/null +++ b/src/main/java/com/orderflow/ecommerce/entities/CartItem.java @@ -0,0 +1,31 @@ +package com.orderflow.ecommerce.entities; + +import jakarta.persistence.*; +import lombok.*; +import java.io.Serializable; + +@Entity +@Table(name = "tb_cart_item") +@Getter @Setter +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(onlyExplicitlyIncluded = true) +public class CartItem implements Serializable { + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @EqualsAndHashCode.Include + private Long id; + + private Integer quantity; + private Double price; + + @ManyToOne + @JoinColumn(name = "cart_id") + private Cart cart; + + @ManyToOne + @JoinColumn(name = "product_id") + private Product product; +} \ No newline at end of file diff --git a/src/main/java/com/orderflow/ecommerce/repositories/CartItemRepository.java b/src/main/java/com/orderflow/ecommerce/repositories/CartItemRepository.java new file mode 100644 index 0000000..43bc50e --- /dev/null +++ b/src/main/java/com/orderflow/ecommerce/repositories/CartItemRepository.java @@ -0,0 +1,9 @@ +package com.orderflow.ecommerce.repositories; + +import com.orderflow.ecommerce.entities.CartItem; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface CartItemRepository extends JpaRepository { +} \ No newline at end of file diff --git a/src/main/java/com/orderflow/ecommerce/repositories/CartRepository.java b/src/main/java/com/orderflow/ecommerce/repositories/CartRepository.java new file mode 100644 index 0000000..04bffdf --- /dev/null +++ b/src/main/java/com/orderflow/ecommerce/repositories/CartRepository.java @@ -0,0 +1,9 @@ +package com.orderflow.ecommerce.repositories; + +import com.orderflow.ecommerce.entities.CartItem; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface CartRepository extends JpaRepository { +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index b03a5ad..84ba200 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,4 +1,4 @@ -spring.datasource.url=jdbc:postgresql://postgres:5432/orderflow +spring.datasource.url=jdbc:postgresql://localhost:5432/orderflow spring.datasource.username=orderflow spring.datasource.password=orderflow123 spring.datasource.driver-class-name=org.postgresql.Driver @@ -7,7 +7,7 @@ spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect -spring.rabbitmq.host=rabbitmq +spring.rabbitmq.host=localhost spring.rabbitmq.port=5672 spring.rabbitmq.username=orderflow spring.rabbitmq.password=orderflow123 \ No newline at end of file From cdad097350329285b062aa8de3aea24421ab6ca0 Mon Sep 17 00:00:00 2001 From: gio448 Date: Wed, 1 Apr 2026 14:02:15 -0300 Subject: [PATCH 3/8] fix: logic for user cart clear and postgres config --- .../ecommerce/controllers/CartController.java | 14 ++++++++++---- .../repositories/CartItemRepository.java | 1 + .../ecommerce/services/CartService.java | 18 ++++++++++++++++++ src/main/resources/application.properties | 15 ++++++--------- 4 files changed, 35 insertions(+), 13 deletions(-) create mode 100644 src/main/java/com/orderflow/ecommerce/services/CartService.java diff --git a/src/main/java/com/orderflow/ecommerce/controllers/CartController.java b/src/main/java/com/orderflow/ecommerce/controllers/CartController.java index 2e0a81b..11c7e74 100644 --- a/src/main/java/com/orderflow/ecommerce/controllers/CartController.java +++ b/src/main/java/com/orderflow/ecommerce/controllers/CartController.java @@ -1,8 +1,12 @@ package com.orderflow.ecommerce.controllers; import com.orderflow.ecommerce.entities.CartItem; +import com.orderflow.ecommerce.repositories.CartItemRepository; import com.orderflow.ecommerce.repositories.CartRepository; +import com.orderflow.ecommerce.services.CartService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; import java.util.List; @@ -12,7 +16,8 @@ @RestController @RequestMapping("/api/cart") public class CartController { - + @Autowired + private CartService cartService; @Autowired private CartRepository repository; @@ -40,8 +45,9 @@ public CartItem updateItem(@PathVariable Long id, @RequestBody CartItem itemDeta return repository.save(item); } - @DeleteMapping("/clear") - public void clearCart() { - repository.deleteAll(); + @DeleteMapping("/clear/{userId}") + public ResponseEntity clearCart(@PathVariable Long userId) { + cartService.clearCartByUserId(userId); + return ResponseEntity.noContent().build(); } } diff --git a/src/main/java/com/orderflow/ecommerce/repositories/CartItemRepository.java b/src/main/java/com/orderflow/ecommerce/repositories/CartItemRepository.java index 43bc50e..912095e 100644 --- a/src/main/java/com/orderflow/ecommerce/repositories/CartItemRepository.java +++ b/src/main/java/com/orderflow/ecommerce/repositories/CartItemRepository.java @@ -6,4 +6,5 @@ @Repository public interface CartItemRepository extends JpaRepository { + void deleteByCartUserId(Long userId); } \ No newline at end of file diff --git a/src/main/java/com/orderflow/ecommerce/services/CartService.java b/src/main/java/com/orderflow/ecommerce/services/CartService.java new file mode 100644 index 0000000..1e08aa0 --- /dev/null +++ b/src/main/java/com/orderflow/ecommerce/services/CartService.java @@ -0,0 +1,18 @@ +package com.orderflow.ecommerce.services; + +import com.orderflow.ecommerce.repositories.CartItemRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class CartService { + + @Autowired + private CartItemRepository cartItemRepository; + + @Transactional + public void clearCartByUserId(Long userId) { + cartItemRepository.deleteByCartUserId(userId); + } +} \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index f780901..817efdf 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,13 +1,10 @@ -# H2 Database -spring.datasource.url=jdbc:h2:mem:orderflowdb -spring.datasource.driverClassName=org.h2.Driver -spring.datasource.username=sa -spring.datasource.password= +spring.datasource.url=jdbc:postgresql://localhost:5433/orderflow_db +spring.datasource.username=postgres +spring.datasource.password=123 +spring.datasource.driverClassName=org.postgresql.Driver -# JPA -spring.jpa.database-platform=org.hibernate.dialect.H2Dialect spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect -spring.h2.console.enabled=true -spring.h2.console.path=/h2-console \ No newline at end of file +spring.jpa.properties.hibernate.jdbc.time_zone=UTC \ No newline at end of file From 5348b097d390eef0f13e2e80ff84df88de18aa46 Mon Sep 17 00:00:00 2001 From: gio448 Date: Wed, 1 Apr 2026 14:09:35 -0300 Subject: [PATCH 4/8] fix: logic for user cart clear and postgres config --- .../ecommerce/dtos/UserRequestDTO.java | 4 +++ .../orderflow/ecommerce/entities/User.java | 26 +++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 src/main/java/com/orderflow/ecommerce/dtos/UserRequestDTO.java create mode 100644 src/main/java/com/orderflow/ecommerce/entities/User.java diff --git a/src/main/java/com/orderflow/ecommerce/dtos/UserRequestDTO.java b/src/main/java/com/orderflow/ecommerce/dtos/UserRequestDTO.java new file mode 100644 index 0000000..42011bc --- /dev/null +++ b/src/main/java/com/orderflow/ecommerce/dtos/UserRequestDTO.java @@ -0,0 +1,4 @@ +package com.orderflow.ecommerce.dtos; + +public record UserRequestDTO(String name, String email, String password) { +} \ No newline at end of file diff --git a/src/main/java/com/orderflow/ecommerce/entities/User.java b/src/main/java/com/orderflow/ecommerce/entities/User.java new file mode 100644 index 0000000..30bf19b --- /dev/null +++ b/src/main/java/com/orderflow/ecommerce/entities/User.java @@ -0,0 +1,26 @@ +package com.orderflow.ecommerce.entities; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Entity +@Table(name = "tb_users") +@Data +@NoArgsConstructor +@AllArgsConstructor +public class User { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String name; + + @Column(unique = true, nullable = false) + private String email; + + @Column(nullable = false) + private String password; +} From 17347790eeae07e2d988c7df7f14b4a4e286f163 Mon Sep 17 00:00:00 2001 From: gio448 Date: Wed, 1 Apr 2026 14:10:56 -0300 Subject: [PATCH 5/8] fix: logic for user cart clear and postgres config --- .../java/com/orderflow/ecommerce/dtos/UserRequestDTO.java | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 src/main/java/com/orderflow/ecommerce/dtos/UserRequestDTO.java diff --git a/src/main/java/com/orderflow/ecommerce/dtos/UserRequestDTO.java b/src/main/java/com/orderflow/ecommerce/dtos/UserRequestDTO.java deleted file mode 100644 index 42011bc..0000000 --- a/src/main/java/com/orderflow/ecommerce/dtos/UserRequestDTO.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.orderflow.ecommerce.dtos; - -public record UserRequestDTO(String name, String email, String password) { -} \ No newline at end of file From c5aca087b82a47b4430dad2976070015b16a1ca4 Mon Sep 17 00:00:00 2001 From: gio448 Date: Wed, 1 Apr 2026 14:16:29 -0300 Subject: [PATCH 6/8] chore: remove unrelated user files from cart branch --- .../orderflow/ecommerce/entities/User.java | 26 ------------------- 1 file changed, 26 deletions(-) delete mode 100644 src/main/java/com/orderflow/ecommerce/entities/User.java diff --git a/src/main/java/com/orderflow/ecommerce/entities/User.java b/src/main/java/com/orderflow/ecommerce/entities/User.java deleted file mode 100644 index 30bf19b..0000000 --- a/src/main/java/com/orderflow/ecommerce/entities/User.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.orderflow.ecommerce.entities; - -import jakarta.persistence.*; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Entity -@Table(name = "tb_users") -@Data -@NoArgsConstructor -@AllArgsConstructor -public class User { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - private String name; - - @Column(unique = true, nullable = false) - private String email; - - @Column(nullable = false) - private String password; -} From 4aaf4e1738b159495cc42e856ace356b74f826d1 Mon Sep 17 00:00:00 2001 From: gio448 Date: Sat, 4 Apr 2026 17:07:19 -0300 Subject: [PATCH 7/8] fix: revert application.properties to original configuration --- src/main/resources/application.properties | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 817efdf..842455d 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,10 +1,17 @@ -spring.datasource.url=jdbc:postgresql://localhost:5433/orderflow_db -spring.datasource.username=postgres -spring.datasource.password=123 -spring.datasource.driverClassName=org.postgresql.Driver +spring.datasource.url=jdbc:postgresql://postgres:5432/orderflow +spring.datasource.username=orderflow +spring.datasource.password=orderflow123 +spring.datasource.driver-class-name=org.postgresql.Driver spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect -spring.jpa.properties.hibernate.jdbc.time_zone=UTC \ No newline at end of file +spring.rabbitmq.host=rabbitmq + +spring.rabbitmq.port=5672 +spring.rabbitmq.username=orderflow +spring.rabbitmq.password=orderflow123 + +spring.devtools.restart.poll-interval=2s +spring.devtools.restart.quiet-period=1s \ No newline at end of file From 6a51abcf8f124d860dc35e97dbbd8ab4d538ad4b Mon Sep 17 00:00:00 2001 From: gio448 Date: Wed, 8 Apr 2026 15:54:07 -0300 Subject: [PATCH 8/8] feat: Implementing shopping cart and persistence adjustments --- pom.xml | 6 +++ .../ecommerce/controllers/CartController.java | 48 +++++++++++------ .../controllers/CategoryController.java | 53 ------------------- .../controllers/ProductController.java | 53 ------------------- .../ecommerce/controllers/TestController.java | 24 --------- .../ecommerce/dtos/AddItemRequest.java | 12 +++++ .../ecommerce/dtos/CartItemResponse.java | 21 ++++++++ .../ecommerce/dtos/UpdateQuantityRequest.java | 10 ++++ .../orderflow/ecommerce/entities/Cart.java | 4 ++ .../ecommerce/entities/CartItem.java | 10 ++-- .../ecommerce/entities/Category.java | 20 ------- .../orderflow/ecommerce/entities/Product.java | 3 -- .../repositories/CartItemRepository.java | 7 +++ .../repositories/CartRepository.java | 11 ++-- .../repositories/CategoryRepository.java | 9 ---- .../repositories/ProductRepository.java | 9 ---- .../ecommerce/services/CartService.java | 47 +++++++++++++++- 17 files changed, 147 insertions(+), 200 deletions(-) delete mode 100644 src/main/java/com/orderflow/ecommerce/controllers/CategoryController.java delete mode 100644 src/main/java/com/orderflow/ecommerce/controllers/ProductController.java delete mode 100644 src/main/java/com/orderflow/ecommerce/controllers/TestController.java create mode 100644 src/main/java/com/orderflow/ecommerce/dtos/AddItemRequest.java create mode 100644 src/main/java/com/orderflow/ecommerce/dtos/CartItemResponse.java create mode 100644 src/main/java/com/orderflow/ecommerce/dtos/UpdateQuantityRequest.java delete mode 100644 src/main/java/com/orderflow/ecommerce/entities/Category.java delete mode 100644 src/main/java/com/orderflow/ecommerce/repositories/CategoryRepository.java delete mode 100644 src/main/java/com/orderflow/ecommerce/repositories/ProductRepository.java diff --git a/pom.xml b/pom.xml index a4d8bf9..6524c3a 100644 --- a/pom.xml +++ b/pom.xml @@ -33,11 +33,17 @@ true + + org.springframework.boot + spring-boot-starter-validation + + org.springframework.boot spring-boot-starter-web + org.postgresql postgresql diff --git a/src/main/java/com/orderflow/ecommerce/controllers/CartController.java b/src/main/java/com/orderflow/ecommerce/controllers/CartController.java index 11c7e74..35531d5 100644 --- a/src/main/java/com/orderflow/ecommerce/controllers/CartController.java +++ b/src/main/java/com/orderflow/ecommerce/controllers/CartController.java @@ -1,53 +1,67 @@ package com.orderflow.ecommerce.controllers; +import com.orderflow.ecommerce.dtos.AddItemRequest; +import com.orderflow.ecommerce.dtos.CartItemResponse; +import com.orderflow.ecommerce.dtos.UpdateQuantityRequest; +import com.orderflow.ecommerce.entities.Cart; import com.orderflow.ecommerce.entities.CartItem; import com.orderflow.ecommerce.repositories.CartItemRepository; import com.orderflow.ecommerce.repositories.CartRepository; import com.orderflow.ecommerce.services.CartService; +import jakarta.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; +import org.springframework.web.server.ResponseStatusException; -import java.util.List; -import static org.springframework.data.jpa.domain.AbstractPersistable_.id; +import java.util.Optional; @RestController @RequestMapping("/api/cart") public class CartController { + @Autowired private CartService cartService; + @Autowired private CartRepository repository; + @Autowired + private CartItemRepository itemRepository; + @GetMapping - public List listCart() { - return repository.findAll(); + public Optional listCart() { + return repository.findByUserId(1L); } @PostMapping - public CartItem addItem(@RequestBody CartItem item) { - return repository.save(item); + public CartItemResponse addItem(@Valid @RequestBody AddItemRequest request) { + return cartService.addItemToCart(request); } + @DeleteMapping("/{id}") - public void removeItem(@PathVariable Long id) { + public ResponseEntity removeItem(@PathVariable Long id) { repository.deleteById(id); + return ResponseEntity.noContent().build(); } - @PutMapping("/{id}") - public CartItem updateItem(@PathVariable Long id, @RequestBody CartItem itemDetails) { - CartItem item = repository.findById(id) - .orElseThrow(() -> new RuntimeException("Item não encontrado com id: " + id)); + @PutMapping("/items/{id}") + public CartItemResponse updateItem(@PathVariable Long id, @Valid @RequestBody UpdateQuantityRequest request) { + + CartItem item = itemRepository.findById(id) + .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Cart item not found with id: " + id)); + + item.setQuantity(request.quantity()); - item.setQuantity(itemDetails.getQuantity()); - return repository.save(item); + return CartItemResponse.from(itemRepository.save(item)); } - @DeleteMapping("/clear/{userId}") - public ResponseEntity clearCart(@PathVariable Long userId) { - cartService.clearCartByUserId(userId); + @DeleteMapping("/clear") + public ResponseEntity clearCart() { + cartService.clearCurrentCart(); return ResponseEntity.noContent().build(); } } diff --git a/src/main/java/com/orderflow/ecommerce/controllers/CategoryController.java b/src/main/java/com/orderflow/ecommerce/controllers/CategoryController.java deleted file mode 100644 index 7d1292d..0000000 --- a/src/main/java/com/orderflow/ecommerce/controllers/CategoryController.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.orderflow.ecommerce.controllers; - -import com.orderflow.ecommerce.entities.Category; -import com.orderflow.ecommerce.repositories.CategoryRepository; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -@RestController -@RequestMapping(value = "/categories") -public class CategoryController { - - @Autowired - private CategoryRepository repository; - - @GetMapping - public ResponseEntity> findAll() { - return ResponseEntity.ok().body(repository.findAll()); - } - - @GetMapping(value = "/{id}") - public ResponseEntity findById(@PathVariable Long id) { - - - return repository.findById(id) - .map(obj -> ResponseEntity.ok().body(obj)) - .orElse(ResponseEntity.notFound().build()); - } - - @PostMapping - public ResponseEntity insert(@RequestBody Category obj) { - return ResponseEntity.ok().body(repository.save(obj)); - } - - @DeleteMapping(value = "/{id}") - public ResponseEntity delete(@PathVariable Long id) { - repository.deleteById(id); - return ResponseEntity.noContent().build(); - } - - @PutMapping(value = "/{id}") - public ResponseEntity update(@PathVariable Long id, @RequestBody Category obj) { - return repository.findById(id) - .map(entity -> { - entity.setName(obj.getName()); - Category updated = repository.save(entity); - return ResponseEntity.ok().body(updated); - }) - .orElse(ResponseEntity.notFound().build()); - } -} \ No newline at end of file diff --git a/src/main/java/com/orderflow/ecommerce/controllers/ProductController.java b/src/main/java/com/orderflow/ecommerce/controllers/ProductController.java deleted file mode 100644 index 8c14bb0..0000000 --- a/src/main/java/com/orderflow/ecommerce/controllers/ProductController.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.orderflow.ecommerce.controllers; - -import com.orderflow.ecommerce.entities.Product; -import com.orderflow.ecommerce.repositories.ProductRepository; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -@RestController -@RequestMapping(value = "/products") -public class ProductController { - - @Autowired - private ProductRepository repository; - - @GetMapping - public ResponseEntity> findAll() { - return ResponseEntity.ok().body(repository.findAll()); - } - - @GetMapping(value = "/{id}") - public ResponseEntity findById(@PathVariable Long id) { - return repository.findById(id) - .map(obj -> ResponseEntity.ok().body(obj)) - .orElse(ResponseEntity.notFound().build()); - } - - @PostMapping - public ResponseEntity insert(@RequestBody Product obj) { - return ResponseEntity.ok().body(repository.save(obj)); - } - - @DeleteMapping(value = "/{id}") - public ResponseEntity delete(@PathVariable Long id) { - repository.deleteById(id); - return ResponseEntity.noContent().build(); - } - - @PutMapping(value = "/{id}") - public ResponseEntity update(@PathVariable Long id, @RequestBody Product obj) { - Product entity = repository.findById(id).get(); - entity.setName(obj.getName()); - entity.setDescription(obj.getDescription()); - entity.setPrice(obj.getPrice()); - entity.setStockQuantity(obj.getStockQuantity()); - entity.setCategory(obj.getCategory()); - System.out.println("aavavvvv"); - return ResponseEntity.ok().body(repository.save(entity)); - - } -} \ No newline at end of file diff --git a/src/main/java/com/orderflow/ecommerce/controllers/TestController.java b/src/main/java/com/orderflow/ecommerce/controllers/TestController.java deleted file mode 100644 index 746932c..0000000 --- a/src/main/java/com/orderflow/ecommerce/controllers/TestController.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.orderflow.ecommerce.controllers; - -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import java.time.LocalDateTime; -import java.util.Map; - -@RestController -@RequestMapping("/test") -public class TestController { - - @GetMapping("/ping") - public Map ping() { - - return Map.of( - "status", "ok", - "message", "versão 1.", - "timestamp", LocalDateTime.now().toString() - ); - } - -} diff --git a/src/main/java/com/orderflow/ecommerce/dtos/AddItemRequest.java b/src/main/java/com/orderflow/ecommerce/dtos/AddItemRequest.java new file mode 100644 index 0000000..0803457 --- /dev/null +++ b/src/main/java/com/orderflow/ecommerce/dtos/AddItemRequest.java @@ -0,0 +1,12 @@ +package com.orderflow.ecommerce.dtos; + +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Positive; + +public record AddItemRequest( + @NotNull Long productId, + @NotNull @Positive Integer quantity, + @NotNull @Positive Double price +) { + +} \ No newline at end of file diff --git a/src/main/java/com/orderflow/ecommerce/dtos/CartItemResponse.java b/src/main/java/com/orderflow/ecommerce/dtos/CartItemResponse.java new file mode 100644 index 0000000..07ff16b --- /dev/null +++ b/src/main/java/com/orderflow/ecommerce/dtos/CartItemResponse.java @@ -0,0 +1,21 @@ +package com.orderflow.ecommerce.dtos; + +import com.orderflow.ecommerce.entities.CartItem; + +public record CartItemResponse( + Long id, + Long productId, + String productName, + Integer quantity, + Double price +) { + public static CartItemResponse from(CartItem item) { + return new CartItemResponse( + item.getId(), + item.getProductId(), + "Produto #" + item.getProductId(), + item.getQuantity(), + item.getPrice() + ); + } +} \ No newline at end of file diff --git a/src/main/java/com/orderflow/ecommerce/dtos/UpdateQuantityRequest.java b/src/main/java/com/orderflow/ecommerce/dtos/UpdateQuantityRequest.java new file mode 100644 index 0000000..ebb25c6 --- /dev/null +++ b/src/main/java/com/orderflow/ecommerce/dtos/UpdateQuantityRequest.java @@ -0,0 +1,10 @@ +package com.orderflow.ecommerce.dtos; + +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; + +public record UpdateQuantityRequest( + @NotNull(message = "A quantidade não pode ser nula") + @Min(value = 1, message = "A quantidade deve ser no mínimo 1") + Integer quantity +) {} \ No newline at end of file diff --git a/src/main/java/com/orderflow/ecommerce/entities/Cart.java b/src/main/java/com/orderflow/ecommerce/entities/Cart.java index 4ac60a4..9f478a0 100644 --- a/src/main/java/com/orderflow/ecommerce/entities/Cart.java +++ b/src/main/java/com/orderflow/ecommerce/entities/Cart.java @@ -6,6 +6,7 @@ import lombok.NoArgsConstructor; import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; + import java.io.Serial; import java.io.Serializable; import java.time.Instant; @@ -32,4 +33,7 @@ public class Cart implements Serializable { @OneToMany(mappedBy = "cart", cascade = CascadeType.ALL) private List items = new ArrayList<>(); + + @Column(name = "user_id") + private Long userId; } \ No newline at end of file diff --git a/src/main/java/com/orderflow/ecommerce/entities/CartItem.java b/src/main/java/com/orderflow/ecommerce/entities/CartItem.java index 9c0173a..96ec591 100644 --- a/src/main/java/com/orderflow/ecommerce/entities/CartItem.java +++ b/src/main/java/com/orderflow/ecommerce/entities/CartItem.java @@ -1,5 +1,6 @@ package com.orderflow.ecommerce.entities; +import com.fasterxml.jackson.annotation.JsonIgnore; import jakarta.persistence.*; import lombok.*; import java.io.Serializable; @@ -9,23 +10,20 @@ @Getter @Setter @NoArgsConstructor @AllArgsConstructor -@EqualsAndHashCode(onlyExplicitlyIncluded = true) public class CartItem implements Serializable { - private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @EqualsAndHashCode.Include private Long id; private Integer quantity; private Double price; + @JsonIgnore @ManyToOne @JoinColumn(name = "cart_id") private Cart cart; - @ManyToOne - @JoinColumn(name = "product_id") - private Product product; + @Column(name = "product_id_temp") + private Long productId; } \ No newline at end of file diff --git a/src/main/java/com/orderflow/ecommerce/entities/Category.java b/src/main/java/com/orderflow/ecommerce/entities/Category.java deleted file mode 100644 index 3c08a5e..0000000 --- a/src/main/java/com/orderflow/ecommerce/entities/Category.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.orderflow.ecommerce.entities; - -import jakarta.persistence.*; -import lombok.*; - -@Entity -@Table(name = "tb_category") -@Getter @Setter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor -@EqualsAndHashCode(of = "id") -public class Category { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @Column(nullable = false, unique = true) - private String name; -} diff --git a/src/main/java/com/orderflow/ecommerce/entities/Product.java b/src/main/java/com/orderflow/ecommerce/entities/Product.java index e72b010..d64acfc 100644 --- a/src/main/java/com/orderflow/ecommerce/entities/Product.java +++ b/src/main/java/com/orderflow/ecommerce/entities/Product.java @@ -27,7 +27,4 @@ public class Product { private Integer stockQuantity; - @ManyToOne - @JoinColumn(name = "category_id") - private Category category; } \ No newline at end of file diff --git a/src/main/java/com/orderflow/ecommerce/repositories/CartItemRepository.java b/src/main/java/com/orderflow/ecommerce/repositories/CartItemRepository.java index 912095e..a423b33 100644 --- a/src/main/java/com/orderflow/ecommerce/repositories/CartItemRepository.java +++ b/src/main/java/com/orderflow/ecommerce/repositories/CartItemRepository.java @@ -2,9 +2,16 @@ import com.orderflow.ecommerce.entities.CartItem; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; @Repository public interface CartItemRepository extends JpaRepository { + + @Modifying + @Transactional + @Query("DELETE FROM CartItem c WHERE c.cart.userId = :userId") void deleteByCartUserId(Long userId); } \ No newline at end of file diff --git a/src/main/java/com/orderflow/ecommerce/repositories/CartRepository.java b/src/main/java/com/orderflow/ecommerce/repositories/CartRepository.java index 04bffdf..3858c14 100644 --- a/src/main/java/com/orderflow/ecommerce/repositories/CartRepository.java +++ b/src/main/java/com/orderflow/ecommerce/repositories/CartRepository.java @@ -1,9 +1,12 @@ package com.orderflow.ecommerce.repositories; -import com.orderflow.ecommerce.entities.CartItem; +import com.orderflow.ecommerce.entities.Cart; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; +import java.util.Optional; // <--- Importante ter esse import! -@Repository -public interface CartRepository extends JpaRepository { +public interface CartRepository extends JpaRepository { + + Optional findByUserId(Long userId); + + void deleteByUserId(Long userId); } diff --git a/src/main/java/com/orderflow/ecommerce/repositories/CategoryRepository.java b/src/main/java/com/orderflow/ecommerce/repositories/CategoryRepository.java deleted file mode 100644 index cebc3c0..0000000 --- a/src/main/java/com/orderflow/ecommerce/repositories/CategoryRepository.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.orderflow.ecommerce.repositories; - -import com.orderflow.ecommerce.entities.Category; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -@Repository -public interface CategoryRepository extends JpaRepository { -} \ No newline at end of file diff --git a/src/main/java/com/orderflow/ecommerce/repositories/ProductRepository.java b/src/main/java/com/orderflow/ecommerce/repositories/ProductRepository.java deleted file mode 100644 index d49a9fe..0000000 --- a/src/main/java/com/orderflow/ecommerce/repositories/ProductRepository.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.orderflow.ecommerce.repositories; - -import com.orderflow.ecommerce.entities.Product; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -@Repository -public interface ProductRepository extends JpaRepository { -} diff --git a/src/main/java/com/orderflow/ecommerce/services/CartService.java b/src/main/java/com/orderflow/ecommerce/services/CartService.java index 1e08aa0..2cc687c 100644 --- a/src/main/java/com/orderflow/ecommerce/services/CartService.java +++ b/src/main/java/com/orderflow/ecommerce/services/CartService.java @@ -1,6 +1,11 @@ package com.orderflow.ecommerce.services; +import com.orderflow.ecommerce.dtos.AddItemRequest; +import com.orderflow.ecommerce.dtos.CartItemResponse; +import com.orderflow.ecommerce.entities.Cart; +import com.orderflow.ecommerce.entities.CartItem; import com.orderflow.ecommerce.repositories.CartItemRepository; +import com.orderflow.ecommerce.repositories.CartRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -8,11 +13,49 @@ @Service public class CartService { + @Autowired + private CartRepository cartRepository; + @Autowired private CartItemRepository cartItemRepository; @Transactional - public void clearCartByUserId(Long userId) { - cartItemRepository.deleteByCartUserId(userId); + public CartItemResponse addItemToCart(AddItemRequest request) { + Cart cart = cartRepository.findByUserId(1L) + .orElseGet(() -> { + Cart newCart = new Cart(); + newCart.setUserId(1L); + + return cartRepository.saveAndFlush(newCart); + }); + + CartItem item = new CartItem(); + item.setQuantity(request.quantity()); + item.setPrice(request.price()); + item.setCart(cart); + item.setProductId(request.productId()); + + CartItem savedItem = cartItemRepository.saveAndFlush(item); + return CartItemResponse.from(savedItem); + } + + @Transactional + public CartItemResponse updateItem(Long itemId, AddItemRequest request) { + CartItem item = cartItemRepository.findById(itemId) + .orElseThrow(() -> new RuntimeException("Item não encontrado")); + + item.setQuantity(request.quantity()); + item.setPrice(request.price()); + item.setProductId(request.productId()); + + CartItem updatedItem = cartItemRepository.saveAndFlush(item); + return CartItemResponse.from(updatedItem); + } + + @Transactional + public void clearCurrentCart() { + cartRepository.deleteByUserId(1L); + + cartRepository.flush(); } } \ No newline at end of file