Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,40 @@
package ru.practicum.category.controller;

import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import ru.practicum.category.dto.CategoryDto;
import ru.practicum.category.dto.NewCategoryDto;
import ru.practicum.category.service.CategoryService;

@Slf4j
@RestController
@RequestMapping("/admin/categories")
@RequiredArgsConstructor
public class AdminCategoryController {
private final CategoryService categoryService;

@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public CategoryDto createCategory(@RequestBody @Valid NewCategoryDto newCategoryDto) {
log.debug("Controller: createCategory with data {}", newCategoryDto);
return categoryService.createCategory(newCategoryDto);
}

@DeleteMapping("/{categoryId}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void deleteCategory(@PathVariable Long categoryId) {
log.debug("Controller: deleteCategory with id={}", categoryId);
categoryService.deleteCategory(categoryId);
}

@PatchMapping("/{categoryId}")
public CategoryDto updateCategory(
@PathVariable Long categoryId,
@RequestBody @Valid NewCategoryDto newCategoryDto) {
log.debug("Controller: updateCategory with id={} with data={}", categoryId, newCategoryDto);
return categoryService.updateCategory(categoryId, newCategoryDto);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,37 @@
package ru.practicum.category.controller;

import jakarta.validation.constraints.Positive;
import jakarta.validation.constraints.PositiveOrZero;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.*;
import ru.practicum.category.dto.CategoryDto;
import ru.practicum.category.service.CategoryService;

import java.util.List;

@Slf4j
@RestController
@RequestMapping("/categories")
@RequiredArgsConstructor
public class PublicCategoryController {
private final CategoryService categoryService;

@GetMapping
public List<CategoryDto> getCategories(
@RequestParam(defaultValue = "0") @PositiveOrZero Integer from,
@RequestParam(defaultValue = "10") @Positive Integer size) {
int page = from / size;
Pageable pageable = PageRequest.of(page, size);
log.debug("Controller: getCategories with from={}, size={}", from, size);
return categoryService.getCategories(pageable);
}

@GetMapping("/{categoryId}")
public CategoryDto getCategoryById(@PathVariable Long categoryId) {
log.debug("Controller: getCategoryById with id={}", categoryId);
return categoryService.getCategoryById(categoryId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import ru.practicum.category.dto.CategoryDto;
import ru.practicum.category.dto.NewCategoryDto;
import ru.practicum.category.model.Category;
Expand All @@ -10,7 +11,12 @@
public interface CategoryMapper {

@Mapping(target = "id", ignore = true)
Category toEntity(NewCategoryDto dto);
Category toEntity(NewCategoryDto newCategoryDto);

CategoryDto toDto(Category category);

@Mapping(target = "id", ignore = true)
void updateCategoryFromDto(NewCategoryDto dto, @MappingTarget Category category);

Category toEntityFromDto(CategoryDto dto);
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
package ru.practicum.category.model;

import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;

@Entity
@Table(name = "categories")
@Getter
@Setter(AccessLevel.PROTECTED)
@Setter
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class Category {
@Id
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,23 @@
package ru.practicum.category.repository;

public class CategoryRepository {
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import ru.practicum.category.model.Category;

import java.util.Optional;

public interface CategoryRepository extends JpaRepository<Category, Long> {

@Query("""
SELECT c FROM Category c
WHERE c.name = :name"""
)
Optional<Category> findByName(@Param("name") String name);

@Query("""
SELECT c FROM Category c
WHERE c.name = :name AND c.id != :id"""
)
Optional<Category> findByNameAndIdNot(@Param("name") String name, @Param("id") Long id);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,19 @@
package ru.practicum.category.service;

import org.springframework.data.domain.Pageable;
import ru.practicum.category.dto.CategoryDto;
import ru.practicum.category.dto.NewCategoryDto;

import java.util.List;

public interface CategoryService {
CategoryDto createCategory(NewCategoryDto newCategoryDto);

void deleteCategory(Long categoryId);

CategoryDto updateCategory(Long categoryId, NewCategoryDto newCategoryDto);

List<CategoryDto> getCategories(Pageable pageable);

CategoryDto getCategoryById(Long categoryId);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,109 @@
package ru.practicum.category.service;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import ru.practicum.category.dto.CategoryDto;
import ru.practicum.category.dto.NewCategoryDto;
import ru.practicum.category.mapper.CategoryMapper;
import ru.practicum.category.model.Category;
import ru.practicum.category.repository.CategoryRepository;
import ru.practicum.event.repository.EventRepository;
import ru.practicum.exception.ConflictException;
import ru.practicum.exception.NotFoundException;

import java.util.List;
import java.util.Optional;

@Slf4j
@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class CategoryServiceImpl implements CategoryService {
private final CategoryRepository categoryRepository;
private final CategoryMapper categoryMapper;
private final EventRepository eventRepository;

@Override
@Transactional
public CategoryDto createCategory(NewCategoryDto newCategoryDto) {
checkCategoryNameUnique(newCategoryDto.name(), null);

Category category = categoryMapper.toEntity(newCategoryDto);

Category savedCategory = categoryRepository.save(category);

log.info("Создана новая категория: {}", savedCategory);
Comment thread
Mult1k33 marked this conversation as resolved.
return categoryMapper.toDto(savedCategory);
}

@Override
@Transactional
public void deleteCategory(Long categoryId) {
Category category = getCategoryByIdOrThrow(categoryId);

if (eventRepository.existsByCategoryId(categoryId)) {
throw new ConflictException("Невозможно удалить категорию с существующими событиями");
}

categoryRepository.delete(category);
log.info("Удалена категория с ID: {}", categoryId);
}

@Override
@Transactional
public CategoryDto updateCategory(Long categoryId, NewCategoryDto newCategoryDto) {
Category category = getCategoryByIdOrThrow(categoryId);

checkCategoryNameUnique(newCategoryDto.name(), categoryId);

categoryMapper.updateCategoryFromDto(newCategoryDto, category);
Category updatedCategory = categoryRepository.save(category);

log.info("Обновлена категория: {}", updatedCategory);
return categoryMapper.toDto(updatedCategory);
}

@Override
public List<CategoryDto> getCategories(Pageable pageable) {
Page<Category> categoriesPage = categoryRepository.findAll(pageable);

if (categoriesPage.isEmpty()) {
return List.of();
}

List<CategoryDto> result = categoriesPage.stream()
.map(categoryMapper::toDto)
.toList();

log.info("Найдено {} категорий", result.size());
return result;
}

@Override
public CategoryDto getCategoryById(Long categoryId) {
Category category = getCategoryByIdOrThrow(categoryId);
CategoryDto result = categoryMapper.toDto(category);

log.info("Найдена категория: {}", result);
return result;
}

private void checkCategoryNameUnique(String name, Long excludedId) {
Optional<Category> existingCategory = (excludedId == null)
? categoryRepository.findByName(name)
: categoryRepository.findByNameAndIdNot(name, excludedId);

existingCategory.ifPresent(category -> {
throw new ConflictException("Категория с названием '" + name + "' уже существует");
});
}

private Category getCategoryByIdOrThrow(Long categoryId) {
return categoryRepository.findById(categoryId)
.orElseThrow(() -> new NotFoundException("Категория с id " + categoryId + " не найдена"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import ru.practicum.category.model.Category;
import ru.practicum.event.dto.*;
import ru.practicum.event.model.Event;
import ru.practicum.event.model.EventState;
Expand All @@ -14,7 +15,7 @@ public interface EventMapper {
@Mapping(target = "id", ignore = true)
@Mapping(target = "publishedOn", ignore = true)
@Mapping(target = "category", ignore = true) //TODO убрать после реализации Category
Event fromNewEvent(NewEventDto dto, User initiator, EventState state);
Event fromNewEvent(NewEventDto dto, User initiator, Category category, EventState state);

EventShortDto toEventShortDto(Event event, Long confirmedRequests, Long views);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,6 @@ public interface EventRepository extends JpaRepository<Event, Long>, JpaSpecific
WHERE e.id = :eventId"""
)
Optional<Event> findByIdNew(@Param("eventId") Long eventId);

boolean existsByCategoryId(@Param("categoryId") Long categoryId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
import ru.practicum.CreateEndpointHitDto;
import ru.practicum.StatsClient;
import ru.practicum.ViewStatsDto;
import ru.practicum.category.dto.CategoryDto;
import ru.practicum.category.mapper.CategoryMapper;
import ru.practicum.category.model.Category;
import ru.practicum.category.service.CategoryService;
import ru.practicum.event.dto.*;
import ru.practicum.event.mapper.EventMapper;
import ru.practicum.event.model.*;
Expand Down Expand Up @@ -38,16 +42,21 @@ public class EventServiceImpl implements EventService {
private final UserService userService;
private final RequestRepository requestRepository;
private final StatsClient statsClient;
// private final CategoryService categoryService;
private final CategoryService categoryService;
private final CategoryMapper categoryMapper;

@Override
@Transactional
public EventFullDto createEvent(Long userId, NewEventDto newEventDto) {
validateDateEvent(newEventDto.eventDate(), 2);

User user = userService.getUserById(userId);
// Category category = categoryService.getCategoryById(newEventDto.category()); TODO
Event event = eventMapper.fromNewEvent(newEventDto, user, EventState.PENDING);

CategoryDto categoryDto = categoryService.getCategoryById(newEventDto.category());
Category category = categoryMapper.toEntityFromDto(categoryDto);

Event event = eventMapper.fromNewEvent(newEventDto, user, category, EventState.PENDING);
event.setCategory(category);
Comment thread
Mult1k33 marked this conversation as resolved.
log.info("Создано новое событие: {}", event);
return eventMapper.toEventFullDto(eventRepository.save(event), 0L, 0L);
}
Expand Down
Loading