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
new file mode 100644
index 0000000..35531d5
--- /dev/null
+++ b/src/main/java/com/orderflow/ecommerce/controllers/CartController.java
@@ -0,0 +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.web.bind.annotation.*;
+import org.springframework.web.server.ResponseStatusException;
+
+
+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 Optional listCart() {
+ return repository.findByUserId(1L);
+ }
+
+ @PostMapping
+ public CartItemResponse addItem(@Valid @RequestBody AddItemRequest request) {
+ return cartService.addItemToCart(request);
+ }
+
+
+ @DeleteMapping("/{id}")
+ public ResponseEntity removeItem(@PathVariable Long id) {
+ repository.deleteById(id);
+ return ResponseEntity.noContent().build();
+ }
+
+ @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());
+
+ return CartItemResponse.from(itemRepository.save(item));
+ }
+
+ @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
new file mode 100644
index 0000000..9f478a0
--- /dev/null
+++ b/src/main/java/com/orderflow/ecommerce/entities/Cart.java
@@ -0,0 +1,39 @@
+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<>();
+
+ @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
new file mode 100644
index 0000000..96ec591
--- /dev/null
+++ b/src/main/java/com/orderflow/ecommerce/entities/CartItem.java
@@ -0,0 +1,29 @@
+package com.orderflow.ecommerce.entities;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import jakarta.persistence.*;
+import lombok.*;
+import java.io.Serializable;
+
+@Entity
+@Table(name = "tb_cart_item")
+@Getter @Setter
+@NoArgsConstructor
+@AllArgsConstructor
+public class CartItem implements Serializable {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ private Integer quantity;
+ private Double price;
+
+ @JsonIgnore
+ @ManyToOne
+ @JoinColumn(name = "cart_id")
+ private Cart cart;
+
+ @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
new file mode 100644
index 0000000..a423b33
--- /dev/null
+++ b/src/main/java/com/orderflow/ecommerce/repositories/CartItemRepository.java
@@ -0,0 +1,17 @@
+package com.orderflow.ecommerce.repositories;
+
+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
new file mode 100644
index 0000000..3858c14
--- /dev/null
+++ b/src/main/java/com/orderflow/ecommerce/repositories/CartRepository.java
@@ -0,0 +1,12 @@
+package com.orderflow.ecommerce.repositories;
+
+import com.orderflow.ecommerce.entities.Cart;
+import org.springframework.data.jpa.repository.JpaRepository;
+import java.util.Optional; // <--- Importante ter esse import!
+
+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
new file mode 100644
index 0000000..2cc687c
--- /dev/null
+++ b/src/main/java/com/orderflow/ecommerce/services/CartService.java
@@ -0,0 +1,61 @@
+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;
+
+@Service
+public class CartService {
+
+ @Autowired
+ private CartRepository cartRepository;
+
+ @Autowired
+ private CartItemRepository cartItemRepository;
+
+ @Transactional
+ 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
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 8685680..842455d 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -8,6 +8,7 @@ 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