Skip to content

Commit 35f963b

Browse files
committed
fix24
1 parent 3907039 commit 35f963b

3 files changed

Lines changed: 95 additions & 51 deletions

File tree

ewm-service/src/main/java/ru/practicum/ewm/event/repository/EventRepository.java

Lines changed: 2 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,49 +3,18 @@
33
import org.springframework.data.domain.Page;
44
import org.springframework.data.domain.Pageable;
55
import org.springframework.data.jpa.repository.JpaRepository;
6+
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
67
import org.springframework.data.jpa.repository.Query;
78
import org.springframework.data.repository.query.Param;
89
import ru.practicum.ewm.event.model.Event;
910

10-
import java.time.LocalDateTime;
1111
import java.util.List;
1212
import java.util.Map;
1313

14-
public interface EventRepository extends JpaRepository<Event, Long> {
14+
public interface EventRepository extends JpaRepository<Event, Long>, JpaSpecificationExecutor<Event> {
1515

1616
boolean existsByCategoryId(Long categoryId);
1717

18-
@Query("SELECT e FROM Event e " +
19-
"WHERE (:users IS NULL OR e.initiator.id IN :users) " +
20-
"AND (:states IS NULL OR e.state IN :states) " +
21-
"AND (:categories IS NULL OR e.category.id IN :categories) " +
22-
"AND (CAST(:rangeStart AS timestamp) IS NULL OR e.eventDate >= :rangeStart) " +
23-
"AND (CAST(:rangeEnd AS timestamp) IS NULL OR e.eventDate <= :rangeEnd) " +
24-
"ORDER BY e.id")
25-
Page<Event> searchEventsAdmin(@Param("users") List<Long> users,
26-
@Param("states") List<String> states,
27-
@Param("categories") List<Long> categories,
28-
@Param("rangeStart") LocalDateTime rangeStart,
29-
@Param("rangeEnd") LocalDateTime rangeEnd,
30-
Pageable pageable);
31-
32-
@Query("SELECT e FROM Event e " +
33-
"WHERE e.state = 'PUBLISHED' " +
34-
"AND (:text IS NULL OR :text = '' OR " +
35-
" LOWER(e.annotation) LIKE LOWER(CONCAT('%', :text, '%')) OR " +
36-
" LOWER(e.description) LIKE LOWER(CONCAT('%', :text, '%'))) " +
37-
"AND (:categories IS NULL OR e.category.id IN :categories) " +
38-
"AND (:paid IS NULL OR e.paid = :paid) " +
39-
"AND (CAST(:rangeStart AS timestamp) IS NULL OR e.eventDate >= :rangeStart) " +
40-
"AND (CAST(:rangeEnd AS timestamp) IS NULL OR e.eventDate <= :rangeEnd) " +
41-
"ORDER BY e.eventDate")
42-
Page<Event> searchEventsPublic(@Param("text") String text,
43-
@Param("categories") List<Long> categories,
44-
@Param("paid") Boolean paid,
45-
@Param("rangeStart") LocalDateTime rangeStart,
46-
@Param("rangeEnd") LocalDateTime rangeEnd,
47-
Pageable pageable);
48-
4918
@Query("SELECT COUNT(r) FROM Request r WHERE r.event.id = :eventId AND r.status = 'CONFIRMED'")
5019
Long countConfirmedRequests(@Param("eventId") Long eventId);
5120

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package ru.practicum.ewm.event.repository;
2+
3+
import org.springframework.data.jpa.domain.Specification;
4+
import ru.practicum.ewm.event.model.Event;
5+
import ru.practicum.ewm.event.model.EventState;
6+
7+
import jakarta.persistence.criteria.*;
8+
import java.time.LocalDateTime;
9+
import java.util.List;
10+
11+
public class EventSpecifications {
12+
13+
public static Specification<Event> hasInitiators(List<Long> users) {
14+
return (root, query, cb) -> {
15+
if (users == null || users.isEmpty()) return null;
16+
return root.get("initiator").get("id").in(users);
17+
};
18+
}
19+
20+
public static Specification<Event> hasStates(List<String> stateStrings) {
21+
return (root, query, cb) -> {
22+
if (stateStrings == null || stateStrings.isEmpty()) return null;
23+
List<EventState> states = stateStrings.stream()
24+
.map(EventState::valueOf)
25+
.toList();
26+
return root.get("state").in(states);
27+
};
28+
}
29+
30+
public static Specification<Event> hasCategories(List<Long> categories) {
31+
return (root, query, cb) -> {
32+
if (categories == null || categories.isEmpty()) return null;
33+
return root.get("category").get("id").in(categories);
34+
};
35+
}
36+
37+
public static Specification<Event> eventDateBetween(LocalDateTime rangeStart, LocalDateTime rangeEnd) {
38+
return (root, query, cb) -> {
39+
if (rangeStart == null && rangeEnd == null) return null;
40+
Path<LocalDateTime> eventDate = root.get("eventDate");
41+
if (rangeStart != null && rangeEnd != null) {
42+
return cb.between(eventDate, rangeStart, rangeEnd);
43+
} else if (rangeStart != null) {
44+
return cb.greaterThanOrEqualTo(eventDate, rangeStart);
45+
} else {
46+
return cb.lessThanOrEqualTo(eventDate, rangeEnd);
47+
}
48+
};
49+
}
50+
51+
public static Specification<Event> isPublished() {
52+
return (root, query, cb) -> cb.equal(root.get("state"), EventState.PUBLISHED);
53+
}
54+
55+
public static Specification<Event> textContains(String text) {
56+
return (root, query, cb) -> {
57+
if (text == null || text.isBlank()) return null;
58+
String pattern = "%" + text.toLowerCase() + "%";
59+
return cb.or(
60+
cb.like(cb.lower(root.get("annotation")), pattern),
61+
cb.like(cb.lower(root.get("description")), pattern)
62+
);
63+
};
64+
}
65+
66+
public static Specification<Event> paidEquals(Boolean paid) {
67+
return (root, query, cb) -> paid == null ? null : cb.equal(root.get("paid"), paid);
68+
}
69+
}

ewm-service/src/main/java/ru/practicum/ewm/event/service/EventServiceImpl.java

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import org.springframework.data.domain.PageRequest;
88
import org.springframework.data.domain.Pageable;
99
import org.springframework.data.domain.Sort;
10+
import org.springframework.data.jpa.domain.Specification;
1011
import org.springframework.stereotype.Service;
1112
import org.springframework.transaction.annotation.Transactional;
1213
import ru.practicum.ewm.category.model.Category;
@@ -16,6 +17,7 @@
1617
import ru.practicum.ewm.event.model.Event;
1718
import ru.practicum.ewm.event.model.EventState;
1819
import ru.practicum.ewm.event.repository.EventRepository;
20+
import ru.practicum.ewm.event.repository.EventSpecifications;
1921
import ru.practicum.ewm.event.util.SortType;
2022
import ru.practicum.ewm.exception.ConflictException;
2123
import ru.practicum.ewm.exception.NotFoundException;
@@ -112,15 +114,16 @@ public List<EventFullDto> getEventsForAdmin(AdminEventSearchParams params) {
112114
}
113115

114116
Pageable pageable = PageRequest.of(from / size, size, Sort.by("id"));
115-
Page<Event> page = eventRepository.searchEventsAdmin(
116-
params.getUsers(),
117-
params.getStates(),
118-
params.getCategories(),
119-
params.getRangeStart(),
120-
params.getRangeEnd(),
121-
pageable);
122117

118+
Specification<Event> spec = Specification
119+
.where(EventSpecifications.hasInitiators(params.getUsers()))
120+
.and(EventSpecifications.hasStates(params.getStates()))
121+
.and(EventSpecifications.hasCategories(params.getCategories()))
122+
.and(EventSpecifications.eventDateBetween(params.getRangeStart(), params.getRangeEnd()));
123+
124+
Page<Event> page = eventRepository.findAll(spec, pageable);
123125
List<Event> events = page.getContent();
126+
124127
List<Long> eventIds = events.stream().map(Event::getId).collect(Collectors.toList());
125128
Map<Long, Long> confirmedRequestsMap = eventRepository.countConfirmedRequestsBatch(eventIds);
126129

@@ -196,16 +199,19 @@ public List<EventShortDto> getEventsForPublic(PublicEventSearchParams params, Ht
196199
log.warn("Не удалось отправить статистику: {}", e.getMessage());
197200
}
198201

199-
Pageable pageable = PageRequest.of(from / size, size, Sort.by("eventDate").ascending());
200-
Page<Event> page = eventRepository.searchEventsPublic(
201-
params.getText(),
202-
params.getCategories(),
203-
params.getPaid(),
204-
params.getRangeStart(),
205-
params.getRangeEnd(),
206-
pageable);
202+
Sort sort = Sort.by("eventDate").ascending();
203+
Pageable pageable = PageRequest.of(from / size, size, sort);
207204

205+
Specification<Event> spec = Specification
206+
.where(EventSpecifications.isPublished())
207+
.and(EventSpecifications.textContains(params.getText()))
208+
.and(EventSpecifications.hasCategories(params.getCategories()))
209+
.and(EventSpecifications.paidEquals(params.getPaid()))
210+
.and(EventSpecifications.eventDateBetween(params.getRangeStart(), params.getRangeEnd()));
211+
212+
Page<Event> page = eventRepository.findAll(spec, pageable);
208213
List<Event> events = page.getContent();
214+
209215
Map<Long, Long> confirmedRequestsMap = getConfirmedRequestsMap(events);
210216

211217
if (params.getOnlyAvailable()) {
@@ -226,10 +232,10 @@ public List<EventShortDto> getEventsForPublic(PublicEventSearchParams params, Ht
226232
confirmedRequestsMap.getOrDefault(event.getId(), 0L)))
227233
.collect(Collectors.toList());
228234

229-
SortType sort = params.getSort();
230-
if (sort == SortType.VIEWS) {
235+
SortType sortParam = params.getSort();
236+
if (sortParam == SortType.VIEWS) {
231237
result.sort(Comparator.comparing(EventShortDto::getViews).reversed());
232-
} else if (sort == SortType.EVENT_DATE) {
238+
} else if (sortParam == SortType.EVENT_DATE) {
233239
result.sort(Comparator.comparing(EventShortDto::getEventDate));
234240
}
235241

0 commit comments

Comments
 (0)