Skip to content

Commit

Permalink
added category implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
fmIst0 committed Sep 8, 2023
1 parent 3ec7307 commit 2129a83
Show file tree
Hide file tree
Showing 19 changed files with 381 additions and 10 deletions.
11 changes: 6 additions & 5 deletions src/main/java/com/bookstore/controller/BookController.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,30 +46,31 @@ 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, Pageable pageable) {
return bookService.searchBooks(searchParameters, pageable);
public List<BookDto> searchBooks(BookSearchParametersDto searchParameters) {
return bookService.searchBooks(searchParameters);
}

@PostMapping
@ResponseStatus(HttpStatus.CREATED)
@PreAuthorize("hasRole('ADMIN')")
@Operation(summary = "Create a new book", description = "Create a new book")
@Operation(summary = "Create a new book(only for admins)", description = "Create a new book")
public BookDto createBook(@RequestBody @Valid CreateBookRequestDto bookRequestDto) {
return bookService.createBook(bookRequestDto);
}

@PutMapping("/{id}")
@ResponseStatus(HttpStatus.ACCEPTED)
@PreAuthorize("hasRole('ADMIN')")
@Operation(summary = "Update the existing book", description = "Update the existing book")
@Operation(summary = "Update the existing book(only for admins)",
description = "Update the existing book")
public void updateBook(@PathVariable Long id,
@RequestBody @Valid CreateBookRequestDto bookRequestDto) {
bookService.updateBook(id, bookRequestDto);
}

@DeleteMapping("/{id}")
@PreAuthorize("hasRole('ADMIN')")
@Operation(summary = "Delete book", description = "Delete book by specific id")
@Operation(summary = "Delete book(only for admins)", description = "Delete book by specific id")
public void deleteBookById(@PathVariable Long id) {
bookService.deleteBookById(id);
}
Expand Down
79 changes: 79 additions & 0 deletions src/main/java/com/bookstore/controller/CategoryController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package com.bookstore.controller;

import com.bookstore.dto.book.BookDtoWithoutCategoryIds;
import com.bookstore.dto.category.CategoryDto;
import com.bookstore.service.BookService;
import com.bookstore.service.CategoryService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
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;

@Tag(name = "Category management", description = "Endpoints for managing categories")
@RequiredArgsConstructor
@RestController
@RequestMapping(value = "/api/categories")
public class CategoryController {
private final CategoryService categoryService;
private final BookService bookService;

@PostMapping
@ResponseStatus(HttpStatus.CREATED)
@PreAuthorize("hasRole('ADMIN')")
@Operation(summary = "Create a new category(only for admins)",
description = "Create a new category")
public CategoryDto createCategory(@RequestBody CategoryDto categoryDto) {
return categoryService.save(categoryDto);
}

@GetMapping
@PreAuthorize("hasRole('USER')")
@Operation(summary = "Get all categories", description = "Get all categories")
public List<CategoryDto> getAll(Pageable pageable) {
return categoryService.findAll(pageable);
}

@GetMapping("/{id}")
@PreAuthorize("hasRole('USER')")
@Operation(summary = "Get category by specific id", description = "Get category by specific id")
public CategoryDto getCategoryById(@PathVariable Long id) {
return categoryService.getById(id);
}

@PutMapping("/{id}")
@ResponseStatus(HttpStatus.ACCEPTED)
@PreAuthorize("hasRole('ADMIN')")
@Operation(summary = "Update category(only for admins)", description = "Update category")
public CategoryDto updateCategory(@PathVariable Long id,
@RequestBody CategoryDto categoryDto) {
return categoryService.update(id, categoryDto);
}

@DeleteMapping("/{id}")
@PreAuthorize("hasRole('ADMIN')")
@Operation(summary = "Delete book(only for admins)", description = "Delete book")
public void deleteCategory(@PathVariable Long id) {
categoryService.deleteById(id);
}

@GetMapping("/{id}/books")
@PreAuthorize("hasRole('USER')")
@Operation(summary = "Get books by specific category_id",
description = "Get books by specific category_id")
public List<BookDtoWithoutCategoryIds> getBooksByCategoryId(@PathVariable Long id,
Pageable pageable) {
return bookService.findAllByCategoryId(id, pageable);
}
}
2 changes: 2 additions & 0 deletions src/main/java/com/bookstore/dto/book/BookDto.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.bookstore.dto.book;

import java.math.BigDecimal;
import java.util.Set;
import lombok.Data;

@Data
Expand All @@ -12,4 +13,5 @@ public class BookDto {
private BigDecimal price;
private String description;
private String coverImage;
private Set<Long> categoryIds;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.bookstore.dto.book;

import java.math.BigDecimal;
import lombok.Data;

@Data
public class BookDtoWithoutCategoryIds {
private Long id;
private String title;
private String author;
private String isbn;
private BigDecimal price;
private String description;
private String coverImage;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.Set;
import lombok.Data;

@Data
Expand All @@ -19,4 +20,6 @@ public class CreateBookRequestDto {
private BigDecimal price;
private String description;
private String coverImage;
@NotNull
private Set<Long> categoryIds;
}
9 changes: 9 additions & 0 deletions src/main/java/com/bookstore/dto/category/CategoryDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.bookstore.dto.category;

import lombok.Data;

@Data
public class CategoryDto {
private String name;
private String description;
}
28 changes: 28 additions & 0 deletions src/main/java/com/bookstore/mapper/BookMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,41 @@

import com.bookstore.config.MapperConfig;
import com.bookstore.dto.book.BookDto;
import com.bookstore.dto.book.BookDtoWithoutCategoryIds;
import com.bookstore.dto.book.CreateBookRequestDto;
import com.bookstore.model.Book;
import com.bookstore.model.Category;
import java.util.Set;
import java.util.stream.Collectors;
import org.mapstruct.AfterMapping;
import org.mapstruct.Mapper;
import org.mapstruct.MappingTarget;
import org.mapstruct.Named;

@Mapper(config = MapperConfig.class)
public interface BookMapper {
BookDto toDto(Book book);

Book toBookModel(CreateBookRequestDto bookRequestDto);

BookDtoWithoutCategoryIds toDtoWithoutCategories(Book book);

@AfterMapping
default void setCategoryIds(@MappingTarget BookDto bookDto, Book book) {
Set<Long> ids = book.getCategories()
.stream()
.map(Category::getId)
.collect(Collectors.toSet());
bookDto.setCategoryIds(ids);
}

@Named("bookFromId")
default Book bookFromId(Long id) {
if (id == null) {
throw new RuntimeException("Id can't be null.");
}
Book book = new Book();
book.setId(id);
return book;
}
}
13 changes: 13 additions & 0 deletions src/main/java/com/bookstore/mapper/CategoryMapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.bookstore.mapper;

import com.bookstore.config.MapperConfig;
import com.bookstore.dto.category.CategoryDto;
import com.bookstore.model.Category;
import org.mapstruct.Mapper;

@Mapper(config = MapperConfig.class)
public interface CategoryMapper {
CategoryDto toDto(Category category);

Category toEntity(CategoryDto categoryDto);
}
11 changes: 11 additions & 0 deletions src/main/java/com/bookstore/model/Book.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,13 @@
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.JoinTable;
import jakarta.persistence.ManyToMany;
import jakarta.persistence.Table;
import java.math.BigDecimal;
import java.util.HashSet;
import java.util.Set;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.SQLDelete;
Expand Down Expand Up @@ -36,5 +41,11 @@ public class Book {
private String coverImage;
@Column(name = "is_deleted",
nullable = false)
@ManyToMany
@JoinTable(name = "books_categories",
joinColumns = @JoinColumn(name = "book_id"),
inverseJoinColumns = @JoinColumn(name = "category_id"))
private Set<Category> categories = new HashSet<>();
@Column(name = "is_deleted", nullable = false)
private boolean isDeleted = false;
}
31 changes: 31 additions & 0 deletions src/main/java/com/bookstore/model/Category.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
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.Table;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;

@Getter
@Setter
@EqualsAndHashCode
@Entity
@SQLDelete(sql = "UPDATE categories SET is_deleted=true WHERE id=?")
@Where(clause = "is_deleted=false")
@Table(name = "categories")
public class Category {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
private String description;
@Column(name = "is_deleted", nullable = false)
private boolean isDeleted = false;
}
18 changes: 18 additions & 0 deletions src/main/java/com/bookstore/repository/book/BookRepository.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,27 @@
package com.bookstore.repository.book;

import com.bookstore.model.Book;
import java.util.List;
import java.util.Optional;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;

public interface BookRepository extends JpaRepository<Book, Long>,
JpaSpecificationExecutor<Book> {
@Query("FROM Book b JOIN FETCH b.categories c "
+ "WHERE c.id = :categoryId")
List<Book> findAllByCategoryId(Long categoryId, Pageable pageable);

@EntityGraph(attributePaths = "categories")
Optional<Book> findById(Long id);

@Query("FROM Book b LEFT JOIN FETCH b.categories c")
List<Book> findAllPageable(Pageable pageable);

@EntityGraph(attributePaths = "categories")
List<Book> findAll(Specification<Book> bookSpecification);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.bookstore.repository.category;

import com.bookstore.model.Category;
import java.util.Set;
import org.springframework.data.jpa.repository.JpaRepository;

public interface CategoryRepository extends JpaRepository<Category, Long> {
Set<Category> findByIdIn(Set<Long> categoryIds);
}
5 changes: 4 additions & 1 deletion src/main/java/com/bookstore/service/BookService.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.bookstore.service;

import com.bookstore.dto.book.BookDto;
import com.bookstore.dto.book.BookDtoWithoutCategoryIds;
import com.bookstore.dto.book.BookSearchParametersDto;
import com.bookstore.dto.book.CreateBookRequestDto;
import java.util.List;
Expand All @@ -17,5 +18,7 @@ public interface BookService {

void deleteBookById(Long id);

List<BookDto> searchBooks(BookSearchParametersDto searchParameters, Pageable pageable);
List<BookDto> searchBooks(BookSearchParametersDto searchParameters);

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

import com.bookstore.dto.category.CategoryDto;
import java.util.List;
import org.springframework.data.domain.Pageable;

public interface CategoryService {
List<CategoryDto> findAll(Pageable pageable);

CategoryDto getById(Long id);

CategoryDto save(CategoryDto categoryDto);

CategoryDto update(Long id, CategoryDto categoryDto);

void deleteById(Long id);
}
Loading

0 comments on commit 2129a83

Please sign in to comment.