From 045a90ad07e719a0e461920993e4c6e1f9e86306 Mon Sep 17 00:00:00 2001 From: kmebin Date: Sat, 9 Sep 2023 16:10:41 +0900 Subject: [PATCH 01/10] =?UTF-8?q?[JT-40]=20feat:=20=EC=9B=B9=ED=88=B0=20?= =?UTF-8?q?=EB=AA=A8=EB=93=88=20=EC=BB=A4=EC=8A=A4=ED=85=80=20Exception=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../webtoon/application/WebtoonService.java | 12 ++-- .../webtoon/entity/DayOfWeekWebtoon.java | 5 +- .../devtoon/jtoon/webtoon/entity/Episode.java | 12 ++-- .../jtoon/webtoon/entity/GenreWebtoon.java | 5 +- .../devtoon/jtoon/webtoon/entity/Webtoon.java | 12 ++-- .../jtoon/webtoon/entity/enums/Genre.java | 3 +- .../jtoon/error/model/ErrorStatus.java | 62 ++++++++++++------- 7 files changed, 69 insertions(+), 42 deletions(-) diff --git a/module-domain/src/main/java/com/devtoon/jtoon/webtoon/application/WebtoonService.java b/module-domain/src/main/java/com/devtoon/jtoon/webtoon/application/WebtoonService.java index c780830e..b587381a 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/webtoon/application/WebtoonService.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/webtoon/application/WebtoonService.java @@ -1,6 +1,7 @@ package com.devtoon.jtoon.webtoon.application; import static com.devtoon.jtoon.common.ImageType.*; +import static com.devtoon.jtoon.error.model.ErrorStatus.*; import static java.util.stream.Collectors.*; import java.util.List; @@ -12,6 +13,9 @@ import com.devtoon.jtoon.application.S3Service; import com.devtoon.jtoon.common.FileName; +import com.devtoon.jtoon.error.exception.DuplicatedException; +import com.devtoon.jtoon.error.exception.InvalidRequestException; +import com.devtoon.jtoon.error.exception.NotFoundException; import com.devtoon.jtoon.global.util.CustomPageRequest; import com.devtoon.jtoon.member.entity.Member; import com.devtoon.jtoon.member.repository.MemberRepository; @@ -51,7 +55,7 @@ public class WebtoonService { private final EpisodeSearchRepository episodeSearchRepository; private final MemberRepository memberRepository; private final S3Service s3Service; - + @Transactional public void createWebtoon(Member member, MultipartFile thumbnailImage, CreateWebtoonReq request) { validateDuplicateTitle(request.title()); @@ -126,7 +130,7 @@ public EpisodeRes getDetailEpisode(Long episodeId, GetEpisodeReq request) { private Webtoon getWebtoonById(Long webtoonId) { return webtoonRepository.findById(webtoonId) - .orElseThrow(() -> new RuntimeException("존재하는 웹툰이 아닙니다.")); + .orElseThrow(() -> new NotFoundException(WEBTOON_NOT_FOUND)); } private List getDayOfWeeks(Long webtoonId) { @@ -145,13 +149,13 @@ private List getGenres(Long webtoonId) { private void validateDuplicateTitle(String title) { if (webtoonRepository.existsByTitle(title)) { - throw new RuntimeException("이미 존재하는 웹툰 제목입니다."); + throw new DuplicatedException(WEBTOON_TITLE_DUPLICATED); } } private void validateAuthorOfWebtoon(Member member, Webtoon webtoon) { if (!webtoon.isAuthor(member.getId())) { - throw new RuntimeException("해당 웹툰의 작가가 아닙니다."); + throw new InvalidRequestException(WEBTOON_NOT_AUTHOR); } } } diff --git a/module-domain/src/main/java/com/devtoon/jtoon/webtoon/entity/DayOfWeekWebtoon.java b/module-domain/src/main/java/com/devtoon/jtoon/webtoon/entity/DayOfWeekWebtoon.java index 68a29328..91c367c7 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/webtoon/entity/DayOfWeekWebtoon.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/webtoon/entity/DayOfWeekWebtoon.java @@ -1,5 +1,6 @@ package com.devtoon.jtoon.webtoon.entity; +import static com.devtoon.jtoon.error.model.ErrorStatus.*; import static java.util.Objects.*; import com.devtoon.jtoon.global.common.BaseTimeEntity; @@ -42,7 +43,7 @@ public class DayOfWeekWebtoon extends BaseTimeEntity { @Builder private DayOfWeekWebtoon(DayOfWeek dayOfWeek, Webtoon webtoon) { - this.dayOfWeek = requireNonNull(dayOfWeek, "dayOfWeek is null"); - this.webtoon = requireNonNull(webtoon, "webtoon is null"); + this.dayOfWeek = requireNonNull(dayOfWeek, WEBTOON_DAY_OF_WEEK_IS_NULL.getMessage()); + this.webtoon = requireNonNull(webtoon, WEBTOON_IS_NULL.getMessage()); } } diff --git a/module-domain/src/main/java/com/devtoon/jtoon/webtoon/entity/Episode.java b/module-domain/src/main/java/com/devtoon/jtoon/webtoon/entity/Episode.java index a7685dfd..df9dd801 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/webtoon/entity/Episode.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/webtoon/entity/Episode.java @@ -1,11 +1,13 @@ package com.devtoon.jtoon.webtoon.entity; +import static com.devtoon.jtoon.error.model.ErrorStatus.*; import static java.util.Objects.*; import java.time.LocalDateTime; import org.hibernate.annotations.ColumnDefault; +import com.devtoon.jtoon.error.exception.InvalidRequestException; import com.devtoon.jtoon.global.common.BaseTimeEntity; import jakarta.persistence.Column; @@ -69,15 +71,15 @@ private Episode( Webtoon webtoon ) { if (no <= 0) { - throw new RuntimeException("number is zero or negative number"); + throw new InvalidRequestException(EPISODE_NUMBER_POSITIVE); } this.no = no; - this.title = requireNonNull(title, "title is null"); - this.mainUrl = requireNonNull(mainUrl, "mainUrl is null"); + this.title = requireNonNull(title, EPISODE_TITLE_IS_NULL.getMessage()); + this.mainUrl = requireNonNull(mainUrl, EPISODE_MAIN_URL_IS_NULL.getMessage()); this.thumbnailUrl = thumbnailUrl; this.hasComment = hasComment; - this.openedAt = requireNonNull(openedAt, "openedAt is null"); - this.webtoon = requireNonNull(webtoon, "webtoon is null"); + this.openedAt = requireNonNull(openedAt, EPISODE_OPENED_AT_IS_NULL.getMessage()); + this.webtoon = requireNonNull(webtoon, WEBTOON_IS_NULL.getMessage()); } } diff --git a/module-domain/src/main/java/com/devtoon/jtoon/webtoon/entity/GenreWebtoon.java b/module-domain/src/main/java/com/devtoon/jtoon/webtoon/entity/GenreWebtoon.java index 88c84279..c34c3e87 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/webtoon/entity/GenreWebtoon.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/webtoon/entity/GenreWebtoon.java @@ -1,5 +1,6 @@ package com.devtoon.jtoon.webtoon.entity; +import static com.devtoon.jtoon.error.model.ErrorStatus.*; import static java.util.Objects.*; import com.devtoon.jtoon.global.common.BaseTimeEntity; @@ -42,7 +43,7 @@ public class GenreWebtoon extends BaseTimeEntity { @Builder private GenreWebtoon(Genre genre, Webtoon webtoon) { - this.genre = requireNonNull(genre, "genre is null"); - this.webtoon = requireNonNull(webtoon, "webtoon is null"); + this.genre = requireNonNull(genre, WEBTOON_GENRE_IS_NULL.getMessage()); + this.webtoon = requireNonNull(webtoon, WEBTOON_IS_NULL.getMessage()); } } diff --git a/module-domain/src/main/java/com/devtoon/jtoon/webtoon/entity/Webtoon.java b/module-domain/src/main/java/com/devtoon/jtoon/webtoon/entity/Webtoon.java index ca52df0e..1a4fbb42 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/webtoon/entity/Webtoon.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/webtoon/entity/Webtoon.java @@ -1,9 +1,11 @@ package com.devtoon.jtoon.webtoon.entity; +import static com.devtoon.jtoon.error.model.ErrorStatus.*; import static java.util.Objects.*; import org.hibernate.annotations.ColumnDefault; +import com.devtoon.jtoon.error.exception.InvalidRequestException; import com.devtoon.jtoon.global.common.BaseTimeEntity; import com.devtoon.jtoon.member.entity.Member; import com.devtoon.jtoon.webtoon.entity.enums.AgeLimit; @@ -66,15 +68,15 @@ private Webtoon( Member author ) { if (cookieCount < 0) { - throw new RuntimeException("cookieCount is negative number"); + throw new InvalidRequestException(WEBTOON_COOKIE_COUNT_NOT_NEGATIVE); } - this.title = requireNonNull(title, "title is null"); - this.description = requireNonNull(description, "description is null"); - this.ageLimit = requireNonNull(ageLimit, "ageLimit is null"); + this.title = requireNonNull(title, WEBTOON_TITLE_IS_NULL.getMessage()); + this.description = requireNonNull(description, WEBTOON_DESCRIPTION_IS_NULL.getMessage()); + this.ageLimit = requireNonNull(ageLimit, WEBTOON_AGE_LIMIT_IS_NULL.getMessage()); this.thumbnailUrl = thumbnailUrl; this.cookieCount = cookieCount; - this.author = requireNonNull(author, "author is null"); + this.author = requireNonNull(author, WEBTOON_AUTHOR_IS_NULL.getMessage()); } public boolean isAuthor(Long memberId) { diff --git a/module-domain/src/main/java/com/devtoon/jtoon/webtoon/entity/enums/Genre.java b/module-domain/src/main/java/com/devtoon/jtoon/webtoon/entity/enums/Genre.java index f6d18ccd..a7a71c11 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/webtoon/entity/enums/Genre.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/webtoon/entity/enums/Genre.java @@ -17,7 +17,8 @@ public enum Genre { HISTORICAL("무협/사극"), DRAMA("드라마"), SENSIBILITY("감성"), - SPORTS("스포츠"); + SPORTS("스포츠"), + ; private final String text; } diff --git a/module-internal/src/main/java/com/devtoon/jtoon/error/model/ErrorStatus.java b/module-internal/src/main/java/com/devtoon/jtoon/error/model/ErrorStatus.java index 15901d2b..5b22a401 100644 --- a/module-internal/src/main/java/com/devtoon/jtoon/error/model/ErrorStatus.java +++ b/module-internal/src/main/java/com/devtoon/jtoon/error/model/ErrorStatus.java @@ -8,30 +8,46 @@ @RequiredArgsConstructor(access = AccessLevel.PRIVATE) public enum ErrorStatus { - COMMON_DTO_FIELD_INVALID_FORMAT("올바른 요청 정보가 아닙니다."), + COMMON_DTO_FIELD_INVALID_FORMAT("올바른 요청 정보가 아닙니다."), - MEMBER_EMAIL_INVALID_FORMAT("올바른 이메일 형식이 아닙니다."), - MEMBER_PASSWORD_INVALID_FORMAT("올바른 비밀번호형식이 아닙니다."), - MEMBER_NAME_INVALID_FORMAT("올바른 이름이 아닙니다."), - MEMBER_NICKNAME_INVALID_FORMAT("올바른 닉네임이 아닙니다."), - MEMBER_GENDER_INVALID_FORMAT("올바른 성이 아닙니다."), - MEMBER_PHONE_INVALID_FORMAT("올바른 전화번호 형식이 아닙니다."), - MEMBER_ROLE_INVALID_FORMAT("올바른 회원 역할이 아닙니다"), - MEMBER_LOGIN_TYPE_INVALID_FORMAT("올바른 로그인 타입이 아닙니다."), - MEMBER_MESSAGE_SEND_FAILED("이메일 인증 메세지 전송 실패"), - MEMBER_EMAIL_CONFLICT("Email 중복"), + MEMBER_EMAIL_INVALID_FORMAT("올바른 이메일 형식이 아닙니다."), + MEMBER_PASSWORD_INVALID_FORMAT("올바른 비밀번호형식이 아닙니다."), + MEMBER_NAME_INVALID_FORMAT("올바른 이름이 아닙니다."), + MEMBER_NICKNAME_INVALID_FORMAT("올바른 닉네임이 아닙니다."), + MEMBER_GENDER_INVALID_FORMAT("올바른 성이 아닙니다."), + MEMBER_PHONE_INVALID_FORMAT("올바른 전화번호 형식이 아닙니다."), + MEMBER_ROLE_INVALID_FORMAT("올바른 회원 역할이 아닙니다"), + MEMBER_LOGIN_TYPE_INVALID_FORMAT("올바른 로그인 타입이 아닙니다."), + MEMBER_MESSAGE_SEND_FAILED("이메일 인증 메세지 전송 실패"), + MEMBER_EMAIL_CONFLICT("Email 중복"), - PAYMENT_IMP_UID_IS_NULL("결제 고유번호 값이 NULL 입니다."), - PAYMENT_MERCHANT_UID_IS_NULL("주문번호 값이 NULL 입니다."), - PAYMENT_PAY_METHOD_IS_NULL("결제 방법 값이 NULL 입니다."), - PAYMENT_COOKIE_ITEM_IS_NULL("쿠키 아이템 값이 NULL 입니다."), - PAYMENT_AMOUNT_IS_NULL("결제 금액 값이 NULL 입니다."), - PAYMENT_MEMBER_IS_NULL("결제 사용자 값이 NULL 입니다."), - PAYMENT_IMP_UID_DUPLICATED("결제 고유번호가 중복되었습니다."), - PAYMENT_MERCHANT_UID_DUPLICATED("주문 번호가 중복되었습니다."), - PAYMENT_AMOUNT_INVALID("잘못된 결제 금액입니다."), - PAYMENT_COOKIE_NOT_FOUND("등록되지 않은 쿠키 상품입니다."), - ; + PAYMENT_IMP_UID_IS_NULL("결제 고유번호 값이 NULL 입니다."), + PAYMENT_MERCHANT_UID_IS_NULL("주문번호 값이 NULL 입니다."), + PAYMENT_PAY_METHOD_IS_NULL("결제 방법 값이 NULL 입니다."), + PAYMENT_COOKIE_ITEM_IS_NULL("쿠키 아이템 값이 NULL 입니다."), + PAYMENT_AMOUNT_IS_NULL("결제 금액 값이 NULL 입니다."), + PAYMENT_MEMBER_IS_NULL("결제 사용자 값이 NULL 입니다."), + PAYMENT_IMP_UID_DUPLICATED("결제 고유번호가 중복되었습니다."), + PAYMENT_MERCHANT_UID_DUPLICATED("주문 번호가 중복되었습니다."), + PAYMENT_AMOUNT_INVALID("잘못된 결제 금액입니다."), + PAYMENT_COOKIE_NOT_FOUND("등록되지 않은 쿠키 상품입니다."), - private final String message; + WEBTOON_TITLE_DUPLICATED("이미 존재하는 웹툰 제목입니다."), + WEBTOON_NOT_FOUND("존재하지 않는 웹툰입니다."), + WEBTOON_NOT_AUTHOR("해당 웹툰의 작가가 아닙니다."), + WEBTOON_IS_NULL("웹툰 값이 NULL 입니다."), + WEBTOON_TITLE_IS_NULL("웹툰 제목 값이 NULL 입니다."), + WEBTOON_DESCRIPTION_IS_NULL("웹툰 설명 값이 NULL 입니다."), + WEBTOON_AGE_LIMIT_IS_NULL("웹툰 연령 값이 NULL 입니다."), + WEBTOON_AUTHOR_IS_NULL("웹툰 작가 값이 NULL 입니다."), + WEBTOON_DAY_OF_WEEK_IS_NULL("웹툰 요일 값이 NULL 입니다."), + WEBTOON_GENRE_IS_NULL("웹툰 장르 값이 NULL 입니다."), + WEBTOON_COOKIE_COUNT_NOT_NEGATIVE("쿠키 개수는 음수일 수 없습니다."), + EPISODE_NUMBER_POSITIVE("회차 번호는 양수여야 합니다."), + EPISODE_TITLE_IS_NULL("회차 제목 값이 NULL 입니다."), + EPISODE_MAIN_URL_IS_NULL("회차 메인 이미지 URL 값이 NULL 입니다."), + EPISODE_OPENED_AT_IS_NULL("회차 공개일자 값이 NULL 입니다."), + ; + + private final String message; } From 5ae0862ef3c5b71a818475608b6b885161b01f58 Mon Sep 17 00:00:00 2001 From: kmebin Date: Sat, 9 Sep 2023 16:12:51 +0900 Subject: [PATCH 02/10] =?UTF-8?q?[JT-40]=20feat:=20S3=20=EB=AA=A8=EB=93=88?= =?UTF-8?q?=20=EC=BB=A4=EC=8A=A4=ED=85=80=20Exception=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 1 + .../src/main/java/com/devtoon/jtoon/util/S3Uploader.java | 6 +++++- .../java/com/devtoon/jtoon/error/model/ErrorStatus.java | 2 ++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index a934e3bd..ff7d7e56 100644 --- a/build.gradle +++ b/build.gradle @@ -62,6 +62,7 @@ project(':module-domain-s3') { bootJar.enabled = false dependencies { + implementation project(':module-internal') implementation project(':module-core') } } diff --git a/module-domain-s3/src/main/java/com/devtoon/jtoon/util/S3Uploader.java b/module-domain-s3/src/main/java/com/devtoon/jtoon/util/S3Uploader.java index 725162ff..426424f0 100644 --- a/module-domain-s3/src/main/java/com/devtoon/jtoon/util/S3Uploader.java +++ b/module-domain-s3/src/main/java/com/devtoon/jtoon/util/S3Uploader.java @@ -1,11 +1,15 @@ package com.devtoon.jtoon.util; +import static com.devtoon.jtoon.error.model.ErrorStatus.*; + import java.io.IOException; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile; +import com.devtoon.jtoon.error.exception.InvalidRequestException; + import io.awspring.cloud.s3.ObjectMetadata; import io.awspring.cloud.s3.S3Template; import lombok.RequiredArgsConstructor; @@ -28,7 +32,7 @@ public void upload(String key, MultipartFile file) { ObjectMetadata.builder().contentType("image/png").build() ); } catch (IOException e) { - throw new RuntimeException(e); + throw new InvalidRequestException(S3_UPLOAD_FAIL); } } diff --git a/module-internal/src/main/java/com/devtoon/jtoon/error/model/ErrorStatus.java b/module-internal/src/main/java/com/devtoon/jtoon/error/model/ErrorStatus.java index 5b22a401..e665356f 100644 --- a/module-internal/src/main/java/com/devtoon/jtoon/error/model/ErrorStatus.java +++ b/module-internal/src/main/java/com/devtoon/jtoon/error/model/ErrorStatus.java @@ -47,6 +47,8 @@ public enum ErrorStatus { EPISODE_TITLE_IS_NULL("회차 제목 값이 NULL 입니다."), EPISODE_MAIN_URL_IS_NULL("회차 메인 이미지 URL 값이 NULL 입니다."), EPISODE_OPENED_AT_IS_NULL("회차 공개일자 값이 NULL 입니다."), + + S3_UPLOAD_FAIL("S3 이미지 업로드에 실패했습니다."), ; private final String message; From ed540659a709a801ed13050f424673cadc9b2a5a Mon Sep 17 00:00:00 2001 From: kmebin Date: Sat, 9 Sep 2023 16:41:06 +0900 Subject: [PATCH 03/10] =?UTF-8?q?[JT-40]=20refactor:=20=ED=9A=8C=EC=B0=A8?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=20=EC=8B=9C=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=9A=94=EC=B2=AD=20=EA=B0=92=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - episodeId 값으로 조회할 수 있도록 수정 --- .../jtoon/webtoon/presentation/WebtoonController.java | 8 +++----- .../jtoon/webtoon/application/WebtoonService.java | 10 +++++++--- .../jtoon/webtoon/repository/EpisodeRepository.java | 2 -- .../devtoon/jtoon/webtoon/request/GetEpisodeReq.java | 8 -------- .../com/devtoon/jtoon/error/model/ErrorStatus.java | 1 + 5 files changed, 11 insertions(+), 18 deletions(-) delete mode 100644 module-domain/src/main/java/com/devtoon/jtoon/webtoon/request/GetEpisodeReq.java diff --git a/module-application/src/main/java/com/devtoon/jtoon/webtoon/presentation/WebtoonController.java b/module-application/src/main/java/com/devtoon/jtoon/webtoon/presentation/WebtoonController.java index 1dc7dbb1..85ca59f3 100644 --- a/module-application/src/main/java/com/devtoon/jtoon/webtoon/presentation/WebtoonController.java +++ b/module-application/src/main/java/com/devtoon/jtoon/webtoon/presentation/WebtoonController.java @@ -21,7 +21,6 @@ import com.devtoon.jtoon.webtoon.entity.enums.DayOfWeek; import com.devtoon.jtoon.webtoon.request.CreateEpisodeReq; import com.devtoon.jtoon.webtoon.request.CreateWebtoonReq; -import com.devtoon.jtoon.webtoon.request.GetEpisodeReq; import com.devtoon.jtoon.webtoon.request.GetWebtoonsReq; import com.devtoon.jtoon.webtoon.response.EpisodeRes; import com.devtoon.jtoon.webtoon.response.EpisodesRes; @@ -74,9 +73,8 @@ public List getEpisodes(@RequestParam Long webtoonId, CustomPageReq return webtoonService.getEpisodes(webtoonId, request); } - @GetMapping("/detail") - @ResponseStatus(HttpStatus.OK) - public EpisodeRes detailEpisode(@RequestParam Long episodeId, @RequestParam GetEpisodeReq request) { - return webtoonService.getDetailEpisode(episodeId, request); + @GetMapping("/episodes/{episodeId}") + public EpisodeRes getEpisode(@PathVariable Long episodeId) { + return webtoonService.getEpisode(episodeId); } } diff --git a/module-domain/src/main/java/com/devtoon/jtoon/webtoon/application/WebtoonService.java b/module-domain/src/main/java/com/devtoon/jtoon/webtoon/application/WebtoonService.java index b587381a..845d1a18 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/webtoon/application/WebtoonService.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/webtoon/application/WebtoonService.java @@ -32,7 +32,6 @@ import com.devtoon.jtoon.webtoon.repository.WebtoonSearchRepository; import com.devtoon.jtoon.webtoon.request.CreateEpisodeReq; import com.devtoon.jtoon.webtoon.request.CreateWebtoonReq; -import com.devtoon.jtoon.webtoon.request.GetEpisodeReq; import com.devtoon.jtoon.webtoon.request.GetWebtoonsReq; import com.devtoon.jtoon.webtoon.response.EpisodeRes; import com.devtoon.jtoon.webtoon.response.EpisodesRes; @@ -123,8 +122,8 @@ public List getEpisodes(Long webtoonId, CustomPageRequest request) .toList(); } - public EpisodeRes getDetailEpisode(Long episodeId, GetEpisodeReq request) { - Episode episode = episodeRepository.findByIdAndNo(episodeId, request.no()); + public EpisodeRes getEpisode(Long episodeId) { + Episode episode = getEpisodeById(episodeId); return EpisodeRes.from(episode); } @@ -133,6 +132,11 @@ private Webtoon getWebtoonById(Long webtoonId) { .orElseThrow(() -> new NotFoundException(WEBTOON_NOT_FOUND)); } + private Episode getEpisodeById(Long episodeId) { + return episodeRepository.findById(episodeId) + .orElseThrow(() -> new NotFoundException(EPISODE_NOT_FOUND)); + } + private List getDayOfWeeks(Long webtoonId) { return dayOfWeekWebtoonRepository.findById(webtoonId) .stream() diff --git a/module-domain/src/main/java/com/devtoon/jtoon/webtoon/repository/EpisodeRepository.java b/module-domain/src/main/java/com/devtoon/jtoon/webtoon/repository/EpisodeRepository.java index f73de940..1da04916 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/webtoon/repository/EpisodeRepository.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/webtoon/repository/EpisodeRepository.java @@ -5,6 +5,4 @@ import com.devtoon.jtoon.webtoon.entity.Episode; public interface EpisodeRepository extends JpaRepository { - - Episode findByIdAndNo(Long id, int no); } diff --git a/module-domain/src/main/java/com/devtoon/jtoon/webtoon/request/GetEpisodeReq.java b/module-domain/src/main/java/com/devtoon/jtoon/webtoon/request/GetEpisodeReq.java deleted file mode 100644 index 749c0d98..00000000 --- a/module-domain/src/main/java/com/devtoon/jtoon/webtoon/request/GetEpisodeReq.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.devtoon.jtoon.webtoon.request; - -import jakarta.validation.constraints.Min; - -public record GetEpisodeReq( - @Min(1) int no -) { -} diff --git a/module-internal/src/main/java/com/devtoon/jtoon/error/model/ErrorStatus.java b/module-internal/src/main/java/com/devtoon/jtoon/error/model/ErrorStatus.java index e665356f..7ed8ba3a 100644 --- a/module-internal/src/main/java/com/devtoon/jtoon/error/model/ErrorStatus.java +++ b/module-internal/src/main/java/com/devtoon/jtoon/error/model/ErrorStatus.java @@ -43,6 +43,7 @@ public enum ErrorStatus { WEBTOON_DAY_OF_WEEK_IS_NULL("웹툰 요일 값이 NULL 입니다."), WEBTOON_GENRE_IS_NULL("웹툰 장르 값이 NULL 입니다."), WEBTOON_COOKIE_COUNT_NOT_NEGATIVE("쿠키 개수는 음수일 수 없습니다."), + EPISODE_NOT_FOUND("존재하지 않는 회차입니다."), EPISODE_NUMBER_POSITIVE("회차 번호는 양수여야 합니다."), EPISODE_TITLE_IS_NULL("회차 제목 값이 NULL 입니다."), EPISODE_MAIN_URL_IS_NULL("회차 메인 이미지 URL 값이 NULL 입니다."), From d3cf1c8384f610cdd47a0d1cd2a09e620f387cad Mon Sep 17 00:00:00 2001 From: kmebin Date: Sat, 9 Sep 2023 16:53:03 +0900 Subject: [PATCH 04/10] =?UTF-8?q?[JT-40]=20feat:=20Exception=20=ED=95=B8?= =?UTF-8?q?=EB=93=A4=EB=9F=AC=EC=97=90=20=EC=9D=91=EB=8B=B5=20Status=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../error/handler/GlobalExceptionHandler.java | 130 ++++++++++-------- 1 file changed, 72 insertions(+), 58 deletions(-) diff --git a/module-internal/src/main/java/com/devtoon/jtoon/error/handler/GlobalExceptionHandler.java b/module-internal/src/main/java/com/devtoon/jtoon/error/handler/GlobalExceptionHandler.java index ed25966a..3a2407aa 100644 --- a/module-internal/src/main/java/com/devtoon/jtoon/error/handler/GlobalExceptionHandler.java +++ b/module-internal/src/main/java/com/devtoon/jtoon/error/handler/GlobalExceptionHandler.java @@ -1,71 +1,85 @@ package com.devtoon.jtoon.error.handler; -import com.devtoon.jtoon.error.exception.*; -import com.devtoon.jtoon.error.model.ErrorResponse; -import com.devtoon.jtoon.error.model.ErrorStatus; +import java.util.List; + +import org.springframework.http.HttpStatus; import org.springframework.validation.BindException; import org.springframework.validation.FieldError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestControllerAdvice; -import java.util.List; +import com.devtoon.jtoon.error.exception.DuplicatedException; +import com.devtoon.jtoon.error.exception.ForbiddenException; +import com.devtoon.jtoon.error.exception.InvalidRequestException; +import com.devtoon.jtoon.error.exception.NotFoundException; +import com.devtoon.jtoon.error.exception.UnauthorizedException; +import com.devtoon.jtoon.error.model.ErrorResponse; +import com.devtoon.jtoon.error.model.ErrorStatus; @RestControllerAdvice public class GlobalExceptionHandler { - @ExceptionHandler(MethodArgumentNotValidException.class) - public ErrorResponse handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { - final ErrorStatus error = ErrorStatus.COMMON_DTO_FIELD_INVALID_FORMAT; - - return makeResponseErrorFormat(error, e); - } - - @ExceptionHandler(NullPointerException.class) - public ErrorResponse handleNullPointerException(NullPointerException e) { - return makeResponseErrorFormat(e.getMessage()); - } - - @ExceptionHandler(NotFoundException.class) - protected ErrorResponse handleNotFoundException(NotFoundException e) { - return makeResponseErrorFormat(e.getErrorStatus()); - } - - @ExceptionHandler(InvalidRequestException.class) - protected ErrorResponse handleInvalidRequestException(InvalidRequestException e) { - return makeResponseErrorFormat(e.getErrorStatus()); - } - - @ExceptionHandler(DuplicatedException.class) - protected ErrorResponse handleDuplicatedException(DuplicatedException e) { - return makeResponseErrorFormat(e.getErrorStatus()); - } - - @ExceptionHandler(UnauthorizedException.class) - protected ErrorResponse handleUnauthorizedException(UnauthorizedException e) { - return makeResponseErrorFormat(e.getErrorStatus()); - } - - @ExceptionHandler(ForbiddenException.class) - protected ErrorResponse handleForbiddenException(ForbiddenException e) { - return makeResponseErrorFormat(e.getErrorStatus()); - } - - private ErrorResponse makeResponseErrorFormat(String message) { - return new ErrorResponse(message, null); - } - - private ErrorResponse makeResponseErrorFormat(ErrorStatus error) { - return new ErrorResponse(error.getMessage(), null); - } - - private ErrorResponse makeResponseErrorFormat(ErrorStatus error, BindException e) { - List fieldErrors = e.getBindingResult() - .getFieldErrors(); - List errors = fieldErrors.stream() - .map(ErrorResponse.FieldErrorStatus::of) - .toList(); - - return new ErrorResponse(error.getMessage(), errors); - } + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler(MethodArgumentNotValidException.class) + public ErrorResponse handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { + final ErrorStatus error = ErrorStatus.COMMON_DTO_FIELD_INVALID_FORMAT; + + return makeResponseErrorFormat(error, e); + } + + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler(NullPointerException.class) + public ErrorResponse handleNullPointerException(NullPointerException e) { + return makeResponseErrorFormat(e.getMessage()); + } + + @ResponseStatus(HttpStatus.NOT_FOUND) + @ExceptionHandler(NotFoundException.class) + protected ErrorResponse handleNotFoundException(NotFoundException e) { + return makeResponseErrorFormat(e.getErrorStatus()); + } + + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler(InvalidRequestException.class) + protected ErrorResponse handleInvalidRequestException(InvalidRequestException e) { + return makeResponseErrorFormat(e.getErrorStatus()); + } + + @ResponseStatus(HttpStatus.CONFLICT) + @ExceptionHandler(DuplicatedException.class) + protected ErrorResponse handleDuplicatedException(DuplicatedException e) { + return makeResponseErrorFormat(e.getErrorStatus()); + } + + @ResponseStatus(HttpStatus.UNAUTHORIZED) + @ExceptionHandler(UnauthorizedException.class) + protected ErrorResponse handleUnauthorizedException(UnauthorizedException e) { + return makeResponseErrorFormat(e.getErrorStatus()); + } + + @ResponseStatus(HttpStatus.FORBIDDEN) + @ExceptionHandler(ForbiddenException.class) + protected ErrorResponse handleForbiddenException(ForbiddenException e) { + return makeResponseErrorFormat(e.getErrorStatus()); + } + + private ErrorResponse makeResponseErrorFormat(String message) { + return new ErrorResponse(message, null); + } + + private ErrorResponse makeResponseErrorFormat(ErrorStatus error) { + return new ErrorResponse(error.getMessage(), null); + } + + private ErrorResponse makeResponseErrorFormat(ErrorStatus error, BindException e) { + List fieldErrors = e.getBindingResult() + .getFieldErrors(); + List errors = fieldErrors.stream() + .map(ErrorResponse.FieldErrorStatus::of) + .toList(); + + return new ErrorResponse(error.getMessage(), errors); + } } From 2438e6b4c10804d83aa34105ac67da8233473418 Mon Sep 17 00:00:00 2001 From: kmebin Date: Sun, 10 Sep 2023 18:15:34 +0900 Subject: [PATCH 05/10] =?UTF-8?q?[JT-40]=20refactor:=20=EC=96=B4=ED=94=8C?= =?UTF-8?q?=EB=A6=AC=EC=BC=80=EC=9D=B4=EC=85=98=20Service=EC=99=80=20?= =?UTF-8?q?=EB=8F=84=EB=A9=94=EC=9D=B8=20Service=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 1 - .../WebtoonApplicationService.java | 92 +++++++++++++++++++ .../presentation/WebtoonController.java | 10 +- .../devtoon/jtoon/application/S3Service.java | 10 +- .../devtoon/jtoon/request/UploadImageReq.java | 21 +++++ .../WebtoonDomainService.java} | 68 ++++---------- 6 files changed, 139 insertions(+), 63 deletions(-) create mode 100644 module-application/src/main/java/com/devtoon/jtoon/webtoon/application/WebtoonApplicationService.java create mode 100644 module-domain-s3/src/main/java/com/devtoon/jtoon/request/UploadImageReq.java rename module-domain/src/main/java/com/devtoon/jtoon/webtoon/{application/WebtoonService.java => service/WebtoonDomainService.java} (76%) diff --git a/build.gradle b/build.gradle index ff7d7e56..80acef83 100644 --- a/build.gradle +++ b/build.gradle @@ -51,7 +51,6 @@ project(':module-domain') { bootJar.enabled = false dependencies { - implementation project(':module-domain-s3') implementation project(':module-domain-smtp') implementation project(':module-internal') implementation project(':module-core') diff --git a/module-application/src/main/java/com/devtoon/jtoon/webtoon/application/WebtoonApplicationService.java b/module-application/src/main/java/com/devtoon/jtoon/webtoon/application/WebtoonApplicationService.java new file mode 100644 index 00000000..3a5ee64e --- /dev/null +++ b/module-application/src/main/java/com/devtoon/jtoon/webtoon/application/WebtoonApplicationService.java @@ -0,0 +1,92 @@ +package com.devtoon.jtoon.webtoon.application; + +import static com.devtoon.jtoon.common.ImageType.*; + +import java.util.List; +import java.util.Map; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import com.devtoon.jtoon.application.S3Service; +import com.devtoon.jtoon.common.FileName; +import com.devtoon.jtoon.global.util.CustomPageRequest; +import com.devtoon.jtoon.member.entity.Member; +import com.devtoon.jtoon.request.UploadImageReq; +import com.devtoon.jtoon.webtoon.entity.Webtoon; +import com.devtoon.jtoon.webtoon.entity.enums.DayOfWeek; +import com.devtoon.jtoon.webtoon.request.CreateEpisodeReq; +import com.devtoon.jtoon.webtoon.request.CreateWebtoonReq; +import com.devtoon.jtoon.webtoon.request.GetWebtoonsReq; +import com.devtoon.jtoon.webtoon.response.EpisodeRes; +import com.devtoon.jtoon.webtoon.response.EpisodesRes; +import com.devtoon.jtoon.webtoon.response.WebtoonInfoRes; +import com.devtoon.jtoon.webtoon.response.WebtoonItemRes; +import com.devtoon.jtoon.webtoon.service.WebtoonDomainService; + +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class WebtoonApplicationService { + + private final WebtoonDomainService webtoonDomainService; + private final S3Service s3Service; + + @Transactional + public void createWebtoon(Member member, MultipartFile thumbnailImage, CreateWebtoonReq request) { + webtoonDomainService.validateDuplicateTitle(request.title()); + String thumbnailUrl = s3Service.upload(UploadImageReq.builder() + .imageType(WEBTOON_THUMBNAIL) + .webtoonTitle(request.title()) + .fileName(FileName.forWebtoon()) + .image(thumbnailImage) + .build() + ); + webtoonDomainService.createWebtoon(member, thumbnailUrl, request); + } + + @Transactional + public void createEpisode( + Member member, + Long webtoonId, + MultipartFile mainImage, + MultipartFile thumbnailImage, + CreateEpisodeReq request + ) { + Webtoon webtoon = webtoonDomainService.getWebtoonById(webtoonId); + webtoonDomainService.validateAuthorOfWebtoon(member, webtoon); + String mainUrl = s3Service.upload(UploadImageReq.builder() + .imageType(EPISODE_MAIN) + .webtoonTitle(webtoon.getTitle()) + .fileName(FileName.forEpisode(request.no())) + .image(mainImage) + .build() + ); + String thumbnailUrl = s3Service.upload(UploadImageReq.builder() + .imageType(EPISODE_THUMBNAIL) + .webtoonTitle(webtoon.getTitle()) + .fileName(FileName.forEpisode(request.no())) + .image(thumbnailImage) + .build() + ); + webtoonDomainService.createEpisode(webtoon, mainUrl, thumbnailUrl, request); + } + + public Map> getWebtoons(GetWebtoonsReq request) { + return webtoonDomainService.getWebtoons(request); + } + + public WebtoonInfoRes getWebtoon(Long webtoonId) { + return webtoonDomainService.getWebtoon(webtoonId); + } + + public List getEpisodes(Long webtoonId, CustomPageRequest request) { + return webtoonDomainService.getEpisodes(webtoonId, request); + } + + public EpisodeRes getEpisode(Long episodeId) { + return webtoonDomainService.getEpisode(episodeId); + } +} diff --git a/module-application/src/main/java/com/devtoon/jtoon/webtoon/presentation/WebtoonController.java b/module-application/src/main/java/com/devtoon/jtoon/webtoon/presentation/WebtoonController.java index 85ca59f3..14268d69 100644 --- a/module-application/src/main/java/com/devtoon/jtoon/webtoon/presentation/WebtoonController.java +++ b/module-application/src/main/java/com/devtoon/jtoon/webtoon/presentation/WebtoonController.java @@ -17,7 +17,7 @@ import com.devtoon.jtoon.global.util.CustomPageRequest; import com.devtoon.jtoon.member.entity.Member; import com.devtoon.jtoon.security.jwt.domain.MemberThreadLocal; -import com.devtoon.jtoon.webtoon.application.WebtoonService; +import com.devtoon.jtoon.webtoon.application.WebtoonApplicationService; import com.devtoon.jtoon.webtoon.entity.enums.DayOfWeek; import com.devtoon.jtoon.webtoon.request.CreateEpisodeReq; import com.devtoon.jtoon.webtoon.request.CreateWebtoonReq; @@ -35,7 +35,7 @@ @RequestMapping("/webtoons") public class WebtoonController { - private final WebtoonService webtoonService; + private final WebtoonApplicationService webtoonService; @PostMapping @ResponseStatus(HttpStatus.CREATED) @@ -48,12 +48,12 @@ public void createWebtoon(@RequestPart MultipartFile thumbnailImage, @RequestPar @ResponseStatus(HttpStatus.CREATED) public void createEpisode( @PathVariable Long webtoonId, - @RequestPart @Valid CreateEpisodeReq request, @RequestPart MultipartFile mainImage, - @RequestPart(required = false) MultipartFile thumbnailImage + @RequestPart(required = false) MultipartFile thumbnailImage, + @RequestPart @Valid CreateEpisodeReq request ) { Member member = MemberThreadLocal.getMember(); - webtoonService.createEpisode(member, webtoonId, request, mainImage, thumbnailImage); + webtoonService.createEpisode(member, webtoonId, mainImage, thumbnailImage, request); } @GetMapping diff --git a/module-domain-s3/src/main/java/com/devtoon/jtoon/application/S3Service.java b/module-domain-s3/src/main/java/com/devtoon/jtoon/application/S3Service.java index 688ade1f..40de2ac8 100644 --- a/module-domain-s3/src/main/java/com/devtoon/jtoon/application/S3Service.java +++ b/module-domain-s3/src/main/java/com/devtoon/jtoon/application/S3Service.java @@ -2,10 +2,8 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; -import org.springframework.web.multipart.MultipartFile; -import com.devtoon.jtoon.common.FileName; -import com.devtoon.jtoon.common.ImageType; +import com.devtoon.jtoon.request.UploadImageReq; import com.devtoon.jtoon.util.S3Uploader; import lombok.RequiredArgsConstructor; @@ -19,9 +17,9 @@ public class S3Service { @Value("${spring.cloud.aws.cloud-front.url}") private String IMAGE_URL; - public String upload(ImageType imageType, String webtoonTitle, FileName fileName, MultipartFile image) { - String key = imageType.getPath(webtoonTitle, fileName.getValue()); - s3Uploader.upload(key, image); + public String upload(UploadImageReq request) { + String key = request.toKey(); + s3Uploader.upload(key, request.image()); return IMAGE_URL + key; } diff --git a/module-domain-s3/src/main/java/com/devtoon/jtoon/request/UploadImageReq.java b/module-domain-s3/src/main/java/com/devtoon/jtoon/request/UploadImageReq.java new file mode 100644 index 00000000..6ec8175e --- /dev/null +++ b/module-domain-s3/src/main/java/com/devtoon/jtoon/request/UploadImageReq.java @@ -0,0 +1,21 @@ +package com.devtoon.jtoon.request; + +import org.springframework.web.multipart.MultipartFile; + +import com.devtoon.jtoon.common.FileName; +import com.devtoon.jtoon.common.ImageType; + +import lombok.Builder; + +@Builder +public record UploadImageReq( + ImageType imageType, + String webtoonTitle, + FileName fileName, + MultipartFile image +) { + + public String toKey() { + return imageType.getPath(webtoonTitle, fileName.getValue()); + } +} diff --git a/module-domain/src/main/java/com/devtoon/jtoon/webtoon/application/WebtoonService.java b/module-domain/src/main/java/com/devtoon/jtoon/webtoon/service/WebtoonDomainService.java similarity index 76% rename from module-domain/src/main/java/com/devtoon/jtoon/webtoon/application/WebtoonService.java rename to module-domain/src/main/java/com/devtoon/jtoon/webtoon/service/WebtoonDomainService.java index 845d1a18..186e86ef 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/webtoon/application/WebtoonService.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/webtoon/service/WebtoonDomainService.java @@ -1,6 +1,5 @@ -package com.devtoon.jtoon.webtoon.application; +package com.devtoon.jtoon.webtoon.service; -import static com.devtoon.jtoon.common.ImageType.*; import static com.devtoon.jtoon.error.model.ErrorStatus.*; import static java.util.stream.Collectors.*; @@ -9,16 +8,12 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.multipart.MultipartFile; -import com.devtoon.jtoon.application.S3Service; -import com.devtoon.jtoon.common.FileName; import com.devtoon.jtoon.error.exception.DuplicatedException; import com.devtoon.jtoon.error.exception.InvalidRequestException; import com.devtoon.jtoon.error.exception.NotFoundException; import com.devtoon.jtoon.global.util.CustomPageRequest; import com.devtoon.jtoon.member.entity.Member; -import com.devtoon.jtoon.member.repository.MemberRepository; import com.devtoon.jtoon.webtoon.entity.DayOfWeekWebtoon; import com.devtoon.jtoon.webtoon.entity.Episode; import com.devtoon.jtoon.webtoon.entity.GenreWebtoon; @@ -44,7 +39,7 @@ @Service @Transactional(readOnly = true) @RequiredArgsConstructor -public class WebtoonService { +public class WebtoonDomainService { private final WebtoonRepository webtoonRepository; private final WebtoonSearchRepository webtoonSearchRepository; @@ -52,18 +47,9 @@ public class WebtoonService { private final GenreWebtoonRepository genreWebtoonRepository; private final EpisodeRepository episodeRepository; private final EpisodeSearchRepository episodeSearchRepository; - private final MemberRepository memberRepository; - private final S3Service s3Service; @Transactional - public void createWebtoon(Member member, MultipartFile thumbnailImage, CreateWebtoonReq request) { - validateDuplicateTitle(request.title()); - String thumbnailUrl = s3Service.upload( - WEBTOON_THUMBNAIL, - request.title(), - FileName.forWebtoon(), - thumbnailImage - ); + public void createWebtoon(Member member, String thumbnailUrl, CreateWebtoonReq request) { Webtoon webtoon = request.toWebtoonEntity(member, thumbnailUrl); List dayOfWeekWebtoons = request.toDayOfWeekWebtoonEntity(webtoon); List genreWebtoons = request.toGenreWebtoonEntity(webtoon); @@ -73,27 +59,7 @@ public void createWebtoon(Member member, MultipartFile thumbnailImage, CreateWeb } @Transactional - public void createEpisode( - Member member, - Long webtoonId, - CreateEpisodeReq request, - MultipartFile mainImage, - MultipartFile thumbnailImage - ) { - Webtoon webtoon = getWebtoonById(webtoonId); - validateAuthorOfWebtoon(member, webtoon); - String mainUrl = s3Service.upload( - EPISODE_MAIN, - webtoon.getTitle(), - FileName.forEpisode(request.no()), - mainImage - ); - String thumbnailUrl = s3Service.upload( - EPISODE_THUMBNAIL, - webtoon.getTitle(), - FileName.forEpisode(request.no()), - thumbnailImage - ); + public void createEpisode(Webtoon webtoon, String mainUrl, String thumbnailUrl, CreateEpisodeReq request) { Episode episode = request.toEntity(webtoon, mainUrl, thumbnailUrl); episodeRepository.save(episode); } @@ -127,7 +93,19 @@ public EpisodeRes getEpisode(Long episodeId) { return EpisodeRes.from(episode); } - private Webtoon getWebtoonById(Long webtoonId) { + public void validateDuplicateTitle(String title) { + if (webtoonRepository.existsByTitle(title)) { + throw new DuplicatedException(WEBTOON_TITLE_DUPLICATED); + } + } + + public void validateAuthorOfWebtoon(Member member, Webtoon webtoon) { + if (!webtoon.isAuthor(member.getId())) { + throw new InvalidRequestException(WEBTOON_NOT_AUTHOR); + } + } + + public Webtoon getWebtoonById(Long webtoonId) { return webtoonRepository.findById(webtoonId) .orElseThrow(() -> new NotFoundException(WEBTOON_NOT_FOUND)); } @@ -150,16 +128,4 @@ private List getGenres(Long webtoonId) { .map(GenreRes::from) .toList(); } - - private void validateDuplicateTitle(String title) { - if (webtoonRepository.existsByTitle(title)) { - throw new DuplicatedException(WEBTOON_TITLE_DUPLICATED); - } - } - - private void validateAuthorOfWebtoon(Member member, Webtoon webtoon) { - if (!webtoon.isAuthor(member.getId())) { - throw new InvalidRequestException(WEBTOON_NOT_AUTHOR); - } - } } From 62492f69e7ce8bed3acf540aa2dc9c3eafa9a848 Mon Sep 17 00:00:00 2001 From: kmebin Date: Sun, 10 Sep 2023 19:01:27 +0900 Subject: [PATCH 06/10] =?UTF-8?q?[JT-40]=20feat:=20=ED=9A=8C=EC=9B=90=20?= =?UTF-8?q?=EC=BF=A0=ED=82=A4=20=EC=97=94=ED=8B=B0=ED=8B=B0=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jtoon/member/entity/MemberCookie.java | 50 +++++++++++++++++++ .../repository/MemberCookieRepository.java | 8 +++ .../jtoon/error/model/ErrorStatus.java | 6 ++- 3 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 module-domain/src/main/java/com/devtoon/jtoon/member/entity/MemberCookie.java create mode 100644 module-domain/src/main/java/com/devtoon/jtoon/member/repository/MemberCookieRepository.java diff --git a/module-domain/src/main/java/com/devtoon/jtoon/member/entity/MemberCookie.java b/module-domain/src/main/java/com/devtoon/jtoon/member/entity/MemberCookie.java new file mode 100644 index 00000000..a6754611 --- /dev/null +++ b/module-domain/src/main/java/com/devtoon/jtoon/member/entity/MemberCookie.java @@ -0,0 +1,50 @@ +package com.devtoon.jtoon.member.entity; + +import static com.devtoon.jtoon.error.model.ErrorStatus.*; +import static java.util.Objects.*; + +import com.devtoon.jtoon.error.exception.InvalidRequestException; +import com.devtoon.jtoon.global.common.BaseTimeEntity; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@Table(name = "member_cookies") +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class MemberCookie extends BaseTimeEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "member_cookie_id") + private Long id; + + @Column(name = "cookie_count", nullable = false) + private int cookieCount; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id", nullable = false) + private Member member; + + @Builder + public MemberCookie(int cookieCount, Member member) { + if (cookieCount < 0) { + throw new InvalidRequestException(COOKIE_COUNT_NOT_NEGATIVE); + } + + this.cookieCount = cookieCount; + this.member = requireNonNull(member, MEMBER_IS_NULL.getMessage()); + } +} diff --git a/module-domain/src/main/java/com/devtoon/jtoon/member/repository/MemberCookieRepository.java b/module-domain/src/main/java/com/devtoon/jtoon/member/repository/MemberCookieRepository.java new file mode 100644 index 00000000..33727905 --- /dev/null +++ b/module-domain/src/main/java/com/devtoon/jtoon/member/repository/MemberCookieRepository.java @@ -0,0 +1,8 @@ +package com.devtoon.jtoon.member.repository; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.devtoon.jtoon.member.entity.MemberCookie; + +public interface MemberCookieRepository extends JpaRepository { +} diff --git a/module-internal/src/main/java/com/devtoon/jtoon/error/model/ErrorStatus.java b/module-internal/src/main/java/com/devtoon/jtoon/error/model/ErrorStatus.java index 7ed8ba3a..3a9f6dfa 100644 --- a/module-internal/src/main/java/com/devtoon/jtoon/error/model/ErrorStatus.java +++ b/module-internal/src/main/java/com/devtoon/jtoon/error/model/ErrorStatus.java @@ -10,6 +10,7 @@ public enum ErrorStatus { COMMON_DTO_FIELD_INVALID_FORMAT("올바른 요청 정보가 아닙니다."), + MEMBER_IS_NULL("회원 값이 NULL 입니다."), MEMBER_EMAIL_INVALID_FORMAT("올바른 이메일 형식이 아닙니다."), MEMBER_PASSWORD_INVALID_FORMAT("올바른 비밀번호형식이 아닙니다."), MEMBER_NAME_INVALID_FORMAT("올바른 이름이 아닙니다."), @@ -20,6 +21,7 @@ public enum ErrorStatus { MEMBER_LOGIN_TYPE_INVALID_FORMAT("올바른 로그인 타입이 아닙니다."), MEMBER_MESSAGE_SEND_FAILED("이메일 인증 메세지 전송 실패"), MEMBER_EMAIL_CONFLICT("Email 중복"), + MEMBER_COOKIE_NOT_FOUND("회원의 쿠키 정보가 존재하지 않습니다."), PAYMENT_IMP_UID_IS_NULL("결제 고유번호 값이 NULL 입니다."), PAYMENT_MERCHANT_UID_IS_NULL("주문번호 값이 NULL 입니다."), @@ -42,9 +44,11 @@ public enum ErrorStatus { WEBTOON_AUTHOR_IS_NULL("웹툰 작가 값이 NULL 입니다."), WEBTOON_DAY_OF_WEEK_IS_NULL("웹툰 요일 값이 NULL 입니다."), WEBTOON_GENRE_IS_NULL("웹툰 장르 값이 NULL 입니다."), - WEBTOON_COOKIE_COUNT_NOT_NEGATIVE("쿠키 개수는 음수일 수 없습니다."), + COOKIE_COUNT_NOT_NEGATIVE("쿠키 개수는 음수일 수 없습니다."), + EPISODE_IS_NULL("회차 값이 NULL 입니다."), EPISODE_NOT_FOUND("존재하지 않는 회차입니다."), EPISODE_NUMBER_POSITIVE("회차 번호는 양수여야 합니다."), + EPISODE_NOT_ENOUGH_COOKIES("쿠키 개수가 부족합니다."), EPISODE_TITLE_IS_NULL("회차 제목 값이 NULL 입니다."), EPISODE_MAIN_URL_IS_NULL("회차 메인 이미지 URL 값이 NULL 입니다."), EPISODE_OPENED_AT_IS_NULL("회차 공개일자 값이 NULL 입니다."), From f8c4e0ea20582eefef94561cfbde9f7f99fc688f Mon Sep 17 00:00:00 2001 From: kmebin Date: Sun, 10 Sep 2023 22:09:33 +0900 Subject: [PATCH 07/10] =?UTF-8?q?[JT-40]=20feat:=20=EA=B5=AC=EB=A7=A4?= =?UTF-8?q?=ED=95=9C=20=ED=9A=8C=EC=B0=A8=20=EC=97=94=ED=8B=B0=ED=8B=B0=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../webtoon/entity/PurchasedEpisode.java | 47 +++++++++++++++++++ .../PurchasedEpisodeRepository.java | 8 ++++ 2 files changed, 55 insertions(+) create mode 100644 module-domain/src/main/java/com/devtoon/jtoon/webtoon/entity/PurchasedEpisode.java create mode 100644 module-domain/src/main/java/com/devtoon/jtoon/webtoon/repository/PurchasedEpisodeRepository.java diff --git a/module-domain/src/main/java/com/devtoon/jtoon/webtoon/entity/PurchasedEpisode.java b/module-domain/src/main/java/com/devtoon/jtoon/webtoon/entity/PurchasedEpisode.java new file mode 100644 index 00000000..0a67e124 --- /dev/null +++ b/module-domain/src/main/java/com/devtoon/jtoon/webtoon/entity/PurchasedEpisode.java @@ -0,0 +1,47 @@ +package com.devtoon.jtoon.webtoon.entity; + +import static com.devtoon.jtoon.error.model.ErrorStatus.*; +import static java.util.Objects.*; + +import com.devtoon.jtoon.global.common.BaseTimeEntity; +import com.devtoon.jtoon.member.entity.Member; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@Table(name = "purchased_episodes") +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class PurchasedEpisode extends BaseTimeEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "purchased_episode_id") + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id", nullable = false) + private Member member; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "episode_id", nullable = false) + private Episode episode; + + @Builder + private PurchasedEpisode(Member member, Episode episode) { + this.member = requireNonNull(member, MEMBER_IS_NULL.getMessage()); + this.episode = requireNonNull(episode, EPISODE_IS_NULL.getMessage()); + } +} diff --git a/module-domain/src/main/java/com/devtoon/jtoon/webtoon/repository/PurchasedEpisodeRepository.java b/module-domain/src/main/java/com/devtoon/jtoon/webtoon/repository/PurchasedEpisodeRepository.java new file mode 100644 index 00000000..f53c7eb5 --- /dev/null +++ b/module-domain/src/main/java/com/devtoon/jtoon/webtoon/repository/PurchasedEpisodeRepository.java @@ -0,0 +1,8 @@ +package com.devtoon.jtoon.webtoon.repository; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.devtoon.jtoon.webtoon.entity.PurchasedEpisode; + +public interface PurchasedEpisodeRepository extends JpaRepository { +} From 90927ecacfaefb90132d3428d7afd16be3a7b876 Mon Sep 17 00:00:00 2001 From: kmebin Date: Sun, 10 Sep 2023 22:10:26 +0900 Subject: [PATCH 08/10] =?UTF-8?q?[JT-40]=20feat:=20=ED=9A=8C=EC=B0=A8=20?= =?UTF-8?q?=EA=B5=AC=EB=A7=A4=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WebtoonApplicationService.java | 7 ++++- .../presentation/WebtoonController.java | 6 +++++ .../jtoon/member/entity/MemberCookie.java | 10 ++++++- .../devtoon/jtoon/webtoon/entity/Episode.java | 4 +++ .../devtoon/jtoon/webtoon/entity/Webtoon.java | 2 +- .../webtoon/service/WebtoonDomainService.java | 27 +++++++++++++++++-- 6 files changed, 51 insertions(+), 5 deletions(-) diff --git a/module-application/src/main/java/com/devtoon/jtoon/webtoon/application/WebtoonApplicationService.java b/module-application/src/main/java/com/devtoon/jtoon/webtoon/application/WebtoonApplicationService.java index 3a5ee64e..cf3e99ee 100644 --- a/module-application/src/main/java/com/devtoon/jtoon/webtoon/application/WebtoonApplicationService.java +++ b/module-application/src/main/java/com/devtoon/jtoon/webtoon/application/WebtoonApplicationService.java @@ -56,7 +56,7 @@ public void createEpisode( CreateEpisodeReq request ) { Webtoon webtoon = webtoonDomainService.getWebtoonById(webtoonId); - webtoonDomainService.validateAuthorOfWebtoon(member, webtoon); + webtoonDomainService.validateAuthorOfWebtoon(member.getId(), webtoon); String mainUrl = s3Service.upload(UploadImageReq.builder() .imageType(EPISODE_MAIN) .webtoonTitle(webtoon.getTitle()) @@ -89,4 +89,9 @@ public List getEpisodes(Long webtoonId, CustomPageRequest request) public EpisodeRes getEpisode(Long episodeId) { return webtoonDomainService.getEpisode(episodeId); } + + @Transactional + public void purchaseEpisode(Member member, Long episodeId) { + webtoonDomainService.purchaseEpisode(member, episodeId); + } } diff --git a/module-application/src/main/java/com/devtoon/jtoon/webtoon/presentation/WebtoonController.java b/module-application/src/main/java/com/devtoon/jtoon/webtoon/presentation/WebtoonController.java index 14268d69..8dbd5c3c 100644 --- a/module-application/src/main/java/com/devtoon/jtoon/webtoon/presentation/WebtoonController.java +++ b/module-application/src/main/java/com/devtoon/jtoon/webtoon/presentation/WebtoonController.java @@ -77,4 +77,10 @@ public List getEpisodes(@RequestParam Long webtoonId, CustomPageReq public EpisodeRes getEpisode(@PathVariable Long episodeId) { return webtoonService.getEpisode(episodeId); } + + @PostMapping("/episodes/{episodeId}/purchase") + public void purchaseEpisode(@PathVariable Long episodeId) { + Member member = MemberThreadLocal.getMember(); + webtoonService.purchaseEpisode(member, episodeId); + } } diff --git a/module-domain/src/main/java/com/devtoon/jtoon/member/entity/MemberCookie.java b/module-domain/src/main/java/com/devtoon/jtoon/member/entity/MemberCookie.java index a6754611..87532a7b 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/member/entity/MemberCookie.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/member/entity/MemberCookie.java @@ -39,7 +39,7 @@ public class MemberCookie extends BaseTimeEntity { private Member member; @Builder - public MemberCookie(int cookieCount, Member member) { + private MemberCookie(int cookieCount, Member member) { if (cookieCount < 0) { throw new InvalidRequestException(COOKIE_COUNT_NOT_NEGATIVE); } @@ -47,4 +47,12 @@ public MemberCookie(int cookieCount, Member member) { this.cookieCount = cookieCount; this.member = requireNonNull(member, MEMBER_IS_NULL.getMessage()); } + + public void decreaseCookieCount(int cookieCount) { + if (this.cookieCount < cookieCount) { + throw new InvalidRequestException(EPISODE_NOT_ENOUGH_COOKIES); + } + + this.cookieCount -= cookieCount; + } } diff --git a/module-domain/src/main/java/com/devtoon/jtoon/webtoon/entity/Episode.java b/module-domain/src/main/java/com/devtoon/jtoon/webtoon/entity/Episode.java index df9dd801..6bad889c 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/webtoon/entity/Episode.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/webtoon/entity/Episode.java @@ -82,4 +82,8 @@ private Episode( this.openedAt = requireNonNull(openedAt, EPISODE_OPENED_AT_IS_NULL.getMessage()); this.webtoon = requireNonNull(webtoon, WEBTOON_IS_NULL.getMessage()); } + + public int getCookieCount() { + return webtoon.getCookieCount(); + } } diff --git a/module-domain/src/main/java/com/devtoon/jtoon/webtoon/entity/Webtoon.java b/module-domain/src/main/java/com/devtoon/jtoon/webtoon/entity/Webtoon.java index 1a4fbb42..f7ed691f 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/webtoon/entity/Webtoon.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/webtoon/entity/Webtoon.java @@ -68,7 +68,7 @@ private Webtoon( Member author ) { if (cookieCount < 0) { - throw new InvalidRequestException(WEBTOON_COOKIE_COUNT_NOT_NEGATIVE); + throw new InvalidRequestException(COOKIE_COUNT_NOT_NEGATIVE); } this.title = requireNonNull(title, WEBTOON_TITLE_IS_NULL.getMessage()); diff --git a/module-domain/src/main/java/com/devtoon/jtoon/webtoon/service/WebtoonDomainService.java b/module-domain/src/main/java/com/devtoon/jtoon/webtoon/service/WebtoonDomainService.java index 186e86ef..f8af9424 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/webtoon/service/WebtoonDomainService.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/webtoon/service/WebtoonDomainService.java @@ -14,15 +14,19 @@ import com.devtoon.jtoon.error.exception.NotFoundException; import com.devtoon.jtoon.global.util.CustomPageRequest; import com.devtoon.jtoon.member.entity.Member; +import com.devtoon.jtoon.member.entity.MemberCookie; +import com.devtoon.jtoon.member.repository.MemberCookieRepository; import com.devtoon.jtoon.webtoon.entity.DayOfWeekWebtoon; import com.devtoon.jtoon.webtoon.entity.Episode; import com.devtoon.jtoon.webtoon.entity.GenreWebtoon; +import com.devtoon.jtoon.webtoon.entity.PurchasedEpisode; import com.devtoon.jtoon.webtoon.entity.Webtoon; import com.devtoon.jtoon.webtoon.entity.enums.DayOfWeek; import com.devtoon.jtoon.webtoon.repository.DayOfWeekWebtoonRepository; import com.devtoon.jtoon.webtoon.repository.EpisodeRepository; import com.devtoon.jtoon.webtoon.repository.EpisodeSearchRepository; import com.devtoon.jtoon.webtoon.repository.GenreWebtoonRepository; +import com.devtoon.jtoon.webtoon.repository.PurchasedEpisodeRepository; import com.devtoon.jtoon.webtoon.repository.WebtoonRepository; import com.devtoon.jtoon.webtoon.repository.WebtoonSearchRepository; import com.devtoon.jtoon.webtoon.request.CreateEpisodeReq; @@ -47,6 +51,8 @@ public class WebtoonDomainService { private final GenreWebtoonRepository genreWebtoonRepository; private final EpisodeRepository episodeRepository; private final EpisodeSearchRepository episodeSearchRepository; + private final PurchasedEpisodeRepository purchasedEpisodeRepository; + private final MemberCookieRepository memberCookieRepository; @Transactional public void createWebtoon(Member member, String thumbnailUrl, CreateWebtoonReq request) { @@ -93,14 +99,26 @@ public EpisodeRes getEpisode(Long episodeId) { return EpisodeRes.from(episode); } + @Transactional + public void purchaseEpisode(Member member, Long episodeId) { + Episode episode = getEpisodeById(episodeId); + MemberCookie memberCookie = getMemberCookieById(member.getId()); + memberCookie.decreaseCookieCount(episode.getCookieCount()); + purchasedEpisodeRepository.save(PurchasedEpisode.builder() + .member(member) + .episode(episode) + .build() + ); + } + public void validateDuplicateTitle(String title) { if (webtoonRepository.existsByTitle(title)) { throw new DuplicatedException(WEBTOON_TITLE_DUPLICATED); } } - public void validateAuthorOfWebtoon(Member member, Webtoon webtoon) { - if (!webtoon.isAuthor(member.getId())) { + public void validateAuthorOfWebtoon(Long memberId, Webtoon webtoon) { + if (!webtoon.isAuthor(memberId)) { throw new InvalidRequestException(WEBTOON_NOT_AUTHOR); } } @@ -115,6 +133,11 @@ private Episode getEpisodeById(Long episodeId) { .orElseThrow(() -> new NotFoundException(EPISODE_NOT_FOUND)); } + private MemberCookie getMemberCookieById(Long memberId) { + return memberCookieRepository.findById(memberId) + .orElseThrow(() -> new NotFoundException(MEMBER_COOKIE_NOT_FOUND)); + } + private List getDayOfWeeks(Long webtoonId) { return dayOfWeekWebtoonRepository.findById(webtoonId) .stream() From 0046117e596656ff8c2f9a18bc69e502d6a30c19 Mon Sep 17 00:00:00 2001 From: kmebin Date: Sun, 10 Sep 2023 22:30:50 +0900 Subject: [PATCH 09/10] =?UTF-8?q?[JT-40]=20refactor:=20=EC=9E=91=EA=B0=80?= =?UTF-8?q?=EC=9D=B8=EC=A7=80=20=EA=B2=80=EC=A6=9D=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=97=94=ED=8B=B0=ED=8B=B0=EB=A1=9C=20=EC=9C=84=EC=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/WebtoonApplicationService.java | 2 +- .../com/devtoon/jtoon/webtoon/entity/Webtoon.java | 12 ++++++++++-- .../jtoon/webtoon/service/WebtoonDomainService.java | 7 ------- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/module-application/src/main/java/com/devtoon/jtoon/webtoon/application/WebtoonApplicationService.java b/module-application/src/main/java/com/devtoon/jtoon/webtoon/application/WebtoonApplicationService.java index cf3e99ee..5e1382f5 100644 --- a/module-application/src/main/java/com/devtoon/jtoon/webtoon/application/WebtoonApplicationService.java +++ b/module-application/src/main/java/com/devtoon/jtoon/webtoon/application/WebtoonApplicationService.java @@ -56,7 +56,7 @@ public void createEpisode( CreateEpisodeReq request ) { Webtoon webtoon = webtoonDomainService.getWebtoonById(webtoonId); - webtoonDomainService.validateAuthorOfWebtoon(member.getId(), webtoon); + webtoon.validateAuthor(member.getId()); String mainUrl = s3Service.upload(UploadImageReq.builder() .imageType(EPISODE_MAIN) .webtoonTitle(webtoon.getTitle()) diff --git a/module-domain/src/main/java/com/devtoon/jtoon/webtoon/entity/Webtoon.java b/module-domain/src/main/java/com/devtoon/jtoon/webtoon/entity/Webtoon.java index f7ed691f..5d9bb54d 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/webtoon/entity/Webtoon.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/webtoon/entity/Webtoon.java @@ -3,6 +3,8 @@ import static com.devtoon.jtoon.error.model.ErrorStatus.*; import static java.util.Objects.*; +import java.util.Objects; + import org.hibernate.annotations.ColumnDefault; import com.devtoon.jtoon.error.exception.InvalidRequestException; @@ -79,7 +81,13 @@ private Webtoon( this.author = requireNonNull(author, WEBTOON_AUTHOR_IS_NULL.getMessage()); } - public boolean isAuthor(Long memberId) { - return memberId.equals(author.getId()); + public void validateAuthor(Long memberId) { + if (!isAuthor(memberId)) { + throw new InvalidRequestException(WEBTOON_NOT_AUTHOR); + } + } + + private boolean isAuthor(Long memberId) { + return Objects.equals(author.getId(), memberId); } } diff --git a/module-domain/src/main/java/com/devtoon/jtoon/webtoon/service/WebtoonDomainService.java b/module-domain/src/main/java/com/devtoon/jtoon/webtoon/service/WebtoonDomainService.java index f8af9424..26c874d4 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/webtoon/service/WebtoonDomainService.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/webtoon/service/WebtoonDomainService.java @@ -10,7 +10,6 @@ import org.springframework.transaction.annotation.Transactional; import com.devtoon.jtoon.error.exception.DuplicatedException; -import com.devtoon.jtoon.error.exception.InvalidRequestException; import com.devtoon.jtoon.error.exception.NotFoundException; import com.devtoon.jtoon.global.util.CustomPageRequest; import com.devtoon.jtoon.member.entity.Member; @@ -117,12 +116,6 @@ public void validateDuplicateTitle(String title) { } } - public void validateAuthorOfWebtoon(Long memberId, Webtoon webtoon) { - if (!webtoon.isAuthor(memberId)) { - throw new InvalidRequestException(WEBTOON_NOT_AUTHOR); - } - } - public Webtoon getWebtoonById(Long webtoonId) { return webtoonRepository.findById(webtoonId) .orElseThrow(() -> new NotFoundException(WEBTOON_NOT_FOUND)); From 67694e82da73490e478f6172d9e5fe4cc29e0e20 Mon Sep 17 00:00:00 2001 From: kmebin Date: Mon, 11 Sep 2023 17:00:23 +0900 Subject: [PATCH 10/10] =?UTF-8?q?[JT-40]=20fix:=20MemberThreadLocal=20?= =?UTF-8?q?=EA=B2=BD=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jtoon/webtoon/presentation/WebtoonController.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/module-application/src/main/java/com/devtoon/jtoon/webtoon/presentation/WebtoonController.java b/module-application/src/main/java/com/devtoon/jtoon/webtoon/presentation/WebtoonController.java index 258c5466..8b48bfc9 100644 --- a/module-application/src/main/java/com/devtoon/jtoon/webtoon/presentation/WebtoonController.java +++ b/module-application/src/main/java/com/devtoon/jtoon/webtoon/presentation/WebtoonController.java @@ -1,5 +1,8 @@ package com.devtoon.jtoon.webtoon.presentation; +import java.util.List; +import java.util.Map; + import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -13,7 +16,7 @@ import com.devtoon.jtoon.global.util.CustomPageRequest; import com.devtoon.jtoon.member.entity.Member; -import com.devtoon.jtoon.security.jwt.domain.MemberThreadLocal; +import com.devtoon.jtoon.security.domain.jwt.MemberThreadLocal; import com.devtoon.jtoon.webtoon.application.WebtoonApplicationService; import com.devtoon.jtoon.webtoon.entity.enums.DayOfWeek; import com.devtoon.jtoon.webtoon.request.CreateEpisodeReq; @@ -23,9 +26,8 @@ import com.devtoon.jtoon.webtoon.response.EpisodesRes; import com.devtoon.jtoon.webtoon.response.WebtoonInfoRes; import com.devtoon.jtoon.webtoon.response.WebtoonItemRes; + import jakarta.validation.Valid; -import java.util.List; -import java.util.Map; import lombok.RequiredArgsConstructor; @RestController