Skip to content

Commit

Permalink
Merge pull request #8 from fmIst0/implementing-shopping-cart-model
Browse files Browse the repository at this point in the history
added shopping cart implementation
  • Loading branch information
fmIst0 authored Sep 15, 2023
2 parents d54b0eb + ae430e3 commit 1189d13
Show file tree
Hide file tree
Showing 21 changed files with 455 additions and 5 deletions.
3 changes: 2 additions & 1 deletion src/main/java/com/bookstore/controller/BookController.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import jakarta.validation.Valid;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
Expand Down Expand Up @@ -46,7 +47,7 @@ public BookDto getBookById(@PathVariable Long id) {
@GetMapping("/search")
@PreAuthorize("hasRole('USER')")
@Operation(summary = "Search books", description = "Search book by specific search parameters")
public List<BookDto> searchBooks(BookSearchParametersDto searchParameters) {
public Page<BookDto> searchBooks(BookSearchParametersDto searchParameters) {
return bookService.searchBooks(searchParameters);
}

Expand Down
79 changes: 79 additions & 0 deletions src/main/java/com/bookstore/controller/ShoppingCartController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package com.bookstore.controller;

import com.bookstore.dto.cartitem.CartItemCreateDto;
import com.bookstore.dto.cartitem.CartItemUpdateDto;
import com.bookstore.dto.shoppingcart.ShoppingCartDto;
import com.bookstore.model.User;
import com.bookstore.service.ShoppingCartService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
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.RestController;

@Tag(name = "Shopping cart management", description = "Endpoints for managing shopping carts")
@RequiredArgsConstructor
@RestController
@RequestMapping(value = "/api/cart")
public class ShoppingCartController {
private final ShoppingCartService shoppingCartService;

@GetMapping(value = "/all")
@PreAuthorize("hasRole('ADMIN')")
@Operation(summary = "Get all shopping carts",
description = "Get all shopping carts only for admins")
public List<ShoppingCartDto> getAll(Pageable pageable) {
return shoppingCartService.findAll(pageable);
}

@GetMapping
@PreAuthorize("hasRole('USER')")
@Operation(summary = "Retrieve user's shopping cart",
description = "Retrieve user's shopping cart")
public ShoppingCartDto getShoppingCartByUser(Authentication authentication) {
User user = (User) authentication.getPrincipal();
return shoppingCartService.getByUserId(user.getId());
}

@PostMapping
@PreAuthorize("hasRole('USER')")
@Operation(summary = "Add book to the shopping cart",
description = "Add book to the shopping cart")
public ShoppingCartDto addBookToTheCart(Authentication authentication,
@RequestBody @Valid
CartItemCreateDto cartItemCreateDto) {
User user = (User) authentication.getPrincipal();
return shoppingCartService.saveBookToTheCart(user.getId(), cartItemCreateDto);
}

@PutMapping(value = "/cart-items/{cartItemId}")
@PreAuthorize("hasRole('USER')")
@Operation(summary = "Update quantity of a book in the shopping cart",
description = "Update quantity of a book in the shopping cart")
public ShoppingCartDto updateBookInTheCart(Authentication authentication,
@PathVariable Long cartItemId,
@RequestBody @Valid
CartItemUpdateDto cartItemUpdateDto) {
User user = (User) authentication.getPrincipal();
return shoppingCartService.update(user.getId(), cartItemId, cartItemUpdateDto);
}

@DeleteMapping(value = "/cart-items/{cartItemId}")
@PreAuthorize("hasRole('USER')")
@Operation(summary = "Remove a book from the shopping cart",
description = "Remove a book from the shopping cart")
public void removeBookFromTheCart(@PathVariable Long cartItemId) {
shoppingCartService.deleteCartItemFromTheCart(cartItemId);
}
}
14 changes: 14 additions & 0 deletions src/main/java/com/bookstore/dto/cartitem/CartItemCreateDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.bookstore.dto.cartitem;

import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import lombok.Data;

@Data
public class CartItemCreateDto {
@NotNull
private Long bookId;
@NotNull
@Min(1)
private int quantity;
}
11 changes: 11 additions & 0 deletions src/main/java/com/bookstore/dto/cartitem/CartItemResponseDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.bookstore.dto.cartitem;

import lombok.Data;

@Data
public class CartItemResponseDto {
private Long id;
private Long bookId;
private String bookTitle;
private int quantity;
}
12 changes: 12 additions & 0 deletions src/main/java/com/bookstore/dto/cartitem/CartItemUpdateDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.bookstore.dto.cartitem;

import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import lombok.Data;

@Data
public class CartItemUpdateDto {
@NotNull
@Min(1)
private int quantity;
}
11 changes: 11 additions & 0 deletions src/main/java/com/bookstore/dto/shoppingcart/ShoppingCartDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.bookstore.dto.shoppingcart;

import com.bookstore.dto.cartitem.CartItemResponseDto;
import java.util.Set;
import lombok.Data;

@Data
public class ShoppingCartDto {
private Long userId;
private Set<CartItemResponseDto> cartItemsDto;
}
22 changes: 22 additions & 0 deletions src/main/java/com/bookstore/mapper/CartItemMapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.bookstore.mapper;

import com.bookstore.config.MapperConfig;
import com.bookstore.dto.cartitem.CartItemCreateDto;
import com.bookstore.dto.cartitem.CartItemResponseDto;
import com.bookstore.model.Book;
import com.bookstore.model.CartItem;
import com.bookstore.model.ShoppingCart;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

@Mapper(config = MapperConfig.class)
public interface CartItemMapper {
@Mapping(target = "id", ignore = true)
CartItem toEntity(CartItemCreateDto cartItemCreateDto,
Book book,
ShoppingCart shoppingCart);

@Mapping(source = "cartItem.book.id", target = "bookId")
@Mapping(source = "cartItem.book.title", target = "bookTitle")
CartItemResponseDto toDto(CartItem cartItem);
}
14 changes: 14 additions & 0 deletions src/main/java/com/bookstore/mapper/ShoppingCartMapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.bookstore.mapper;

import com.bookstore.config.MapperConfig;
import com.bookstore.dto.shoppingcart.ShoppingCartDto;
import com.bookstore.model.ShoppingCart;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

@Mapper(config = MapperConfig.class, uses = CartItemMapper.class)
public interface ShoppingCartMapper {
@Mapping(source = "user.id", target = "userId")
@Mapping(source = "cartItems", target = "cartItemsDto")
ShoppingCartDto toDto(ShoppingCart shoppingCart);
}
32 changes: 32 additions & 0 deletions src/main/java/com/bookstore/model/CartItem.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.bookstore.model;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
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 lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@EqualsAndHashCode
@Entity
@Table(name = "cart_items")
public class CartItem {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "shopping_cart_id", nullable = false)
private ShoppingCart shoppingCart;
@ManyToOne
@JoinColumn(name = "book_id", nullable = false)
private Book book;
@Column(nullable = false)
private int quantity;
}
40 changes: 40 additions & 0 deletions src/main/java/com/bookstore/model/ShoppingCart.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.bookstore.model;

import jakarta.persistence.CascadeType;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.MapsId;
import jakarta.persistence.OneToMany;
import jakarta.persistence.OneToOne;
import jakarta.persistence.PrimaryKeyJoinColumn;
import jakarta.persistence.Table;
import java.util.Set;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.hibernate.annotations.SQLDelete;

@Getter
@Setter
@EqualsAndHashCode
@Entity
@SQLDelete(sql = "UPDATE shopping_carts SET is_deleted=true WHERE id=?")
@Table(name = "shopping_carts")
public class ShoppingCart {
@Id
private Long id;
@OneToOne
@MapsId
@PrimaryKeyJoinColumn(name = "user_id")
private User user;
@ToString.Exclude
@EqualsAndHashCode.Exclude
@OneToMany(mappedBy = "shoppingCart", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<CartItem> cartItems;

public void addCartItemToSet(CartItem cartItem) {
cartItems.add(cartItem);
cartItem.setShoppingCart(this);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.bookstore.repository.cartitem;

import com.bookstore.model.CartItem;
import org.springframework.data.jpa.repository.JpaRepository;

public interface CartItemRepository extends JpaRepository<CartItem, Long> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.bookstore.repository.shoppingcart;

import com.bookstore.model.ShoppingCart;
import java.util.Optional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.data.jpa.repository.JpaRepository;

public interface ShoppingCartRepository extends JpaRepository<ShoppingCart, Long> {

@EntityGraph(attributePaths = {"cartItems", "cartItems.book"})
Page<ShoppingCart> findAll(Pageable pageable);

@EntityGraph(attributePaths = {"cartItems", "cartItems.book"})
Optional<ShoppingCart> findByUserId(Long id);
}
3 changes: 2 additions & 1 deletion src/main/java/com/bookstore/service/BookService.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.bookstore.dto.book.BookSearchParametersDto;
import com.bookstore.dto.book.CreateBookRequestDto;
import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

public interface BookService {
Expand All @@ -18,7 +19,7 @@ public interface BookService {

void deleteBookById(Long id);

List<BookDto> searchBooks(BookSearchParametersDto searchParameters);
Page<BookDto> searchBooks(BookSearchParametersDto searchParameters);

List<BookDtoWithoutCategoryIds> findAllByCategoryId(Long categoryId, Pageable pageable);
}
19 changes: 19 additions & 0 deletions src/main/java/com/bookstore/service/ShoppingCartService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.bookstore.service;

import com.bookstore.dto.cartitem.CartItemCreateDto;
import com.bookstore.dto.cartitem.CartItemUpdateDto;
import com.bookstore.dto.shoppingcart.ShoppingCartDto;
import java.util.List;
import org.springframework.data.domain.Pageable;

public interface ShoppingCartService {
List<ShoppingCartDto> findAll(Pageable pageable);

ShoppingCartDto getByUserId(Long id);

ShoppingCartDto saveBookToTheCart(Long id, CartItemCreateDto cartItemCreateDto);

ShoppingCartDto update(Long id, Long cartItemId, CartItemUpdateDto cartItemUpdateDto);

void deleteCartItemFromTheCart(Long id);
}
7 changes: 5 additions & 2 deletions src/main/java/com/bookstore/service/impl/BookServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import java.util.List;
import java.util.Set;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
Expand Down Expand Up @@ -73,12 +75,13 @@ public void deleteBookById(Long id) {
}

@Override
public List<BookDto> searchBooks(BookSearchParametersDto searchParameters) {
public Page<BookDto> searchBooks(BookSearchParametersDto searchParameters) {
Specification<Book> bookSpecification = bookSpecificationBuilder.build(searchParameters);
return bookRepository.findAll(bookSpecification)
List<BookDto> bookDtos = bookRepository.findAll(bookSpecification)
.stream()
.map(bookMapper::toDto)
.toList();
return new PageImpl<>(bookDtos, Pageable.ofSize(10), bookDtos.size());
}

@Override
Expand Down
Loading

0 comments on commit 1189d13

Please sign in to comment.