diff --git a/src/main/java/com/tave/tavewebsite/domain/session/controller/SessionController.java b/src/main/java/com/tave/tavewebsite/domain/session/controller/SessionController.java new file mode 100644 index 0000000..2910262 --- /dev/null +++ b/src/main/java/com/tave/tavewebsite/domain/session/controller/SessionController.java @@ -0,0 +1,57 @@ +package com.tave.tavewebsite.domain.session.controller; + +import com.tave.tavewebsite.domain.session.dto.request.SessionRequestDto; +import com.tave.tavewebsite.domain.session.dto.response.SessionResponseDto; +import com.tave.tavewebsite.domain.session.service.SessionService; +import com.tave.tavewebsite.global.success.SuccessResponse; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +import static com.tave.tavewebsite.domain.session.controller.SuccessMessage.*; + +@Slf4j +@RestController +@RequestMapping("/api/v1/session") +@RequiredArgsConstructor +public class SessionController { + + private final SessionService sessionService; + + @PostMapping + public SuccessResponse registerSession(@RequestPart(name = "request") SessionRequestDto sessionRequestDto, + @RequestPart(name = "file", required = false) MultipartFile file){ + SessionResponseDto response = sessionService.saveSession(sessionRequestDto, file); + + return new SuccessResponse<>(response, SESSION_SUCCESS_REGISTER.getMessage()); + } + + @GetMapping("/{generation}/{page}/{size}") + public SuccessResponse> getSession(@PathVariable String generation, + @PathVariable int page, + @PathVariable int size){ + List response = sessionService.findSessionByGeneration(generation, page, size); + return new SuccessResponse<>(response, SESSION_SUCCESS_REGISTER.getMessage()); + } + + @DeleteMapping("/{sessionId}") + public SuccessResponse deleteSession(@PathVariable Long sessionId){ + sessionService.deleteSession(sessionId); + return new SuccessResponse<>(null, SESSION_DELETE.getMessage()); + } + + @PatchMapping("/{sessionId}") + public SuccessResponse updateSession(@PathVariable Long sessionId, + @RequestPart(name = "request") SessionRequestDto sessionRequestDto, + @RequestPart(name = "file", required = false) MultipartFile file){ + sessionService.updateSession(sessionId, sessionRequestDto, file); + return new SuccessResponse<>(null, SESSION_UPDATE.getMessage()); + } + + + + +} diff --git a/src/main/java/com/tave/tavewebsite/domain/session/controller/SuccessMessage.java b/src/main/java/com/tave/tavewebsite/domain/session/controller/SuccessMessage.java new file mode 100644 index 0000000..04760d6 --- /dev/null +++ b/src/main/java/com/tave/tavewebsite/domain/session/controller/SuccessMessage.java @@ -0,0 +1,16 @@ +package com.tave.tavewebsite.domain.session.controller; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum SuccessMessage { + + SESSION_SUCCESS_REGISTER("새로운 정규 세션 정보를 기입했습니다."), + SESSION_SUCCESS_GET("성공적으로 세션을 조회했습니다."), + SESSION_DELETE("성공적으로 세션을 삭제했습니다."), + SESSION_UPDATE("성공적으로 세션을 수정했습니다."); + + private final String message; +} diff --git a/src/main/java/com/tave/tavewebsite/domain/session/dto/request/SessionRequestDto.java b/src/main/java/com/tave/tavewebsite/domain/session/dto/request/SessionRequestDto.java new file mode 100644 index 0000000..94b6ee5 --- /dev/null +++ b/src/main/java/com/tave/tavewebsite/domain/session/dto/request/SessionRequestDto.java @@ -0,0 +1,13 @@ +package com.tave.tavewebsite.domain.session.dto.request; + +import com.tave.tavewebsite.domain.session.entity.Session; + +public record SessionRequestDto( + + String title, + String description, + String generation, + boolean isPublic + +) { +} diff --git a/src/main/java/com/tave/tavewebsite/domain/session/dto/response/SessionResponseDto.java b/src/main/java/com/tave/tavewebsite/domain/session/dto/response/SessionResponseDto.java new file mode 100644 index 0000000..669606b --- /dev/null +++ b/src/main/java/com/tave/tavewebsite/domain/session/dto/response/SessionResponseDto.java @@ -0,0 +1,24 @@ +package com.tave.tavewebsite.domain.session.dto.response; + +import com.tave.tavewebsite.domain.session.entity.Session; + +public record SessionResponseDto( + Long sessionId, + String title, + String description, + String generation, + boolean isPublic, + String imgUrl + +) { + public static SessionResponseDto from(Session session) { + return new SessionResponseDto( + session.getId(), + session.getTitle(), + session.getDescription(), + session.getGeneration(), + session.isPublic(), + session.getImgUrl() + ); + } +} diff --git a/src/main/java/com/tave/tavewebsite/domain/session/entity/Session.java b/src/main/java/com/tave/tavewebsite/domain/session/entity/Session.java index 0659679..8326171 100644 --- a/src/main/java/com/tave/tavewebsite/domain/session/entity/Session.java +++ b/src/main/java/com/tave/tavewebsite/domain/session/entity/Session.java @@ -1,5 +1,6 @@ package com.tave.tavewebsite.domain.session.entity; +import com.tave.tavewebsite.domain.session.dto.request.SessionRequestDto; import com.tave.tavewebsite.global.common.BaseEntity; import jakarta.persistence.*; import jakarta.validation.constraints.NotNull; @@ -31,6 +32,14 @@ public class Session extends BaseEntity { @Column(nullable = false) private String description; + /* + * 동아리 지원 관리자 페이지에서 사용 시 "세션 진행 날짜" 필드를 추가하는 게 좋다고 생각. + * */ + + @Size(min = 1, max = 5) + @Column(length = 5) + private String generation; + @NotNull @Column(nullable = false) private boolean isPublic; @@ -41,10 +50,32 @@ public class Session extends BaseEntity { private String imgUrl; @Builder - public Session(String title, String description, boolean isPublic, String imgUrl) { + public Session(String title, String description, String generation,boolean isPublic, String imgUrl) { this.title = title; this.description = description; + this.generation = generation; this.isPublic = isPublic; this.imgUrl = imgUrl; } + + public static Session of(SessionRequestDto sessionRequestDto, java.net.URL imgUrl) { + return Session.builder() + .title(sessionRequestDto.title()) + .description(sessionRequestDto.description()) + .generation(sessionRequestDto.generation()) + .isPublic(sessionRequestDto.isPublic()) + .imgUrl(imgUrl.toString()) + .build(); + } + + public void updateField(SessionRequestDto sessionRequestDto) { + this.title = sessionRequestDto.title(); + this.description = sessionRequestDto.description(); + this.generation = sessionRequestDto.generation(); + this.isPublic = sessionRequestDto.isPublic(); + } + + public void updateImgUrl( java.net.URL imgUrl) { + this.imgUrl = imgUrl.toString(); + } } diff --git a/src/main/java/com/tave/tavewebsite/domain/session/exception/ErrorMessage.java b/src/main/java/com/tave/tavewebsite/domain/session/exception/ErrorMessage.java new file mode 100644 index 0000000..e8a0a54 --- /dev/null +++ b/src/main/java/com/tave/tavewebsite/domain/session/exception/ErrorMessage.java @@ -0,0 +1,15 @@ +package com.tave.tavewebsite.domain.session.exception; + +import jakarta.annotation.security.DenyAll; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum ErrorMessage { + + SESSION_NOT_FOUND(400, "세션을 찾을 수 없습니다."); + + private final int code; + private final String message; +} diff --git a/src/main/java/com/tave/tavewebsite/domain/session/exception/SessionNotFoundException.java b/src/main/java/com/tave/tavewebsite/domain/session/exception/SessionNotFoundException.java new file mode 100644 index 0000000..7f75a73 --- /dev/null +++ b/src/main/java/com/tave/tavewebsite/domain/session/exception/SessionNotFoundException.java @@ -0,0 +1,11 @@ +package com.tave.tavewebsite.domain.session.exception; + +import com.tave.tavewebsite.global.exception.BaseErrorException; + +import static com.tave.tavewebsite.domain.session.exception.ErrorMessage.SESSION_NOT_FOUND; + +public class SessionNotFoundException extends BaseErrorException { + public SessionNotFoundException() { + super(SESSION_NOT_FOUND.getCode(), SESSION_NOT_FOUND.getMessage()); + } +} diff --git a/src/main/java/com/tave/tavewebsite/domain/session/repository/SessionRepository.java b/src/main/java/com/tave/tavewebsite/domain/session/repository/SessionRepository.java new file mode 100644 index 0000000..520503d --- /dev/null +++ b/src/main/java/com/tave/tavewebsite/domain/session/repository/SessionRepository.java @@ -0,0 +1,14 @@ +package com.tave.tavewebsite.domain.session.repository; + +import com.tave.tavewebsite.domain.session.entity.Session; +import org.springframework.data.domain.Page; +import org.springframework.data.jpa.repository.JpaRepository; + +import org.springframework.data.domain.Pageable; +import java.util.List; + +public interface SessionRepository extends JpaRepository { + + Page findByGenerationAndIsPublic(String generation, boolean isPublic, Pageable pageable); + +} diff --git a/src/main/java/com/tave/tavewebsite/domain/session/service/SessionService.java b/src/main/java/com/tave/tavewebsite/domain/session/service/SessionService.java new file mode 100644 index 0000000..332cdc3 --- /dev/null +++ b/src/main/java/com/tave/tavewebsite/domain/session/service/SessionService.java @@ -0,0 +1,75 @@ +package com.tave.tavewebsite.domain.session.service; + +import com.tave.tavewebsite.domain.session.entity.Session; +import com.tave.tavewebsite.domain.session.dto.request.SessionRequestDto; +import com.tave.tavewebsite.domain.session.dto.response.SessionResponseDto; +import com.tave.tavewebsite.domain.session.exception.SessionNotFoundException; +import com.tave.tavewebsite.domain.session.repository.SessionRepository; +import com.tave.tavewebsite.global.s3.service.S3Service; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.domain.PageRequest; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import java.net.URL; +import java.util.List; + +@Slf4j +@Service +@RequiredArgsConstructor +public class SessionService { + + private final SessionRepository sessionRepository; + private final S3Service s3Service; + + public SessionResponseDto saveSession(SessionRequestDto sessionRequestDto, MultipartFile file) { + URL savedImageUrl = s3Service.uploadImages(file); + Session savedSession = sessionRepository.save(Session.of(sessionRequestDto, savedImageUrl)); + return SessionResponseDto.from(savedSession); + } + + public List findSessionByGeneration(String generation, int page, int size) { + return sessionRepository.findByGenerationAndIsPublic(generation, true, PageRequest.of(page- 1, size)) + .getContent() + .stream() + .map(SessionResponseDto::from) + .toList(); + } + + public void deleteSession(Long sessionId) { + Session findSession = findBySessionId(sessionId); + sessionRepository.delete(findSession); + } + + @Transactional + public void updateSession(Long sessionId, SessionRequestDto sessionRequestDto, MultipartFile file){ + Session findSession = findBySessionId(sessionId); + updateSessionField(findSession,sessionRequestDto); + updateSessionImgUrl(findSession, file); + } + + /* + * 리팩토링 + * */ + + private Session findBySessionId(Long sessionId) { + return sessionRepository.findById(sessionId) + .orElseThrow(SessionNotFoundException::new); + } + + private void updateSessionField(Session findSession, SessionRequestDto sessionRequestDto) { + log.info(findSession.getTitle(), findSession.getDescription()); + findSession.updateField(sessionRequestDto); + log.info(findSession.getTitle(), findSession.getDescription()); + } + + private void updateSessionImgUrl( Session findSession, MultipartFile file) { + if(file != null){ + URL savedImageUrl = s3Service.uploadImages(file); + findSession.updateImgUrl(savedImageUrl); + } + } + +}