CategoryService.java
package com.learning.yasminishop.category;
import com.learning.yasminishop.category.dto.request.CategoryCreation;
import com.learning.yasminishop.category.dto.request.CategoryUpdate;
import com.learning.yasminishop.category.dto.response.CategoryAdminResponse;
import com.learning.yasminishop.category.dto.response.CategoryResponse;
import com.learning.yasminishop.category.mapper.CategoryMapper;
import com.learning.yasminishop.common.dto.PaginationResponse;
import com.learning.yasminishop.common.entity.Category;
import com.learning.yasminishop.common.exception.AppException;
import com.learning.yasminishop.common.exception.ErrorCode;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
@RequiredArgsConstructor
@Slf4j
@Transactional(readOnly = true)
public class CategoryService {
private final CategoryRepository categoryRepository;
private final CategoryMapper categoryMapper;
@Transactional
public CategoryResponse create(CategoryCreation categoryCreation) {
if (categoryRepository.existsBySlug(categoryCreation.getSlug())) {
throw new AppException(ErrorCode.SLUG_ALREADY_EXISTS);
}
Category category = categoryMapper.toCategory(categoryCreation);
category.setIsAvailable(true);
category = categoryRepository.save(category);
return categoryMapper.toCategoryResponse(category);
}
public List<CategoryResponse> getAllCategories() {
List<Category> categories = categoryRepository.findAllByIsAvailable(true);
return categories.stream()
.map(categoryMapper::toCategoryResponse)
.toList();
}
public CategoryResponse getBySlug(String slug) {
Category category = categoryRepository.findBySlug(slug)
.orElseThrow(() -> new AppException(ErrorCode.CATEGORY_NOT_FOUND));
return categoryMapper.toCategoryResponse(category);
}
public CategoryAdminResponse getCategory(String id) {
Category category = categoryRepository.findById(id)
.orElseThrow(() -> new AppException(ErrorCode.CATEGORY_NOT_FOUND));
return categoryMapper.toCategoryAdminResponse(category);
}
@Transactional
public void delete(List<String> ids) {
List<Category> categories = categoryRepository.findAllById(ids);
if (categories.size() != ids.size()) {
throw new AppException(ErrorCode.CATEGORY_NOT_FOUND);
}
// check if the categories are not used in any product
for (Category category : categories) {
if (!category.getProducts().isEmpty()) {
throw new AppException(ErrorCode.CATEGORY_USED_IN_PRODUCT);
}
}
categoryRepository.deleteAll(categories);
}
@Transactional
public void toggleAvailability(List<String> ids) {
List<Category> categories = categoryRepository.findAllById(ids);
if (categories.size() != ids.size()) {
throw new AppException(ErrorCode.CATEGORY_NOT_FOUND);
}
for (Category category : categories) {
if (!category.getProducts().isEmpty()) {
throw new AppException(ErrorCode.CATEGORY_USED_IN_PRODUCT);
}
}
for (Category category : categories) {
category.setIsAvailable(!category.getIsAvailable());
}
categoryRepository.saveAll(categories);
}
@Transactional
public CategoryResponse update(String id, CategoryUpdate categoryUpdate) {
Category category = categoryRepository.findById(id)
.orElseThrow(() -> new AppException(ErrorCode.CATEGORY_NOT_FOUND));
if (!category.getSlug().equals(categoryUpdate.getSlug()) && categoryRepository.existsBySlug(categoryUpdate.getSlug())) {
throw new AppException(ErrorCode.SLUG_ALREADY_EXISTS);
}
categoryMapper.updateCategory(category, categoryUpdate);
category = categoryRepository.save(category);
return categoryMapper.toCategoryResponse(category);
}
public PaginationResponse<CategoryAdminResponse> getAllCategoriesAdmin(String name, Boolean isAvailable, Pageable pageable) {
Page<Category> categories = categoryRepository.findAll(
Specification.where(CategorySpecifications.hasName(name))
.and(CategorySpecifications.hasIsAvailable(isAvailable)),
pageable
);
return PaginationResponse.<CategoryAdminResponse>builder()
.page(pageable.getPageNumber() + 1)
.total(categories.getTotalElements())
.itemsPerPage(pageable.getPageSize())
.data(categories.map(categoryMapper::toCategoryAdminResponse).toList())
.build();
}
}