Skip to content

Commit

Permalink
merge: Feature/#115 이벤트 cud 기능 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
hyeonjerry authored Jul 31, 2023
2 parents 6943aac + bcc8b67 commit 7754fc5
Show file tree
Hide file tree
Showing 15 changed files with 969 additions and 59 deletions.
40 changes: 39 additions & 1 deletion backend/emm-sale/src/docs/asciidoc/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@ include::{snippets}/find-profile/http-response.adoc[]
.HTTP response 설명
include::{snippets}/find-profile/response-fields.adoc[]


== Event

=== `GET` : 행사 상세정보 조회
Expand Down Expand Up @@ -153,6 +152,45 @@ include::{snippets}/find-participants/http-response.adoc[]
.HTTP response 설명
include::{snippets}/find-participants/response-fields.adoc[]

=== `POST` : 이벤트 생성

.HTTP request
include::{snippets}/add-event/http-request.adoc[]

.HTTP request 설명
include::{snippets}/add-event/request-fields.adoc[]

.HTTP response
include::{snippets}/add-event/http-response.adoc[]

.HTTP response 설명
include::{snippets}/add-event/response-fields.adoc[]

=== `PUT` : 이벤트 업데이트

.HTTP request
include::{snippets}/update-event/http-request.adoc[]

.HTTP request 설명
include::{snippets}/update-event/request-fields.adoc[]

.HTTP response
include::{snippets}/update-event/http-response.adoc[]

.HTTP response 설명
include::{snippets}/update-event/response-fields.adoc[]

=== `PUT` : 이벤트 삭제

.HTTP request
include::{snippets}/delete-event/http-request.adoc[]

.HTTP response
include::{snippets}/delete-event/http-response.adoc[]

.HTTP response 설명
include::{snippets}/delete-event/response-fields.adoc[]

== Comment

=== `GET` : 댓글 모두 조회
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@

import com.emmsale.base.BaseException;
import com.emmsale.base.BaseExceptionType;
import java.time.format.DateTimeParseException;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

Expand All @@ -18,6 +23,24 @@ public ResponseEntity<ExceptionResponse> handleException(final BaseException e)
return new ResponseEntity<>(ExceptionResponse.from(e), type.httpStatus());
}

@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ExceptionResponse> handleValidationException(
final MethodArgumentNotValidException e) {
final String message = e.getBindingResult().getAllErrors().stream()
.map(DefaultMessageSourceResolvable::getDefaultMessage)
.collect(Collectors.joining("\n"));
log.warn("[WARN] MESSAGE: {}", message);
return new ResponseEntity<>(new ExceptionResponse(message), HttpStatus.BAD_REQUEST);
}

@ExceptionHandler(DateTimeParseException.class)
public ResponseEntity<ExceptionResponse> handleDateTimeParseException(
final DateTimeParseException e) {
final String message = "DateTime 입력 형식이 올바르지 않습니다.";
log.warn("[WARN] MESSAGE: " + message);
return new ResponseEntity<>(new ExceptionResponse(message), HttpStatus.BAD_REQUEST);
}

static class ExceptionResponse {

private final String message;
Expand Down
26 changes: 26 additions & 0 deletions backend/emm-sale/src/main/java/com/emmsale/event/api/EventApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,27 @@
import static java.net.URI.create;

import com.emmsale.event.application.EventService;
import com.emmsale.event.application.dto.EventDetailRequest;
import com.emmsale.event.application.dto.EventDetailResponse;
import com.emmsale.event.application.dto.EventParticipateRequest;
import com.emmsale.event.application.dto.EventResponse;
import com.emmsale.event.application.dto.ParticipantResponse;
import com.emmsale.member.domain.Member;
import java.time.LocalDate;
import java.util.List;
import javax.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

@RestController
Expand Down Expand Up @@ -62,4 +68,24 @@ public ResponseEntity<List<EventResponse>> findEvents(@RequestParam final int ye
@RequestParam(required = false) final String status) {
return ResponseEntity.ok(eventService.findEvents(LocalDate.now(), year, month, tag, status));
}

@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public EventDetailResponse addEvent(
@RequestBody @Valid final EventDetailRequest request) {
return eventService.addEvent(request);
}

@PutMapping("/{event-id}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public EventDetailResponse updateEvent(@PathVariable(name = "event-id") final Long eventId,
@RequestBody @Valid final EventDetailRequest request) {
return eventService.updateEvent(eventId, request);
}

@DeleteMapping("/{event-id}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public EventDetailResponse deleteEvent(@PathVariable(name = "event-id") final Long eventId) {
return eventService.deleteEvent(eventId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toUnmodifiableList;

import com.emmsale.event.application.dto.EventDetailRequest;
import com.emmsale.event.application.dto.EventDetailResponse;
import com.emmsale.event.application.dto.EventResponse;
import com.emmsale.event.application.dto.ParticipantResponse;
Expand All @@ -22,10 +23,12 @@
import com.emmsale.event.exception.EventException;
import com.emmsale.event.exception.EventExceptionType;
import com.emmsale.member.domain.Member;
import com.emmsale.tag.application.dto.TagRequest;
import com.emmsale.tag.domain.Tag;
import com.emmsale.tag.domain.TagRepository;
import com.emmsale.tag.exception.TagException;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import lombok.RequiredArgsConstructor;
Expand All @@ -46,6 +49,12 @@ public class EventService {
private final EventTagRepository eventTagRepository;
private final TagRepository tagRepository;

private static void validateMemberNotAllowed(final Long memberId, final Member member) {
if (member.isNotMe(memberId)) {
throw new EventException(EventExceptionType.FORBIDDEN_PARTICIPATE_EVENT);
}
}

@Transactional(readOnly = true)
public EventDetailResponse findEvent(final Long id) {
final Event event = eventRepository.findById(id)
Expand All @@ -63,17 +72,11 @@ public Long participate(final Long eventId, final Long memberId, final Member me
return participant.getId();
}

private void validateMemberNotAllowed(final Long memberId, final Member member) {
if (member.isNotMe(memberId)) {
throw new EventException(EventExceptionType.FORBIDDEN_PARTICIPATE_EVENT);
}
}

@Transactional(readOnly = true)
public List<EventResponse> findEvents(final LocalDate nowDate, final int year, final int month,
final String tagName, final String statusName) {
validateYearAndMonth(year, month);
List<Event> events = filterEventsByTag(tagName);
final List<Event> events = filterEventsByTag(tagName);

final EnumMap<EventStatus, List<Event>> eventsForEventStatus
= groupByEventStatus(nowDate, events, year, month);
Expand Down Expand Up @@ -101,7 +104,7 @@ private void validateYearAndMonth(final int year, final int month) {

private List<Event> filterEventsByTag(final String tagName) {
if (isExistTagName(tagName)) {
Tag tag = tagRepository.findByName(tagName)
final Tag tag = tagRepository.findByName(tagName)
.orElseThrow(() -> new TagException(NOT_FOUND_TAG));

return eventTagRepository.findEventTagsByTag(tag)
Expand Down Expand Up @@ -131,15 +134,15 @@ private EnumMap<EventStatus, List<Event>> groupByEventStatus(final LocalDate now

private boolean isOverlapToMonth(final int year, final int month,
final LocalDate eventStart, final LocalDate eventEnd) {
LocalDate monthStart = LocalDate.of(year, month, 1);
LocalDate monthEnd = LocalDate.of(year, month, monthStart.lengthOfMonth());
final LocalDate monthStart = LocalDate.of(year, month, 1);
final LocalDate monthEnd = LocalDate.of(year, month, monthStart.lengthOfMonth());

return (isBeforeOrEquals(eventStart, monthEnd) && isBeforeOrEquals(monthStart, eventEnd))
|| (isBeforeOrEquals(monthStart, eventStart) && isBeforeOrEquals(eventStart, monthEnd))
|| (isBeforeOrEquals(monthStart, eventEnd) && isBeforeOrEquals(eventEnd, monthEnd));
}

private boolean isBeforeOrEquals(LocalDate criteria, LocalDate comparison) {
private boolean isBeforeOrEquals(final LocalDate criteria, final LocalDate comparison) {
return criteria.isBefore(comparison) || criteria.isEqual(comparison);
}

Expand All @@ -164,5 +167,54 @@ private boolean isExistStatusName(final String statusName) {
return statusName != null;
}

public EventDetailResponse addEvent(final EventDetailRequest request) {
final Event event = saveNewEvent(request);

final List<Tag> tags = findAllPersistTagsOrElseThrow(request.getTags());

event.addAllEventTags(tags);

return EventDetailResponse.from(event);
}

public EventDetailResponse updateEvent(final Long eventId, final EventDetailRequest request) {
final Event event = eventRepository.findById(eventId)
.orElseThrow(() -> new EventException(NOT_FOUND_EVENT));

final List<Tag> tags = findAllPersistTagsOrElseThrow(request.getTags());

eventTagRepository.deleteAllByEventId(eventId);

final Event updatedEvent = event.updateEventContent(request.getName(), request.getLocation(),
request.getStartDateTime(), request.getEndDateTime(), request.getInformationUrl(), tags);

return EventDetailResponse.from(updatedEvent);
}

public EventDetailResponse deleteEvent(final Long eventId) {
final Event event = eventRepository.findById(eventId)
.orElseThrow(() -> new EventException(NOT_FOUND_EVENT));

eventRepository.deleteById(eventId);

return EventDetailResponse.from(event);
}

private List<Tag> findAllPersistTagsOrElseThrow(final List<TagRequest> tags) {
if (tags == null || tags.isEmpty()) {
return new ArrayList<>();
}

return tags.stream()
.map(tag -> tagRepository.findByName(tag.getName())
.orElseThrow(() -> new EventException(EventExceptionType.NOT_FOUND_TAG)))
.collect(toList());
}

private Event saveNewEvent(final EventDetailRequest request) {
final Event event = new Event(request.getName(), request.getLocation(),
request.getStartDateTime(), request.getEndDateTime(), request.getInformationUrl());

return eventRepository.save(event);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.emmsale.event.application.dto;

import com.emmsale.tag.application.dto.TagRequest;
import java.time.LocalDateTime;
import java.util.List;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;

@RequiredArgsConstructor
@Getter
public class EventDetailRequest {

private static final String DATE_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss";

@NotBlank(message = "행사의 이름을 입력해 주세요.")
private final String name;
@NotBlank(message = "행사의 장소를 입력해 주세요.")
private final String location;
@NotBlank(message = "행사의 상세 URL을 입력해 주세요.")
@Pattern(regexp = "(http.?://).*", message = "http:// 혹은 https://로 시작하는 주소를 입력해 주세요.")
private final String informationUrl;

@DateTimeFormat(pattern = DATE_TIME_FORMAT)
@NotNull(message = "행사의 시작 일시를 입력해 주세요.")
private final LocalDateTime startDateTime;
@DateTimeFormat(pattern = DATE_TIME_FORMAT)
@NotNull(message = "행사의 종료 일시를 입력해 주세요.")
private final LocalDateTime endDateTime;

private final List<TagRequest> tags;
}
Loading

0 comments on commit 7754fc5

Please sign in to comment.