diff --git a/main-service/src/main/java/ru/practicum/category/controller/CategoryAdminController.java b/main-service/src/main/java/ru/practicum/category/controller/CategoryAdminController.java index 4dda309..5495dcd 100644 --- a/main-service/src/main/java/ru/practicum/category/controller/CategoryAdminController.java +++ b/main-service/src/main/java/ru/practicum/category/controller/CategoryAdminController.java @@ -4,7 +4,6 @@ import ru.practicum.category.dto.CategoryDto; import ru.practicum.category.dto.NewCategoryDto; -import ru.practicum.category.dto.UpdateCategoryDto; import ru.practicum.category.service.CategoryService; import org.springframework.http.HttpStatus; @@ -29,7 +28,7 @@ public CategoryDto createCategory(@Valid @RequestBody NewCategoryDto newCategory @PatchMapping("/{catId}") public CategoryDto updateCategory( - @PathVariable Long catId, @Valid @RequestBody UpdateCategoryDto updateCategoryDto) { + @PathVariable Long catId, @Valid @RequestBody NewCategoryDto updateCategoryDto) { log.info( "Update category with id={} requested, updated category {}", catId, diff --git a/main-service/src/main/java/ru/practicum/category/controller/CategoryPublicController.java b/main-service/src/main/java/ru/practicum/category/controller/CategoryPublicController.java index 0831614..1ffa2f0 100644 --- a/main-service/src/main/java/ru/practicum/category/controller/CategoryPublicController.java +++ b/main-service/src/main/java/ru/practicum/category/controller/CategoryPublicController.java @@ -2,15 +2,20 @@ import java.util.Collection; +import jakarta.validation.constraints.Positive; +import jakarta.validation.constraints.PositiveOrZero; + import ru.practicum.category.dto.CategoryDto; import ru.practicum.category.service.CategoryService; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @Slf4j +@Validated @RestController @RequiredArgsConstructor @RequestMapping("/categories") @@ -19,8 +24,8 @@ public class CategoryPublicController { @GetMapping public Collection getAllCategoriesPaged( - @RequestParam(defaultValue = "0") int from, - @RequestParam(defaultValue = "10") int size) { + @RequestParam(defaultValue = "0") @PositiveOrZero int from, + @RequestParam(defaultValue = "10") @Positive int size) { log.info("View categories page by page requested from={}, size={}", from, size); return categoryService.getAllCategoriesPaged(from, size); } diff --git a/main-service/src/main/java/ru/practicum/category/dto/UpdateCategoryDto.java b/main-service/src/main/java/ru/practicum/category/dto/UpdateCategoryDto.java deleted file mode 100644 index 58611f4..0000000 --- a/main-service/src/main/java/ru/practicum/category/dto/UpdateCategoryDto.java +++ /dev/null @@ -1,6 +0,0 @@ -package ru.practicum.category.dto; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.Size; - -public record UpdateCategoryDto(@Size(min = 1, max = 50) @NotBlank String name) {} diff --git a/main-service/src/main/java/ru/practicum/category/service/CategoryService.java b/main-service/src/main/java/ru/practicum/category/service/CategoryService.java index 9058f1e..69d5377 100644 --- a/main-service/src/main/java/ru/practicum/category/service/CategoryService.java +++ b/main-service/src/main/java/ru/practicum/category/service/CategoryService.java @@ -4,7 +4,6 @@ import ru.practicum.category.dto.CategoryDto; import ru.practicum.category.dto.NewCategoryDto; -import ru.practicum.category.dto.UpdateCategoryDto; public interface CategoryService { CategoryDto createCategory(NewCategoryDto newCategoryDto); @@ -15,5 +14,5 @@ public interface CategoryService { void deleteCategoryById(Long id); - CategoryDto updateCategory(Long catId, UpdateCategoryDto updateCategoryDto); + CategoryDto updateCategory(Long catId, NewCategoryDto updateCategoryDto); } diff --git a/main-service/src/main/java/ru/practicum/category/service/CategoryServiceImpl.java b/main-service/src/main/java/ru/practicum/category/service/CategoryServiceImpl.java index e91d26b..2697af3 100644 --- a/main-service/src/main/java/ru/practicum/category/service/CategoryServiceImpl.java +++ b/main-service/src/main/java/ru/practicum/category/service/CategoryServiceImpl.java @@ -4,7 +4,6 @@ import ru.practicum.category.dto.CategoryDto; import ru.practicum.category.dto.NewCategoryDto; -import ru.practicum.category.dto.UpdateCategoryDto; import ru.practicum.category.mapper.CategoryMapper; import ru.practicum.category.model.Category; import ru.practicum.category.repository.CategoryRepository; @@ -30,7 +29,7 @@ public CategoryDto createCategory(NewCategoryDto newCategoryDto) { } @Override - public CategoryDto updateCategory(Long catId, UpdateCategoryDto updateCategoryDto) { + public CategoryDto updateCategory(Long catId, NewCategoryDto updateCategoryDto) { Category category = categoryRepository .findById(catId) diff --git a/main-service/src/main/java/ru/practicum/compilation/controller/CompilationsPublicController.java b/main-service/src/main/java/ru/practicum/compilation/controller/CompilationsPublicController.java index 0f6be83..fbf0812 100644 --- a/main-service/src/main/java/ru/practicum/compilation/controller/CompilationsPublicController.java +++ b/main-service/src/main/java/ru/practicum/compilation/controller/CompilationsPublicController.java @@ -2,16 +2,21 @@ import java.util.Collection; +import jakarta.validation.constraints.Positive; +import jakarta.validation.constraints.PositiveOrZero; + import ru.practicum.compilation.dto.CompilationDto; import ru.practicum.compilation.service.CompilationsPublicGetRequest; import ru.practicum.compilation.service.CompilationsService; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @Slf4j +@Validated @RestController @RequiredArgsConstructor @RequestMapping("/compilations") @@ -21,8 +26,8 @@ public class CompilationsPublicController { @GetMapping public Collection getCompilations( @RequestParam(required = false) Boolean pinned, - @RequestParam(defaultValue = "0") int from, - @RequestParam(defaultValue = "10") int size) { + @RequestParam(defaultValue = "0") @PositiveOrZero int from, + @RequestParam(defaultValue = "10") @Positive int size) { CompilationsPublicGetRequest getRequest = new CompilationsPublicGetRequest(pinned, from, size); log.info("Public get compilations requested with params= {}", getRequest); diff --git a/main-service/src/main/java/ru/practicum/compilation/service/CompilationsServiceImpl.java b/main-service/src/main/java/ru/practicum/compilation/service/CompilationsServiceImpl.java index 32ffbe8..e4e3d1c 100644 --- a/main-service/src/main/java/ru/practicum/compilation/service/CompilationsServiceImpl.java +++ b/main-service/src/main/java/ru/practicum/compilation/service/CompilationsServiceImpl.java @@ -1,20 +1,17 @@ package ru.practicum.compilation.service; -import java.time.LocalDateTime; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; -import ru.practicum.client.StatsClient; import ru.practicum.compilation.dto.CompilationDto; import ru.practicum.compilation.dto.NewCompilationDto; import ru.practicum.compilation.dto.UpdateCompilationRequest; import ru.practicum.compilation.mapper.CompilationsMapper; import ru.practicum.compilation.model.Compilation; import ru.practicum.compilation.repository.CompilationsRepository; -import ru.practicum.dto.ViewStatsDto; import ru.practicum.event.dto.EventShortDto; import ru.practicum.event.mapper.EventMapper; import ru.practicum.event.model.Event; @@ -35,12 +32,9 @@ @RequiredArgsConstructor @Transactional(readOnly = true) public class CompilationsServiceImpl implements CompilationsService { - private static final LocalDateTime MINIMAL_LOCAL_DATE_TIME = - LocalDateTime.of(1000, 1, 1, 0, 0, 0); private final CompilationsRepository compRepository; private final EventRepository eventRepository; private final ParticipationRequestRepository requestRepository; - private final StatsClient statsClient; @Override public Collection findAll(CompilationsPublicGetRequest getRequest) { @@ -52,9 +46,8 @@ public Collection findAll(CompilationsPublicGetRequest getReques page.stream().flatMap(c -> c.getEvents().stream()).collect(Collectors.toSet()); Map confirmedRequests = getConfirmedRequests(events); - Map views = getViews(events); - return page.stream().map(c -> toDto(c, confirmedRequests, views)).toList(); + return page.stream().map(c -> toDto(c, confirmedRequests)).toList(); } @Override @@ -70,9 +63,8 @@ public CompilationDto findById(long compId) { Set events = compilation.getEvents(); Map confirmedRequests = getConfirmedRequests(events); - Map views = getViews(events); - return toDto(compilation, confirmedRequests, views); + return toDto(compilation, confirmedRequests); } @Override @@ -91,9 +83,8 @@ public CompilationDto save(NewCompilationDto newCompilationDto) { Compilation saved = compRepository.save(compilation); Map confirmedRequests = getConfirmedRequests(events); - Map views = getViews(events); - return toDto(saved, confirmedRequests, views); + return toDto(saved, confirmedRequests); } @Override @@ -129,13 +120,11 @@ public CompilationDto update(long compId, UpdateCompilationRequest updateRequest Set actualEvents = updated.getEvents(); Map confirmedRequests = getConfirmedRequests(actualEvents); - Map views = getViews(actualEvents); - return toDto(updated, confirmedRequests, views); + return toDto(updated, confirmedRequests); } - private CompilationDto toDto( - Compilation compilation, Map confirmedRequests, Map views) { + private CompilationDto toDto(Compilation compilation, Map confirmedRequests) { List events = compilation.getEvents().stream() .map( @@ -143,7 +132,7 @@ private CompilationDto toDto( EventMapper.mapToShortDto( event, confirmedRequests.getOrDefault(event.getId(), 0L), - views.get(event.getId()))) + null)) .toList(); return CompilationsMapper.mapToDto(compilation, events); @@ -172,31 +161,4 @@ private Map getConfirmedRequests(Set events) { return requestRepository.countConfirmedByEventIds(eventIds); } - - private Map getViews(Set events) { - if (events.isEmpty()) { - return Map.of(); - } - - List uris = events.stream().map(e -> "/events/%s".formatted(e.getId())).toList(); - - try { - List stats = - statsClient.getStats(MINIMAL_LOCAL_DATE_TIME, LocalDateTime.now(), uris, true); - - return stats.stream() - .collect( - Collectors.toMap( - s -> { - String uri = s.uri(); - return Long.parseLong( - uri.substring(uri.lastIndexOf("/") + 1)); - }, - ViewStatsDto::hits)); - - } catch (Exception e) { - log.error("Error during getting stats for events", e); - return Map.of(); - } - } } diff --git a/main-service/src/main/java/ru/practicum/event/controller/EventAdminController.java b/main-service/src/main/java/ru/practicum/event/controller/EventAdminController.java index 31fd7e7..c0760d6 100644 --- a/main-service/src/main/java/ru/practicum/event/controller/EventAdminController.java +++ b/main-service/src/main/java/ru/practicum/event/controller/EventAdminController.java @@ -5,6 +5,8 @@ import java.util.List; import jakarta.validation.Valid; +import jakarta.validation.constraints.Positive; +import jakarta.validation.constraints.PositiveOrZero; import ru.practicum.event.dto.EventFullDto; import ru.practicum.event.dto.UpdateEventAdminRequest; @@ -12,12 +14,14 @@ import ru.practicum.event.service.EventService; import ru.practicum.event.service.EventsAdminGetRequest; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @Slf4j +@Validated @RestController @RequiredArgsConstructor @RequestMapping("/admin/events") @@ -31,8 +35,8 @@ public Collection getEventsFiltered( @RequestParam(required = false) List categories, @RequestParam(required = false) LocalDateTime rangeStart, @RequestParam(required = false) LocalDateTime rangeEnd, - @RequestParam(defaultValue = "0") int from, - @RequestParam(defaultValue = "10") int size) { + @RequestParam(defaultValue = "0") @PositiveOrZero int from, + @RequestParam(defaultValue = "10") @Positive int size) { EventsAdminGetRequest getRequest = new EventsAdminGetRequest( users, states, categories, rangeStart, rangeEnd, from, size); diff --git a/main-service/src/main/java/ru/practicum/event/controller/EventPrivateController.java b/main-service/src/main/java/ru/practicum/event/controller/EventPrivateController.java index d0c0976..aee1200 100644 --- a/main-service/src/main/java/ru/practicum/event/controller/EventPrivateController.java +++ b/main-service/src/main/java/ru/practicum/event/controller/EventPrivateController.java @@ -3,6 +3,8 @@ import java.util.Collection; import jakarta.validation.Valid; +import jakarta.validation.constraints.Positive; +import jakarta.validation.constraints.PositiveOrZero; import ru.practicum.event.dto.EventFullDto; import ru.practicum.event.dto.EventShortDto; @@ -12,12 +14,14 @@ import ru.practicum.event.service.EventsPrivateGetRequest; import org.springframework.http.HttpStatus; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @Slf4j +@Validated @RestController @RequiredArgsConstructor @RequestMapping("/users/{userId}/events") @@ -27,8 +31,8 @@ public class EventPrivateController { @GetMapping() public Collection getEventsOfUserPaged( @PathVariable Long userId, - @RequestParam(defaultValue = "0") int from, - @RequestParam(defaultValue = "10") int size) { + @RequestParam(defaultValue = "0") @PositiveOrZero int from, + @RequestParam(defaultValue = "10") @Positive int size) { EventsPrivateGetRequest getRequest = new EventsPrivateGetRequest(userId, from, size); log.info("Private get events requested with params= {}", getRequest); return eventService.getEvents(getRequest); diff --git a/main-service/src/main/java/ru/practicum/event/controller/EventPublicController.java b/main-service/src/main/java/ru/practicum/event/controller/EventPublicController.java index 8501170..2f4d5ee 100644 --- a/main-service/src/main/java/ru/practicum/event/controller/EventPublicController.java +++ b/main-service/src/main/java/ru/practicum/event/controller/EventPublicController.java @@ -5,6 +5,8 @@ import java.util.List; import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.constraints.Positive; +import jakarta.validation.constraints.PositiveOrZero; import ru.practicum.event.dto.EventFullDto; import ru.practicum.event.dto.EventShortDto; @@ -12,12 +14,14 @@ import ru.practicum.event.service.EventsPublicGetRequest; import ru.practicum.exception.ValidationException; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @Slf4j +@Validated @RestController @RequiredArgsConstructor @RequestMapping("/events") @@ -33,8 +37,8 @@ public Collection getEventsFiltered( @RequestParam(required = false) LocalDateTime rangeEnd, @RequestParam(defaultValue = "false") boolean onlyAvailable, @RequestParam(required = false) EventSortBy sort, - @RequestParam(defaultValue = "0") int from, - @RequestParam(defaultValue = "10") int size, + @RequestParam(defaultValue = "0") @PositiveOrZero int from, + @RequestParam(defaultValue = "10") @Positive int size, HttpServletRequest request) { EventsPublicGetRequest getRequest = new EventsPublicGetRequest( diff --git a/main-service/src/main/java/ru/practicum/event/service/EventServiceImpl.java b/main-service/src/main/java/ru/practicum/event/service/EventServiceImpl.java index b19d9db..246a538 100644 --- a/main-service/src/main/java/ru/practicum/event/service/EventServiceImpl.java +++ b/main-service/src/main/java/ru/practicum/event/service/EventServiceImpl.java @@ -30,6 +30,7 @@ import org.springframework.data.domain.Page; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.client.RestClientException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -40,8 +41,6 @@ @Transactional(readOnly = true) public class EventServiceImpl implements EventService { private static final Duration MIN_TIME_BEFORE_EVENT = Duration.ofHours(2); - private static final LocalDateTime MINIMAL_LOCAL_DATE_TIME = - LocalDateTime.of(1000, 1, 1, 0, 0, 0); private static final String EVENTS_URI = "/events/%d"; private final EventRepository eventRepository; private final UserRepository userRepository; @@ -238,9 +237,19 @@ public EventFullDto updateEventByUser( } private Map getStatsMapForEvents(Page events) { + if (events.isEmpty()) { + return Collections.emptyMap(); + } List listOfUris = events.stream().map(event -> EVENTS_URI.formatted(event.getId())).toList(); - return getStatsForEvents(listOfUris).stream() + LocalDateTime minimalPublishDate = + events.stream() + .map(Event::getPublishedOn) + .filter(Objects::nonNull) + .min(LocalDateTime::compareTo) + .orElse(LocalDateTime.of(1000, 1, 1, 1, 1)); + + return getStatsForEvents(listOfUris, minimalPublishDate).stream() .collect( Collectors.toMap( statsDto -> @@ -262,30 +271,30 @@ private Map getConfirmedRequests(Set events) { return requestRepository.countConfirmedByEventIds(eventIds); } - private List getStatsForEvents(List uris) { + private List getStatsForEvents(List uris, LocalDateTime startDate) { try { - return statsClient.getStats(MINIMAL_LOCAL_DATE_TIME, LocalDateTime.now(), uris, true); - } catch (Exception e) { + return statsClient.getStats(startDate, LocalDateTime.now(), uris, true); + } catch (RestClientException e) { log.error("Error during getting stats for events", e); } return List.of(); } private ViewStatsDto getStatsForEvent(Event event, String uri) { + if (event.getPublishedOn() == null) { + return new ViewStatsDto(null, null, null); + } + + LocalDateTime startDate = event.getPublishedOn().minusSeconds(10); + LocalDateTime endDate = LocalDateTime.now().plusSeconds(10); ViewStatsDto statsDto; + try { - statsDto = - statsClient - .getStats( - MINIMAL_LOCAL_DATE_TIME, - LocalDateTime.now(), - List.of(uri), - true) - .getFirst(); + statsDto = statsClient.getStats(startDate, endDate, List.of(uri), true).getFirst(); } catch (NoSuchElementException e) { log.trace("No stats for event with id={} found", event.getId()); statsDto = new ViewStatsDto(null, null, 0L); - } catch (Exception e) { + } catch (RestClientException e) { log.error("Error during getting stats for event with id={}", event.getId(), e); statsDto = new ViewStatsDto(null, null, null); } diff --git a/main-service/src/main/java/ru/practicum/user/controller/UserAdminController.java b/main-service/src/main/java/ru/practicum/user/controller/UserAdminController.java index f239a1e..b8c4699 100644 --- a/main-service/src/main/java/ru/practicum/user/controller/UserAdminController.java +++ b/main-service/src/main/java/ru/practicum/user/controller/UserAdminController.java @@ -4,6 +4,8 @@ import java.util.List; import jakarta.validation.Valid; +import jakarta.validation.constraints.Positive; +import jakarta.validation.constraints.PositiveOrZero; import ru.practicum.user.dto.NewUserRequest; import ru.practicum.user.dto.UserDto; @@ -11,12 +13,14 @@ import ru.practicum.user.service.UsersGetRequest; import org.springframework.http.HttpStatus; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @Slf4j +@Validated @RestController @RequiredArgsConstructor @RequestMapping("/admin/users") @@ -26,8 +30,8 @@ public class UserAdminController { @GetMapping() public Collection getUsersPaged( @RequestParam(required = false) List ids, - @RequestParam(defaultValue = "0") int from, - @RequestParam(defaultValue = "10") int size) { + @RequestParam(defaultValue = "0") @PositiveOrZero int from, + @RequestParam(defaultValue = "10") @Positive int size) { log.info("Get users requested with ids={} from={} size={}", ids, from, size); UsersGetRequest request = new UsersGetRequest(from, size, ids); return userService.getUsersPaged(request);