Skip to content

Commit

Permalink
Merge pull request #8 from don-bigdad/cart-dev
Browse files Browse the repository at this point in the history
Cart dev
  • Loading branch information
don-bigdad authored Nov 15, 2023
2 parents 13fdda5 + e45d401 commit 0bf7d31
Show file tree
Hide file tree
Showing 21 changed files with 462 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
@Tag(name = "Book management",description = "Endpoints for managing books")
@RestController
@Validated
@RequestMapping(value = "/books")
@RequestMapping("/books")
public class BookController {
private final BookService bookService;

Expand All @@ -41,23 +41,23 @@ public List<BookDto> getAll(@PageableDefault(size = 5, page = 0)
return bookService.findAll(pageable);
}

@DeleteMapping(value = "/{id}")
@DeleteMapping("/{id}")
@PreAuthorize("hasRole('ADMIN')")
@Operation(summary = "Delete book by id")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void deleteBookById(@PathVariable @Positive Long id) {
bookService.deleteById(id);
}

@GetMapping(value = "/{id}")
@GetMapping("/{id}")
@Operation(summary = "Get book by Id from DB")
@PreAuthorize("hasRole('USER')")
@ResponseStatus(HttpStatus.OK)
public BookDto getBookById(@PathVariable @Positive Long id) {
return bookService.getBookById(id);
}

@PutMapping(value = "/{id}")
@PutMapping("/{id}")
@PreAuthorize("hasRole('ADMIN')")
@Operation(summary = "Update book by Id in DB")
@ResponseStatus(HttpStatus.OK)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package com.example.springbootbookshop.controller;

import com.example.springbootbookshop.dto.cart.CartDto;
import com.example.springbootbookshop.dto.cart.item.CartItemDto;
import com.example.springbootbookshop.dto.cart.item.RequestCartItemDto;
import com.example.springbootbookshop.dto.cart.item.UpdateRequestCartItemDto;
import com.example.springbootbookshop.entity.User;
import com.example.springbootbookshop.service.CartService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import jakarta.validation.constraints.Positive;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
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.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

@RequiredArgsConstructor
@Tag(name = "Cart management",description = "Endpoints for managing carts")
@RestController
@Validated
@RequestMapping("/cart")
public class CartController {
private final CartService cartService;

@GetMapping
@Operation(summary = "Get cart by user id from DB")
@PreAuthorize("hasRole('USER')")
public CartDto getUserCart(Authentication authentication) {
return cartService.findById(getUserId(authentication));
}

@PostMapping
@Operation(summary = "Add books to the user cart")
@PreAuthorize("hasRole('USER')")
public CartItemDto addItemToCart(Authentication authentication,
@Valid @RequestBody RequestCartItemDto cartItem) {
return cartService.addItemToCart(getUserId(authentication), cartItem);
}

@DeleteMapping("cart-items/{id}")
@Operation(summary = "Delete cart item from the user cart")
@PreAuthorize("hasRole('USER')")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void removeCartItem(Authentication authentication,
@PathVariable @Positive Long id) {
cartService.removeItem(getUserId(authentication), id);
}

@PutMapping("cart-items/{id}")
@Operation(summary = "Update cart item in the user cart")
@PreAuthorize("hasRole('USER')")
@ResponseStatus(HttpStatus.OK)
public CartItemDto updateItemQuantity(@PathVariable @Positive Long id,
@RequestBody @Valid UpdateRequestCartItemDto quantity) {
return cartService.updateCartItem(id, quantity);
}

private Long getUserId(Authentication authentication) {
User user = (User) authentication.getPrincipal();
return user.getId();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.example.springbootbookshop.dto.cart;

import com.example.springbootbookshop.dto.cart.item.CartItemDto;
import java.util.Set;

public record CartDto(Long id,
Long userId,
Set<CartItemDto> cartItems) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.example.springbootbookshop.dto.cart.item;

public record CartItemDto(Long id,
Long bookId,
String bookTitle,
Integer quantity){
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.example.springbootbookshop.dto.cart.item;

import jakarta.validation.constraints.Positive;

public record RequestCartItemDto(@Positive Long bookId,
@Positive Integer quantity) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.example.springbootbookshop.dto.cart.item;

import jakarta.validation.constraints.Positive;

public record UpdateRequestCartItemDto(@Positive Integer quantity) {
}
7 changes: 7 additions & 0 deletions src/main/java/com/example/springbootbookshop/entity/Book.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.example.springbootbookshop.entity;

import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
Expand All @@ -8,9 +9,12 @@
import jakarta.persistence.JoinColumn;
import jakarta.persistence.JoinTable;
import jakarta.persistence.ManyToMany;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import lombok.Data;
import lombok.EqualsAndHashCode;
Expand Down Expand Up @@ -49,4 +53,7 @@ public class Book {
@ToString.Exclude
@EqualsAndHashCode.Exclude
private Set<Category> categories = new HashSet<>();

@OneToMany(mappedBy = "book",orphanRemoval = true, cascade = CascadeType.REMOVE)
private List<CartItem> cartItems = new ArrayList<>();
}
42 changes: 42 additions & 0 deletions src/main/java/com/example/springbootbookshop/entity/Cart.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.example.springbootbookshop.entity;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.OneToMany;
import jakarta.persistence.OneToOne;
import jakarta.persistence.Table;
import java.util.HashSet;
import java.util.Set;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;

@Entity
@Data
@SQLDelete(sql = "UPDATE carts SET is_deleted = true WHERE id = ?")
@Where(clause = "is_deleted=false")
@Table(name = "carts")
public class Cart {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@OneToOne(fetch = FetchType.LAZY, optional = false)
@ToString.Exclude
@EqualsAndHashCode.Exclude
@JoinColumn(name = "user_id", nullable = false)
private User user;

@OneToMany(mappedBy = "cart")
private Set<CartItem> cartItems = new HashSet<>();

@Column(nullable = false)
private boolean isDeleted = false;
}
38 changes: 38 additions & 0 deletions src/main/java/com/example/springbootbookshop/entity/CartItem.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.example.springbootbookshop.entity;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;

@Entity
@Data
@Table(name = "cart_items")
public class CartItem {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@ManyToOne(fetch = FetchType.LAZY, optional = false)
@ToString.Exclude
@EqualsAndHashCode.Exclude
@JoinColumn(name = "cart_id", nullable = false)
private Cart cart;

@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "book_id", nullable = false)
private Book book;

@Column(nullable = false)
@NotNull
private int quantity;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.example.springbootbookshop.mapper;

import com.example.springbootbookshop.dto.cart.item.CartItemDto;
import com.example.springbootbookshop.dto.cart.item.RequestCartItemDto;
import com.example.springbootbookshop.entity.CartItem;
import org.mapstruct.InjectionStrategy;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.NullValueCheckStrategy;

@Mapper(componentModel = "spring",
injectionStrategy = InjectionStrategy.CONSTRUCTOR,
nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS,
implementationPackage = "<PACKAGE_NAME>.impl")
public interface CartItemMapper {
@Mapping(source = "book.id", target = "bookId")
@Mapping(source = "book.title", target = "bookTitle")
CartItemDto toDto(CartItem cartItem);

CartItem toEntity(RequestCartItemDto cartItemDto);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.example.springbootbookshop.mapper;

import com.example.springbootbookshop.dto.cart.CartDto;
import com.example.springbootbookshop.dto.cart.item.RequestCartItemDto;
import com.example.springbootbookshop.entity.Cart;
import org.mapstruct.InjectionStrategy;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.NullValueCheckStrategy;

@Mapper(componentModel = "spring",
injectionStrategy = InjectionStrategy.CONSTRUCTOR,
nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS,
implementationPackage = "<PACKAGE_NAME>.impl",
uses = CartItemMapper.class
)
public interface CartMapper {
@Mapping(source = "user.id", target = "userId")
CartDto toDto(Cart cart);

Cart toEntity(RequestCartItemDto cart);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.example.springbootbookshop.repository;

import com.example.springbootbookshop.entity.Book;
import com.example.springbootbookshop.entity.Cart;
import com.example.springbootbookshop.entity.CartItem;
import java.util.Optional;
import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface CartItemsRepository extends JpaRepository<CartItem, Long> {
@EntityGraph(attributePaths = "book")
Optional<CartItem> findByCartAndBook(Cart cart, Book book);

Optional<CartItem> getCartItemsByIdAndCartId(Long itemId,Long cartId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.example.springbootbookshop.repository;

import com.example.springbootbookshop.entity.Cart;
import java.util.Optional;
import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface CartRepository extends JpaRepository<Cart,Long> {
@EntityGraph(attributePaths = {"user","cartItems"})
Optional<Cart> getCartByUserId(Long id);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.example.springbootbookshop.service;

import com.example.springbootbookshop.dto.cart.CartDto;
import com.example.springbootbookshop.dto.cart.item.CartItemDto;
import com.example.springbootbookshop.dto.cart.item.RequestCartItemDto;
import com.example.springbootbookshop.dto.cart.item.UpdateRequestCartItemDto;

public interface CartService {
CartDto findById(Long id);

CartItemDto addItemToCart(Long id, RequestCartItemDto requestCartItemDto);

void removeItem(Long userId, Long itemId);

CartItemDto updateCartItem(Long id, UpdateRequestCartItemDto quantity);
}
Loading

0 comments on commit 0bf7d31

Please sign in to comment.