Skip to content

Commit

Permalink
merge: Feature/#324 행사 검색 기능 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
amaran-th authored Oct 9, 2023
2 parents 6418b68 + ffe4b9b commit ce3e2a3
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 91 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ void findEvents() throws Exception {
RequestDocumentation.parameterWithName("tags").description("필터링하려는 태그(option)").optional(),
RequestDocumentation.parameterWithName("statuses")
.description("필터링하려는 상태(UPCOMING, IN_PROGRESS, ENDED)(option)")
.optional(),
RequestDocumentation.parameterWithName("keyword")
.description("검색하려는 키워드")
.optional()
);

Expand All @@ -144,18 +147,6 @@ void findEvents() throws Exception {
);

final List<EventResponse> eventResponses = List.of(
new EventResponse(
1L,
"인프콘 2023",
LocalDateTime.parse("2023-06-03T12:00:00"),
LocalDateTime.parse("2023-09-03T12:00:00"),
LocalDateTime.parse("2023-09-01T00:00:00"),
LocalDateTime.parse("2023-09-02T23:59:59"),
List.of("백엔드", "프론트엔드", "안드로이드", "IOS", "AI"),
"https://biz.pusan.ac.kr/dext5editordata/2022/08/20220810_160546511_10103.jpg",
EventMode.ONLINE.getValue(),
PaymentType.PAID.getValue()
),
new EventResponse(
5L,
"웹 컨퍼런스",
Expand All @@ -182,14 +173,15 @@ void findEvents() throws Exception {
Mockito.when(eventService.findEvents(any(EventType.class),
any(LocalDate.class), eq("2023-07-01"),
eq("2023-07-31"),
eq(null), any())).thenReturn(eventResponses);
eq(null), any(), eq("컨퍼"))).thenReturn(eventResponses);

// when & then
mockMvc.perform(get("/events")
.param("category", "CONFERENCE")
.param("start_date", "2023-07-01")
.param("end_date", "2023-07-31")
.param("statuses", "UPCOMING,IN_PROGRESS")
.param("keyword", "컨퍼")
)
.andExpect(status().isOk())
.andDo(MockMvcRestDocumentation.document("find-events", requestParameters, responseFields));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,11 @@ public ResponseEntity<List<EventResponse>> findEvents(
@RequestParam(name = "start_date", required = false) final String startDate,
@RequestParam(name = "end_date", required = false) final String endDate,
@RequestParam(required = false) final List<String> tags,
@RequestParam(required = false) final List<EventStatus> statuses) {
@RequestParam(required = false) final List<EventStatus> statuses,
@RequestParam(required = false) final String keyword) {
return ResponseEntity.ok(
eventService.findEvents(category, LocalDate.now(), startDate, endDate, tags, statuses));
eventService.findEvents(category, LocalDate.now(), startDate, endDate, tags, statuses,
keyword));
}

@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.emmsale.event.application;

import static com.emmsale.event.domain.repository.EventSpecification.filterByCategory;
import static com.emmsale.event.domain.repository.EventSpecification.filterByNameContainsSearchKeywords;
import static com.emmsale.event.domain.repository.EventSpecification.filterByPeriod;
import static com.emmsale.event.domain.repository.EventSpecification.filterByTags;
import static com.emmsale.event.exception.EventExceptionType.NOT_FOUND_EVENT;
import static com.emmsale.tag.exception.TagExceptionType.NOT_FOUND_TAG;
Expand All @@ -15,7 +17,6 @@
import com.emmsale.event.domain.EventStatus;
import com.emmsale.event.domain.EventType;
import com.emmsale.event.domain.repository.EventRepository;
import com.emmsale.event.domain.repository.EventSpecification;
import com.emmsale.event.domain.repository.EventTagRepository;
import com.emmsale.event.exception.EventException;
import com.emmsale.event.exception.EventExceptionType;
Expand Down Expand Up @@ -92,20 +93,13 @@ private List<String> extractInformationImages(final List<String> imageUrls) {
@Transactional(readOnly = true)
public List<EventResponse> findEvents(final EventType category,
final LocalDate nowDate, final String startDate, final String endDate,
final List<String> tagNames, final List<EventStatus> statuses) {
final List<String> tagNames, final List<EventStatus> statuses, final String keyword) {
Specification<Event> spec = Specification.where(filterByCategory(category));

if (isExistTagNames(tagNames)) {
validateTags(tagNames);
spec = spec.and(filterByTags(tagNames));
}
spec = filterByTagIfExist(tagNames, spec);
spec = filterByDateIfExist(startDate, endDate, spec);
spec = filterByKeywordIfExist(keyword, spec);

if (isExistFilterDate(startDate, endDate)) {
final LocalDateTime startDateTime = validateStartDate(startDate);
final LocalDateTime endDateTime = validateEndDate(endDate);
validateEndDateAfterDateStart(startDateTime, endDateTime);
spec = spec.and(EventSpecification.filterByPeriod(startDateTime, endDateTime));
}
final List<Event> events = eventRepository.findAll(spec);

final EnumMap<EventStatus, List<Event>> eventsForEventStatus
Expand All @@ -114,6 +108,15 @@ public List<EventResponse> findEvents(final EventType category,
return filterByStatuses(statuses, eventsForEventStatus, makeImageUrlPerEventId(events));
}

private Specification<Event> filterByTagIfExist(final List<String> tagNames,
Specification<Event> spec) {
if (isExistTagNames(tagNames)) {
validateTags(tagNames);
spec = spec.and(filterByTags(tagNames));
}
return spec;
}

private boolean isExistTagNames(final List<String> tagNames) {
return tagNames != null;
}
Expand All @@ -125,6 +128,17 @@ private void validateTags(final List<String> tagNames) {
}
}

private Specification<Event> filterByDateIfExist(final String startDate, final String endDate,
Specification<Event> spec) {
if (isExistFilterDate(startDate, endDate)) {
final LocalDateTime startDateTime = validateStartDate(startDate);
final LocalDateTime endDateTime = validateEndDate(endDate);
validateEndDateAfterDateStart(startDateTime, endDateTime);
spec = spec.and(filterByPeriod(startDateTime, endDateTime));
}
return spec;
}

private boolean isExistFilterDate(final String startDate, final String endDate) {
return startDate != null || endDate != null;
}
Expand Down Expand Up @@ -171,6 +185,19 @@ private Map<Long, String> makeImageUrlPerEventId(final List<Event> events) {
return imageUrlPerEventId;
}

private Specification<Event> filterByKeywordIfExist(final String keyword,
Specification<Event> spec) {
if (isExistKeyword(keyword)) {
final String[] keywords = keyword.trim().split(" ");
spec = spec.and(filterByNameContainsSearchKeywords(keywords));
}
return spec;
}

private boolean isExistKeyword(final String keyword) {
return keyword != null && !keyword.isBlank();
}

private EnumMap<EventStatus, List<Event>> groupByEventStatus(final LocalDate nowDate,
final List<Event> events) {
return events.stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.util.List;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Predicate;
import org.springframework.data.jpa.domain.Specification;

public class EventSpecification {
Expand Down Expand Up @@ -38,4 +39,16 @@ public static Specification<Event> filterByPeriod(final LocalDateTime startDate,
startDate))
);
}

public static Specification<Event> filterByNameContainsSearchKeywords(final String[] keywords) {
return (root, query, criteriaBuilder) -> {
Predicate[] predicates = new Predicate[keywords.length];

for (int i = 0; i < keywords.length; i++) {
predicates[i] = criteriaBuilder.like(root.get("name"), "%" + keywords[i] + "%");
}

return criteriaBuilder.and(predicates);
};
}
}
Loading

0 comments on commit ce3e2a3

Please sign in to comment.