Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 공연 기능 추가 #22

Merged
merged 8 commits into from
Dec 24, 2023
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.pgms.apievent.event.controller;

import java.net.URI;

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.ModelAttribute;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import com.pgms.apievent.event.dto.request.EventCreateRequest;
import com.pgms.apievent.event.dto.request.EventUpdateRequest;
import com.pgms.apievent.event.dto.response.EventResponse;
import com.pgms.apievent.event.service.EventService;
import com.pgms.coredomain.response.ApiResponse;

import lombok.RequiredArgsConstructor;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/events")
public class EventController {

private final EventService eventService;

@PostMapping
public ResponseEntity<ApiResponse> createEvent(@ModelAttribute EventCreateRequest request) {
EventResponse response = eventService.createEvent(request);
URI location = ServletUriComponentsBuilder.fromCurrentRequest()
.path("/{id}")
.buildAndExpand(response.id())
.toUri();
return ResponseEntity.created(location).body(ApiResponse.created(response));
}

@GetMapping("/{id}")
public ResponseEntity<ApiResponse> getEventById(@PathVariable Long id) {
EventResponse response = eventService.getEventById(id);
return ResponseEntity.ok(ApiResponse.ok(response));
}

@PutMapping("/{id}")
public ResponseEntity<ApiResponse> updateEvent(
@PathVariable Long id,
@ModelAttribute EventUpdateRequest request) {
EventResponse response = eventService.updateEvent(id, request);
return ResponseEntity.ok(ApiResponse.ok(response));
}

@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteEventById(@PathVariable Long id) {
eventService.deleteEventById(id);
return ResponseEntity.noContent().build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.pgms.apievent.event.dto.request;

import java.time.LocalDateTime;

import com.pgms.coredomain.domain.event.Event;
import com.pgms.coredomain.domain.event.EventHall;
import com.pgms.coredomain.domain.event.GenreType;

public record EventCreateRequest(
String title,
String description,
int runningTime,
LocalDateTime startDate,
LocalDateTime endDate,
String rating,
GenreType genreType,
String thumbnail,
Long eventHallId
) {
public Event toEntity(EventHall eventHall) {
return Event.builder()
.title(title)
.description(description)
.runningTime(runningTime)
.startDate(startDate)
.endDate(endDate)
.rating(rating)
.genreType(genreType)
.thumbnail(thumbnail)
.eventHall(eventHall)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.pgms.apievent.event.dto.request;

import java.time.LocalDateTime;

import com.pgms.coredomain.domain.event.GenreType;

public record EventUpdateRequest(
String title,
String description,
int runningTime,
LocalDateTime startDate,
LocalDateTime endDate,
String rating,
GenreType genreType,
String thumbnail,
Long eventHallId
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.pgms.apievent.event.dto.response;

import com.pgms.coredomain.domain.event.Event;

public record EventResponse(
Long id,
String title,
String description,
int runningTime,
String startDate,
String endDate,
String rating,
String genreType,
String thumbnail,
String eventHall
) {
public static EventResponse of(Event event) {
return new EventResponse(
event.getId(),
event.getTitle(),
event.getDescription(),
event.getRunningTime(),
event.getStartDate().toString(),
event.getEndDate().toString(),
event.getRating(),
event.getGenreType().toString(),
event.getThumbnail(),
event.getEventHall().getName()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package com.pgms.apievent.event.service;

import static com.pgms.apievent.exception.EventErrorCode.*;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.pgms.apievent.event.dto.request.EventCreateRequest;
import com.pgms.apievent.event.dto.request.EventUpdateRequest;
import com.pgms.apievent.event.dto.response.EventResponse;
import com.pgms.apievent.exception.CustomException;
import com.pgms.coredomain.domain.event.Event;
import com.pgms.coredomain.domain.event.EventEdit;
import com.pgms.coredomain.domain.event.repository.EventRepository;

import lombok.RequiredArgsConstructor;

@Service
@Transactional
@RequiredArgsConstructor
public class EventService {

private final EventRepository eventRepository;
// private final EventHallRepository eventHallRepository;

public EventResponse createEvent(EventCreateRequest request) {
validateDuplicateEvent(request.title());
/**
* TODO
* 1) 공연장 정보를 통해 공연장 가져오기
* 2) toEntity 메소드에 eventHall 넘겨주기
*/
Event event = request.toEntity(null);
eventRepository.save(event);
return EventResponse.of(event);
}

@Transactional(readOnly = true)
public EventResponse getEventById(Long id) {
Event event = eventRepository.findById(id)
.orElseThrow(() -> new CustomException(EVENT_NOT_FOUND));
return EventResponse.of(event);
}

public EventResponse updateEvent(Long id, EventUpdateRequest request) {
Event event = eventRepository.findById(id)
.orElseThrow();
EventEdit eventEdit = getEventEdit(request);
event.updateEvent(eventEdit);
return EventResponse.of(event);
}

public void deleteEventById(Long id) {
Event event = eventRepository.findById(id)
.orElseThrow();
eventRepository.delete(event);
}

private void validateDuplicateEvent(String title) {
if (Boolean.TRUE.equals((eventRepository.existsEventByTitle(title)))) {
throw new CustomException(ALREADY_EXIST_EVENT);
}
}

private EventEdit getEventEdit(EventUpdateRequest request) {
/**
* TODO
* eventHall 찾아서 eventHall 부분에 넣어주기
*/
return EventEdit.builder()
.title(request.title())
.description(request.description())
.runningTime(request.runningTime())
.startDate(request.startDate())
.endDate(request.endDate())
.rating(request.rating())
.genreType(request.genreType())
.thumbnail(request.thumbnail())
.eventHall(null).build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.pgms.apievent.exception;

import lombok.Getter;

@Getter
public class CustomException extends RuntimeException {

private final EventErrorCode errorCode;

public CustomException(EventErrorCode errorCode) {
super(errorCode.getMessage());
this.errorCode = errorCode;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.pgms.apievent.exception;

import org.springframework.http.HttpStatus;

import lombok.Getter;

@Getter
public enum EventErrorCode {

EVENT_NOT_FOUND("NOT FOUND", HttpStatus.NOT_FOUND, "존재하지 않는 공연입니다."),
ALREADY_EXIST_EVENT("DUPLICATE EVENT", HttpStatus.CONFLICT, "이미 존재하는 공연입니다."),
VALIDATION_FAILED("VALIDATION FAILED", HttpStatus.BAD_REQUEST, "입력값에 대한 검증에 실패했습니다.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


private final String errorCode;
private final HttpStatus status;
private final String message;

EventErrorCode(String errorCode, HttpStatus status, String message) {
this.errorCode = errorCode;
this.status = status;
this.message = message;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.pgms.apievent.exception;

import static com.pgms.apievent.exception.EventErrorCode.*;

import java.util.List;
import java.util.Objects;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import com.pgms.coredomain.response.ErrorResponse;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@RestControllerAdvice
public class EventGlobalExceptionHandler {

@ExceptionHandler(Exception.class)
protected ResponseEntity<ErrorResponse> handleGlobalException(Exception ex) {
log.error("Internal Server Error : {}", ex.getMessage());
ErrorResponse errorResponse = new ErrorResponse("INTERNAL SERVER ERROR", ex.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse);
}

@ExceptionHandler(CustomException.class)
protected ResponseEntity<ErrorResponse> handleEventCustomException(CustomException ex) {
log.warn("Custom Exception : {}", ex.getMessage());
EventErrorCode errorCode = ex.getErrorCode();
ErrorResponse errorResponse = new ErrorResponse(errorCode.getErrorCode(), errorCode.getMessage());
return ResponseEntity.status(errorCode.getStatus()).body(errorResponse);
}

@ExceptionHandler(MethodArgumentNotValidException.class)
protected ResponseEntity<ErrorResponse> handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
BindingResult bindingResult = ex.getBindingResult();
String errorMessage = Objects.requireNonNull(bindingResult.getFieldError())
.getDefaultMessage();
log.warn("validation Failed : {}", errorMessage);

List<FieldError> fieldErrors = bindingResult.getFieldErrors();
ErrorResponse errorResponse = new ErrorResponse(VALIDATION_FAILED.getErrorCode(), errorMessage);
fieldErrors.forEach(error -> errorResponse.addValidation(error.getField(), error.getDefaultMessage()));
return ResponseEntity.status(ex.getStatusCode()).body(errorResponse);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,20 @@

import com.pgms.coredomain.domain.common.BaseEntity;

import jakarta.persistence.*;
import jakarta.persistence.Column;
import jakarta.persistence.ConstraintMode;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.FetchType;
import jakarta.persistence.ForeignKey;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.Lob;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
Expand Down Expand Up @@ -51,4 +64,38 @@ public class Event extends BaseEntity {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "event_hall_id", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
private EventHall eventHall;

@Builder
public Event(
String title,
String description,
int runningTime,
LocalDateTime startDate,
LocalDateTime endDate,
String rating,
GenreType genreType,
String thumbnail,
EventHall eventHall) {
this.title = title;
this.description = description;
this.runningTime = runningTime;
this.startDate = startDate;
this.endDate = endDate;
this.rating = rating;
this.genreType = genreType;
this.thumbnail = thumbnail;
this.eventHall = eventHall;
}

public void updateEvent(EventEdit eventEdit) {
this.title = eventEdit.title();
this.description = eventEdit.description();
this.runningTime = eventEdit.runningTime();
this.startDate = eventEdit.startDate();
this.endDate = eventEdit.endDate();
this.rating = eventEdit.rating();
this.genreType = eventEdit.genreType();
this.thumbnail = eventEdit.thumbnail();
this.eventHall = eventEdit.eventHall();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.pgms.coredomain.domain.event;

import java.time.LocalDateTime;

import lombok.Builder;

@Builder
public record EventEdit(
String title,
String description,
int runningTime,
LocalDateTime startDate,
LocalDateTime endDate,
String rating,
GenreType genreType,
String thumbnail,
EventHall eventHall
) {
}
Loading