From 2aaccce98dc35b3ea1b9bb3fdd826d0f47c408b3 Mon Sep 17 00:00:00 2001 From: Yang JiWoong Date: Thu, 18 Apr 2024 10:38:38 +0900 Subject: [PATCH 01/52] =?UTF-8?q?[BE]=20refactor=20:=20=EB=AA=A8=EC=9E=84?= =?UTF-8?q?=EC=9D=98=20=EC=8B=9C=EC=9E=91/=EC=A2=85=EB=A3=8C=20=EA=B8=B0?= =?UTF-8?q?=EA=B0=84=20=EC=9E=90=EB=A3=8C=ED=98=95=20=EB=B3=80=EA=B2=BD(da?= =?UTF-8?q?tetime=20->=20date)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../entity/moim/moim/MoimJpaEntity.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/backend/src/main/java/moim_today/persistence/entity/moim/moim/MoimJpaEntity.java b/backend/src/main/java/moim_today/persistence/entity/moim/moim/MoimJpaEntity.java index ed20047b..22c82fa4 100644 --- a/backend/src/main/java/moim_today/persistence/entity/moim/moim/MoimJpaEntity.java +++ b/backend/src/main/java/moim_today/persistence/entity/moim/moim/MoimJpaEntity.java @@ -1,11 +1,11 @@ package moim_today.persistence.entity.moim.moim; -import moim_today.domain.moim.enums.MoimCategory; -import moim_today.global.annotation.Association; -import moim_today.global.base_entity.BaseTimeEntity; import jakarta.persistence.*; import lombok.Builder; import lombok.Getter; +import moim_today.domain.moim.enums.MoimCategory; +import moim_today.global.annotation.Association; +import moim_today.global.base_entity.BaseTimeEntity; import java.time.LocalDate; @@ -41,9 +41,9 @@ public class MoimJpaEntity extends BaseTimeEntity { private int views; - private LocalDate startDateTime; + private LocalDate startDate; - private LocalDate endDateTime; + private LocalDate endDate; protected MoimJpaEntity() { } @@ -52,7 +52,7 @@ protected MoimJpaEntity() { private MoimJpaEntity(final long universityId, final long memberId, final String title, final String contents, final int capacity, final int currentCount, final String imageUrl, final String password, final MoimCategory moimCategory, - final int views, final LocalDate startDateTime, final LocalDate endDateTime) { + final int views, final LocalDate startDate, final LocalDate endDate) { this.universityId = universityId; this.memberId = memberId; this.title = title; @@ -63,7 +63,7 @@ private MoimJpaEntity(final long universityId, final long memberId, final String this.password = password; this.moimCategory = moimCategory; this.views = views; - this.startDateTime = startDateTime; - this.endDateTime = endDateTime; + this.startDate = startDate; + this.endDate = endDate; } } From 4a04060862e8e7b0f6ceb8f768bf4a2a7ca1ba47 Mon Sep 17 00:00:00 2001 From: Yang JiWoong Date: Thu, 18 Apr 2024 11:05:19 +0900 Subject: [PATCH 02/52] =?UTF-8?q?[BE]=20feat=20:=20=EA=B3=B5=EA=B0=9C=20?= =?UTF-8?q?=EB=AA=A8=EC=9E=84=20=EC=83=9D=EC=84=B1=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=ED=8B=80=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/moim/MoimService.java | 20 ++++++++++++++ .../dto/moim/PublicMoimAppendRequest.java | 15 +++++++++++ .../implement/moim/MoimAppender.java | 22 +++++++++++++++ .../presentation/moim/MoimController.java | 27 +++++++++++++++++++ 4 files changed, 84 insertions(+) create mode 100644 backend/src/main/java/moim_today/application/moim/MoimService.java create mode 100644 backend/src/main/java/moim_today/dto/moim/PublicMoimAppendRequest.java create mode 100644 backend/src/main/java/moim_today/implement/moim/MoimAppender.java create mode 100644 backend/src/main/java/moim_today/presentation/moim/MoimController.java diff --git a/backend/src/main/java/moim_today/application/moim/MoimService.java b/backend/src/main/java/moim_today/application/moim/MoimService.java new file mode 100644 index 00000000..c7717c2c --- /dev/null +++ b/backend/src/main/java/moim_today/application/moim/MoimService.java @@ -0,0 +1,20 @@ +package moim_today.application.moim; + +import moim_today.dto.moim.PublicMoimAppendRequest; +import moim_today.implement.moim.MoimAppender; +import org.springframework.stereotype.Service; + +@Service +public class MoimService { + + private final MoimAppender moimAppender; + + public MoimService(final MoimAppender moimAppender) { + this.moimAppender = moimAppender; + } + + public void createPublicMoim(final long memberId, final long universityId, + final PublicMoimAppendRequest publicMoimAppendRequest) { + moimAppender.createPublicMoim(memberId, universityId, publicMoimAppendRequest); + } +} diff --git a/backend/src/main/java/moim_today/dto/moim/PublicMoimAppendRequest.java b/backend/src/main/java/moim_today/dto/moim/PublicMoimAppendRequest.java new file mode 100644 index 00000000..7bb16373 --- /dev/null +++ b/backend/src/main/java/moim_today/dto/moim/PublicMoimAppendRequest.java @@ -0,0 +1,15 @@ +package moim_today.dto.moim; + +import moim_today.domain.moim.enums.MoimCategory; + +import java.time.LocalDate; + +public record PublicMoimAppendRequest( + String title, + String contents, + int capacity, + MoimCategory moimCategory, + LocalDate startDate, + LocalDate endDate +) { +} diff --git a/backend/src/main/java/moim_today/implement/moim/MoimAppender.java b/backend/src/main/java/moim_today/implement/moim/MoimAppender.java new file mode 100644 index 00000000..8c50c4ce --- /dev/null +++ b/backend/src/main/java/moim_today/implement/moim/MoimAppender.java @@ -0,0 +1,22 @@ +package moim_today.implement.moim; + +import moim_today.dto.moim.PublicMoimAppendRequest; +import moim_today.global.annotation.Implement; +import moim_today.persistence.repository.moim.moim.MoimJpaRepository; +import org.springframework.transaction.annotation.Transactional; + +@Implement +public class MoimAppender { + + private final MoimJpaRepository moimJpaRepository; + + public MoimAppender(final MoimJpaRepository moimJpaRepository) { + this.moimJpaRepository = moimJpaRepository; + } + + @Transactional + public void createPublicMoim(final long memberId, final long universityId, + final PublicMoimAppendRequest publicMoimAppendRequest) { + + } +} diff --git a/backend/src/main/java/moim_today/presentation/moim/MoimController.java b/backend/src/main/java/moim_today/presentation/moim/MoimController.java new file mode 100644 index 00000000..6d8b1bcd --- /dev/null +++ b/backend/src/main/java/moim_today/presentation/moim/MoimController.java @@ -0,0 +1,27 @@ +package moim_today.presentation.moim; + +import moim_today.application.moim.MoimService; +import moim_today.domain.member.MemberSession; +import moim_today.dto.moim.PublicMoimAppendRequest; +import moim_today.global.annotation.Login; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RequestMapping("/api/moims") +@RestController +public class MoimController { + + private final MoimService moimService; + + public MoimController(final MoimService moimService) { + this.moimService = moimService; + } + + @PostMapping() + public void createPubicMoim(@Login final MemberSession memberSession, + @RequestBody final PublicMoimAppendRequest publicMoimAppendRequest) { + moimService.createPublicMoim(memberSession.id(), memberSession.universityId(), publicMoimAppendRequest); + } +} From ca2df0a2a1b53a6059986b9273da992b413b57bb Mon Sep 17 00:00:00 2001 From: Yang JiWoong Date: Thu, 18 Apr 2024 11:10:28 +0900 Subject: [PATCH 03/52] =?UTF-8?q?[BE]=20feat=20:=20=EB=B9=84=EA=B3=B5?= =?UTF-8?q?=EA=B0=9C=20=EB=AA=A8=EC=9E=84=20=EC=83=9D=EC=84=B1=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=ED=8B=80=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../moim_today/application/moim/MoimService.java | 6 ++++++ .../dto/moim/PrivateMoimAppendRequest.java | 16 ++++++++++++++++ .../moim_today/implement/moim/MoimAppender.java | 7 +++++++ .../presentation/moim/MoimController.java | 9 ++++++++- 4 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 backend/src/main/java/moim_today/dto/moim/PrivateMoimAppendRequest.java diff --git a/backend/src/main/java/moim_today/application/moim/MoimService.java b/backend/src/main/java/moim_today/application/moim/MoimService.java index c7717c2c..883ba986 100644 --- a/backend/src/main/java/moim_today/application/moim/MoimService.java +++ b/backend/src/main/java/moim_today/application/moim/MoimService.java @@ -1,5 +1,6 @@ package moim_today.application.moim; +import moim_today.dto.moim.PrivateMoimAppendRequest; import moim_today.dto.moim.PublicMoimAppendRequest; import moim_today.implement.moim.MoimAppender; import org.springframework.stereotype.Service; @@ -17,4 +18,9 @@ public void createPublicMoim(final long memberId, final long universityId, final PublicMoimAppendRequest publicMoimAppendRequest) { moimAppender.createPublicMoim(memberId, universityId, publicMoimAppendRequest); } + + public void createPrivateMoim(final long memberId, final long universityId, + final PrivateMoimAppendRequest privateMoimAppendRequest) { + moimAppender.createPrivateMoim(memberId, universityId, privateMoimAppendRequest); + } } diff --git a/backend/src/main/java/moim_today/dto/moim/PrivateMoimAppendRequest.java b/backend/src/main/java/moim_today/dto/moim/PrivateMoimAppendRequest.java new file mode 100644 index 00000000..104e7128 --- /dev/null +++ b/backend/src/main/java/moim_today/dto/moim/PrivateMoimAppendRequest.java @@ -0,0 +1,16 @@ +package moim_today.dto.moim; + +import moim_today.domain.moim.enums.MoimCategory; + +import java.time.LocalDate; + +public record PrivateMoimAppendRequest( + String title, + String contents, + int capacity, + String password, + MoimCategory moimCategory, + LocalDate startDate, + LocalDate endDate +) { +} diff --git a/backend/src/main/java/moim_today/implement/moim/MoimAppender.java b/backend/src/main/java/moim_today/implement/moim/MoimAppender.java index 8c50c4ce..d1f3f4b7 100644 --- a/backend/src/main/java/moim_today/implement/moim/MoimAppender.java +++ b/backend/src/main/java/moim_today/implement/moim/MoimAppender.java @@ -1,5 +1,6 @@ package moim_today.implement.moim; +import moim_today.dto.moim.PrivateMoimAppendRequest; import moim_today.dto.moim.PublicMoimAppendRequest; import moim_today.global.annotation.Implement; import moim_today.persistence.repository.moim.moim.MoimJpaRepository; @@ -19,4 +20,10 @@ public void createPublicMoim(final long memberId, final long universityId, final PublicMoimAppendRequest publicMoimAppendRequest) { } + + @Transactional + public void createPrivateMoim(final long memberId, final long universityId, + final PrivateMoimAppendRequest privateMoimAppendRequest) { + + } } diff --git a/backend/src/main/java/moim_today/presentation/moim/MoimController.java b/backend/src/main/java/moim_today/presentation/moim/MoimController.java index 6d8b1bcd..4d009e09 100644 --- a/backend/src/main/java/moim_today/presentation/moim/MoimController.java +++ b/backend/src/main/java/moim_today/presentation/moim/MoimController.java @@ -2,6 +2,7 @@ import moim_today.application.moim.MoimService; import moim_today.domain.member.MemberSession; +import moim_today.dto.moim.PrivateMoimAppendRequest; import moim_today.dto.moim.PublicMoimAppendRequest; import moim_today.global.annotation.Login; import org.springframework.web.bind.annotation.PostMapping; @@ -19,9 +20,15 @@ public MoimController(final MoimService moimService) { this.moimService = moimService; } - @PostMapping() + @PostMapping("/pubilc") public void createPubicMoim(@Login final MemberSession memberSession, @RequestBody final PublicMoimAppendRequest publicMoimAppendRequest) { moimService.createPublicMoim(memberSession.id(), memberSession.universityId(), publicMoimAppendRequest); } + + @PostMapping("/private") + public void createPrivateMoim(@Login final MemberSession memberSession, + @RequestBody final PrivateMoimAppendRequest privateMoimAppendRequest) { + moimService.createPrivateMoim(memberSession.id(), memberSession.universityId(), privateMoimAppendRequest); + } } From c7375d3e80c5435361e3a1f4a8e291fe1e965b8a Mon Sep 17 00:00:00 2001 From: Yang JiWoong Date: Thu, 18 Apr 2024 11:22:52 +0900 Subject: [PATCH 04/52] =?UTF-8?q?[BE]=20fix=20:=20MoimAppender=EA=B0=80=20?= =?UTF-8?q?JpaRepo=EB=A5=BC=20=EC=9D=98=EC=A1=B4=ED=95=98=EC=A7=80=20?= =?UTF-8?q?=EC=95=8A=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/moim_today/implement/moim/MoimAppender.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/src/main/java/moim_today/implement/moim/MoimAppender.java b/backend/src/main/java/moim_today/implement/moim/MoimAppender.java index d1f3f4b7..b82c85b5 100644 --- a/backend/src/main/java/moim_today/implement/moim/MoimAppender.java +++ b/backend/src/main/java/moim_today/implement/moim/MoimAppender.java @@ -3,16 +3,16 @@ import moim_today.dto.moim.PrivateMoimAppendRequest; import moim_today.dto.moim.PublicMoimAppendRequest; import moim_today.global.annotation.Implement; -import moim_today.persistence.repository.moim.moim.MoimJpaRepository; +import moim_today.persistence.repository.moim.moim.MoimRepository; import org.springframework.transaction.annotation.Transactional; @Implement public class MoimAppender { - private final MoimJpaRepository moimJpaRepository; + private final MoimRepository moimRepository; - public MoimAppender(final MoimJpaRepository moimJpaRepository) { - this.moimJpaRepository = moimJpaRepository; + public MoimAppender(final MoimRepository moimRepository) { + this.moimRepository = moimRepository; } @Transactional From c661adad218b84747254d9d43a3475df875322fb Mon Sep 17 00:00:00 2001 From: Yang JiWoong Date: Thu, 18 Apr 2024 13:27:48 +0900 Subject: [PATCH 05/52] =?UTF-8?q?[BE]=20refactor=20:=20=EB=AA=A8=EC=9E=84?= =?UTF-8?q?=20=EC=97=94=ED=8B=B0=ED=8B=B0=EC=97=90=20=EA=B3=B5=EA=B0=9C=20?= =?UTF-8?q?=EC=97=AC=EB=B6=80=20=ED=95=84=EB=93=9C=20=EC=B6=94=EA=B0=80(Di?= =?UTF-8?q?splayStatus)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/moim_today/domain/moim/DisplayStatus.java | 6 ++++++ .../persistence/entity/moim/moim/MoimJpaEntity.java | 8 +++++++- 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 backend/src/main/java/moim_today/domain/moim/DisplayStatus.java diff --git a/backend/src/main/java/moim_today/domain/moim/DisplayStatus.java b/backend/src/main/java/moim_today/domain/moim/DisplayStatus.java new file mode 100644 index 00000000..33ab452b --- /dev/null +++ b/backend/src/main/java/moim_today/domain/moim/DisplayStatus.java @@ -0,0 +1,6 @@ +package moim_today.domain.moim; + +public enum DisplayStatus { + + PUBILC, PRIAVE +} diff --git a/backend/src/main/java/moim_today/persistence/entity/moim/moim/MoimJpaEntity.java b/backend/src/main/java/moim_today/persistence/entity/moim/moim/MoimJpaEntity.java index 22c82fa4..b6a4a883 100644 --- a/backend/src/main/java/moim_today/persistence/entity/moim/moim/MoimJpaEntity.java +++ b/backend/src/main/java/moim_today/persistence/entity/moim/moim/MoimJpaEntity.java @@ -3,6 +3,7 @@ import jakarta.persistence.*; import lombok.Builder; import lombok.Getter; +import moim_today.domain.moim.DisplayStatus; import moim_today.domain.moim.enums.MoimCategory; import moim_today.global.annotation.Association; import moim_today.global.base_entity.BaseTimeEntity; @@ -39,6 +40,9 @@ public class MoimJpaEntity extends BaseTimeEntity { @Enumerated(EnumType.STRING) private MoimCategory moimCategory; + @Enumerated(EnumType.STRING) + private DisplayStatus displayStatus; + private int views; private LocalDate startDate; @@ -52,7 +56,8 @@ protected MoimJpaEntity() { private MoimJpaEntity(final long universityId, final long memberId, final String title, final String contents, final int capacity, final int currentCount, final String imageUrl, final String password, final MoimCategory moimCategory, - final int views, final LocalDate startDate, final LocalDate endDate) { + final DisplayStatus displayStatus, final int views, + final LocalDate startDate, final LocalDate endDate) { this.universityId = universityId; this.memberId = memberId; this.title = title; @@ -62,6 +67,7 @@ private MoimJpaEntity(final long universityId, final long memberId, final String this.imageUrl = imageUrl; this.password = password; this.moimCategory = moimCategory; + this.displayStatus = displayStatus; this.views = views; this.startDate = startDate; this.endDate = endDate; From 423b72b14c08b0bab0ecebd5306c60c292071061 Mon Sep 17 00:00:00 2001 From: Yang JiWoong Date: Thu, 18 Apr 2024 13:56:34 +0900 Subject: [PATCH 06/52] =?UTF-8?q?[BE]=20feat=20:=20=EA=B3=B5=EA=B0=9C=20?= =?UTF-8?q?=EB=AA=A8=EC=9E=84=20=EC=83=9D=EC=84=B1=20=EB=A1=9C=EC=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/moim/PublicMoimAppendRequest.java | 39 +++++++++++++++++++ .../global/constant/MoimConstant.java | 17 ++++++++ .../global/constant/NumberConstant.java | 3 ++ .../implement/moim/MoimAppender.java | 3 ++ .../repository/moim/moim/MoimRepository.java | 4 ++ .../moim/moim/MoimRepositoryImpl.java | 6 +++ 6 files changed, 72 insertions(+) create mode 100644 backend/src/main/java/moim_today/global/constant/MoimConstant.java diff --git a/backend/src/main/java/moim_today/dto/moim/PublicMoimAppendRequest.java b/backend/src/main/java/moim_today/dto/moim/PublicMoimAppendRequest.java index 7bb16373..9291d673 100644 --- a/backend/src/main/java/moim_today/dto/moim/PublicMoimAppendRequest.java +++ b/backend/src/main/java/moim_today/dto/moim/PublicMoimAppendRequest.java @@ -1,15 +1,54 @@ package moim_today.dto.moim; +import moim_today.domain.moim.DisplayStatus; import moim_today.domain.moim.enums.MoimCategory; +import moim_today.persistence.entity.moim.moim.MoimJpaEntity; +import moim_today.persistence.entity.moim.moim.MoimJpaEntity.MoimJpaEntityBuilder; import java.time.LocalDate; +import static moim_today.global.constant.MoimConstant.DEFAULT_MOIM_IMAGE_URL; +import static moim_today.global.constant.MoimConstant.DEFAULT_MOIM_PASSWORD; +import static moim_today.global.constant.NumberConstant.DEFAULT_MOIM_CURRENT_COUNT; +import static moim_today.global.constant.NumberConstant.DEFAULT_MOIM_VIEWS; + public record PublicMoimAppendRequest( String title, String contents, int capacity, + String imageUrl, MoimCategory moimCategory, LocalDate startDate, LocalDate endDate ) { + + public MoimJpaEntity toEntity(final long memberId, final long universityId) { + + MoimJpaEntityBuilder moimJpaEntityBuilder = MoimJpaEntity.builder() + .memberId(memberId) + .universityId(universityId) + .title(title) + .contents(contents) + .capacity(capacity) + .currentCount(DEFAULT_MOIM_CURRENT_COUNT.value()) + .password(DEFAULT_MOIM_PASSWORD.value()) + .moimCategory(moimCategory) + .displayStatus(DisplayStatus.PUBILC) + .views(DEFAULT_MOIM_VIEWS.value()) + .startDate(startDate) + .endDate(endDate); + + if (imageUrl.isEmpty()) { + return buildMoimByImageUrl(moimJpaEntityBuilder, DEFAULT_MOIM_IMAGE_URL.value()); + } else { + return buildMoimByImageUrl(moimJpaEntityBuilder, imageUrl); + } + } + + private MoimJpaEntity buildMoimByImageUrl(final MoimJpaEntityBuilder moimJpaEntityBuilder, + final String imageUrl) { + return moimJpaEntityBuilder + .imageUrl(imageUrl) + .build(); + } } diff --git a/backend/src/main/java/moim_today/global/constant/MoimConstant.java b/backend/src/main/java/moim_today/global/constant/MoimConstant.java new file mode 100644 index 00000000..966fe062 --- /dev/null +++ b/backend/src/main/java/moim_today/global/constant/MoimConstant.java @@ -0,0 +1,17 @@ +package moim_today.global.constant; + +public enum MoimConstant { + //TODO: 기본 모임 이미지 추가 예정 + DEFAULT_MOIM_IMAGE_URL("defaultMoimImageUrl"), + DEFAULT_MOIM_PASSWORD("NONE"); + + private final String value; + + MoimConstant(final String value) { + this.value = value; + } + + public String value() { + return value; + } +} diff --git a/backend/src/main/java/moim_today/global/constant/NumberConstant.java b/backend/src/main/java/moim_today/global/constant/NumberConstant.java index 66d2e535..16933000 100644 --- a/backend/src/main/java/moim_today/global/constant/NumberConstant.java +++ b/backend/src/main/java/moim_today/global/constant/NumberConstant.java @@ -8,6 +8,9 @@ public enum NumberConstant { SLASH_CNT_START(0), MAX_SLASH_CNT(2), + DEFAULT_MOIM_CURRENT_COUNT(1), + DEFAULT_MOIM_VIEWS(0), + SCHEDULE_MEETING_ID(0), TIME_TABLE_SCHEDULING_COUNT(10), diff --git a/backend/src/main/java/moim_today/implement/moim/MoimAppender.java b/backend/src/main/java/moim_today/implement/moim/MoimAppender.java index b82c85b5..251d3591 100644 --- a/backend/src/main/java/moim_today/implement/moim/MoimAppender.java +++ b/backend/src/main/java/moim_today/implement/moim/MoimAppender.java @@ -3,6 +3,7 @@ import moim_today.dto.moim.PrivateMoimAppendRequest; import moim_today.dto.moim.PublicMoimAppendRequest; import moim_today.global.annotation.Implement; +import moim_today.persistence.entity.moim.moim.MoimJpaEntity; import moim_today.persistence.repository.moim.moim.MoimRepository; import org.springframework.transaction.annotation.Transactional; @@ -19,6 +20,8 @@ public MoimAppender(final MoimRepository moimRepository) { public void createPublicMoim(final long memberId, final long universityId, final PublicMoimAppendRequest publicMoimAppendRequest) { + MoimJpaEntity moimJpaEntity = publicMoimAppendRequest.toEntity(memberId, universityId); + moimRepository.save(moimJpaEntity); } @Transactional diff --git a/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepository.java b/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepository.java index ddfa0bc3..b7373996 100644 --- a/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepository.java +++ b/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepository.java @@ -1,4 +1,8 @@ package moim_today.persistence.repository.moim.moim; +import moim_today.persistence.entity.moim.moim.MoimJpaEntity; + public interface MoimRepository { + + void save(MoimJpaEntity moimJpaEntity); } diff --git a/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepositoryImpl.java b/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepositoryImpl.java index c7d43851..0625a6ac 100644 --- a/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepositoryImpl.java +++ b/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepositoryImpl.java @@ -1,5 +1,6 @@ package moim_today.persistence.repository.moim.moim; +import moim_today.persistence.entity.moim.moim.MoimJpaEntity; import org.springframework.stereotype.Repository; @Repository @@ -10,4 +11,9 @@ public class MoimRepositoryImpl implements MoimRepository { public MoimRepositoryImpl(final MoimJpaRepository moimJpaRepository) { this.moimJpaRepository = moimJpaRepository; } + + @Override + public void save(final MoimJpaEntity moimJpaEntity) { + moimJpaRepository.save(moimJpaEntity); + } } From 2c82ecc77a1395cffb1dd7f5d902610f7704cea0 Mon Sep 17 00:00:00 2001 From: Yang JiWoong Date: Thu, 18 Apr 2024 20:02:27 +0900 Subject: [PATCH 07/52] =?UTF-8?q?[BE]=20feat=20:=20=EB=B9=84=EA=B3=B5?= =?UTF-8?q?=EA=B0=9C=20=EB=AA=A8=EC=9E=84=20=EC=83=9D=EC=84=B1=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/.gitignore | 3 ++ .../dto/moim/PrivateMoimAppendRequest.java | 38 +++++++++++++++++++ .../dto/moim/PublicMoimAppendRequest.java | 2 +- .../global/constant/MoimConstant.java | 4 +- .../implement/moim/MoimAppender.java | 3 +- 5 files changed, 46 insertions(+), 4 deletions(-) diff --git a/backend/.gitignore b/backend/.gitignore index fea34685..9f039158 100644 --- a/backend/.gitignore +++ b/backend/.gitignore @@ -8,6 +8,9 @@ build/ ### Generated ### **/src/main/generated/ +### initDB ### +**/src/main/java/moim_today/global/init/** + ### Properties ### application.yml application-dev.yml diff --git a/backend/src/main/java/moim_today/dto/moim/PrivateMoimAppendRequest.java b/backend/src/main/java/moim_today/dto/moim/PrivateMoimAppendRequest.java index 104e7128..2b4532ef 100644 --- a/backend/src/main/java/moim_today/dto/moim/PrivateMoimAppendRequest.java +++ b/backend/src/main/java/moim_today/dto/moim/PrivateMoimAppendRequest.java @@ -1,16 +1,54 @@ package moim_today.dto.moim; +import moim_today.domain.moim.DisplayStatus; import moim_today.domain.moim.enums.MoimCategory; +import moim_today.persistence.entity.moim.moim.MoimJpaEntity; +import moim_today.persistence.entity.moim.moim.MoimJpaEntity.MoimJpaEntityBuilder; import java.time.LocalDate; +import static moim_today.global.constant.MoimConstant.DEFAULT_MOIM_IMAGE_URL; +import static moim_today.global.constant.NumberConstant.DEFAULT_MOIM_CURRENT_COUNT; +import static moim_today.global.constant.NumberConstant.DEFAULT_MOIM_VIEWS; + public record PrivateMoimAppendRequest( String title, String contents, int capacity, String password, + String imageUrl, MoimCategory moimCategory, LocalDate startDate, LocalDate endDate ) { + + public MoimJpaEntity toEntity(final long memberId, final long universityId) { + + MoimJpaEntityBuilder moimJpaEntityBuilder = MoimJpaEntity.builder() + .universityId(universityId) + .memberId(memberId) + .title(title) + .contents(contents) + .capacity(capacity) + .currentCount(DEFAULT_MOIM_CURRENT_COUNT.value()) + .password(password) + .moimCategory(moimCategory) + .displayStatus(DisplayStatus.PRIAVE) + .views(DEFAULT_MOIM_VIEWS.value()) + .startDate(startDate) + .endDate(endDate); + + if (imageUrl.isEmpty()) { + return buildMoimByImageUrl(moimJpaEntityBuilder, DEFAULT_MOIM_IMAGE_URL.value()); + } else{ + return buildMoimByImageUrl(moimJpaEntityBuilder, imageUrl); + } + } + + private MoimJpaEntity buildMoimByImageUrl(final MoimJpaEntityBuilder moimJpaEntityBuilder, + final String imageUrl) { + return moimJpaEntityBuilder + .imageUrl(imageUrl) + .build(); + } } diff --git a/backend/src/main/java/moim_today/dto/moim/PublicMoimAppendRequest.java b/backend/src/main/java/moim_today/dto/moim/PublicMoimAppendRequest.java index 9291d673..29bbbe43 100644 --- a/backend/src/main/java/moim_today/dto/moim/PublicMoimAppendRequest.java +++ b/backend/src/main/java/moim_today/dto/moim/PublicMoimAppendRequest.java @@ -25,8 +25,8 @@ public record PublicMoimAppendRequest( public MoimJpaEntity toEntity(final long memberId, final long universityId) { MoimJpaEntityBuilder moimJpaEntityBuilder = MoimJpaEntity.builder() - .memberId(memberId) .universityId(universityId) + .memberId(memberId) .title(title) .contents(contents) .capacity(capacity) diff --git a/backend/src/main/java/moim_today/global/constant/MoimConstant.java b/backend/src/main/java/moim_today/global/constant/MoimConstant.java index 966fe062..2cc4947e 100644 --- a/backend/src/main/java/moim_today/global/constant/MoimConstant.java +++ b/backend/src/main/java/moim_today/global/constant/MoimConstant.java @@ -1,8 +1,8 @@ package moim_today.global.constant; public enum MoimConstant { - //TODO: 기본 모임 이미지 추가 예정 - DEFAULT_MOIM_IMAGE_URL("defaultMoimImageUrl"), + + DEFAULT_MOIM_IMAGE_URL("https://anak2.s3.ap-northeast-2.amazonaws.com/moim/default-moim.jpg"), DEFAULT_MOIM_PASSWORD("NONE"); private final String value; diff --git a/backend/src/main/java/moim_today/implement/moim/MoimAppender.java b/backend/src/main/java/moim_today/implement/moim/MoimAppender.java index 251d3591..1710ffad 100644 --- a/backend/src/main/java/moim_today/implement/moim/MoimAppender.java +++ b/backend/src/main/java/moim_today/implement/moim/MoimAppender.java @@ -27,6 +27,7 @@ public void createPublicMoim(final long memberId, final long universityId, @Transactional public void createPrivateMoim(final long memberId, final long universityId, final PrivateMoimAppendRequest privateMoimAppendRequest) { - + MoimJpaEntity moimJpaEntity = privateMoimAppendRequest.toEntity(memberId, universityId); + moimRepository.save(moimJpaEntity); } } From 0568e375dbfa1c848423f5fbfdda01c21bf4698c Mon Sep 17 00:00:00 2001 From: Yang JiWoong Date: Wed, 24 Apr 2024 19:33:02 +0900 Subject: [PATCH 08/52] =?UTF-8?q?[BE]=20feat=20:=20=EB=AC=B8=EC=84=9C?= =?UTF-8?q?=ED=99=94=EB=A5=BC=20=EC=9C=84=ED=95=9C=20FakeMoimService=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 --- .../application/moim/MoimService.java | 23 ++++----------- .../application/moim/MoimServiceImpl.java | 28 +++++++++++++++++++ .../presentation/moim/MoimController.java | 1 + .../fake_class/moim/FakeMoimService.java | 18 ++++++++++++ .../presentation/moim/MoimControllerTest.java | 15 ++++++++++ 5 files changed, 67 insertions(+), 18 deletions(-) create mode 100644 backend/src/main/java/moim_today/application/moim/MoimServiceImpl.java create mode 100644 backend/src/test/java/moim_today/fake_class/moim/FakeMoimService.java create mode 100644 backend/src/test/java/moim_today/presentation/moim/MoimControllerTest.java diff --git a/backend/src/main/java/moim_today/application/moim/MoimService.java b/backend/src/main/java/moim_today/application/moim/MoimService.java index 883ba986..38a05db6 100644 --- a/backend/src/main/java/moim_today/application/moim/MoimService.java +++ b/backend/src/main/java/moim_today/application/moim/MoimService.java @@ -2,25 +2,12 @@ import moim_today.dto.moim.PrivateMoimAppendRequest; import moim_today.dto.moim.PublicMoimAppendRequest; -import moim_today.implement.moim.MoimAppender; -import org.springframework.stereotype.Service; -@Service -public class MoimService { +public interface MoimService { - private final MoimAppender moimAppender; + void createPublicMoim(final long memberId, final long universityId, + final PublicMoimAppendRequest publicMoimAppendRequest); - public MoimService(final MoimAppender moimAppender) { - this.moimAppender = moimAppender; - } - - public void createPublicMoim(final long memberId, final long universityId, - final PublicMoimAppendRequest publicMoimAppendRequest) { - moimAppender.createPublicMoim(memberId, universityId, publicMoimAppendRequest); - } - - public void createPrivateMoim(final long memberId, final long universityId, - final PrivateMoimAppendRequest privateMoimAppendRequest) { - moimAppender.createPrivateMoim(memberId, universityId, privateMoimAppendRequest); - } + void createPrivateMoim(final long memberId, final long universityId, + final PrivateMoimAppendRequest privateMoimAppendRequest); } diff --git a/backend/src/main/java/moim_today/application/moim/MoimServiceImpl.java b/backend/src/main/java/moim_today/application/moim/MoimServiceImpl.java new file mode 100644 index 00000000..21cb4dad --- /dev/null +++ b/backend/src/main/java/moim_today/application/moim/MoimServiceImpl.java @@ -0,0 +1,28 @@ +package moim_today.application.moim; + +import moim_today.dto.moim.PrivateMoimAppendRequest; +import moim_today.dto.moim.PublicMoimAppendRequest; +import moim_today.implement.moim.MoimAppender; +import org.springframework.stereotype.Service; + +@Service +public class MoimServiceImpl implements MoimService{ + + private final MoimAppender moimAppender; + + public MoimServiceImpl(final MoimAppender moimAppender) { + this.moimAppender = moimAppender; + } + + @Override + public void createPublicMoim(final long memberId, final long universityId, + final PublicMoimAppendRequest publicMoimAppendRequest) { + moimAppender.createPublicMoim(memberId, universityId, publicMoimAppendRequest); + } + + @Override + public void createPrivateMoim(final long memberId, final long universityId, + final PrivateMoimAppendRequest privateMoimAppendRequest) { + moimAppender.createPrivateMoim(memberId, universityId, privateMoimAppendRequest); + } +} diff --git a/backend/src/main/java/moim_today/presentation/moim/MoimController.java b/backend/src/main/java/moim_today/presentation/moim/MoimController.java index 4d009e09..7032010e 100644 --- a/backend/src/main/java/moim_today/presentation/moim/MoimController.java +++ b/backend/src/main/java/moim_today/presentation/moim/MoimController.java @@ -1,6 +1,7 @@ package moim_today.presentation.moim; import moim_today.application.moim.MoimService; +import moim_today.application.moim.MoimServiceImpl; import moim_today.domain.member.MemberSession; import moim_today.dto.moim.PrivateMoimAppendRequest; import moim_today.dto.moim.PublicMoimAppendRequest; diff --git a/backend/src/test/java/moim_today/fake_class/moim/FakeMoimService.java b/backend/src/test/java/moim_today/fake_class/moim/FakeMoimService.java new file mode 100644 index 00000000..0c1546b0 --- /dev/null +++ b/backend/src/test/java/moim_today/fake_class/moim/FakeMoimService.java @@ -0,0 +1,18 @@ +package moim_today.fake_class.moim; + +import moim_today.application.moim.MoimService; +import moim_today.dto.moim.PrivateMoimAppendRequest; +import moim_today.dto.moim.PublicMoimAppendRequest; + +public class FakeMoimService implements MoimService { + + @Override + public void createPublicMoim(final long memberId, final long universityId, final PublicMoimAppendRequest publicMoimAppendRequest) { + + } + + @Override + public void createPrivateMoim(final long memberId, final long universityId, final PrivateMoimAppendRequest privateMoimAppendRequest) { + + } +} diff --git a/backend/src/test/java/moim_today/presentation/moim/MoimControllerTest.java b/backend/src/test/java/moim_today/presentation/moim/MoimControllerTest.java new file mode 100644 index 00000000..3f0fe7b1 --- /dev/null +++ b/backend/src/test/java/moim_today/presentation/moim/MoimControllerTest.java @@ -0,0 +1,15 @@ +package moim_today.presentation.moim; + +import moim_today.fake_class.moim.FakeMoimService; +import moim_today.util.ControllerTest; + +class MoimControllerTest extends ControllerTest { + + private final FakeMoimService fakeMoimService = new FakeMoimService(); + + @Override + protected Object initController() { + return new MoimController(fakeMoimService); + } + +} \ No newline at end of file From 34844ba83cefccff07348e89ee888bd3efd68e6c Mon Sep 17 00:00:00 2001 From: Yang JiWoong Date: Wed, 24 Apr 2024 19:56:33 +0900 Subject: [PATCH 09/52] =?UTF-8?q?[BE]=20fix=20:=20=EA=B3=B5=EA=B0=9C=20?= =?UTF-8?q?=EB=AA=A8=EC=9E=84=20=EC=83=9D=EC=84=B1=20URL=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/moim_today/presentation/moim/MoimController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/moim_today/presentation/moim/MoimController.java b/backend/src/main/java/moim_today/presentation/moim/MoimController.java index 7032010e..0e63157b 100644 --- a/backend/src/main/java/moim_today/presentation/moim/MoimController.java +++ b/backend/src/main/java/moim_today/presentation/moim/MoimController.java @@ -21,7 +21,7 @@ public MoimController(final MoimService moimService) { this.moimService = moimService; } - @PostMapping("/pubilc") + @PostMapping("/public") public void createPubicMoim(@Login final MemberSession memberSession, @RequestBody final PublicMoimAppendRequest publicMoimAppendRequest) { moimService.createPublicMoim(memberSession.id(), memberSession.universityId(), publicMoimAppendRequest); From 3943f30e70de9e40e98772450bac6c1ecb39d5d3 Mon Sep 17 00:00:00 2001 From: Yang JiWoong Date: Wed, 24 Apr 2024 20:01:33 +0900 Subject: [PATCH 10/52] =?UTF-8?q?[BE]=20feat=20:=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=EB=A5=BC=20=EC=9C=84=ED=95=9C=20=EB=AA=A8=EC=9E=84=20?= =?UTF-8?q?=EC=B9=B4=ED=85=8C=EA=B3=A0=EB=A6=AC=20=EC=9E=84=EC=9D=98=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/moim_today/domain/moim/enums/MoimCategory.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/src/main/java/moim_today/domain/moim/enums/MoimCategory.java b/backend/src/main/java/moim_today/domain/moim/enums/MoimCategory.java index ab08b5e9..b3d25e55 100644 --- a/backend/src/main/java/moim_today/domain/moim/enums/MoimCategory.java +++ b/backend/src/main/java/moim_today/domain/moim/enums/MoimCategory.java @@ -2,4 +2,6 @@ // todo 정기 모임 카테고리 세부사항 추가 public enum MoimCategory { + + STUDY, TEAM_PROJECT } From 0c9334016c4273ffba878b93366b5ec954f0c3f8 Mon Sep 17 00:00:00 2001 From: Yang JiWoong Date: Wed, 24 Apr 2024 20:28:45 +0900 Subject: [PATCH 11/52] =?UTF-8?q?[BE]=20refactor=20:=20=EB=AA=A8=EC=9E=84?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1=20=ED=85=8C=EC=8A=A4=ED=8A=B8=EB=A5=BC=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20=EB=B0=98=ED=99=98=20=EA=B0=9D=EC=B2=B4=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/moim_today/implement/moim/MoimAppender.java | 8 ++++---- .../persistence/repository/moim/moim/MoimRepository.java | 2 +- .../repository/moim/moim/MoimRepositoryImpl.java | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/backend/src/main/java/moim_today/implement/moim/MoimAppender.java b/backend/src/main/java/moim_today/implement/moim/MoimAppender.java index 1710ffad..af35a76d 100644 --- a/backend/src/main/java/moim_today/implement/moim/MoimAppender.java +++ b/backend/src/main/java/moim_today/implement/moim/MoimAppender.java @@ -17,17 +17,17 @@ public MoimAppender(final MoimRepository moimRepository) { } @Transactional - public void createPublicMoim(final long memberId, final long universityId, + public MoimJpaEntity createPublicMoim(final long memberId, final long universityId, final PublicMoimAppendRequest publicMoimAppendRequest) { MoimJpaEntity moimJpaEntity = publicMoimAppendRequest.toEntity(memberId, universityId); - moimRepository.save(moimJpaEntity); + return moimRepository.save(moimJpaEntity); } @Transactional - public void createPrivateMoim(final long memberId, final long universityId, + public MoimJpaEntity createPrivateMoim(final long memberId, final long universityId, final PrivateMoimAppendRequest privateMoimAppendRequest) { MoimJpaEntity moimJpaEntity = privateMoimAppendRequest.toEntity(memberId, universityId); - moimRepository.save(moimJpaEntity); + return moimRepository.save(moimJpaEntity); } } diff --git a/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepository.java b/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepository.java index b7373996..4b5e665f 100644 --- a/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepository.java +++ b/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepository.java @@ -4,5 +4,5 @@ public interface MoimRepository { - void save(MoimJpaEntity moimJpaEntity); + MoimJpaEntity save(MoimJpaEntity moimJpaEntity); } diff --git a/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepositoryImpl.java b/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepositoryImpl.java index 0625a6ac..5a667709 100644 --- a/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepositoryImpl.java +++ b/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepositoryImpl.java @@ -13,7 +13,7 @@ public MoimRepositoryImpl(final MoimJpaRepository moimJpaRepository) { } @Override - public void save(final MoimJpaEntity moimJpaEntity) { - moimJpaRepository.save(moimJpaEntity); + public MoimJpaEntity save(final MoimJpaEntity moimJpaEntity) { + return moimJpaRepository.save(moimJpaEntity); } } From 1cc13d04c3bf50b2aedb023dddfaee78afe33128 Mon Sep 17 00:00:00 2001 From: Yang JiWoong Date: Wed, 24 Apr 2024 21:17:12 +0900 Subject: [PATCH 12/52] =?UTF-8?q?[BE]=20feat=20:=20=EB=AA=A8=EC=9E=84=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../moim_today/domain/moim/DisplayStatus.java | 2 +- .../dto/moim/PrivateMoimAppendRequest.java | 6 +- .../dto/moim/PublicMoimAppendRequest.java | 6 +- .../repository/moim/moim/MoimRepository.java | 2 + .../moim/moim/MoimRepositoryImpl.java | 5 + .../moim/PrivateMoimAppendRequestTest.java | 72 +++++++++++ .../dto/moim/PublicMoimAppendRequestTest.java | 70 +++++++++++ .../implement/moim/MoimAppenderTest.java | 118 ++++++++++++++++++ .../presentation/moim/MoimControllerTest.java | 96 +++++++++++++- .../java/moim_today/util/ImplementTest.java | 4 + .../java/moim_today/util/TestConstant.java | 24 +++- 11 files changed, 397 insertions(+), 8 deletions(-) create mode 100644 backend/src/test/java/moim_today/dto/moim/PrivateMoimAppendRequestTest.java create mode 100644 backend/src/test/java/moim_today/dto/moim/PublicMoimAppendRequestTest.java create mode 100644 backend/src/test/java/moim_today/implement/moim/MoimAppenderTest.java diff --git a/backend/src/main/java/moim_today/domain/moim/DisplayStatus.java b/backend/src/main/java/moim_today/domain/moim/DisplayStatus.java index 33ab452b..1ed31ba1 100644 --- a/backend/src/main/java/moim_today/domain/moim/DisplayStatus.java +++ b/backend/src/main/java/moim_today/domain/moim/DisplayStatus.java @@ -2,5 +2,5 @@ public enum DisplayStatus { - PUBILC, PRIAVE + PUBLIC, PRIVATE } diff --git a/backend/src/main/java/moim_today/dto/moim/PrivateMoimAppendRequest.java b/backend/src/main/java/moim_today/dto/moim/PrivateMoimAppendRequest.java index 2b4532ef..29a0e075 100644 --- a/backend/src/main/java/moim_today/dto/moim/PrivateMoimAppendRequest.java +++ b/backend/src/main/java/moim_today/dto/moim/PrivateMoimAppendRequest.java @@ -1,5 +1,6 @@ package moim_today.dto.moim; +import lombok.Builder; import moim_today.domain.moim.DisplayStatus; import moim_today.domain.moim.enums.MoimCategory; import moim_today.persistence.entity.moim.moim.MoimJpaEntity; @@ -11,6 +12,7 @@ import static moim_today.global.constant.NumberConstant.DEFAULT_MOIM_CURRENT_COUNT; import static moim_today.global.constant.NumberConstant.DEFAULT_MOIM_VIEWS; +@Builder public record PrivateMoimAppendRequest( String title, String contents, @@ -33,12 +35,12 @@ public MoimJpaEntity toEntity(final long memberId, final long universityId) { .currentCount(DEFAULT_MOIM_CURRENT_COUNT.value()) .password(password) .moimCategory(moimCategory) - .displayStatus(DisplayStatus.PRIAVE) + .displayStatus(DisplayStatus.PRIVATE) .views(DEFAULT_MOIM_VIEWS.value()) .startDate(startDate) .endDate(endDate); - if (imageUrl.isEmpty()) { + if (imageUrl == null) { return buildMoimByImageUrl(moimJpaEntityBuilder, DEFAULT_MOIM_IMAGE_URL.value()); } else{ return buildMoimByImageUrl(moimJpaEntityBuilder, imageUrl); diff --git a/backend/src/main/java/moim_today/dto/moim/PublicMoimAppendRequest.java b/backend/src/main/java/moim_today/dto/moim/PublicMoimAppendRequest.java index 29bbbe43..a54c3161 100644 --- a/backend/src/main/java/moim_today/dto/moim/PublicMoimAppendRequest.java +++ b/backend/src/main/java/moim_today/dto/moim/PublicMoimAppendRequest.java @@ -1,5 +1,6 @@ package moim_today.dto.moim; +import lombok.Builder; import moim_today.domain.moim.DisplayStatus; import moim_today.domain.moim.enums.MoimCategory; import moim_today.persistence.entity.moim.moim.MoimJpaEntity; @@ -12,6 +13,7 @@ import static moim_today.global.constant.NumberConstant.DEFAULT_MOIM_CURRENT_COUNT; import static moim_today.global.constant.NumberConstant.DEFAULT_MOIM_VIEWS; +@Builder public record PublicMoimAppendRequest( String title, String contents, @@ -33,12 +35,12 @@ public MoimJpaEntity toEntity(final long memberId, final long universityId) { .currentCount(DEFAULT_MOIM_CURRENT_COUNT.value()) .password(DEFAULT_MOIM_PASSWORD.value()) .moimCategory(moimCategory) - .displayStatus(DisplayStatus.PUBILC) + .displayStatus(DisplayStatus.PUBLIC) .views(DEFAULT_MOIM_VIEWS.value()) .startDate(startDate) .endDate(endDate); - if (imageUrl.isEmpty()) { + if (imageUrl == null) { return buildMoimByImageUrl(moimJpaEntityBuilder, DEFAULT_MOIM_IMAGE_URL.value()); } else { return buildMoimByImageUrl(moimJpaEntityBuilder, imageUrl); diff --git a/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepository.java b/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepository.java index 4b5e665f..49fa52b7 100644 --- a/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepository.java +++ b/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepository.java @@ -5,4 +5,6 @@ public interface MoimRepository { MoimJpaEntity save(MoimJpaEntity moimJpaEntity); + + long count(); } diff --git a/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepositoryImpl.java b/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepositoryImpl.java index 5a667709..cdc4c950 100644 --- a/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepositoryImpl.java +++ b/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepositoryImpl.java @@ -16,4 +16,9 @@ public MoimRepositoryImpl(final MoimJpaRepository moimJpaRepository) { public MoimJpaEntity save(final MoimJpaEntity moimJpaEntity) { return moimJpaRepository.save(moimJpaEntity); } + + @Override + public long count() { + return moimJpaRepository.count(); + } } diff --git a/backend/src/test/java/moim_today/dto/moim/PrivateMoimAppendRequestTest.java b/backend/src/test/java/moim_today/dto/moim/PrivateMoimAppendRequestTest.java new file mode 100644 index 00000000..e1739218 --- /dev/null +++ b/backend/src/test/java/moim_today/dto/moim/PrivateMoimAppendRequestTest.java @@ -0,0 +1,72 @@ +package moim_today.dto.moim; + +import moim_today.domain.moim.enums.MoimCategory; +import moim_today.persistence.entity.moim.moim.MoimJpaEntity; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.time.LocalDate; + +import static moim_today.global.constant.MoimConstant.DEFAULT_MOIM_IMAGE_URL; +import static moim_today.util.TestConstant.*; + +class PrivateMoimAppendRequestTest { + + @DisplayName("Request에 ImageUrl 값이 없다면 DefaultUrl을 가진 엔티티를 생성한다.") + @Test + void NoneImageUrlCreateEntityWithDefaultUrl() { + + //given + int capacity = Integer.parseInt(CAPACITY.value()); + long memberId = Long.parseLong(MEMBER_ID.value()); + long universityId = Long.parseLong(UNIV_ID.value()); + LocalDate startDate = LocalDate.of(2024, 03, 01); + LocalDate endDate = LocalDate.of(2024, 06, 30); + + PrivateMoimAppendRequest privateMoimAppendRequest = PrivateMoimAppendRequest.builder() + .title(TITLE.value()) + .contents(CONTENTS.value()) + .capacity(capacity) + .password(PASSWORD.value()) + .moimCategory(MoimCategory.STUDY) + .startDate(startDate) + .endDate(endDate) + .build(); + + //when + MoimJpaEntity entity = privateMoimAppendRequest.toEntity(memberId, universityId); + + //then + Assertions.assertThat((entity.getImageUrl())).isEqualTo(DEFAULT_MOIM_IMAGE_URL.value()); + } + + @DisplayName("Request에 ImageUrl 값이 있다면 엔티티에 정상적으로 들어간다.") + @Test + void CreateMoimJpaEntityWithRequestImageUrl() { + + //given + int capacity = Integer.parseInt(CAPACITY.value()); + long memberId = Long.parseLong(MEMBER_ID.value()); + long universityId = Long.parseLong(UNIV_ID.value()); + LocalDate startDate = LocalDate.of(2024, 03, 01); + LocalDate endDate = LocalDate.of(2024, 06, 30); + + PrivateMoimAppendRequest privateMoimAppendRequest = PrivateMoimAppendRequest.builder() + .title(TITLE.value()) + .contents(CONTENTS.value()) + .capacity(capacity) + .imageUrl(MOIM_IMAGE_URL.value()) + .password(PASSWORD.value()) + .moimCategory(MoimCategory.STUDY) + .startDate(startDate) + .endDate(endDate) + .build(); + + //when + MoimJpaEntity entity = privateMoimAppendRequest.toEntity(memberId, universityId); + + //then + Assertions.assertThat((entity.getImageUrl())).isEqualTo(MOIM_IMAGE_URL.value()); + } +} diff --git a/backend/src/test/java/moim_today/dto/moim/PublicMoimAppendRequestTest.java b/backend/src/test/java/moim_today/dto/moim/PublicMoimAppendRequestTest.java new file mode 100644 index 00000000..17f3ca52 --- /dev/null +++ b/backend/src/test/java/moim_today/dto/moim/PublicMoimAppendRequestTest.java @@ -0,0 +1,70 @@ +package moim_today.dto.moim; + +import moim_today.domain.moim.enums.MoimCategory; +import moim_today.persistence.entity.moim.moim.MoimJpaEntity; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.time.LocalDate; + +import static moim_today.global.constant.MoimConstant.DEFAULT_MOIM_IMAGE_URL; +import static moim_today.util.TestConstant.*; + +class PublicMoimAppendRequestTest { + + @DisplayName("Request에 ImageUrl 값이 없다면 DefaultUrl을 가진 엔티티를 생성한다.") + @Test + void NoneImageUrlCreateEntityWithDefaultUrl() { + + //given + int capacity = Integer.parseInt(CAPACITY.value()); + long memberId = Long.parseLong(MEMBER_ID.value()); + long universityId = Long.parseLong(UNIV_ID.value()); + LocalDate startDate = LocalDate.of(2024, 03, 01); + LocalDate endDate = LocalDate.of(2024, 06, 30); + + PublicMoimAppendRequest publicMoimAppendRequest = PublicMoimAppendRequest.builder() + .title(TITLE.value()) + .contents(CONTENTS.value()) + .capacity(capacity) + .moimCategory(MoimCategory.STUDY) + .startDate(startDate) + .endDate(endDate) + .build(); + + //when + MoimJpaEntity entity = publicMoimAppendRequest.toEntity(memberId, universityId); + + //then + Assertions.assertThat((entity.getImageUrl())).isEqualTo(DEFAULT_MOIM_IMAGE_URL.value()); + } + + @DisplayName("Request에 ImageUrl 값이 있다면 엔티티에 정상적으로 들어간다.") + @Test + void CreateMoimJpaEntityWithRequestImageUrl() { + + //given + int capacity = Integer.parseInt(CAPACITY.value()); + long memberId = Long.parseLong(MEMBER_ID.value()); + long universityId = Long.parseLong(UNIV_ID.value()); + LocalDate startDate = LocalDate.of(2024, 03, 01); + LocalDate endDate = LocalDate.of(2024, 06, 30); + + PublicMoimAppendRequest publicMoimAppendRequest = PublicMoimAppendRequest.builder() + .title(TITLE.value()) + .contents(CONTENTS.value()) + .capacity(capacity) + .imageUrl(MOIM_IMAGE_URL.value()) + .moimCategory(MoimCategory.STUDY) + .startDate(startDate) + .endDate(endDate) + .build(); + + //when + MoimJpaEntity entity = publicMoimAppendRequest.toEntity(memberId, universityId); + + //then + Assertions.assertThat((entity.getImageUrl())).isEqualTo(MOIM_IMAGE_URL.value()); + } +} diff --git a/backend/src/test/java/moim_today/implement/moim/MoimAppenderTest.java b/backend/src/test/java/moim_today/implement/moim/MoimAppenderTest.java new file mode 100644 index 00000000..10299c18 --- /dev/null +++ b/backend/src/test/java/moim_today/implement/moim/MoimAppenderTest.java @@ -0,0 +1,118 @@ +package moim_today.implement.moim; + +import moim_today.domain.moim.DisplayStatus; +import moim_today.domain.moim.enums.MoimCategory; +import moim_today.dto.moim.PrivateMoimAppendRequest; +import moim_today.dto.moim.PublicMoimAppendRequest; +import moim_today.persistence.entity.moim.moim.MoimJpaEntity; +import moim_today.util.ImplementTest; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.time.LocalDate; + +import static moim_today.global.constant.MoimConstant.DEFAULT_MOIM_PASSWORD; +import static moim_today.global.constant.NumberConstant.DEFAULT_MOIM_CURRENT_COUNT; +import static moim_today.global.constant.NumberConstant.DEFAULT_MOIM_VIEWS; +import static moim_today.util.TestConstant.*; +import static org.assertj.core.api.Assertions.assertThat; + +class MoimAppenderTest extends ImplementTest { + + @Autowired + private MoimAppender moimAppender; + + @DisplayName("공개 모임 생성 요청을 보내면 정상적으로 모든 필드가 초기화되어 DB에 저장된다.") + @Test + void savePublicMoim(){ + + //given + int capacity = Integer.parseInt(CAPACITY.value()); + long memberId = Long.parseLong(MEMBER_ID.value()); + long universityId = Long.parseLong(UNIV_ID.value()); + LocalDate startDate = LocalDate.of(2024, 03, 01); + LocalDate endDate = LocalDate.of(2024, 06, 30); + + PublicMoimAppendRequest publicMoimAppendRequest = new PublicMoimAppendRequest( + TITLE.value(), + CONTENTS.value(), + capacity, + MOIM_IMAGE_URL.value(), + MoimCategory.STUDY, + startDate, + endDate + ); + + //when + MoimJpaEntity moimJpaEntity = moimAppender.createPublicMoim( + memberId, + universityId, + publicMoimAppendRequest + ); + + //then + long count = moimRepository.count(); + assertThat(count).isEqualTo(1); + assertThat(moimJpaEntity.getMemberId()).isEqualTo(memberId); + assertThat(moimJpaEntity.getUniversityId()).isEqualTo(universityId); + assertThat(moimJpaEntity.getTitle()).isEqualTo(TITLE.value()); + assertThat(moimJpaEntity.getContents()).isEqualTo(CONTENTS.value()); + assertThat(moimJpaEntity.getCapacity()).isEqualTo(capacity); + assertThat(moimJpaEntity.getCurrentCount()).isEqualTo(DEFAULT_MOIM_CURRENT_COUNT.value()); + assertThat(moimJpaEntity.getImageUrl()).isEqualTo(MOIM_IMAGE_URL.value()); + assertThat(moimJpaEntity.getPassword()).isEqualTo(DEFAULT_MOIM_PASSWORD.value()); + assertThat(moimJpaEntity.getMoimCategory()).isEqualTo(MoimCategory.STUDY); + assertThat(moimJpaEntity.getDisplayStatus()).isEqualTo(DisplayStatus.PUBLIC); + assertThat(moimJpaEntity.getViews()).isEqualTo(DEFAULT_MOIM_VIEWS.value()); + assertThat(moimJpaEntity.getStartDate()).isEqualTo(startDate); + assertThat(moimJpaEntity.getEndDate()).isEqualTo(endDate); + } + + @DisplayName("비공개 모임 생성 요청을 보내면 정상적으로 모든 필드가 초기화되어 DB에 저장된다.") + @Test + void savePrivateMoim(){ + + //given + int capacity = Integer.parseInt(CAPACITY.value()); + long memberId = Long.parseLong(MEMBER_ID.value()); + long universityId = Long.parseLong(UNIV_ID.value()); + LocalDate startDate = LocalDate.of(2024, 03, 01); + LocalDate endDate = LocalDate.of(2024, 06, 30); + + PrivateMoimAppendRequest privateMoimAppendRequest = new PrivateMoimAppendRequest( + TITLE.value(), + CONTENTS.value(), + capacity, + PASSWORD.value(), + MOIM_IMAGE_URL.value(), + MoimCategory.STUDY, + startDate, + endDate + ); + + //when + MoimJpaEntity moimJpaEntity = moimAppender.createPrivateMoim( + memberId, + universityId, + privateMoimAppendRequest + ); + + //then + long count = moimRepository.count(); + assertThat(count).isEqualTo(1); + assertThat(moimJpaEntity.getMemberId()).isEqualTo(memberId); + assertThat(moimJpaEntity.getUniversityId()).isEqualTo(universityId); + assertThat(moimJpaEntity.getTitle()).isEqualTo(TITLE.value()); + assertThat(moimJpaEntity.getContents()).isEqualTo(CONTENTS.value()); + assertThat(moimJpaEntity.getCapacity()).isEqualTo(capacity); + assertThat(moimJpaEntity.getCurrentCount()).isEqualTo(DEFAULT_MOIM_CURRENT_COUNT.value()); + assertThat(moimJpaEntity.getImageUrl()).isEqualTo(MOIM_IMAGE_URL.value()); + assertThat(moimJpaEntity.getPassword()).isEqualTo(PASSWORD.value()); + assertThat(moimJpaEntity.getMoimCategory()).isEqualTo(MoimCategory.STUDY); + assertThat(moimJpaEntity.getDisplayStatus()).isEqualTo(DisplayStatus.PRIVATE); + assertThat(moimJpaEntity.getViews()).isEqualTo(DEFAULT_MOIM_VIEWS.value()); + assertThat(moimJpaEntity.getStartDate()).isEqualTo(startDate); + assertThat(moimJpaEntity.getEndDate()).isEqualTo(endDate); + } +} diff --git a/backend/src/test/java/moim_today/presentation/moim/MoimControllerTest.java b/backend/src/test/java/moim_today/presentation/moim/MoimControllerTest.java index 3f0fe7b1..097b942c 100644 --- a/backend/src/test/java/moim_today/presentation/moim/MoimControllerTest.java +++ b/backend/src/test/java/moim_today/presentation/moim/MoimControllerTest.java @@ -1,7 +1,24 @@ package moim_today.presentation.moim; +import com.epages.restdocs.apispec.ResourceSnippetParameters; +import moim_today.domain.moim.enums.MoimCategory; +import moim_today.dto.moim.PrivateMoimAppendRequest; +import moim_today.dto.moim.PublicMoimAppendRequest; import moim_today.fake_class.moim.FakeMoimService; import moim_today.util.ControllerTest; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.http.MediaType; + +import java.time.LocalDate; + +import static com.epages.restdocs.apispec.ResourceDocumentation.resource; +import static moim_today.util.TestConstant.*; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; +import static org.springframework.restdocs.payload.JsonFieldType.*; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; class MoimControllerTest extends ControllerTest { @@ -12,4 +29,81 @@ protected Object initController() { return new MoimController(fakeMoimService); } -} \ No newline at end of file + @DisplayName("공개 모임 생성 테스트") + @Test + void createPublicMoimApiTest() throws Exception { + LocalDate startDate = LocalDate.of(2024, 03, 01); + LocalDate endDate = LocalDate.of(2024, 06, 30); + + PublicMoimAppendRequest publicMoimAppendRequest = new PublicMoimAppendRequest( + TITLE.value(), + CONTENTS.value(), + Integer.parseInt(CAPACITY.value()), + MOIM_IMAGE_URL.value(), + MoimCategory.STUDY, + startDate, + endDate + ); + + mockMvc.perform(post("/api/moims/public") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(publicMoimAppendRequest)) + ) + .andExpect(status().isOk()) + .andDo(document("공개 모임 생성 성공", + resource(ResourceSnippetParameters.builder() + .tag("모임") + .summary("모임 생성") + .requestFields( + fieldWithPath("title").type(STRING).description("모임명"), + fieldWithPath("contents").type(STRING).description("내용"), + fieldWithPath("capacity").type(NUMBER).description("모집 인원"), + fieldWithPath("imageUrl").type(STRING).description("모임 사진 URL"), + fieldWithPath("moimCategory").type(VARIES).description("카테고리"), + fieldWithPath("startDate").type(STRING).description("시작 일자"), + fieldWithPath("endDate").type(STRING).description("종료 일자") + ) + .build() + ))); + } + + @DisplayName("비공개 모임 생성 테스트") + @Test + void createPrivateMoimApiTest() throws Exception { + LocalDate startDate = LocalDate.of(2024, 03, 01); + LocalDate endDate = LocalDate.of(2024, 06, 30); + + PrivateMoimAppendRequest privateMoimAppendRequest = new PrivateMoimAppendRequest( + TITLE.value(), + CONTENTS.value(), + Integer.parseInt(CAPACITY.value()), + PASSWORD.value(), + MOIM_IMAGE_URL.value(), + MoimCategory.STUDY, + startDate, + endDate + ); + + mockMvc.perform(post("/api/moims/private") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(privateMoimAppendRequest)) + ) + .andExpect(status().isOk()) + .andDo(document("비공개 모임 생성 성공", + resource(ResourceSnippetParameters.builder() + .tag("모임") + .summary("모임 생성") + .requestFields( + fieldWithPath("title").type(STRING).description("모임명"), + fieldWithPath("contents").type(STRING).description("내용"), + fieldWithPath("capacity").type(NUMBER).description("모집 인원"), + fieldWithPath("password").type(STRING).description("모임 비밀번호"), + fieldWithPath("imageUrl").type(STRING).description("모임 사진 URL"), + fieldWithPath("moimCategory").type(VARIES).description("카테고리"), + fieldWithPath("startDate").type(STRING).description("시작 일자"), + fieldWithPath("endDate").type(STRING).description("종료 일자") + ) + .build() + ))); + } +} diff --git a/backend/src/test/java/moim_today/util/ImplementTest.java b/backend/src/test/java/moim_today/util/ImplementTest.java index 1d4c21ee..0ac0efa9 100644 --- a/backend/src/test/java/moim_today/util/ImplementTest.java +++ b/backend/src/test/java/moim_today/util/ImplementTest.java @@ -5,6 +5,7 @@ import moim_today.persistence.repository.certification.password.PasswordCertificationRepository; import moim_today.persistence.repository.department.DepartmentRepository; import moim_today.persistence.repository.member.MemberRepository; +import moim_today.persistence.repository.moim.moim.MoimRepository; import moim_today.persistence.repository.schedule.ScheduleRepository; import moim_today.persistence.repository.university.UniversityRepository; import org.junit.jupiter.api.BeforeEach; @@ -36,6 +37,9 @@ public abstract class ImplementTest { @Autowired protected DepartmentRepository departmentRepository; + @Autowired + protected MoimRepository moimRepository; + @Autowired protected ScheduleRepository scheduleRepository; diff --git a/backend/src/test/java/moim_today/util/TestConstant.java b/backend/src/test/java/moim_today/util/TestConstant.java index e3bffe1f..662f52f6 100644 --- a/backend/src/test/java/moim_today/util/TestConstant.java +++ b/backend/src/test/java/moim_today/util/TestConstant.java @@ -3,34 +3,54 @@ public enum TestConstant { + // 이메일 EMAIL("email"), AJOU_EMAIL("test@ajou.ac.kr"), AJOU_EMAIL_DOMAIN("ajou.ac.kr"), WRONG_EMAIL("wrongEmail"), ALREADY_EXIST_EMAIL("alreayExist@ajou.ac.kr"), + // 비밀번호 PASSWORD("password"), NEW_PASSWORD("newPassword"), WRONG_PASSWORD("wrongPassword"), + // 에브리타임 EVERY_TIME_ID("everyTimeId"), WRONG_EVERY_TIME_ID("wrong everyTimeId"), + // 인증토큰 CERTIFICATION_TOKEN("certificationToken"), NEW_CERTIFICATION_TOKEN("newCertificationToken"), WRONG_CERTIFICATION_TOKEN("wrongCertificationToken"), + // 파일 FILE_NAME("file"), ORIGINAL_FILE_NAME("file.txt"), FILE_CONTENT("content"), + + // 대학교 + UNIV_ID("194"), UNIVERSITY_NAME("universityName"), + + // 학과 + DEPARTMENT_ID("9369"), DEPARTMENT_NAME("departmentName"), + + // 회원 + MEMBER_ID("1"), USERNAME("username"), STUDENT_ID("studentId"), PROFILE_IMAGE_URL("profileImageUrl"), - UNIV_ID("194"), - DEPARTMENT_ID("9369"), + + + // 모임 + TITLE("title"), + CONTENTS("contents"), + CAPACITY("5"), + MOIM_IMAGE_URL("moimImageUrl"), + STATUS_CODE("200"), MESSAGE("message"), From d21372464132174f8a3027905bb444a404ac500e Mon Sep 17 00:00:00 2001 From: Yang JiWoong Date: Wed, 24 Apr 2024 21:47:57 +0900 Subject: [PATCH 13/52] =?UTF-8?q?[BE]=20refactor=20:=20=ED=8C=8C=EC=9D=BC?= =?UTF-8?q?=20=EC=97=85=EB=A1=9C=EB=93=9C=20=EB=B0=98=ED=99=98=20=ED=83=80?= =?UTF-8?q?=EC=9E=85=20=EC=B6=94=EC=83=81=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/moim_today/application/file/AmazonS3Service.java | 5 ++++- .../moim_today/application/member/MemberServiceImpl.java | 4 ++-- .../main/java/moim_today/implement/file/FileUploader.java | 4 ++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/backend/src/main/java/moim_today/application/file/AmazonS3Service.java b/backend/src/main/java/moim_today/application/file/AmazonS3Service.java index 691e4265..12bb20ef 100644 --- a/backend/src/main/java/moim_today/application/file/AmazonS3Service.java +++ b/backend/src/main/java/moim_today/application/file/AmazonS3Service.java @@ -8,6 +8,8 @@ import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; +import java.io.File; + @Service public class AmazonS3Service implements FileService{ @@ -21,7 +23,8 @@ public AmazonS3Service(final FileUploader fileUploader, final FileRemover fileRe } public FileInfoResponse uploadFile(final String fileType, final MultipartFile multipartFile){ - return fileUploader.uploadFile(fileType, multipartFile); + String imageUrl = fileUploader.uploadFile(fileType, multipartFile); + return new FileInfoResponse(imageUrl); } public void deleteFile(final MemberSession memberSession, final FileDeleteRequest fileDeleteRequest){ diff --git a/backend/src/main/java/moim_today/application/member/MemberServiceImpl.java b/backend/src/main/java/moim_today/application/member/MemberServiceImpl.java index ba773a61..ad8c4d16 100644 --- a/backend/src/main/java/moim_today/application/member/MemberServiceImpl.java +++ b/backend/src/main/java/moim_today/application/member/MemberServiceImpl.java @@ -61,7 +61,7 @@ public void updateProfile(final long memberId, @Override public void updateProfileImage(final long memberId, final MultipartFile file) { - FileInfoResponse fileInfoResponse = fileUploader.uploadFile(PROFILE_IMAGE.value(), file); - memberUpdater.updateProfileImageUrl(memberId, fileInfoResponse.uploadFileUrl()); + String imageUrl = fileUploader.uploadFile(PROFILE_IMAGE.value(), file); + memberUpdater.updateProfileImageUrl(memberId, imageUrl); } } diff --git a/backend/src/main/java/moim_today/implement/file/FileUploader.java b/backend/src/main/java/moim_today/implement/file/FileUploader.java index d0f54bce..714697d6 100644 --- a/backend/src/main/java/moim_today/implement/file/FileUploader.java +++ b/backend/src/main/java/moim_today/implement/file/FileUploader.java @@ -32,7 +32,7 @@ public FileUploader(final AmazonS3 amazonS3) { this.amazonS3 = amazonS3; } - public FileInfoResponse uploadFile(final String fileType, final MultipartFile multipartFile) { + public String uploadFile(final String fileType, final MultipartFile multipartFile) { String uploadFolder = fileType; @@ -49,7 +49,7 @@ public FileInfoResponse uploadFile(final String fileType, final MultipartFile mu new PutObjectRequest(bucketName, keyName, inputStream, objectMetadata) .withCannedAcl(CannedAccessControlList.PublicRead)); // TODO: 데이터베이스에 대학 ID와 학번 ID를 key 값으로, uploadFileName 을 Value 값으로 저장하기 - return new FileInfoResponse(amazonS3.getUrl(bucketName, keyName).toString()); + return amazonS3.getUrl(bucketName, keyName).toString(); } catch (IOException e) { log.error("Exception [Err_Location]: {}", e.getStackTrace()[0]); throw new InternalServerException(FILE_UPLOAD_ERROR.message()); From fda879c53e790c33bd6c08e83337077ab856617f Mon Sep 17 00:00:00 2001 From: Yang JiWoong Date: Wed, 24 Apr 2024 21:51:48 +0900 Subject: [PATCH 14/52] =?UTF-8?q?[BE]=20faet=20:=20=EB=AA=A8=EC=9E=84=20?= =?UTF-8?q?=EC=82=AC=EC=A7=84=20=EC=97=85=EB=A1=9C=EB=93=9C=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84=20=EB=B0=8F=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/moim/MoimService.java | 4 +++ .../application/moim/MoimServiceImpl.java | 16 ++++++++++- .../dto/moim/UploadMoimImageResponse.java | 10 +++++++ .../presentation/moim/MoimController.java | 13 ++++++--- .../fake_class/moim/FakeMoimService.java | 7 +++++ .../presentation/moim/MoimControllerTest.java | 28 +++++++++++++++++++ 6 files changed, 73 insertions(+), 5 deletions(-) create mode 100644 backend/src/main/java/moim_today/dto/moim/UploadMoimImageResponse.java diff --git a/backend/src/main/java/moim_today/application/moim/MoimService.java b/backend/src/main/java/moim_today/application/moim/MoimService.java index 38a05db6..a593ee5f 100644 --- a/backend/src/main/java/moim_today/application/moim/MoimService.java +++ b/backend/src/main/java/moim_today/application/moim/MoimService.java @@ -2,6 +2,8 @@ import moim_today.dto.moim.PrivateMoimAppendRequest; import moim_today.dto.moim.PublicMoimAppendRequest; +import moim_today.dto.moim.UploadMoimImageResponse; +import org.springframework.web.multipart.MultipartFile; public interface MoimService { @@ -10,4 +12,6 @@ void createPublicMoim(final long memberId, final long universityId, void createPrivateMoim(final long memberId, final long universityId, final PrivateMoimAppendRequest privateMoimAppendRequest); + + UploadMoimImageResponse uploadMoimImage(final MultipartFile file); } diff --git a/backend/src/main/java/moim_today/application/moim/MoimServiceImpl.java b/backend/src/main/java/moim_today/application/moim/MoimServiceImpl.java index 21cb4dad..8ca68e0c 100644 --- a/backend/src/main/java/moim_today/application/moim/MoimServiceImpl.java +++ b/backend/src/main/java/moim_today/application/moim/MoimServiceImpl.java @@ -2,16 +2,24 @@ import moim_today.dto.moim.PrivateMoimAppendRequest; import moim_today.dto.moim.PublicMoimAppendRequest; +import moim_today.dto.moim.UploadMoimImageResponse; +import moim_today.implement.file.FileUploader; import moim_today.implement.moim.MoimAppender; import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import static moim_today.global.constant.FileTypeConstant.MOIM_IMAGE; @Service public class MoimServiceImpl implements MoimService{ private final MoimAppender moimAppender; + private final FileUploader fileUploader; - public MoimServiceImpl(final MoimAppender moimAppender) { + public MoimServiceImpl(final MoimAppender moimAppender, + final FileUploader fileUploader) { this.moimAppender = moimAppender; + this.fileUploader = fileUploader; } @Override @@ -25,4 +33,10 @@ public void createPrivateMoim(final long memberId, final long universityId, final PrivateMoimAppendRequest privateMoimAppendRequest) { moimAppender.createPrivateMoim(memberId, universityId, privateMoimAppendRequest); } + + @Override + public UploadMoimImageResponse uploadMoimImage(final MultipartFile file) { + String imageUrl = fileUploader.uploadFile(MOIM_IMAGE.value(), file); + return UploadMoimImageResponse.from(imageUrl); + } } diff --git a/backend/src/main/java/moim_today/dto/moim/UploadMoimImageResponse.java b/backend/src/main/java/moim_today/dto/moim/UploadMoimImageResponse.java new file mode 100644 index 00000000..f5332421 --- /dev/null +++ b/backend/src/main/java/moim_today/dto/moim/UploadMoimImageResponse.java @@ -0,0 +1,10 @@ +package moim_today.dto.moim; + +public record UploadMoimImageResponse( + String imageUrl +) { + + public static UploadMoimImageResponse from(String imageUrl) { + return new UploadMoimImageResponse(imageUrl); + } +} diff --git a/backend/src/main/java/moim_today/presentation/moim/MoimController.java b/backend/src/main/java/moim_today/presentation/moim/MoimController.java index 0e63157b..78534039 100644 --- a/backend/src/main/java/moim_today/presentation/moim/MoimController.java +++ b/backend/src/main/java/moim_today/presentation/moim/MoimController.java @@ -5,11 +5,10 @@ import moim_today.domain.member.MemberSession; import moim_today.dto.moim.PrivateMoimAppendRequest; import moim_today.dto.moim.PublicMoimAppendRequest; +import moim_today.dto.moim.UploadMoimImageResponse; import moim_today.global.annotation.Login; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; @RequestMapping("/api/moims") @RestController @@ -32,4 +31,10 @@ public void createPrivateMoim(@Login final MemberSession memberSession, @RequestBody final PrivateMoimAppendRequest privateMoimAppendRequest) { moimService.createPrivateMoim(memberSession.id(), memberSession.universityId(), privateMoimAppendRequest); } + + @PostMapping("/image") + public UploadMoimImageResponse uploadMoimImage(@Login final MemberSession memberSession, + @RequestPart final MultipartFile file) { + return moimService.uploadMoimImage(file); + } } diff --git a/backend/src/test/java/moim_today/fake_class/moim/FakeMoimService.java b/backend/src/test/java/moim_today/fake_class/moim/FakeMoimService.java index 0c1546b0..b9f538b9 100644 --- a/backend/src/test/java/moim_today/fake_class/moim/FakeMoimService.java +++ b/backend/src/test/java/moim_today/fake_class/moim/FakeMoimService.java @@ -3,6 +3,8 @@ import moim_today.application.moim.MoimService; import moim_today.dto.moim.PrivateMoimAppendRequest; import moim_today.dto.moim.PublicMoimAppendRequest; +import moim_today.dto.moim.UploadMoimImageResponse; +import org.springframework.web.multipart.MultipartFile; public class FakeMoimService implements MoimService { @@ -15,4 +17,9 @@ public void createPublicMoim(final long memberId, final long universityId, final public void createPrivateMoim(final long memberId, final long universityId, final PrivateMoimAppendRequest privateMoimAppendRequest) { } + + @Override + public UploadMoimImageResponse uploadMoimImage(final MultipartFile file) { + return null; + } } diff --git a/backend/src/test/java/moim_today/presentation/moim/MoimControllerTest.java b/backend/src/test/java/moim_today/presentation/moim/MoimControllerTest.java index 097b942c..4c3f870d 100644 --- a/backend/src/test/java/moim_today/presentation/moim/MoimControllerTest.java +++ b/backend/src/test/java/moim_today/presentation/moim/MoimControllerTest.java @@ -8,7 +8,10 @@ import moim_today.util.ControllerTest; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import java.time.LocalDate; @@ -18,6 +21,8 @@ import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; import static org.springframework.restdocs.payload.JsonFieldType.*; import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.request.RequestDocumentation.partWithName; +import static org.springframework.restdocs.request.RequestDocumentation.requestParts; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; class MoimControllerTest extends ControllerTest { @@ -106,4 +111,27 @@ void createPrivateMoimApiTest() throws Exception { .build() ))); } + + @DisplayName("모임 사진 업로드 테스트 성공") + @Test + void uploadMoimImageTest() throws Exception { + + MockMultipartFile file = new MockMultipartFile( + FILE_NAME.value(), + ORIGINAL_FILE_NAME.value(), + MediaType.TEXT_PLAIN_VALUE, + FILE_CONTENT.value().getBytes() + ); + + mockMvc.perform(MockMvcRequestBuilders + .multipart(HttpMethod.POST, "/api/moims/image") + .file(file) + ) + .andExpect(status().isOk()) + .andDo(document("모임 사진 업로드", + requestParts( + partWithName("file").description("모임 사진 파일") + ) + )); + } } From 4c271327e74d6d8c01c6eb8195aabc52e3232682 Mon Sep 17 00:00:00 2001 From: Yang JiWoong Date: Sat, 27 Apr 2024 13:16:41 +0900 Subject: [PATCH 15/52] =?UTF-8?q?[BE]=20refactor=20:=20Assertions=20static?= =?UTF-8?q?=20import=EB=A1=9C=20=EC=B6=94=EC=B6=9C=ED=95=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../moim_today/dto/moim/PrivateMoimAppendRequestTest.java | 6 +++--- .../moim_today/presentation/moim/MoimControllerTest.java | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/src/test/java/moim_today/dto/moim/PrivateMoimAppendRequestTest.java b/backend/src/test/java/moim_today/dto/moim/PrivateMoimAppendRequestTest.java index e1739218..5dba15f6 100644 --- a/backend/src/test/java/moim_today/dto/moim/PrivateMoimAppendRequestTest.java +++ b/backend/src/test/java/moim_today/dto/moim/PrivateMoimAppendRequestTest.java @@ -2,7 +2,6 @@ import moim_today.domain.moim.enums.MoimCategory; import moim_today.persistence.entity.moim.moim.MoimJpaEntity; -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -10,6 +9,7 @@ import static moim_today.global.constant.MoimConstant.DEFAULT_MOIM_IMAGE_URL; import static moim_today.util.TestConstant.*; +import static org.assertj.core.api.Assertions.assertThat; class PrivateMoimAppendRequestTest { @@ -38,7 +38,7 @@ void NoneImageUrlCreateEntityWithDefaultUrl() { MoimJpaEntity entity = privateMoimAppendRequest.toEntity(memberId, universityId); //then - Assertions.assertThat((entity.getImageUrl())).isEqualTo(DEFAULT_MOIM_IMAGE_URL.value()); + assertThat((entity.getImageUrl())).isEqualTo(DEFAULT_MOIM_IMAGE_URL.value()); } @DisplayName("Request에 ImageUrl 값이 있다면 엔티티에 정상적으로 들어간다.") @@ -67,6 +67,6 @@ void CreateMoimJpaEntityWithRequestImageUrl() { MoimJpaEntity entity = privateMoimAppendRequest.toEntity(memberId, universityId); //then - Assertions.assertThat((entity.getImageUrl())).isEqualTo(MOIM_IMAGE_URL.value()); + assertThat((entity.getImageUrl())).isEqualTo(MOIM_IMAGE_URL.value()); } } diff --git a/backend/src/test/java/moim_today/presentation/moim/MoimControllerTest.java b/backend/src/test/java/moim_today/presentation/moim/MoimControllerTest.java index 4c3f870d..9206602b 100644 --- a/backend/src/test/java/moim_today/presentation/moim/MoimControllerTest.java +++ b/backend/src/test/java/moim_today/presentation/moim/MoimControllerTest.java @@ -58,7 +58,7 @@ void createPublicMoimApiTest() throws Exception { .andDo(document("공개 모임 생성 성공", resource(ResourceSnippetParameters.builder() .tag("모임") - .summary("모임 생성") + .summary("공개 모임 생성") .requestFields( fieldWithPath("title").type(STRING).description("모임명"), fieldWithPath("contents").type(STRING).description("내용"), @@ -97,7 +97,7 @@ void createPrivateMoimApiTest() throws Exception { .andDo(document("비공개 모임 생성 성공", resource(ResourceSnippetParameters.builder() .tag("모임") - .summary("모임 생성") + .summary("비공개 모임 생성") .requestFields( fieldWithPath("title").type(STRING).description("모임명"), fieldWithPath("contents").type(STRING).description("내용"), From 3b0ed7c9aacd4c8cf18dd89a251b410bd739405b Mon Sep 17 00:00:00 2001 From: Yang JiWoong Date: Sat, 27 Apr 2024 22:57:32 +0900 Subject: [PATCH 16/52] =?UTF-8?q?[BE]=20refactor=20:=20=EB=AA=A8=EC=9E=84?= =?UTF-8?q?=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=97=85=EB=A1=9C=EB=93=9C=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EB=AC=B8=EC=84=9C=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fake_class/moim/FakeMoimService.java | 4 +++- .../presentation/moim/MoimControllerTest.java | 21 ++++++++++++------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/backend/src/test/java/moim_today/fake_class/moim/FakeMoimService.java b/backend/src/test/java/moim_today/fake_class/moim/FakeMoimService.java index b9f538b9..717f08a6 100644 --- a/backend/src/test/java/moim_today/fake_class/moim/FakeMoimService.java +++ b/backend/src/test/java/moim_today/fake_class/moim/FakeMoimService.java @@ -6,6 +6,8 @@ import moim_today.dto.moim.UploadMoimImageResponse; import org.springframework.web.multipart.MultipartFile; +import static moim_today.util.TestConstant.MOIM_IMAGE_URL; + public class FakeMoimService implements MoimService { @Override @@ -20,6 +22,6 @@ public void createPrivateMoim(final long memberId, final long universityId, fina @Override public UploadMoimImageResponse uploadMoimImage(final MultipartFile file) { - return null; + return UploadMoimImageResponse.from(MOIM_IMAGE_URL.value()); } } diff --git a/backend/src/test/java/moim_today/presentation/moim/MoimControllerTest.java b/backend/src/test/java/moim_today/presentation/moim/MoimControllerTest.java index 9206602b..61b76592 100644 --- a/backend/src/test/java/moim_today/presentation/moim/MoimControllerTest.java +++ b/backend/src/test/java/moim_today/presentation/moim/MoimControllerTest.java @@ -8,16 +8,15 @@ import moim_today.util.ControllerTest; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.mock.web.MockMultipartFile; -import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import java.time.LocalDate; import static com.epages.restdocs.apispec.ResourceDocumentation.resource; import static moim_today.util.TestConstant.*; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.multipart; import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; import static org.springframework.restdocs.payload.JsonFieldType.*; import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; @@ -119,19 +118,25 @@ void uploadMoimImageTest() throws Exception { MockMultipartFile file = new MockMultipartFile( FILE_NAME.value(), ORIGINAL_FILE_NAME.value(), - MediaType.TEXT_PLAIN_VALUE, + MediaType.MULTIPART_FORM_DATA_VALUE, FILE_CONTENT.value().getBytes() ); - mockMvc.perform(MockMvcRequestBuilders - .multipart(HttpMethod.POST, "/api/moims/image") + mockMvc.perform(multipart("/api/moims/image") .file(file) ) .andExpect(status().isOk()) - .andDo(document("모임 사진 업로드", + .andDo(document("모임 사진 업로드 테스트", requestParts( partWithName("file").description("모임 사진 파일") - ) - )); + ), + resource(ResourceSnippetParameters.builder() + .tag("모임") + .summary("모임 사진 업로드 성공 테스트 입니다.") + .responseFields( + fieldWithPath("imageUrl").type(STRING).description("모임 사진 URL") + ) + .build() + ))); } } From dc3b8940ea33b786640f1e41e4fda1b260795f15 Mon Sep 17 00:00:00 2001 From: Jung-YouHwan Date: Sat, 27 Apr 2024 17:37:53 +0900 Subject: [PATCH 17/52] =?UTF-8?q?[BE]=20feat=20:=20=EA=B0=9C=EC=9D=B8=20?= =?UTF-8?q?=EC=9D=BC=EC=A0=95=20=EB=93=B1=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/schedule/ScheduleService.java | 3 ++ .../schedule/ScheduleServiceImpl.java | 6 ++++ .../dto/schedule/ScheduleCreateRequest.java | 29 +++++++++++++++++++ .../exception/ScheduleExceptionConstant.java | 16 ++++++++++ .../implement/schedule/ScheduleAppender.java | 20 ++++++++++++- .../schedule/ScheduleRepository.java | 2 ++ .../schedule/ScheduleRepositoryImpl.java | 16 ++++++++++ .../schedule/ScheduleController.java | 7 +++++ .../schedule/FakeScheduleService.java | 6 ++++ 9 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 backend/src/main/java/moim_today/dto/schedule/ScheduleCreateRequest.java create mode 100644 backend/src/main/java/moim_today/global/constant/exception/ScheduleExceptionConstant.java diff --git a/backend/src/main/java/moim_today/application/schedule/ScheduleService.java b/backend/src/main/java/moim_today/application/schedule/ScheduleService.java index 94171835..cf2ac450 100644 --- a/backend/src/main/java/moim_today/application/schedule/ScheduleService.java +++ b/backend/src/main/java/moim_today/application/schedule/ScheduleService.java @@ -1,9 +1,12 @@ package moim_today.application.schedule; +import moim_today.dto.schedule.ScheduleCreateRequest; import moim_today.dto.schedule.TimeTableRequest; public interface ScheduleService { void fetchTimeTable(final long memberId, final TimeTableRequest timeTableRequest); + + void createSchedule(final long memberId, final ScheduleCreateRequest scheduleCreateRequest); } diff --git a/backend/src/main/java/moim_today/application/schedule/ScheduleServiceImpl.java b/backend/src/main/java/moim_today/application/schedule/ScheduleServiceImpl.java index af20fd22..39b4f3a5 100644 --- a/backend/src/main/java/moim_today/application/schedule/ScheduleServiceImpl.java +++ b/backend/src/main/java/moim_today/application/schedule/ScheduleServiceImpl.java @@ -1,6 +1,7 @@ package moim_today.application.schedule; import moim_today.domain.schedule.Schedule; +import moim_today.dto.schedule.ScheduleCreateRequest; import moim_today.dto.schedule.TimeTableRequest; import moim_today.implement.schedule.ScheduleAppender; import moim_today.implement.schedule.ScheduleManager; @@ -25,4 +26,9 @@ public void fetchTimeTable(final long memberId, final TimeTableRequest timeTable List schedules = scheduleManager.processTimetable(timeTableXML, timeTableRequest); scheduleAppender.batchUpdateSchedules(schedules, memberId); } + + @Override + public void createSchedule(final long memberId, final ScheduleCreateRequest scheduleCreateRequest) { + scheduleAppender.createSchedule(memberId, scheduleCreateRequest); + } } \ No newline at end of file diff --git a/backend/src/main/java/moim_today/dto/schedule/ScheduleCreateRequest.java b/backend/src/main/java/moim_today/dto/schedule/ScheduleCreateRequest.java new file mode 100644 index 00000000..7c9c76f0 --- /dev/null +++ b/backend/src/main/java/moim_today/dto/schedule/ScheduleCreateRequest.java @@ -0,0 +1,29 @@ +package moim_today.dto.schedule; + +import lombok.Builder; +import moim_today.persistence.entity.schedule.ScheduleJpaEntity; + +import java.time.DayOfWeek; +import java.time.LocalDateTime; + +import static moim_today.global.constant.NumberConstant.SCHEDULE_MEETING_ID; + +@Builder +public record ScheduleCreateRequest( + String scheduleName, + DayOfWeek dayOfWeek, + LocalDateTime startDateTime, + LocalDateTime endDateTime +) { + + public ScheduleJpaEntity toEntity(final long memberId) { + return ScheduleJpaEntity.builder() + .memberId(memberId) + .meetingId(SCHEDULE_MEETING_ID.value()) + .scheduleName(scheduleName) + .dayOfWeek(dayOfWeek) + .startDateTime(startDateTime) + .endDateTime(endDateTime) + .build(); + } +} diff --git a/backend/src/main/java/moim_today/global/constant/exception/ScheduleExceptionConstant.java b/backend/src/main/java/moim_today/global/constant/exception/ScheduleExceptionConstant.java new file mode 100644 index 00000000..ca82b2ce --- /dev/null +++ b/backend/src/main/java/moim_today/global/constant/exception/ScheduleExceptionConstant.java @@ -0,0 +1,16 @@ +package moim_today.global.constant.exception; + +public enum ScheduleExceptionConstant { + + SCHEDULE_ALREADY_EXIST("해당 시간에 이미 스케줄이 존재합니다."); + + private final String message; + + ScheduleExceptionConstant(final String message) { + this.message = message; + } + + public String message() { + return message; + } +} diff --git a/backend/src/main/java/moim_today/implement/schedule/ScheduleAppender.java b/backend/src/main/java/moim_today/implement/schedule/ScheduleAppender.java index 8066866e..6ae62fa9 100644 --- a/backend/src/main/java/moim_today/implement/schedule/ScheduleAppender.java +++ b/backend/src/main/java/moim_today/implement/schedule/ScheduleAppender.java @@ -1,13 +1,18 @@ package moim_today.implement.schedule; import moim_today.domain.schedule.Schedule; +import moim_today.dto.schedule.ScheduleCreateRequest; import moim_today.dto.schedule.TimeTableSchedulingTask; import moim_today.global.annotation.Implement; +import moim_today.global.error.BadRequestException; +import moim_today.persistence.entity.schedule.ScheduleJpaEntity; import moim_today.persistence.repository.schedule.ScheduleRepository; import org.springframework.transaction.annotation.Transactional; import java.util.List; +import static moim_today.global.constant.exception.ScheduleExceptionConstant.SCHEDULE_ALREADY_EXIST; + @Implement public class ScheduleAppender { @@ -23,4 +28,17 @@ public void batchUpdateSchedules(final List schedules, final long memb TimeTableSchedulingTask timeTableSchedulingTask = TimeTableSchedulingTask.of(schedules, memberId); scheduleRepository.batchUpdate(timeTableSchedulingTask); } -} + + @Transactional + public void createSchedule(final long memberId, final ScheduleCreateRequest scheduleCreateRequest) { + ScheduleJpaEntity scheduleJpaEntity = scheduleCreateRequest.toEntity(memberId); + validateAlreadyExist(scheduleJpaEntity); + scheduleRepository.save(scheduleJpaEntity); + } + + private void validateAlreadyExist(final ScheduleJpaEntity scheduleJpaEntity) { + if (scheduleRepository.exists(scheduleJpaEntity)) { + throw new BadRequestException(SCHEDULE_ALREADY_EXIST.message()); + } + } +} \ No newline at end of file diff --git a/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepository.java b/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepository.java index 2dac4d34..053f923f 100644 --- a/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepository.java +++ b/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepository.java @@ -9,5 +9,7 @@ public interface ScheduleRepository { void batchUpdate(final TimeTableSchedulingTask timeTableSchedulingTask); + boolean exists(final ScheduleJpaEntity scheduleJpaEntity); + long count(); } diff --git a/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepositoryImpl.java b/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepositoryImpl.java index dd7a9040..cbab6d5a 100644 --- a/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepositoryImpl.java +++ b/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepositoryImpl.java @@ -1,7 +1,9 @@ package moim_today.persistence.repository.schedule; +import com.querydsl.jpa.impl.JPAQueryFactory; import moim_today.domain.schedule.Schedule; import moim_today.dto.schedule.TimeTableSchedulingTask; +import moim_today.persistence.entity.schedule.QScheduleJpaEntity; import moim_today.persistence.entity.schedule.ScheduleJpaEntity; import org.springframework.jdbc.core.BatchPreparedStatementSetter; import org.springframework.jdbc.core.JdbcTemplate; @@ -15,15 +17,19 @@ import static moim_today.global.constant.NumberConstant.SCHEDULE_MEETING_ID; + @Repository public class ScheduleRepositoryImpl implements ScheduleRepository { private final ScheduleJpaRepository scheduleJpaRepository; + private final JPAQueryFactory queryFactory; private final JdbcTemplate jdbcTemplate; public ScheduleRepositoryImpl(final ScheduleJpaRepository scheduleJpaRepository, + final JPAQueryFactory queryFactory, final JdbcTemplate jdbcTemplate) { this.scheduleJpaRepository = scheduleJpaRepository; + this.queryFactory = queryFactory; this.jdbcTemplate = jdbcTemplate; } @@ -64,6 +70,16 @@ public int getBatchSize() { }); } + @Override + public boolean exists(final ScheduleJpaEntity scheduleJpaEntity) { + return queryFactory.selectFrom(QScheduleJpaEntity.scheduleJpaEntity) + .where( + QScheduleJpaEntity.scheduleJpaEntity.startDateTime.before(scheduleJpaEntity.getEndDateTime()) + .and(QScheduleJpaEntity.scheduleJpaEntity.endDateTime.after(scheduleJpaEntity.getStartDateTime())) + ) + .fetchFirst() != null; + } + @Override public long count() { return scheduleJpaRepository.count(); diff --git a/backend/src/main/java/moim_today/presentation/schedule/ScheduleController.java b/backend/src/main/java/moim_today/presentation/schedule/ScheduleController.java index 56eb72fc..623b096c 100644 --- a/backend/src/main/java/moim_today/presentation/schedule/ScheduleController.java +++ b/backend/src/main/java/moim_today/presentation/schedule/ScheduleController.java @@ -2,6 +2,7 @@ import moim_today.application.schedule.ScheduleService; import moim_today.domain.member.MemberSession; +import moim_today.dto.schedule.ScheduleCreateRequest; import moim_today.dto.schedule.TimeTableRequest; import moim_today.global.annotation.Login; import org.springframework.web.bind.annotation.PostMapping; @@ -25,4 +26,10 @@ public void fetchTimeTable(@Login final MemberSession memberSession, @RequestBody final TimeTableRequest timeTableRequest) { scheduleService.fetchTimeTable(memberSession.id(), timeTableRequest); } + + @PostMapping + public void createSchedule(@Login final MemberSession memberSession, + @RequestBody final ScheduleCreateRequest scheduleCreateRequest) { + scheduleService.createSchedule(memberSession.id(), scheduleCreateRequest); + } } \ No newline at end of file diff --git a/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java b/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java index 205339a3..f3925006 100644 --- a/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java +++ b/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java @@ -1,6 +1,7 @@ package moim_today.fake_class.schedule; import moim_today.application.schedule.ScheduleService; +import moim_today.dto.schedule.ScheduleCreateRequest; import moim_today.dto.schedule.TimeTableRequest; import moim_today.global.error.BadRequestException; @@ -15,4 +16,9 @@ public void fetchTimeTable(final long memberId, final TimeTableRequest timeTable throw new BadRequestException(TIME_INPUT_ERROR.value()); } } + + @Override + public void createSchedule(final long memberId, final ScheduleCreateRequest scheduleCreateRequest) { + + } } From 918c1796fb1c013ca6b3307207fb988e5ed5617d Mon Sep 17 00:00:00 2001 From: Jung-YouHwan Date: Sat, 27 Apr 2024 18:53:26 +0900 Subject: [PATCH 18/52] =?UTF-8?q?[BE]=20test=20:=20=EA=B0=9C=EC=9D=B8=20?= =?UTF-8?q?=EC=9D=BC=EC=A0=95=20=EB=93=B1=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../schedule/ScheduleServiceImpl.java | 4 +- .../dto/schedule/ScheduleCreateRequest.java | 3 + .../exception/ScheduleExceptionConstant.java | 3 +- .../implement/schedule/ScheduleAppender.java | 4 +- .../schedule/ScheduleRepository.java | 2 + .../schedule/ScheduleRepositoryImpl.java | 9 ++ .../schedule/FakeScheduleService.java | 7 +- .../schedule/ScheduleAppenderTest.java | 115 ++++++++++++++++++ .../schedule/ScheduleControllerTest.java | 72 +++++++++++ .../java/moim_today/util/ControllerTest.java | 34 +++++- .../java/moim_today/util/TestConstant.java | 5 +- 11 files changed, 245 insertions(+), 13 deletions(-) diff --git a/backend/src/main/java/moim_today/application/schedule/ScheduleServiceImpl.java b/backend/src/main/java/moim_today/application/schedule/ScheduleServiceImpl.java index 39b4f3a5..effaabe3 100644 --- a/backend/src/main/java/moim_today/application/schedule/ScheduleServiceImpl.java +++ b/backend/src/main/java/moim_today/application/schedule/ScheduleServiceImpl.java @@ -5,6 +5,7 @@ import moim_today.dto.schedule.TimeTableRequest; import moim_today.implement.schedule.ScheduleAppender; import moim_today.implement.schedule.ScheduleManager; +import moim_today.persistence.entity.schedule.ScheduleJpaEntity; import org.springframework.stereotype.Service; import java.util.List; @@ -29,6 +30,7 @@ public void fetchTimeTable(final long memberId, final TimeTableRequest timeTable @Override public void createSchedule(final long memberId, final ScheduleCreateRequest scheduleCreateRequest) { - scheduleAppender.createSchedule(memberId, scheduleCreateRequest); + ScheduleJpaEntity scheduleJpaEntity = scheduleCreateRequest.toEntity(memberId); + scheduleAppender.createSchedule(scheduleJpaEntity); } } \ No newline at end of file diff --git a/backend/src/main/java/moim_today/dto/schedule/ScheduleCreateRequest.java b/backend/src/main/java/moim_today/dto/schedule/ScheduleCreateRequest.java index 7c9c76f0..cbf84c39 100644 --- a/backend/src/main/java/moim_today/dto/schedule/ScheduleCreateRequest.java +++ b/backend/src/main/java/moim_today/dto/schedule/ScheduleCreateRequest.java @@ -1,5 +1,6 @@ package moim_today.dto.schedule; +import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Builder; import moim_today.persistence.entity.schedule.ScheduleJpaEntity; @@ -12,7 +13,9 @@ public record ScheduleCreateRequest( String scheduleName, DayOfWeek dayOfWeek, + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul") LocalDateTime startDateTime, + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul") LocalDateTime endDateTime ) { diff --git a/backend/src/main/java/moim_today/global/constant/exception/ScheduleExceptionConstant.java b/backend/src/main/java/moim_today/global/constant/exception/ScheduleExceptionConstant.java index ca82b2ce..e7eaffa4 100644 --- a/backend/src/main/java/moim_today/global/constant/exception/ScheduleExceptionConstant.java +++ b/backend/src/main/java/moim_today/global/constant/exception/ScheduleExceptionConstant.java @@ -2,7 +2,8 @@ public enum ScheduleExceptionConstant { - SCHEDULE_ALREADY_EXIST("해당 시간에 이미 스케줄이 존재합니다."); + SCHEDULE_ALREADY_EXIST("해당 시간에 이미 스케줄이 존재합니다."), + SCHEDULE_NOT_FOUND("해당 스케줄을 찾을 수 없습니다"); private final String message; diff --git a/backend/src/main/java/moim_today/implement/schedule/ScheduleAppender.java b/backend/src/main/java/moim_today/implement/schedule/ScheduleAppender.java index 6ae62fa9..b0f9358b 100644 --- a/backend/src/main/java/moim_today/implement/schedule/ScheduleAppender.java +++ b/backend/src/main/java/moim_today/implement/schedule/ScheduleAppender.java @@ -1,7 +1,6 @@ package moim_today.implement.schedule; import moim_today.domain.schedule.Schedule; -import moim_today.dto.schedule.ScheduleCreateRequest; import moim_today.dto.schedule.TimeTableSchedulingTask; import moim_today.global.annotation.Implement; import moim_today.global.error.BadRequestException; @@ -30,8 +29,7 @@ public void batchUpdateSchedules(final List schedules, final long memb } @Transactional - public void createSchedule(final long memberId, final ScheduleCreateRequest scheduleCreateRequest) { - ScheduleJpaEntity scheduleJpaEntity = scheduleCreateRequest.toEntity(memberId); + public void createSchedule(final ScheduleJpaEntity scheduleJpaEntity) { validateAlreadyExist(scheduleJpaEntity); scheduleRepository.save(scheduleJpaEntity); } diff --git a/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepository.java b/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepository.java index 053f923f..ead15664 100644 --- a/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepository.java +++ b/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepository.java @@ -5,6 +5,8 @@ public interface ScheduleRepository { + ScheduleJpaEntity getById(final long scheduleId); + void save(final ScheduleJpaEntity scheduleJpaEntity); void batchUpdate(final TimeTableSchedulingTask timeTableSchedulingTask); diff --git a/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepositoryImpl.java b/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepositoryImpl.java index cbab6d5a..80055bd0 100644 --- a/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepositoryImpl.java +++ b/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepositoryImpl.java @@ -3,6 +3,8 @@ import com.querydsl.jpa.impl.JPAQueryFactory; import moim_today.domain.schedule.Schedule; import moim_today.dto.schedule.TimeTableSchedulingTask; +import moim_today.global.constant.exception.ScheduleExceptionConstant; +import moim_today.global.error.NotFoundException; import moim_today.persistence.entity.schedule.QScheduleJpaEntity; import moim_today.persistence.entity.schedule.ScheduleJpaEntity; import org.springframework.jdbc.core.BatchPreparedStatementSetter; @@ -16,6 +18,7 @@ import java.util.List; import static moim_today.global.constant.NumberConstant.SCHEDULE_MEETING_ID; +import static moim_today.global.constant.exception.ScheduleExceptionConstant.*; @Repository @@ -33,6 +36,12 @@ public ScheduleRepositoryImpl(final ScheduleJpaRepository scheduleJpaRepository, this.jdbcTemplate = jdbcTemplate; } + @Override + public ScheduleJpaEntity getById(final long scheduleId) { + return scheduleJpaRepository.findById(scheduleId) + .orElseThrow(() -> new NotFoundException(SCHEDULE_NOT_FOUND.message())); + } + @Override public void save(final ScheduleJpaEntity scheduleJpaEntity) { scheduleJpaRepository.save(scheduleJpaEntity); diff --git a/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java b/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java index f3925006..e0b1f55b 100644 --- a/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java +++ b/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java @@ -5,7 +5,10 @@ import moim_today.dto.schedule.TimeTableRequest; import moim_today.global.error.BadRequestException; +import java.time.LocalDateTime; + import static moim_today.global.constant.exception.EveryTimeExceptionConstant.TIME_INPUT_ERROR; +import static moim_today.global.constant.exception.ScheduleExceptionConstant.*; import static moim_today.util.TestConstant.*; public class FakeScheduleService implements ScheduleService { @@ -19,6 +22,8 @@ public void fetchTimeTable(final long memberId, final TimeTableRequest timeTable @Override public void createSchedule(final long memberId, final ScheduleCreateRequest scheduleCreateRequest) { - + if (scheduleCreateRequest.startDateTime().equals(LocalDateTime.of(2024, 1, 1, 0, 0, 0))) { + throw new BadRequestException(SCHEDULE_ALREADY_EXIST.message()); + } } } diff --git a/backend/src/test/java/moim_today/implement/schedule/ScheduleAppenderTest.java b/backend/src/test/java/moim_today/implement/schedule/ScheduleAppenderTest.java index 25a72ae7..5851ad85 100644 --- a/backend/src/test/java/moim_today/implement/schedule/ScheduleAppenderTest.java +++ b/backend/src/test/java/moim_today/implement/schedule/ScheduleAppenderTest.java @@ -1,6 +1,8 @@ package moim_today.implement.schedule; import moim_today.domain.schedule.Schedule; +import moim_today.global.error.BadRequestException; +import moim_today.persistence.entity.schedule.ScheduleJpaEntity; import moim_today.util.ImplementTest; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -10,6 +12,8 @@ import java.time.LocalDateTime; import java.util.List; +import static moim_today.global.constant.exception.ScheduleExceptionConstant.*; +import static moim_today.util.TestConstant.*; import static org.assertj.core.api.Assertions.*; class ScheduleAppenderTest extends ImplementTest { @@ -53,4 +57,115 @@ void batchUpdateSchedules() { // then assertThat(scheduleRepository.count()).isEqualTo(3); } + + @DisplayName("개인 일정을 등록한다.") + @Test + void createSchedule() { + // given + long memberId = 1L; + long meetingId = 2L; + + ScheduleJpaEntity scheduleJpaEntity = ScheduleJpaEntity.builder() + .memberId(memberId) + .meetingId(meetingId) + .scheduleName(SCHEDULE_NAME.value()) + .dayOfWeek(DayOfWeek.MONDAY) + .startDateTime(LocalDateTime.of(2024, 1, 1, 10, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) + .build(); + + // when + scheduleAppender.createSchedule(scheduleJpaEntity); + + // then + ScheduleJpaEntity findEntity = scheduleRepository.getById(scheduleJpaEntity.getId()); + + assertThat(scheduleRepository.count()).isEqualTo(1); + assertThat(findEntity.getMemberId()).isEqualTo(memberId); + assertThat(findEntity.getMeetingId()).isEqualTo(meetingId); + assertThat(findEntity.getScheduleName()).isEqualTo(SCHEDULE_NAME.value()); + assertThat(findEntity.getDayOfWeek()).isEqualTo(DayOfWeek.MONDAY); + assertThat(findEntity.getStartDateTime()).isEqualTo(LocalDateTime.of(2024, 1, 1, 10, 0, 0)); + assertThat(findEntity.getEndDateTime()).isEqualTo(LocalDateTime.of(2024, 1, 1, 12, 0, 0)); + } + + @DisplayName("다른 스케줄 사이에 있는 일정을 등록한다.") + @Test + void createScheduleBetweenOtherSchedules() { + // given 1 + ScheduleJpaEntity BeforeScheduleJpaEntity = ScheduleJpaEntity.builder() + .startDateTime(LocalDateTime.of(2024, 1, 1, 10, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) + .build(); + + ScheduleJpaEntity afterScheduleJpaEntity = ScheduleJpaEntity.builder() + .startDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 14, 0, 0)) + .build(); + + scheduleRepository.save(BeforeScheduleJpaEntity); + scheduleRepository.save(afterScheduleJpaEntity); + + // given 2 + ScheduleJpaEntity newScheduleJpaEntity = ScheduleJpaEntity.builder() + .startDateTime(LocalDateTime.of(2024, 1, 1, 14, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 16, 0, 0)) + .build(); + + // then + assertThatCode(() -> scheduleAppender.createSchedule(newScheduleJpaEntity)) + .doesNotThrowAnyException(); + + assertThat(scheduleRepository.count()).isEqualTo(3); + } + + @DisplayName("해당 시간대 앞에 스케줄이 존재하면 예외가 발생한다.") + @Test + void createScheduleFailAlreadyExistBeforeSchedule() { + // given 1 + ScheduleJpaEntity BeforeScheduleJpaEntity = ScheduleJpaEntity.builder() + .startDateTime(LocalDateTime.of(2024, 1, 1, 10, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) + .build(); + + scheduleRepository.save(BeforeScheduleJpaEntity); + + // given 2 + ScheduleJpaEntity newScheduleJpaEntity = ScheduleJpaEntity.builder() + .startDateTime(LocalDateTime.of(2024, 1, 1, 11, 59, 59)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 16, 0, 0)) + .build(); + + // then + assertThatCode(() -> scheduleAppender.createSchedule(newScheduleJpaEntity)) + .isInstanceOf(BadRequestException.class) + .hasMessage(SCHEDULE_ALREADY_EXIST.message()); + + assertThat(scheduleRepository.count()).isEqualTo(1); + } + + @DisplayName("해당 시간대 뒤에 스케줄이 존재하면 예외가 발생한다.") + @Test + void createScheduleFailAlreadyExistAfterSchedule() { + // given 1 + ScheduleJpaEntity afterScheduleJpaEntity = ScheduleJpaEntity.builder() + .startDateTime(LocalDateTime.of(2024, 1, 1, 10, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) + .build(); + + scheduleRepository.save(afterScheduleJpaEntity); + + // given 2 + ScheduleJpaEntity newScheduleJpaEntity = ScheduleJpaEntity.builder() + .startDateTime(LocalDateTime.of(2024, 1, 1, 8, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 10, 0, 1)) + .build(); + + // then + assertThatCode(() -> scheduleAppender.createSchedule(newScheduleJpaEntity)) + .isInstanceOf(BadRequestException.class) + .hasMessage(SCHEDULE_ALREADY_EXIST.message()); + + assertThat(scheduleRepository.count()).isEqualTo(1); + } } \ No newline at end of file diff --git a/backend/src/test/java/moim_today/presentation/schedule/ScheduleControllerTest.java b/backend/src/test/java/moim_today/presentation/schedule/ScheduleControllerTest.java index c1899d8b..1b061695 100644 --- a/backend/src/test/java/moim_today/presentation/schedule/ScheduleControllerTest.java +++ b/backend/src/test/java/moim_today/presentation/schedule/ScheduleControllerTest.java @@ -2,13 +2,17 @@ import com.epages.restdocs.apispec.ResourceSnippetParameters; import moim_today.application.schedule.ScheduleService; +import moim_today.dto.schedule.ScheduleCreateRequest; import moim_today.dto.schedule.TimeTableRequest; import moim_today.fake_class.schedule.FakeScheduleService; import moim_today.util.ControllerTest; +import moim_today.util.TestConstant; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.time.DayOfWeek; import java.time.LocalDate; +import java.time.LocalDateTime; import static com.epages.restdocs.apispec.MockMvcRestDocumentationWrapper.document; import static com.epages.restdocs.apispec.ResourceDocumentation.resource; @@ -92,4 +96,72 @@ void fetchTimeTableFail() throws Exception { .build() ))); } + + @DisplayName("개인 일정을 생성한다.") + @Test + void createSchedule() throws Exception { + ScheduleCreateRequest scheduleCreateRequest = ScheduleCreateRequest.builder() + .scheduleName(TestConstant.SCHEDULE_NAME.value()) + .dayOfWeek(DayOfWeek.MONDAY) + .startDateTime(LocalDateTime.of(2024, 1, 1, 10, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) + .build(); + + String json = objectMapper.writeValueAsString(scheduleCreateRequest); + System.out.println(json); + + mockMvc.perform(post("/api/schedules") + .contentType(APPLICATION_JSON) + .content(json) + ) + .andExpect(status().isOk()) + .andDo(document("개인 일정 등록 성공", + resource(ResourceSnippetParameters.builder() + .tag("스케줄") + .summary("개인 일정 등록") + .requestFields( + fieldWithPath("scheduleName").type(STRING).description("스케줄명"), + fieldWithPath("dayOfWeek").type(STRING).description("요일"), + fieldWithPath("startDateTime").type(STRING).description("시작 시간"), + fieldWithPath("endDateTime").type(STRING).description("종료 시간") + ) + .build() + ))); + } + + @DisplayName("이미 존재하는 시간대에 개인 일정을 등록하면 예외가 발생한다.") + @Test + void createScheduleFail() throws Exception { + ScheduleCreateRequest scheduleCreateRequest = ScheduleCreateRequest.builder() + .scheduleName(TestConstant.SCHEDULE_NAME.value()) + .dayOfWeek(DayOfWeek.MONDAY) + .startDateTime(LocalDateTime.of(2024, 1, 1, 0, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) + .build(); + + String json = objectMapper.writeValueAsString(scheduleCreateRequest); + System.out.println(json); + + mockMvc.perform(post("/api/schedules") + .contentType(APPLICATION_JSON) + .content(json) + ) + .andExpect(status().isBadRequest()) + .andDo(document("개인 일정 등록 실패 - 이미 존재하는 시간대의 스케줄", + resource(ResourceSnippetParameters.builder() + .tag("스케줄") + .summary("개인 일정 등록") + .requestFields( + fieldWithPath("scheduleName").type(STRING).description("스케줄명"), + fieldWithPath("dayOfWeek").type(STRING).description("요일"), + fieldWithPath("startDateTime").type(STRING).description("시작 시간"), + fieldWithPath("endDateTime").type(STRING).description("종료 시간") + ) + .responseFields( + fieldWithPath("statusCode").type(STRING).description("상태 코드"), + fieldWithPath("message").type(STRING).description("오류 메세지") + ) + .build() + ))); + } } \ No newline at end of file diff --git a/backend/src/test/java/moim_today/util/ControllerTest.java b/backend/src/test/java/moim_today/util/ControllerTest.java index 374386f8..cd965750 100644 --- a/backend/src/test/java/moim_today/util/ControllerTest.java +++ b/backend/src/test/java/moim_today/util/ControllerTest.java @@ -16,9 +16,10 @@ import java.io.IOException; import java.time.LocalDate; +import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; -import static moim_today.util.TestConstant.LOCAL_DATE_FORMAT; +import static moim_today.util.TestConstant.*; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration; @ExtendWith(RestDocumentationExtension.class) @@ -28,7 +29,8 @@ public abstract class ControllerTest { protected ObjectMapper objectMapper = serializingObjectMapper(); - private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern(LOCAL_DATE_FORMAT.value()); + private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern(LOCAL_DATE_FORMAT.value()); + private static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern(LOCAL_DATE_TIME_FORMAT.value()); @BeforeEach void setUp(final RestDocumentationContextProvider provider) { @@ -43,25 +45,45 @@ void setUp(final RestDocumentationContextProvider provider) { private ObjectMapper serializingObjectMapper() { ObjectMapper objectMapper = new ObjectMapper(); JavaTimeModule javaTimeModule = new JavaTimeModule(); + javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer()); javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer()); + javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer()); + javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer()); objectMapper.registerModule(javaTimeModule); + return objectMapper; } - private class LocalDateSerializer extends JsonSerializer { + private static class LocalDateSerializer extends JsonSerializer { @Override public void serialize(final LocalDate value, JsonGenerator gen, final SerializerProvider serializers) throws IOException { - gen.writeString(value.format(FORMATTER)); + gen.writeString(value.format(DATE_FORMATTER)); } } - private class LocalDateDeserializer extends JsonDeserializer { + private static class LocalDateDeserializer extends JsonDeserializer { @Override public LocalDate deserialize(final JsonParser p, final DeserializationContext ctxt) throws IOException { - return LocalDate.parse(p.getValueAsString(), FORMATTER); + return LocalDate.parse(p.getValueAsString(), DATE_FORMATTER); + } + } + + private static class LocalDateTimeSerializer extends JsonSerializer { + + @Override + public void serialize(final LocalDateTime value, final JsonGenerator gen, final SerializerProvider serializerProvider) throws IOException { + gen.writeString(value.format(DATETIME_FORMATTER)); + } + } + + private static class LocalDateTimeDeserializer extends JsonDeserializer { + + @Override + public LocalDateTime deserialize(final JsonParser p, final DeserializationContext deserializationContext) throws IOException { + return LocalDateTime.parse(p.getValueAsString(), DATETIME_FORMATTER); } } diff --git a/backend/src/test/java/moim_today/util/TestConstant.java b/backend/src/test/java/moim_today/util/TestConstant.java index 662f52f6..81ff03cb 100644 --- a/backend/src/test/java/moim_today/util/TestConstant.java +++ b/backend/src/test/java/moim_today/util/TestConstant.java @@ -52,10 +52,13 @@ public enum TestConstant { MOIM_IMAGE_URL("moimImageUrl"), + SCHEDULE_NAME("scheduleName"), + STATUS_CODE("200"), MESSAGE("message"), - LOCAL_DATE_FORMAT("yyyy-MM-dd"); + LOCAL_DATE_FORMAT("yyyy-MM-dd"), + LOCAL_DATE_TIME_FORMAT("yyyy-MM-dd HH:mm:ss"); private final String value; From 33a420bfefd6c825053a801bc2667a37abe785ca Mon Sep 17 00:00:00 2001 From: Jung-YouHwan Date: Sat, 27 Apr 2024 19:02:55 +0900 Subject: [PATCH 19/52] =?UTF-8?q?[BE]=20feat=20:=20=EA=B0=9C=EC=9D=B8=20?= =?UTF-8?q?=EC=9D=BC=EC=A0=95=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/schedule/ScheduleService.java | 3 ++ .../schedule/ScheduleServiceImpl.java | 12 ++++++- .../dto/schedule/ScheduleCreateRequest.java | 1 + .../dto/schedule/ScheduleUpdateRequest.java | 23 +++++++++++++ .../exception/ScheduleExceptionConstant.java | 3 +- .../implement/schedule/ScheduleUpdater.java | 34 +++++++++++++++++++ .../entity/schedule/ScheduleJpaEntity.java | 17 ++++++++++ .../schedule/ScheduleController.java | 12 ++++--- .../schedule/FakeScheduleService.java | 6 ++++ 9 files changed, 105 insertions(+), 6 deletions(-) create mode 100644 backend/src/main/java/moim_today/dto/schedule/ScheduleUpdateRequest.java create mode 100644 backend/src/main/java/moim_today/implement/schedule/ScheduleUpdater.java diff --git a/backend/src/main/java/moim_today/application/schedule/ScheduleService.java b/backend/src/main/java/moim_today/application/schedule/ScheduleService.java index cf2ac450..7295afbd 100644 --- a/backend/src/main/java/moim_today/application/schedule/ScheduleService.java +++ b/backend/src/main/java/moim_today/application/schedule/ScheduleService.java @@ -1,6 +1,7 @@ package moim_today.application.schedule; import moim_today.dto.schedule.ScheduleCreateRequest; +import moim_today.dto.schedule.ScheduleUpdateRequest; import moim_today.dto.schedule.TimeTableRequest; @@ -9,4 +10,6 @@ public interface ScheduleService { void fetchTimeTable(final long memberId, final TimeTableRequest timeTableRequest); void createSchedule(final long memberId, final ScheduleCreateRequest scheduleCreateRequest); + + void updateSchedule(final long memberId, final ScheduleUpdateRequest scheduleUpdateRequest); } diff --git a/backend/src/main/java/moim_today/application/schedule/ScheduleServiceImpl.java b/backend/src/main/java/moim_today/application/schedule/ScheduleServiceImpl.java index effaabe3..25800371 100644 --- a/backend/src/main/java/moim_today/application/schedule/ScheduleServiceImpl.java +++ b/backend/src/main/java/moim_today/application/schedule/ScheduleServiceImpl.java @@ -2,9 +2,11 @@ import moim_today.domain.schedule.Schedule; import moim_today.dto.schedule.ScheduleCreateRequest; +import moim_today.dto.schedule.ScheduleUpdateRequest; import moim_today.dto.schedule.TimeTableRequest; import moim_today.implement.schedule.ScheduleAppender; import moim_today.implement.schedule.ScheduleManager; +import moim_today.implement.schedule.ScheduleUpdater; import moim_today.persistence.entity.schedule.ScheduleJpaEntity; import org.springframework.stereotype.Service; @@ -15,10 +17,13 @@ public class ScheduleServiceImpl implements ScheduleService { private final ScheduleManager scheduleManager; private final ScheduleAppender scheduleAppender; + private final ScheduleUpdater scheduleUpdater; - public ScheduleServiceImpl(final ScheduleManager scheduleManager, final ScheduleAppender scheduleAppender) { + public ScheduleServiceImpl(final ScheduleManager scheduleManager, final ScheduleAppender scheduleAppender, + final ScheduleUpdater scheduleUpdater) { this.scheduleManager = scheduleManager; this.scheduleAppender = scheduleAppender; + this.scheduleUpdater = scheduleUpdater; } @Override @@ -33,4 +38,9 @@ public void createSchedule(final long memberId, final ScheduleCreateRequest sche ScheduleJpaEntity scheduleJpaEntity = scheduleCreateRequest.toEntity(memberId); scheduleAppender.createSchedule(scheduleJpaEntity); } + + @Override + public void updateSchedule(final long memberId, final ScheduleUpdateRequest scheduleUpdateRequest) { + scheduleUpdater.updateSchedule(memberId, scheduleUpdateRequest); + } } \ No newline at end of file diff --git a/backend/src/main/java/moim_today/dto/schedule/ScheduleCreateRequest.java b/backend/src/main/java/moim_today/dto/schedule/ScheduleCreateRequest.java index cbf84c39..9b8b1867 100644 --- a/backend/src/main/java/moim_today/dto/schedule/ScheduleCreateRequest.java +++ b/backend/src/main/java/moim_today/dto/schedule/ScheduleCreateRequest.java @@ -13,6 +13,7 @@ public record ScheduleCreateRequest( String scheduleName, DayOfWeek dayOfWeek, + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul") LocalDateTime startDateTime, @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul") diff --git a/backend/src/main/java/moim_today/dto/schedule/ScheduleUpdateRequest.java b/backend/src/main/java/moim_today/dto/schedule/ScheduleUpdateRequest.java new file mode 100644 index 00000000..aac66abe --- /dev/null +++ b/backend/src/main/java/moim_today/dto/schedule/ScheduleUpdateRequest.java @@ -0,0 +1,23 @@ +package moim_today.dto.schedule; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Builder; +import moim_today.persistence.entity.schedule.ScheduleJpaEntity; + +import java.time.DayOfWeek; +import java.time.LocalDateTime; + +import static moim_today.global.constant.NumberConstant.SCHEDULE_MEETING_ID; + +@Builder +public record ScheduleUpdateRequest( + long scheduleId, + String scheduleName, + DayOfWeek dayOfWeek, + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul") + LocalDateTime startDateTime, + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul") + LocalDateTime endDateTime +) { +} diff --git a/backend/src/main/java/moim_today/global/constant/exception/ScheduleExceptionConstant.java b/backend/src/main/java/moim_today/global/constant/exception/ScheduleExceptionConstant.java index e7eaffa4..f3b0d8b5 100644 --- a/backend/src/main/java/moim_today/global/constant/exception/ScheduleExceptionConstant.java +++ b/backend/src/main/java/moim_today/global/constant/exception/ScheduleExceptionConstant.java @@ -3,7 +3,8 @@ public enum ScheduleExceptionConstant { SCHEDULE_ALREADY_EXIST("해당 시간에 이미 스케줄이 존재합니다."), - SCHEDULE_NOT_FOUND("해당 스케줄을 찾을 수 없습니다"); + SCHEDULE_FORBIDDEN("해당 스케줄에 대한 접근 권한이 없습니다."), + SCHEDULE_NOT_FOUND("해당 스케줄을 찾을 수 없습니다."); private final String message; diff --git a/backend/src/main/java/moim_today/implement/schedule/ScheduleUpdater.java b/backend/src/main/java/moim_today/implement/schedule/ScheduleUpdater.java new file mode 100644 index 00000000..071461df --- /dev/null +++ b/backend/src/main/java/moim_today/implement/schedule/ScheduleUpdater.java @@ -0,0 +1,34 @@ +package moim_today.implement.schedule; + +import moim_today.dto.schedule.ScheduleUpdateRequest; +import moim_today.global.annotation.Implement; +import moim_today.global.error.BadRequestException; +import moim_today.persistence.entity.schedule.ScheduleJpaEntity; +import moim_today.persistence.repository.schedule.ScheduleRepository; +import org.springframework.transaction.annotation.Transactional; + +import static moim_today.global.constant.exception.ScheduleExceptionConstant.SCHEDULE_ALREADY_EXIST; + +@Implement +public class ScheduleUpdater { + + private final ScheduleRepository scheduleRepository; + + public ScheduleUpdater(final ScheduleRepository scheduleRepository) { + this.scheduleRepository = scheduleRepository; + } + + @Transactional + public void updateSchedule(final long memberId, final ScheduleUpdateRequest scheduleUpdateRequest) { + ScheduleJpaEntity scheduleJpaEntity = scheduleRepository.getById(scheduleUpdateRequest.scheduleId()); + scheduleJpaEntity.validateMember(memberId); + scheduleJpaEntity.updateSchedule(scheduleUpdateRequest); + validateAlreadyExist(scheduleJpaEntity); + } + + private void validateAlreadyExist(final ScheduleJpaEntity scheduleJpaEntity) { + if (scheduleRepository.exists(scheduleJpaEntity)) { + throw new BadRequestException(SCHEDULE_ALREADY_EXIST.message()); + } + } +} diff --git a/backend/src/main/java/moim_today/persistence/entity/schedule/ScheduleJpaEntity.java b/backend/src/main/java/moim_today/persistence/entity/schedule/ScheduleJpaEntity.java index fa507e1c..e8fdfe30 100644 --- a/backend/src/main/java/moim_today/persistence/entity/schedule/ScheduleJpaEntity.java +++ b/backend/src/main/java/moim_today/persistence/entity/schedule/ScheduleJpaEntity.java @@ -1,14 +1,18 @@ package moim_today.persistence.entity.schedule; +import moim_today.dto.schedule.ScheduleUpdateRequest; import moim_today.global.annotation.Association; import moim_today.global.base_entity.BaseTimeEntity; import jakarta.persistence.*; import lombok.Builder; import lombok.Getter; +import moim_today.global.error.ForbiddenException; import java.time.DayOfWeek; import java.time.LocalDateTime; +import static moim_today.global.constant.exception.ScheduleExceptionConstant.SCHEDULE_FORBIDDEN; + @Getter @Table(name = "schedule") @Entity @@ -47,4 +51,17 @@ private ScheduleJpaEntity(final long memberId, final long meetingId, final Strin this.startDateTime = startDateTime; this.endDateTime = endDateTime; } + + public void updateSchedule(final ScheduleUpdateRequest scheduleUpdateRequest) { + this.scheduleName = scheduleUpdateRequest.scheduleName(); + this.dayOfWeek = scheduleUpdateRequest.dayOfWeek(); + this.startDateTime = scheduleUpdateRequest.startDateTime(); + this.endDateTime = scheduleUpdateRequest.endDateTime(); + } + + public void validateMember(final long memberId) { + if (this.memberId != memberId) { + throw new ForbiddenException(SCHEDULE_FORBIDDEN.message()); + } + } } diff --git a/backend/src/main/java/moim_today/presentation/schedule/ScheduleController.java b/backend/src/main/java/moim_today/presentation/schedule/ScheduleController.java index 623b096c..334af2cc 100644 --- a/backend/src/main/java/moim_today/presentation/schedule/ScheduleController.java +++ b/backend/src/main/java/moim_today/presentation/schedule/ScheduleController.java @@ -3,12 +3,10 @@ import moim_today.application.schedule.ScheduleService; import moim_today.domain.member.MemberSession; import moim_today.dto.schedule.ScheduleCreateRequest; +import moim_today.dto.schedule.ScheduleUpdateRequest; import moim_today.dto.schedule.TimeTableRequest; import moim_today.global.annotation.Login; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; @RequestMapping("/api/schedules") @@ -32,4 +30,10 @@ public void createSchedule(@Login final MemberSession memberSession, @RequestBody final ScheduleCreateRequest scheduleCreateRequest) { scheduleService.createSchedule(memberSession.id(), scheduleCreateRequest); } + + @PatchMapping + public void updateSchedule(@Login final MemberSession memberSession, + @RequestBody final ScheduleUpdateRequest scheduleUpdateRequest) { + scheduleService.updateSchedule(memberSession.id(), scheduleUpdateRequest); + } } \ No newline at end of file diff --git a/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java b/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java index e0b1f55b..0520be54 100644 --- a/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java +++ b/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java @@ -2,6 +2,7 @@ import moim_today.application.schedule.ScheduleService; import moim_today.dto.schedule.ScheduleCreateRequest; +import moim_today.dto.schedule.ScheduleUpdateRequest; import moim_today.dto.schedule.TimeTableRequest; import moim_today.global.error.BadRequestException; @@ -26,4 +27,9 @@ public void createSchedule(final long memberId, final ScheduleCreateRequest sche throw new BadRequestException(SCHEDULE_ALREADY_EXIST.message()); } } + + @Override + public void updateSchedule(final long memberId, final ScheduleUpdateRequest scheduleUpdateRequest) { + + } } From 955d2359000bb7916c2b8d758e49fc4152a6cc90 Mon Sep 17 00:00:00 2001 From: Jung-YouHwan Date: Sat, 27 Apr 2024 19:57:41 +0900 Subject: [PATCH 20/52] =?UTF-8?q?[BE]=20test=20:=20=EA=B0=9C=EC=9D=B8=20?= =?UTF-8?q?=EC=9D=BC=EC=A0=95=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/schedule/ScheduleUpdateRequest.java | 2 - .../implement/schedule/ScheduleUpdater.java | 8 +- .../schedule/ScheduleRepository.java | 4 + .../schedule/ScheduleRepositoryImpl.java | 14 +- .../schedule/FakeScheduleService.java | 7 + .../schedule/ScheduleUpdaterTest.java | 176 ++++++++++++++++++ .../schedule/ScheduleJpaEntityTest.java | 97 ++++++++++ .../schedule/ScheduleControllerTest.java | 118 +++++++++++- .../java/moim_today/util/TestConstant.java | 2 + 9 files changed, 420 insertions(+), 8 deletions(-) create mode 100644 backend/src/test/java/moim_today/implement/schedule/ScheduleUpdaterTest.java create mode 100644 backend/src/test/java/moim_today/persistence/entity/schedule/ScheduleJpaEntityTest.java diff --git a/backend/src/main/java/moim_today/dto/schedule/ScheduleUpdateRequest.java b/backend/src/main/java/moim_today/dto/schedule/ScheduleUpdateRequest.java index aac66abe..fd3f8834 100644 --- a/backend/src/main/java/moim_today/dto/schedule/ScheduleUpdateRequest.java +++ b/backend/src/main/java/moim_today/dto/schedule/ScheduleUpdateRequest.java @@ -2,12 +2,10 @@ import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Builder; -import moim_today.persistence.entity.schedule.ScheduleJpaEntity; import java.time.DayOfWeek; import java.time.LocalDateTime; -import static moim_today.global.constant.NumberConstant.SCHEDULE_MEETING_ID; @Builder public record ScheduleUpdateRequest( diff --git a/backend/src/main/java/moim_today/implement/schedule/ScheduleUpdater.java b/backend/src/main/java/moim_today/implement/schedule/ScheduleUpdater.java index 071461df..d5e3e888 100644 --- a/backend/src/main/java/moim_today/implement/schedule/ScheduleUpdater.java +++ b/backend/src/main/java/moim_today/implement/schedule/ScheduleUpdater.java @@ -7,6 +7,7 @@ import moim_today.persistence.repository.schedule.ScheduleRepository; import org.springframework.transaction.annotation.Transactional; + import static moim_today.global.constant.exception.ScheduleExceptionConstant.SCHEDULE_ALREADY_EXIST; @Implement @@ -22,12 +23,13 @@ public ScheduleUpdater(final ScheduleRepository scheduleRepository) { public void updateSchedule(final long memberId, final ScheduleUpdateRequest scheduleUpdateRequest) { ScheduleJpaEntity scheduleJpaEntity = scheduleRepository.getById(scheduleUpdateRequest.scheduleId()); scheduleJpaEntity.validateMember(memberId); + validateAlreadyExist(scheduleJpaEntity.getId(), scheduleUpdateRequest); + scheduleJpaEntity.updateSchedule(scheduleUpdateRequest); - validateAlreadyExist(scheduleJpaEntity); } - private void validateAlreadyExist(final ScheduleJpaEntity scheduleJpaEntity) { - if (scheduleRepository.exists(scheduleJpaEntity)) { + private void validateAlreadyExist(final long scheduleId, final ScheduleUpdateRequest scheduleUpdateRequest) { + if (scheduleRepository.existsExcludeEntity(scheduleId, scheduleUpdateRequest)) { throw new BadRequestException(SCHEDULE_ALREADY_EXIST.message()); } } diff --git a/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepository.java b/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepository.java index ead15664..eb3c69d0 100644 --- a/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepository.java +++ b/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepository.java @@ -1,8 +1,10 @@ package moim_today.persistence.repository.schedule; +import moim_today.dto.schedule.ScheduleUpdateRequest; import moim_today.dto.schedule.TimeTableSchedulingTask; import moim_today.persistence.entity.schedule.ScheduleJpaEntity; + public interface ScheduleRepository { ScheduleJpaEntity getById(final long scheduleId); @@ -13,5 +15,7 @@ public interface ScheduleRepository { boolean exists(final ScheduleJpaEntity scheduleJpaEntity); + boolean existsExcludeEntity(final long scheduleId, final ScheduleUpdateRequest scheduleUpdateRequest); + long count(); } diff --git a/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepositoryImpl.java b/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepositoryImpl.java index 80055bd0..26804b96 100644 --- a/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepositoryImpl.java +++ b/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepositoryImpl.java @@ -2,8 +2,8 @@ import com.querydsl.jpa.impl.JPAQueryFactory; import moim_today.domain.schedule.Schedule; +import moim_today.dto.schedule.ScheduleUpdateRequest; import moim_today.dto.schedule.TimeTableSchedulingTask; -import moim_today.global.constant.exception.ScheduleExceptionConstant; import moim_today.global.error.NotFoundException; import moim_today.persistence.entity.schedule.QScheduleJpaEntity; import moim_today.persistence.entity.schedule.ScheduleJpaEntity; @@ -89,6 +89,18 @@ public boolean exists(final ScheduleJpaEntity scheduleJpaEntity) { .fetchFirst() != null; } + @Override + public boolean existsExcludeEntity(final long scheduleId, final ScheduleUpdateRequest scheduleUpdateRequest) { + return queryFactory + .selectFrom(QScheduleJpaEntity.scheduleJpaEntity) + .where( + QScheduleJpaEntity.scheduleJpaEntity.id.ne(scheduleId) + .and(QScheduleJpaEntity.scheduleJpaEntity.startDateTime.before(scheduleUpdateRequest.endDateTime()) + .and(QScheduleJpaEntity.scheduleJpaEntity.endDateTime.after(scheduleUpdateRequest.startDateTime()))) + ) + .fetchFirst() != null; + } + @Override public long count() { return scheduleJpaRepository.count(); diff --git a/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java b/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java index 0520be54..92c71545 100644 --- a/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java +++ b/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java @@ -5,6 +5,7 @@ import moim_today.dto.schedule.ScheduleUpdateRequest; import moim_today.dto.schedule.TimeTableRequest; import moim_today.global.error.BadRequestException; +import moim_today.global.error.ForbiddenException; import java.time.LocalDateTime; @@ -30,6 +31,12 @@ public void createSchedule(final long memberId, final ScheduleCreateRequest sche @Override public void updateSchedule(final long memberId, final ScheduleUpdateRequest scheduleUpdateRequest) { + if (scheduleUpdateRequest.scheduleId() == Long.parseLong(FORBIDDEN_SCHEDULE_ID.value())) { + throw new ForbiddenException(SCHEDULE_FORBIDDEN.message()); + } + if(scheduleUpdateRequest.startDateTime().equals(LocalDateTime.of(2024, 1, 1, 0, 0, 0))) { + throw new BadRequestException(SCHEDULE_ALREADY_EXIST.message()); + } } } diff --git a/backend/src/test/java/moim_today/implement/schedule/ScheduleUpdaterTest.java b/backend/src/test/java/moim_today/implement/schedule/ScheduleUpdaterTest.java new file mode 100644 index 00000000..b370264c --- /dev/null +++ b/backend/src/test/java/moim_today/implement/schedule/ScheduleUpdaterTest.java @@ -0,0 +1,176 @@ +package moim_today.implement.schedule; + +import moim_today.dto.schedule.ScheduleUpdateRequest; +import moim_today.global.error.BadRequestException; +import moim_today.global.error.ForbiddenException; +import moim_today.persistence.entity.schedule.ScheduleJpaEntity; +import moim_today.util.ImplementTest; +import moim_today.util.TestConstant; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.time.DayOfWeek; +import java.time.LocalDateTime; + +import static moim_today.global.constant.exception.ScheduleExceptionConstant.SCHEDULE_ALREADY_EXIST; +import static moim_today.global.constant.exception.ScheduleExceptionConstant.SCHEDULE_FORBIDDEN; +import static moim_today.util.TestConstant.*; +import static moim_today.util.TestConstant.SCHEDULE_NAME; +import static org.assertj.core.api.Assertions.*; + + +class ScheduleUpdaterTest extends ImplementTest { + + @Autowired + private ScheduleUpdater scheduleUpdater; + + @DisplayName("개인 일정을 수정한다.") + @Test + void updateSchedule() { + // given 1 + long memberId = 1L; + long meetingId = 2L; + + ScheduleJpaEntity scheduleJpaEntity = ScheduleJpaEntity.builder() + .memberId(memberId) + .meetingId(meetingId) + .scheduleName(SCHEDULE_NAME.value()) + .dayOfWeek(DayOfWeek.MONDAY) + .startDateTime(LocalDateTime.of(2024, 1, 1, 10, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) + .build(); + + scheduleRepository.save(scheduleJpaEntity); + + // given 2 + ScheduleUpdateRequest scheduleUpdateRequest = ScheduleUpdateRequest.builder() + .scheduleId(scheduleJpaEntity.getId()) + .scheduleName(NEW_SCHEDULE_NAME.value()) + .dayOfWeek(DayOfWeek.SATURDAY) + .startDateTime(LocalDateTime.of(2024, 1, 1, 11, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 13, 0, 0)) + .build(); + + // when + scheduleUpdater.updateSchedule(memberId, scheduleUpdateRequest); + + // then + ScheduleJpaEntity findEntity = scheduleRepository.getById(scheduleJpaEntity.getId()); + + assertThat(scheduleRepository.count()).isEqualTo(1); + assertThat(findEntity.getScheduleName()).isEqualTo(NEW_SCHEDULE_NAME.value()); + assertThat(findEntity.getDayOfWeek()).isEqualTo(DayOfWeek.SATURDAY); + assertThat(findEntity.getStartDateTime()).isEqualTo(LocalDateTime.of(2024, 1, 1, 11, 0, 0)); + assertThat(findEntity.getEndDateTime()).isEqualTo(LocalDateTime.of(2024, 1, 1, 13, 0, 0)); + } + + @DisplayName("해당 시간대 앞에 스케줄이 존재하면 예외가 발생한다.") + @Test + void updateScheduleFailAlreadyExistBeforeSchedule() { + // given 1 + ScheduleJpaEntity BeforeScheduleJpaEntity = ScheduleJpaEntity.builder() + .startDateTime(LocalDateTime.of(2024, 1, 1, 10, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) + .build(); + + scheduleRepository.save(BeforeScheduleJpaEntity); + + // given 2 + long memberId = 1L; + ScheduleJpaEntity scheduleJpaEntity = ScheduleJpaEntity.builder() + .memberId(memberId) + .startDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 14, 0, 0)) + .build(); + + scheduleRepository.save(scheduleJpaEntity); + + // given 2 + ScheduleUpdateRequest scheduleUpdateRequest = ScheduleUpdateRequest.builder() + .scheduleId(scheduleJpaEntity.getId()) + .scheduleName(NEW_SCHEDULE_NAME.value()) + .dayOfWeek(DayOfWeek.SATURDAY) + .startDateTime(LocalDateTime.of(2024, 1, 1, 11, 59, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 14, 0, 0)) + .build(); + + // expected + assertThatCode(() -> scheduleUpdater.updateSchedule(memberId, scheduleUpdateRequest)) + .isInstanceOf(BadRequestException.class) + .hasMessage(SCHEDULE_ALREADY_EXIST.message()); + + assertThat(scheduleRepository.count()).isEqualTo(2); + } + + @DisplayName("해당 시간대 앞에 스케줄이 존재하면 예외가 발생한다.") + @Test + void updateScheduleFailAlreadyExistAfterSchedule() { + // given 1 + ScheduleJpaEntity afterScheduleJpaEntity = ScheduleJpaEntity.builder() + .startDateTime(LocalDateTime.of(2024, 1, 1, 14, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 16, 0, 0)) + .build(); + + scheduleRepository.save(afterScheduleJpaEntity); + + // given 2 + long memberId = 1L; + ScheduleJpaEntity scheduleJpaEntity = ScheduleJpaEntity.builder() + .memberId(memberId) + .startDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 14, 0, 0)) + .build(); + + scheduleRepository.save(scheduleJpaEntity); + + // given 2 + ScheduleUpdateRequest scheduleUpdateRequest = ScheduleUpdateRequest.builder() + .scheduleId(scheduleJpaEntity.getId()) + .scheduleName(NEW_SCHEDULE_NAME.value()) + .dayOfWeek(DayOfWeek.SATURDAY) + .startDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 14, 1, 0)) + .build(); + + // expected + assertThatCode(() -> scheduleUpdater.updateSchedule(memberId, scheduleUpdateRequest)) + .isInstanceOf(BadRequestException.class) + .hasMessage(SCHEDULE_ALREADY_EXIST.message()); + + assertThat(scheduleRepository.count()).isEqualTo(2); + } + + @DisplayName("해당 회원의 스케줄이 아니면 예외가 발생한다.") + @Test + void validateMember() { + // given 1 + long memberId = 1L; + long anotherMemberId = 9999L; + + ScheduleJpaEntity scheduleJpaEntity = ScheduleJpaEntity.builder() + .memberId(memberId) + .startDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 14, 0, 0)) + .build(); + + scheduleRepository.save(scheduleJpaEntity); + + // given 2 + ScheduleUpdateRequest scheduleUpdateRequest = ScheduleUpdateRequest.builder() + .scheduleId(scheduleJpaEntity.getId()) + .scheduleName(NEW_SCHEDULE_NAME.value()) + .dayOfWeek(DayOfWeek.SATURDAY) + .startDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 14, 1, 0)) + .build(); + + // expected + assertThatCode(() -> scheduleUpdater.updateSchedule(anotherMemberId, scheduleUpdateRequest)) + .isInstanceOf(ForbiddenException.class) + .hasMessage(SCHEDULE_FORBIDDEN.message()); + + assertThat(scheduleRepository.count()).isEqualTo(1); + } +} \ No newline at end of file diff --git a/backend/src/test/java/moim_today/persistence/entity/schedule/ScheduleJpaEntityTest.java b/backend/src/test/java/moim_today/persistence/entity/schedule/ScheduleJpaEntityTest.java new file mode 100644 index 00000000..17867dee --- /dev/null +++ b/backend/src/test/java/moim_today/persistence/entity/schedule/ScheduleJpaEntityTest.java @@ -0,0 +1,97 @@ +package moim_today.persistence.entity.schedule; + +import moim_today.dto.schedule.ScheduleUpdateRequest; +import moim_today.global.error.ForbiddenException; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.time.DayOfWeek; +import java.time.LocalDateTime; + +import static moim_today.global.constant.exception.ScheduleExceptionConstant.SCHEDULE_FORBIDDEN; +import static moim_today.util.TestConstant.*; +import static org.assertj.core.api.Assertions.*; + +class ScheduleJpaEntityTest { + + @DisplayName("개인 일정을 수정한다.") + @Test + void updateSchedule() { + // given + long memberId = 1L; + long meetingId = 2L; + + ScheduleJpaEntity scheduleJpaEntity = ScheduleJpaEntity.builder() + .memberId(memberId) + .meetingId(meetingId) + .scheduleName(SCHEDULE_NAME.value()) + .dayOfWeek(DayOfWeek.MONDAY) + .startDateTime(LocalDateTime.of(2024, 1, 1, 10, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) + .build(); + + ScheduleUpdateRequest scheduleUpdateRequest = ScheduleUpdateRequest.builder() + .scheduleId(1L) + .scheduleName(NEW_SCHEDULE_NAME.value()) + .dayOfWeek(DayOfWeek.SATURDAY) + .startDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 14, 0, 0)) + .build(); + + // when + scheduleJpaEntity.updateSchedule(scheduleUpdateRequest); + + // then + assertThat(scheduleJpaEntity.getMemberId()).isEqualTo(memberId); + assertThat(scheduleJpaEntity.getMeetingId()).isEqualTo(meetingId); + assertThat(scheduleJpaEntity.getScheduleName()).isEqualTo(NEW_SCHEDULE_NAME.value()); + assertThat(scheduleJpaEntity.getDayOfWeek()).isEqualTo(DayOfWeek.SATURDAY); + assertThat(scheduleJpaEntity.getStartDateTime()).isEqualTo(LocalDateTime.of(2024, 1, 1, 12, 0, 0)); + assertThat(scheduleJpaEntity.getEndDateTime()).isEqualTo(LocalDateTime.of(2024, 1, 1, 14, 0, 0)); + } + + @DisplayName("회원 id가 일치하면 검증에 성공한다.") + @Test + void validateMember() { + // given + long memberId = 1L; + long meetingId = 2L; + + ScheduleJpaEntity scheduleJpaEntity = ScheduleJpaEntity.builder() + .memberId(memberId) + .meetingId(meetingId) + .scheduleName(SCHEDULE_NAME.value()) + .dayOfWeek(DayOfWeek.MONDAY) + .startDateTime(LocalDateTime.of(2024, 1, 1, 10, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) + .build(); + + // expected + assertThatCode(() -> scheduleJpaEntity.validateMember(memberId)) + .doesNotThrowAnyException(); + } + + @DisplayName("회원 id가 일치하지 않으면 예외가 발생한다.") + @Test + void validateMemberFail() { + // given + long memberId = 1L; + long meetingId = 2L; + + long anotherMemberId = 9999L; + + ScheduleJpaEntity scheduleJpaEntity = ScheduleJpaEntity.builder() + .memberId(memberId) + .meetingId(meetingId) + .scheduleName(SCHEDULE_NAME.value()) + .dayOfWeek(DayOfWeek.MONDAY) + .startDateTime(LocalDateTime.of(2024, 1, 1, 10, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) + .build(); + + // expected + assertThatCode(() -> scheduleJpaEntity.validateMember(anotherMemberId)) + .isInstanceOf(ForbiddenException.class) + .hasMessage(SCHEDULE_FORBIDDEN.message()); + } +} \ No newline at end of file diff --git a/backend/src/test/java/moim_today/presentation/schedule/ScheduleControllerTest.java b/backend/src/test/java/moim_today/presentation/schedule/ScheduleControllerTest.java index 1b061695..eb2a4aef 100644 --- a/backend/src/test/java/moim_today/presentation/schedule/ScheduleControllerTest.java +++ b/backend/src/test/java/moim_today/presentation/schedule/ScheduleControllerTest.java @@ -3,6 +3,7 @@ import com.epages.restdocs.apispec.ResourceSnippetParameters; import moim_today.application.schedule.ScheduleService; import moim_today.dto.schedule.ScheduleCreateRequest; +import moim_today.dto.schedule.ScheduleUpdateRequest; import moim_today.dto.schedule.TimeTableRequest; import moim_today.fake_class.schedule.FakeScheduleService; import moim_today.util.ControllerTest; @@ -16,10 +17,13 @@ import static com.epages.restdocs.apispec.MockMvcRestDocumentationWrapper.document; import static com.epages.restdocs.apispec.ResourceDocumentation.resource; +import static moim_today.util.TestConstant.*; import static moim_today.util.TestConstant.EVERY_TIME_ID; import static moim_today.util.TestConstant.WRONG_EVERY_TIME_ID; import static org.springframework.http.MediaType.APPLICATION_JSON; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.patch; import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; +import static org.springframework.restdocs.payload.JsonFieldType.NUMBER; import static org.springframework.restdocs.payload.JsonFieldType.STRING; import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -101,7 +105,7 @@ void fetchTimeTableFail() throws Exception { @Test void createSchedule() throws Exception { ScheduleCreateRequest scheduleCreateRequest = ScheduleCreateRequest.builder() - .scheduleName(TestConstant.SCHEDULE_NAME.value()) + .scheduleName(SCHEDULE_NAME.value()) .dayOfWeek(DayOfWeek.MONDAY) .startDateTime(LocalDateTime.of(2024, 1, 1, 10, 0, 0)) .endDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) @@ -133,7 +137,7 @@ void createSchedule() throws Exception { @Test void createScheduleFail() throws Exception { ScheduleCreateRequest scheduleCreateRequest = ScheduleCreateRequest.builder() - .scheduleName(TestConstant.SCHEDULE_NAME.value()) + .scheduleName(SCHEDULE_NAME.value()) .dayOfWeek(DayOfWeek.MONDAY) .startDateTime(LocalDateTime.of(2024, 1, 1, 0, 0, 0)) .endDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) @@ -164,4 +168,114 @@ void createScheduleFail() throws Exception { .build() ))); } + + @DisplayName("개인 일정을 수정한다.") + @Test + void updateSchedule() throws Exception { + ScheduleUpdateRequest scheduleUpdateRequest = ScheduleUpdateRequest.builder() + .scheduleId(1L) + .scheduleName(SCHEDULE_NAME.value()) + .dayOfWeek(DayOfWeek.MONDAY) + .startDateTime(LocalDateTime.of(2024, 1, 1, 10, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) + .build(); + + String json = objectMapper.writeValueAsString(scheduleUpdateRequest); + System.out.println(json); + + mockMvc.perform(patch("/api/schedules") + .contentType(APPLICATION_JSON) + .content(json) + ) + .andExpect(status().isOk()) + .andDo(document("개인 일정 수정 성공", + resource(ResourceSnippetParameters.builder() + .tag("스케줄") + .summary("개인 일정 수정") + .requestFields( + fieldWithPath("scheduleId").type(NUMBER).description("스케줄 id"), + fieldWithPath("scheduleName").type(STRING).description("스케줄명"), + fieldWithPath("dayOfWeek").type(STRING).description("요일"), + fieldWithPath("startDateTime").type(STRING).description("시작 시간"), + fieldWithPath("endDateTime").type(STRING).description("종료 시간") + ) + .build() + ))); + } + + @DisplayName("변경하려는 시간에 다른 일정이 있으면 수정에 실패한다") + @Test + void updateScheduleBadRequest() throws Exception { + ScheduleUpdateRequest scheduleUpdateRequest = ScheduleUpdateRequest.builder() + .scheduleId(1L) + .scheduleName(SCHEDULE_NAME.value()) + .dayOfWeek(DayOfWeek.MONDAY) + .startDateTime(LocalDateTime.of(2024, 1, 1, 0, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) + .build(); + + String json = objectMapper.writeValueAsString(scheduleUpdateRequest); + System.out.println(json); + + mockMvc.perform(patch("/api/schedules") + .contentType(APPLICATION_JSON) + .content(json) + ) + .andExpect(status().isBadRequest()) + .andDo(document("개인 일정 수정 실패 - 해당 시간에 다른 일정이 있음", + resource(ResourceSnippetParameters.builder() + .tag("스케줄") + .summary("개인 일정 수정") + .requestFields( + fieldWithPath("scheduleId").type(NUMBER).description("스케줄 id"), + fieldWithPath("scheduleName").type(STRING).description("스케줄명"), + fieldWithPath("dayOfWeek").type(STRING).description("요일"), + fieldWithPath("startDateTime").type(STRING).description("시작 시간"), + fieldWithPath("endDateTime").type(STRING).description("종료 시간") + ) + .responseFields( + fieldWithPath("statusCode").type(STRING).description("상태 코드"), + fieldWithPath("message").type(STRING).description("오류 메세지") + ) + .build() + ))); + } + + @DisplayName("회원의 스케줄이 아니면 수정할 수 없다.") + @Test + void updateScheduleForbidden() throws Exception { + ScheduleUpdateRequest scheduleUpdateRequest = ScheduleUpdateRequest.builder() + .scheduleId(Long.parseLong(FORBIDDEN_SCHEDULE_ID.value())) + .scheduleName(SCHEDULE_NAME.value()) + .dayOfWeek(DayOfWeek.MONDAY) + .startDateTime(LocalDateTime.of(2024, 1, 1, 10, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) + .build(); + + String json = objectMapper.writeValueAsString(scheduleUpdateRequest); + System.out.println(json); + + mockMvc.perform(patch("/api/schedules") + .contentType(APPLICATION_JSON) + .content(json) + ) + .andExpect(status().isForbidden()) + .andDo(document("개인 일정 수정 실패 - 회원의 스케줄이 아님", + resource(ResourceSnippetParameters.builder() + .tag("스케줄") + .summary("개인 일정 수정") + .requestFields( + fieldWithPath("scheduleId").type(NUMBER).description("스케줄 id"), + fieldWithPath("scheduleName").type(STRING).description("스케줄명"), + fieldWithPath("dayOfWeek").type(STRING).description("요일"), + fieldWithPath("startDateTime").type(STRING).description("시작 시간"), + fieldWithPath("endDateTime").type(STRING).description("종료 시간") + ) + .responseFields( + fieldWithPath("statusCode").type(STRING).description("상태 코드"), + fieldWithPath("message").type(STRING).description("오류 메세지") + ) + .build() + ))); + } } \ No newline at end of file diff --git a/backend/src/test/java/moim_today/util/TestConstant.java b/backend/src/test/java/moim_today/util/TestConstant.java index 81ff03cb..16b9d1ac 100644 --- a/backend/src/test/java/moim_today/util/TestConstant.java +++ b/backend/src/test/java/moim_today/util/TestConstant.java @@ -53,6 +53,8 @@ public enum TestConstant { SCHEDULE_NAME("scheduleName"), + NEW_SCHEDULE_NAME("new scheduleName"), + FORBIDDEN_SCHEDULE_ID("9999"), STATUS_CODE("200"), MESSAGE("message"), From f6d69417e0e6ac3270ca8869ca70371487ba1286 Mon Sep 17 00:00:00 2001 From: Jung-YouHwan Date: Sat, 27 Apr 2024 20:04:55 +0900 Subject: [PATCH 21/52] =?UTF-8?q?[BE]=20feat=20:=20=EA=B0=9C=EC=9D=B8=20?= =?UTF-8?q?=EC=9D=BC=EC=A0=95=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/schedule/ScheduleService.java | 2 ++ .../schedule/ScheduleServiceImpl.java | 10 +++++++- .../dto/schedule/ScheduleDeleteRequest.java | 6 +++++ .../implement/schedule/ScheduleDeleter.java | 23 +++++++++++++++++++ .../schedule/ScheduleRepository.java | 2 ++ .../schedule/ScheduleRepositoryImpl.java | 5 ++++ .../schedule/ScheduleController.java | 7 ++++++ .../schedule/FakeScheduleService.java | 5 ++++ 8 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 backend/src/main/java/moim_today/dto/schedule/ScheduleDeleteRequest.java create mode 100644 backend/src/main/java/moim_today/implement/schedule/ScheduleDeleter.java diff --git a/backend/src/main/java/moim_today/application/schedule/ScheduleService.java b/backend/src/main/java/moim_today/application/schedule/ScheduleService.java index 7295afbd..219d10c8 100644 --- a/backend/src/main/java/moim_today/application/schedule/ScheduleService.java +++ b/backend/src/main/java/moim_today/application/schedule/ScheduleService.java @@ -12,4 +12,6 @@ public interface ScheduleService { void createSchedule(final long memberId, final ScheduleCreateRequest scheduleCreateRequest); void updateSchedule(final long memberId, final ScheduleUpdateRequest scheduleUpdateRequest); + + void deleteSchedule(final long memberId, final long scheduleId); } diff --git a/backend/src/main/java/moim_today/application/schedule/ScheduleServiceImpl.java b/backend/src/main/java/moim_today/application/schedule/ScheduleServiceImpl.java index 25800371..ca02c0f0 100644 --- a/backend/src/main/java/moim_today/application/schedule/ScheduleServiceImpl.java +++ b/backend/src/main/java/moim_today/application/schedule/ScheduleServiceImpl.java @@ -5,6 +5,7 @@ import moim_today.dto.schedule.ScheduleUpdateRequest; import moim_today.dto.schedule.TimeTableRequest; import moim_today.implement.schedule.ScheduleAppender; +import moim_today.implement.schedule.ScheduleDeleter; import moim_today.implement.schedule.ScheduleManager; import moim_today.implement.schedule.ScheduleUpdater; import moim_today.persistence.entity.schedule.ScheduleJpaEntity; @@ -18,12 +19,14 @@ public class ScheduleServiceImpl implements ScheduleService { private final ScheduleManager scheduleManager; private final ScheduleAppender scheduleAppender; private final ScheduleUpdater scheduleUpdater; + private final ScheduleDeleter scheduleDeleter; public ScheduleServiceImpl(final ScheduleManager scheduleManager, final ScheduleAppender scheduleAppender, - final ScheduleUpdater scheduleUpdater) { + final ScheduleUpdater scheduleUpdater, final ScheduleDeleter scheduleDeleter) { this.scheduleManager = scheduleManager; this.scheduleAppender = scheduleAppender; this.scheduleUpdater = scheduleUpdater; + this.scheduleDeleter = scheduleDeleter; } @Override @@ -43,4 +46,9 @@ public void createSchedule(final long memberId, final ScheduleCreateRequest sche public void updateSchedule(final long memberId, final ScheduleUpdateRequest scheduleUpdateRequest) { scheduleUpdater.updateSchedule(memberId, scheduleUpdateRequest); } + + @Override + public void deleteSchedule(final long memberId, final long scheduleId) { + scheduleDeleter.deleteSchedule(memberId, scheduleId); + } } \ No newline at end of file diff --git a/backend/src/main/java/moim_today/dto/schedule/ScheduleDeleteRequest.java b/backend/src/main/java/moim_today/dto/schedule/ScheduleDeleteRequest.java new file mode 100644 index 00000000..7a313b5b --- /dev/null +++ b/backend/src/main/java/moim_today/dto/schedule/ScheduleDeleteRequest.java @@ -0,0 +1,6 @@ +package moim_today.dto.schedule; + +public record ScheduleDeleteRequest( + long scheduleId +) { +} diff --git a/backend/src/main/java/moim_today/implement/schedule/ScheduleDeleter.java b/backend/src/main/java/moim_today/implement/schedule/ScheduleDeleter.java new file mode 100644 index 00000000..5a1f177c --- /dev/null +++ b/backend/src/main/java/moim_today/implement/schedule/ScheduleDeleter.java @@ -0,0 +1,23 @@ +package moim_today.implement.schedule; + +import moim_today.global.annotation.Implement; +import moim_today.persistence.entity.schedule.ScheduleJpaEntity; +import moim_today.persistence.repository.schedule.ScheduleRepository; +import org.springframework.transaction.annotation.Transactional; + +@Implement +public class ScheduleDeleter { + + private final ScheduleRepository scheduleRepository; + + public ScheduleDeleter(final ScheduleRepository scheduleRepository) { + this.scheduleRepository = scheduleRepository; + } + + @Transactional + public void deleteSchedule(final long memberId, final long scheduleId) { + ScheduleJpaEntity scheduleJpaEntity = scheduleRepository.getById(scheduleId); + scheduleJpaEntity.validateMember(memberId); + scheduleRepository.delete(scheduleJpaEntity); + } +} diff --git a/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepository.java b/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepository.java index eb3c69d0..034e08d6 100644 --- a/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepository.java +++ b/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepository.java @@ -17,5 +17,7 @@ public interface ScheduleRepository { boolean existsExcludeEntity(final long scheduleId, final ScheduleUpdateRequest scheduleUpdateRequest); + void delete(final ScheduleJpaEntity scheduleJpaEntity); + long count(); } diff --git a/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepositoryImpl.java b/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepositoryImpl.java index 26804b96..0fe7f470 100644 --- a/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepositoryImpl.java +++ b/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepositoryImpl.java @@ -101,6 +101,11 @@ public boolean existsExcludeEntity(final long scheduleId, final ScheduleUpdateRe .fetchFirst() != null; } + @Override + public void delete(final ScheduleJpaEntity scheduleJpaEntity) { + scheduleJpaRepository.delete(scheduleJpaEntity); + } + @Override public long count() { return scheduleJpaRepository.count(); diff --git a/backend/src/main/java/moim_today/presentation/schedule/ScheduleController.java b/backend/src/main/java/moim_today/presentation/schedule/ScheduleController.java index 334af2cc..072de068 100644 --- a/backend/src/main/java/moim_today/presentation/schedule/ScheduleController.java +++ b/backend/src/main/java/moim_today/presentation/schedule/ScheduleController.java @@ -3,6 +3,7 @@ import moim_today.application.schedule.ScheduleService; import moim_today.domain.member.MemberSession; import moim_today.dto.schedule.ScheduleCreateRequest; +import moim_today.dto.schedule.ScheduleDeleteRequest; import moim_today.dto.schedule.ScheduleUpdateRequest; import moim_today.dto.schedule.TimeTableRequest; import moim_today.global.annotation.Login; @@ -36,4 +37,10 @@ public void updateSchedule(@Login final MemberSession memberSession, @RequestBody final ScheduleUpdateRequest scheduleUpdateRequest) { scheduleService.updateSchedule(memberSession.id(), scheduleUpdateRequest); } + + @DeleteMapping + public void deleteSchedule(@Login final MemberSession memberSession, + @RequestBody final ScheduleDeleteRequest scheduleDeleteRequest) { + scheduleService.deleteSchedule(memberSession.id(), scheduleDeleteRequest.scheduleId()); + } } \ No newline at end of file diff --git a/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java b/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java index 92c71545..78db6609 100644 --- a/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java +++ b/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java @@ -39,4 +39,9 @@ public void updateSchedule(final long memberId, final ScheduleUpdateRequest sche throw new BadRequestException(SCHEDULE_ALREADY_EXIST.message()); } } + + @Override + public void deleteSchedule(final long memberId, final long scheduleId) { + + } } From b9a770315886c4bb8f71fe136b92b8355313c18c Mon Sep 17 00:00:00 2001 From: Jung-YouHwan Date: Sat, 27 Apr 2024 20:16:38 +0900 Subject: [PATCH 22/52] =?UTF-8?q?[BE]=20test=20:=20=EA=B0=9C=EC=9D=B8=20?= =?UTF-8?q?=EC=9D=BC=EC=A0=95=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../schedule/FakeScheduleService.java | 7 ++ .../schedule/ScheduleDeleterTest.java | 66 ++++++++++++++ .../schedule/ScheduleControllerTest.java | 87 +++++++++++++++++-- .../java/moim_today/util/TestConstant.java | 1 + 4 files changed, 153 insertions(+), 8 deletions(-) create mode 100644 backend/src/test/java/moim_today/implement/schedule/ScheduleDeleterTest.java diff --git a/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java b/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java index 78db6609..d9e56172 100644 --- a/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java +++ b/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java @@ -6,6 +6,7 @@ import moim_today.dto.schedule.TimeTableRequest; import moim_today.global.error.BadRequestException; import moim_today.global.error.ForbiddenException; +import moim_today.global.error.NotFoundException; import java.time.LocalDateTime; @@ -42,6 +43,12 @@ public void updateSchedule(final long memberId, final ScheduleUpdateRequest sche @Override public void deleteSchedule(final long memberId, final long scheduleId) { + if (scheduleId == Long.parseLong(NOTFOUND_SCHEDULE_ID.value())) { + throw new NotFoundException(SCHEDULE_NOT_FOUND.message()); + } + if (scheduleId == Long.parseLong(FORBIDDEN_SCHEDULE_ID.value())) { + throw new ForbiddenException(SCHEDULE_FORBIDDEN.message()); + } } } diff --git a/backend/src/test/java/moim_today/implement/schedule/ScheduleDeleterTest.java b/backend/src/test/java/moim_today/implement/schedule/ScheduleDeleterTest.java new file mode 100644 index 00000000..747c72fc --- /dev/null +++ b/backend/src/test/java/moim_today/implement/schedule/ScheduleDeleterTest.java @@ -0,0 +1,66 @@ +package moim_today.implement.schedule; + +import moim_today.global.error.ForbiddenException; +import moim_today.global.error.NotFoundException; +import moim_today.persistence.entity.schedule.ScheduleJpaEntity; +import moim_today.util.ImplementTest; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import static moim_today.global.constant.exception.ScheduleExceptionConstant.SCHEDULE_FORBIDDEN; +import static moim_today.global.constant.exception.ScheduleExceptionConstant.SCHEDULE_NOT_FOUND; +import static org.assertj.core.api.Assertions.*; + +class ScheduleDeleterTest extends ImplementTest { + + @Autowired + private ScheduleDeleter scheduleDeleter; + + @DisplayName("개인 일정을 삭제한다.") + @Test + void deleteSchedule() { + // given + long memberId = 1L; + + ScheduleJpaEntity scheduleJpaEntity = ScheduleJpaEntity.builder() + .memberId(memberId) + .build(); + + scheduleRepository.save(scheduleJpaEntity); + + // when + scheduleDeleter.deleteSchedule(memberId, scheduleJpaEntity.getId()); + + // then + assertThat(scheduleRepository.count()).isEqualTo(0); + } + + @DisplayName("해당 회원의 스케줄이 아니면 삭제할 수 없다.") + @Test + void deleteScheduleForbidden() { + // given + long memberId = 1L; + long anotherMemberId = 9999L; + + ScheduleJpaEntity scheduleJpaEntity = ScheduleJpaEntity.builder() + .memberId(memberId) + .build(); + + scheduleRepository.save(scheduleJpaEntity); + + // expected + assertThatCode(() -> scheduleDeleter.deleteSchedule(anotherMemberId, scheduleJpaEntity.getId())) + .isInstanceOf(ForbiddenException.class) + .hasMessage(SCHEDULE_FORBIDDEN.message()); + } + + @DisplayName("스케줄이 존재하지 않으면 삭제할 수 없다.") + @Test + void deleteScheduleNotFound() { + // expected + assertThatCode(() -> scheduleDeleter.deleteSchedule(1L, 9999L)) + .isInstanceOf(NotFoundException.class) + .hasMessage(SCHEDULE_NOT_FOUND.message()); + } +} \ No newline at end of file diff --git a/backend/src/test/java/moim_today/presentation/schedule/ScheduleControllerTest.java b/backend/src/test/java/moim_today/presentation/schedule/ScheduleControllerTest.java index eb2a4aef..36ba1169 100644 --- a/backend/src/test/java/moim_today/presentation/schedule/ScheduleControllerTest.java +++ b/backend/src/test/java/moim_today/presentation/schedule/ScheduleControllerTest.java @@ -3,11 +3,11 @@ import com.epages.restdocs.apispec.ResourceSnippetParameters; import moim_today.application.schedule.ScheduleService; import moim_today.dto.schedule.ScheduleCreateRequest; +import moim_today.dto.schedule.ScheduleDeleteRequest; import moim_today.dto.schedule.ScheduleUpdateRequest; import moim_today.dto.schedule.TimeTableRequest; import moim_today.fake_class.schedule.FakeScheduleService; import moim_today.util.ControllerTest; -import moim_today.util.TestConstant; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -21,8 +21,7 @@ import static moim_today.util.TestConstant.EVERY_TIME_ID; import static moim_today.util.TestConstant.WRONG_EVERY_TIME_ID; import static org.springframework.http.MediaType.APPLICATION_JSON; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.patch; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; import static org.springframework.restdocs.payload.JsonFieldType.NUMBER; import static org.springframework.restdocs.payload.JsonFieldType.STRING; import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; @@ -112,7 +111,6 @@ void createSchedule() throws Exception { .build(); String json = objectMapper.writeValueAsString(scheduleCreateRequest); - System.out.println(json); mockMvc.perform(post("/api/schedules") .contentType(APPLICATION_JSON) @@ -144,7 +142,6 @@ void createScheduleFail() throws Exception { .build(); String json = objectMapper.writeValueAsString(scheduleCreateRequest); - System.out.println(json); mockMvc.perform(post("/api/schedules") .contentType(APPLICATION_JSON) @@ -181,7 +178,6 @@ void updateSchedule() throws Exception { .build(); String json = objectMapper.writeValueAsString(scheduleUpdateRequest); - System.out.println(json); mockMvc.perform(patch("/api/schedules") .contentType(APPLICATION_JSON) @@ -215,7 +211,6 @@ void updateScheduleBadRequest() throws Exception { .build(); String json = objectMapper.writeValueAsString(scheduleUpdateRequest); - System.out.println(json); mockMvc.perform(patch("/api/schedules") .contentType(APPLICATION_JSON) @@ -253,7 +248,6 @@ void updateScheduleForbidden() throws Exception { .build(); String json = objectMapper.writeValueAsString(scheduleUpdateRequest); - System.out.println(json); mockMvc.perform(patch("/api/schedules") .contentType(APPLICATION_JSON) @@ -278,4 +272,81 @@ void updateScheduleForbidden() throws Exception { .build() ))); } + + @DisplayName("개인 일정을 삭제한다.") + @Test + void deleteSchedule() throws Exception { + ScheduleDeleteRequest scheduleDeleteRequest = new ScheduleDeleteRequest(1L); + + String json = objectMapper.writeValueAsString(scheduleDeleteRequest); + + mockMvc.perform(delete("/api/schedules") + .contentType(APPLICATION_JSON) + .content(json) + ) + .andExpect(status().isOk()) + .andDo(document("개인 일정 삭제 성공", + resource(ResourceSnippetParameters.builder() + .tag("스케줄") + .summary("개인 일정 삭제") + .requestFields( + fieldWithPath("scheduleId").type(NUMBER).description("스케줄 id") + ) + .build() + ))); + } + + @DisplayName("회원의 스케줄이 아니면 삭제에 실패한다.") + @Test + void deleteScheduleForbidden() throws Exception { + ScheduleDeleteRequest scheduleDeleteRequest = new ScheduleDeleteRequest(Long.parseLong(FORBIDDEN_SCHEDULE_ID.value())); + + String json = objectMapper.writeValueAsString(scheduleDeleteRequest); + + mockMvc.perform(delete("/api/schedules") + .contentType(APPLICATION_JSON) + .content(json) + ) + .andExpect(status().isForbidden()) + .andDo(document("개인 일정 삭제 실패 - 회원의 스케줄이 아님", + resource(ResourceSnippetParameters.builder() + .tag("스케줄") + .summary("개인 일정 삭제") + .requestFields( + fieldWithPath("scheduleId").type(NUMBER).description("스케줄 id") + ) + .responseFields( + fieldWithPath("statusCode").type(STRING).description("상태 코드"), + fieldWithPath("message").type(STRING).description("오류 메세지") + ) + .build() + ))); + } + + @DisplayName("스케줄 정보를 찾을 수 없으면 삭제에 실패한다.") + @Test + void deleteScheduleNotFound() throws Exception { + ScheduleDeleteRequest scheduleDeleteRequest = new ScheduleDeleteRequest(Long.parseLong(NOTFOUND_SCHEDULE_ID.value())); + + String json = objectMapper.writeValueAsString(scheduleDeleteRequest); + + mockMvc.perform(delete("/api/schedules") + .contentType(APPLICATION_JSON) + .content(json) + ) + .andExpect(status().isNotFound()) + .andDo(document("개인 일정 삭제 실패 - 일정을 찾을 수 없음", + resource(ResourceSnippetParameters.builder() + .tag("스케줄") + .summary("개인 일정 삭제") + .requestFields( + fieldWithPath("scheduleId").type(NUMBER).description("스케줄 id") + ) + .responseFields( + fieldWithPath("statusCode").type(STRING).description("상태 코드"), + fieldWithPath("message").type(STRING).description("오류 메세지") + ) + .build() + ))); + } } \ No newline at end of file diff --git a/backend/src/test/java/moim_today/util/TestConstant.java b/backend/src/test/java/moim_today/util/TestConstant.java index 16b9d1ac..d2db320e 100644 --- a/backend/src/test/java/moim_today/util/TestConstant.java +++ b/backend/src/test/java/moim_today/util/TestConstant.java @@ -55,6 +55,7 @@ public enum TestConstant { SCHEDULE_NAME("scheduleName"), NEW_SCHEDULE_NAME("new scheduleName"), FORBIDDEN_SCHEDULE_ID("9999"), + NOTFOUND_SCHEDULE_ID("0"), STATUS_CODE("200"), MESSAGE("message"), From ee960cdc4d7b2b31c387748b92c3e24b384616b9 Mon Sep 17 00:00:00 2001 From: Jung-YouHwan Date: Sun, 28 Apr 2024 15:48:48 +0900 Subject: [PATCH 23/52] =?UTF-8?q?fix=20:=20=EA=B0=9C=EC=9D=B8=20=EC=9D=BC?= =?UTF-8?q?=EC=A0=95=20=EC=BF=BC=EB=A6=AC=20=EC=98=A4=EB=A5=98=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../implement/schedule/ScheduleUpdater.java | 6 +- .../schedule/ScheduleRepository.java | 2 +- .../schedule/ScheduleRepositoryImpl.java | 21 +++--- .../schedule/ScheduleAppenderTest.java | 44 +++++++++++++ .../schedule/ScheduleUpdaterTest.java | 66 +++++++++++++++++-- 5 files changed, 121 insertions(+), 18 deletions(-) diff --git a/backend/src/main/java/moim_today/implement/schedule/ScheduleUpdater.java b/backend/src/main/java/moim_today/implement/schedule/ScheduleUpdater.java index d5e3e888..10acf4e1 100644 --- a/backend/src/main/java/moim_today/implement/schedule/ScheduleUpdater.java +++ b/backend/src/main/java/moim_today/implement/schedule/ScheduleUpdater.java @@ -23,13 +23,13 @@ public ScheduleUpdater(final ScheduleRepository scheduleRepository) { public void updateSchedule(final long memberId, final ScheduleUpdateRequest scheduleUpdateRequest) { ScheduleJpaEntity scheduleJpaEntity = scheduleRepository.getById(scheduleUpdateRequest.scheduleId()); scheduleJpaEntity.validateMember(memberId); - validateAlreadyExist(scheduleJpaEntity.getId(), scheduleUpdateRequest); + validateAlreadyExist(scheduleJpaEntity.getId(), memberId, scheduleUpdateRequest); scheduleJpaEntity.updateSchedule(scheduleUpdateRequest); } - private void validateAlreadyExist(final long scheduleId, final ScheduleUpdateRequest scheduleUpdateRequest) { - if (scheduleRepository.existsExcludeEntity(scheduleId, scheduleUpdateRequest)) { + private void validateAlreadyExist(final long scheduleId, final long memberId, final ScheduleUpdateRequest scheduleUpdateRequest) { + if (scheduleRepository.existsExcludeEntity(scheduleId, memberId, scheduleUpdateRequest)) { throw new BadRequestException(SCHEDULE_ALREADY_EXIST.message()); } } diff --git a/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepository.java b/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepository.java index 034e08d6..dc95862a 100644 --- a/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepository.java +++ b/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepository.java @@ -15,7 +15,7 @@ public interface ScheduleRepository { boolean exists(final ScheduleJpaEntity scheduleJpaEntity); - boolean existsExcludeEntity(final long scheduleId, final ScheduleUpdateRequest scheduleUpdateRequest); + boolean existsExcludeEntity(final long scheduleId, final long memberId, final ScheduleUpdateRequest scheduleUpdateRequest); void delete(final ScheduleJpaEntity scheduleJpaEntity); diff --git a/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepositoryImpl.java b/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepositoryImpl.java index 0fe7f470..1a08cf3b 100644 --- a/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepositoryImpl.java +++ b/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepositoryImpl.java @@ -19,6 +19,7 @@ import static moim_today.global.constant.NumberConstant.SCHEDULE_MEETING_ID; import static moim_today.global.constant.exception.ScheduleExceptionConstant.*; +import static moim_today.persistence.entity.schedule.QScheduleJpaEntity.*; @Repository @@ -80,23 +81,25 @@ public int getBatchSize() { } @Override - public boolean exists(final ScheduleJpaEntity scheduleJpaEntity) { - return queryFactory.selectFrom(QScheduleJpaEntity.scheduleJpaEntity) + public boolean exists(final ScheduleJpaEntity entity) { + return queryFactory.selectFrom(scheduleJpaEntity) .where( - QScheduleJpaEntity.scheduleJpaEntity.startDateTime.before(scheduleJpaEntity.getEndDateTime()) - .and(QScheduleJpaEntity.scheduleJpaEntity.endDateTime.after(scheduleJpaEntity.getStartDateTime())) + scheduleJpaEntity.memberId.eq(entity.getMemberId()) + .and(scheduleJpaEntity.startDateTime.before(entity.getEndDateTime())) + .and(scheduleJpaEntity.endDateTime.after(entity.getStartDateTime())) ) .fetchFirst() != null; } @Override - public boolean existsExcludeEntity(final long scheduleId, final ScheduleUpdateRequest scheduleUpdateRequest) { + public boolean existsExcludeEntity(final long scheduleId, final long memberId, final ScheduleUpdateRequest scheduleUpdateRequest) { return queryFactory - .selectFrom(QScheduleJpaEntity.scheduleJpaEntity) + .selectFrom(scheduleJpaEntity) .where( - QScheduleJpaEntity.scheduleJpaEntity.id.ne(scheduleId) - .and(QScheduleJpaEntity.scheduleJpaEntity.startDateTime.before(scheduleUpdateRequest.endDateTime()) - .and(QScheduleJpaEntity.scheduleJpaEntity.endDateTime.after(scheduleUpdateRequest.startDateTime()))) + scheduleJpaEntity.memberId.eq(memberId) + .and(scheduleJpaEntity.id.ne(scheduleId)) + .and(scheduleJpaEntity.startDateTime.before(scheduleUpdateRequest.endDateTime()) + .and(scheduleJpaEntity.endDateTime.after(scheduleUpdateRequest.startDateTime()))) ) .fetchFirst() != null; } diff --git a/backend/src/test/java/moim_today/implement/schedule/ScheduleAppenderTest.java b/backend/src/test/java/moim_today/implement/schedule/ScheduleAppenderTest.java index 5851ad85..2a7c1dd5 100644 --- a/backend/src/test/java/moim_today/implement/schedule/ScheduleAppenderTest.java +++ b/backend/src/test/java/moim_today/implement/schedule/ScheduleAppenderTest.java @@ -89,6 +89,50 @@ void createSchedule() { assertThat(findEntity.getEndDateTime()).isEqualTo(LocalDateTime.of(2024, 1, 1, 12, 0, 0)); } + @DisplayName("다른 사용자의 스케줄은 영향을 주지 않는다.") + @Test + void notEffectOtherMemberSchedule() { + // given 1 + long memberId = 1L; + long anotherMemberId = 9999L; + long meetingId = 2L; + + ScheduleJpaEntity otherScheduleJpaEntity = ScheduleJpaEntity.builder() + .memberId(anotherMemberId) + .meetingId(meetingId) + .scheduleName(SCHEDULE_NAME.value()) + .dayOfWeek(DayOfWeek.MONDAY) + .startDateTime(LocalDateTime.of(2024, 1, 1, 10, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) + .build(); + + scheduleRepository.save(otherScheduleJpaEntity); + + // given 2 + ScheduleJpaEntity scheduleJpaEntity = ScheduleJpaEntity.builder() + .memberId(memberId) + .meetingId(meetingId) + .scheduleName(SCHEDULE_NAME.value()) + .dayOfWeek(DayOfWeek.MONDAY) + .startDateTime(LocalDateTime.of(2024, 1, 1, 10, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) + .build(); + + // when + scheduleAppender.createSchedule(scheduleJpaEntity); + + // then + ScheduleJpaEntity findEntity = scheduleRepository.getById(scheduleJpaEntity.getId()); + + assertThat(scheduleRepository.count()).isEqualTo(2); + assertThat(findEntity.getMemberId()).isEqualTo(memberId); + assertThat(findEntity.getMeetingId()).isEqualTo(meetingId); + assertThat(findEntity.getScheduleName()).isEqualTo(SCHEDULE_NAME.value()); + assertThat(findEntity.getDayOfWeek()).isEqualTo(DayOfWeek.MONDAY); + assertThat(findEntity.getStartDateTime()).isEqualTo(LocalDateTime.of(2024, 1, 1, 10, 0, 0)); + assertThat(findEntity.getEndDateTime()).isEqualTo(LocalDateTime.of(2024, 1, 1, 12, 0, 0)); + } + @DisplayName("다른 스케줄 사이에 있는 일정을 등록한다.") @Test void createScheduleBetweenOtherSchedules() { diff --git a/backend/src/test/java/moim_today/implement/schedule/ScheduleUpdaterTest.java b/backend/src/test/java/moim_today/implement/schedule/ScheduleUpdaterTest.java index b370264c..442cb2de 100644 --- a/backend/src/test/java/moim_today/implement/schedule/ScheduleUpdaterTest.java +++ b/backend/src/test/java/moim_today/implement/schedule/ScheduleUpdaterTest.java @@ -5,8 +5,6 @@ import moim_today.global.error.ForbiddenException; import moim_today.persistence.entity.schedule.ScheduleJpaEntity; import moim_today.util.ImplementTest; -import moim_today.util.TestConstant; -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -70,7 +68,10 @@ void updateSchedule() { @Test void updateScheduleFailAlreadyExistBeforeSchedule() { // given 1 + long memberId = 1L; + ScheduleJpaEntity BeforeScheduleJpaEntity = ScheduleJpaEntity.builder() + .memberId(memberId) .startDateTime(LocalDateTime.of(2024, 1, 1, 10, 0, 0)) .endDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) .build(); @@ -78,7 +79,6 @@ void updateScheduleFailAlreadyExistBeforeSchedule() { scheduleRepository.save(BeforeScheduleJpaEntity); // given 2 - long memberId = 1L; ScheduleJpaEntity scheduleJpaEntity = ScheduleJpaEntity.builder() .memberId(memberId) .startDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) @@ -104,11 +104,13 @@ void updateScheduleFailAlreadyExistBeforeSchedule() { assertThat(scheduleRepository.count()).isEqualTo(2); } - @DisplayName("해당 시간대 앞에 스케줄이 존재하면 예외가 발생한다.") + @DisplayName("해당 시간대 뒤에 스케줄이 존재하면 예외가 발생한다.") @Test void updateScheduleFailAlreadyExistAfterSchedule() { // given 1 + long memberId = 1L; ScheduleJpaEntity afterScheduleJpaEntity = ScheduleJpaEntity.builder() + .memberId(memberId) .startDateTime(LocalDateTime.of(2024, 1, 1, 14, 0, 0)) .endDateTime(LocalDateTime.of(2024, 1, 1, 16, 0, 0)) .build(); @@ -116,7 +118,6 @@ void updateScheduleFailAlreadyExistAfterSchedule() { scheduleRepository.save(afterScheduleJpaEntity); // given 2 - long memberId = 1L; ScheduleJpaEntity scheduleJpaEntity = ScheduleJpaEntity.builder() .memberId(memberId) .startDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) @@ -173,4 +174,59 @@ void validateMember() { assertThat(scheduleRepository.count()).isEqualTo(1); } + + @DisplayName("다른 사용자의 스케줄은 영향을 주지 않는다.") + @Test + void notEffectOtherMemberSchedule() { + // given 1 + long memberId = 1L; + long anotherMemberId = 9999L; + long meetingId = 2L; + + ScheduleJpaEntity otherScheduleJpaEntity = ScheduleJpaEntity.builder() + .memberId(anotherMemberId) + .meetingId(meetingId) + .scheduleName(SCHEDULE_NAME.value()) + .dayOfWeek(DayOfWeek.MONDAY) + .startDateTime(LocalDateTime.of(2024, 1, 1, 10, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) + .build(); + + scheduleRepository.save(otherScheduleJpaEntity); + + // given 2 + ScheduleJpaEntity scheduleJpaEntity = ScheduleJpaEntity.builder() + .memberId(memberId) + .meetingId(meetingId) + .scheduleName(SCHEDULE_NAME.value()) + .dayOfWeek(DayOfWeek.MONDAY) + .startDateTime(LocalDateTime.of(2024, 1, 1, 10, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) + .build(); + + scheduleRepository.save(scheduleJpaEntity); + + // given 2 + ScheduleUpdateRequest scheduleUpdateRequest = ScheduleUpdateRequest.builder() + .scheduleId(scheduleJpaEntity.getId()) + .scheduleName(NEW_SCHEDULE_NAME.value()) + .dayOfWeek(DayOfWeek.SATURDAY) + .startDateTime(LocalDateTime.of(2024, 1, 1, 11, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 13, 0, 0)) + .build(); + + // when + scheduleUpdater.updateSchedule(memberId, scheduleUpdateRequest); + + // then + ScheduleJpaEntity findEntity = scheduleRepository.getById(scheduleJpaEntity.getId()); + + assertThat(scheduleRepository.count()).isEqualTo(2); + assertThat(findEntity.getMemberId()).isEqualTo(memberId); + assertThat(findEntity.getMeetingId()).isEqualTo(meetingId); + assertThat(findEntity.getScheduleName()).isEqualTo(NEW_SCHEDULE_NAME.value()); + assertThat(findEntity.getDayOfWeek()).isEqualTo(DayOfWeek.SATURDAY); + assertThat(findEntity.getStartDateTime()).isEqualTo(LocalDateTime.of(2024, 1, 1, 11, 0, 0)); + assertThat(findEntity.getEndDateTime()).isEqualTo(LocalDateTime.of(2024, 1, 1, 13, 0, 0)); + } } \ No newline at end of file From 51580eebeea5bed608d1f560e7e9ca99c9560931 Mon Sep 17 00:00:00 2001 From: Yang JiWoong Date: Sun, 28 Apr 2024 04:10:06 +0900 Subject: [PATCH 24/52] =?UTF-8?q?[BE]=20feat=20:=20=EB=AA=A8=EC=9E=84=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=20=EC=A1=B0=ED=9A=8C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/moim/MoimService.java | 3 ++ .../application/moim/MoimServiceImpl.java | 14 ++++++- .../dto/moim/MoimDetailResponse.java | 39 +++++++++++++++++++ .../moim_today/global/config/WebConfig.java | 6 ++- .../exception/MoimExceptionConstant.java | 16 ++++++++ .../moim_today/implement/moim/MoimFinder.java | 21 ++++++++++ .../repository/moim/moim/MoimRepository.java | 4 +- .../moim/moim/MoimRepositoryImpl.java | 9 +++++ .../presentation/moim/MoimController.java | 7 +++- .../fake_class/moim/FakeMoimService.java | 6 +++ 10 files changed, 121 insertions(+), 4 deletions(-) create mode 100644 backend/src/main/java/moim_today/dto/moim/MoimDetailResponse.java create mode 100644 backend/src/main/java/moim_today/global/constant/exception/MoimExceptionConstant.java create mode 100644 backend/src/main/java/moim_today/implement/moim/MoimFinder.java diff --git a/backend/src/main/java/moim_today/application/moim/MoimService.java b/backend/src/main/java/moim_today/application/moim/MoimService.java index a593ee5f..c6005699 100644 --- a/backend/src/main/java/moim_today/application/moim/MoimService.java +++ b/backend/src/main/java/moim_today/application/moim/MoimService.java @@ -1,5 +1,6 @@ package moim_today.application.moim; +import moim_today.dto.moim.MoimDetailResponse; import moim_today.dto.moim.PrivateMoimAppendRequest; import moim_today.dto.moim.PublicMoimAppendRequest; import moim_today.dto.moim.UploadMoimImageResponse; @@ -14,4 +15,6 @@ void createPrivateMoim(final long memberId, final long universityId, final PrivateMoimAppendRequest privateMoimAppendRequest); UploadMoimImageResponse uploadMoimImage(final MultipartFile file); + + MoimDetailResponse getMoimDetail(long moimId); } diff --git a/backend/src/main/java/moim_today/application/moim/MoimServiceImpl.java b/backend/src/main/java/moim_today/application/moim/MoimServiceImpl.java index 8ca68e0c..336f7981 100644 --- a/backend/src/main/java/moim_today/application/moim/MoimServiceImpl.java +++ b/backend/src/main/java/moim_today/application/moim/MoimServiceImpl.java @@ -1,10 +1,13 @@ package moim_today.application.moim; +import moim_today.dto.moim.MoimDetailResponse; import moim_today.dto.moim.PrivateMoimAppendRequest; import moim_today.dto.moim.PublicMoimAppendRequest; import moim_today.dto.moim.UploadMoimImageResponse; import moim_today.implement.file.FileUploader; import moim_today.implement.moim.MoimAppender; +import moim_today.implement.moim.MoimFinder; +import moim_today.persistence.entity.moim.moim.MoimJpaEntity; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; @@ -15,11 +18,14 @@ public class MoimServiceImpl implements MoimService{ private final MoimAppender moimAppender; private final FileUploader fileUploader; + private final MoimFinder moimFinder; public MoimServiceImpl(final MoimAppender moimAppender, - final FileUploader fileUploader) { + final FileUploader fileUploader, + final MoimFinder moimFinder) { this.moimAppender = moimAppender; this.fileUploader = fileUploader; + this.moimFinder = moimFinder; } @Override @@ -39,4 +45,10 @@ public UploadMoimImageResponse uploadMoimImage(final MultipartFile file) { String imageUrl = fileUploader.uploadFile(MOIM_IMAGE.value(), file); return UploadMoimImageResponse.from(imageUrl); } + + @Override + public MoimDetailResponse getMoimDetail(final long moimId) { + MoimJpaEntity moimJpaEntity = moimFinder.getById(moimId); + return MoimDetailResponse.from(moimJpaEntity); + } } diff --git a/backend/src/main/java/moim_today/dto/moim/MoimDetailResponse.java b/backend/src/main/java/moim_today/dto/moim/MoimDetailResponse.java new file mode 100644 index 00000000..9930ae86 --- /dev/null +++ b/backend/src/main/java/moim_today/dto/moim/MoimDetailResponse.java @@ -0,0 +1,39 @@ +package moim_today.dto.moim; + +import lombok.Builder; +import moim_today.domain.moim.DisplayStatus; +import moim_today.domain.moim.enums.MoimCategory; +import moim_today.persistence.entity.moim.moim.MoimJpaEntity; + +import java.time.LocalDate; + +@Builder +public record MoimDetailResponse( + String title, + String contents, + int capacity, + int currentCount, + String imageUrl, + MoimCategory moimCategory, + DisplayStatus displayStatus, + int views, + LocalDate startDate, + LocalDate endDate + +) { + + public static MoimDetailResponse from(final MoimJpaEntity moimJpaEntity) { + return MoimDetailResponse.builder() + .title(moimJpaEntity.getTitle()) + .contents(moimJpaEntity.getContents()) + .capacity(moimJpaEntity.getCapacity()) + .currentCount(moimJpaEntity.getCurrentCount()) + .imageUrl(moimJpaEntity.getImageUrl()) + .moimCategory(moimJpaEntity.getMoimCategory()) + .displayStatus(moimJpaEntity.getDisplayStatus()) + .views(moimJpaEntity.getViews()) + .startDate(moimJpaEntity.getStartDate()) + .endDate(moimJpaEntity.getEndDate()) + .build(); + } +} diff --git a/backend/src/main/java/moim_today/global/config/WebConfig.java b/backend/src/main/java/moim_today/global/config/WebConfig.java index d3b7d50a..599718f1 100644 --- a/backend/src/main/java/moim_today/global/config/WebConfig.java +++ b/backend/src/main/java/moim_today/global/config/WebConfig.java @@ -24,7 +24,11 @@ public void addInterceptors(final InterceptorRegistry registry) { registry.addInterceptor(new MemberLoginInterceptor()) .order(1) .addPathPatterns("/api/**") - .excludePathPatterns("/api/login", "/api/certification/**"); + .excludePathPatterns( + "/api/login", + "/api/certification/**", + "/api/moims/detail/**" + ); } @Override diff --git a/backend/src/main/java/moim_today/global/constant/exception/MoimExceptionConstant.java b/backend/src/main/java/moim_today/global/constant/exception/MoimExceptionConstant.java new file mode 100644 index 00000000..831432cc --- /dev/null +++ b/backend/src/main/java/moim_today/global/constant/exception/MoimExceptionConstant.java @@ -0,0 +1,16 @@ +package moim_today.global.constant.exception; + +public enum MoimExceptionConstant { + + MOIM_NOT_FOUND_ERROR("존재하지 않거나 삭제된 모임입니다."); + + private final String message; + + MoimExceptionConstant(final String message) { + this.message = message; + } + + public String message() { + return message; + } +} diff --git a/backend/src/main/java/moim_today/implement/moim/MoimFinder.java b/backend/src/main/java/moim_today/implement/moim/MoimFinder.java new file mode 100644 index 00000000..29231055 --- /dev/null +++ b/backend/src/main/java/moim_today/implement/moim/MoimFinder.java @@ -0,0 +1,21 @@ +package moim_today.implement.moim; + +import moim_today.global.annotation.Implement; +import moim_today.persistence.entity.moim.moim.MoimJpaEntity; +import moim_today.persistence.repository.moim.moim.MoimRepository; +import org.springframework.transaction.annotation.Transactional; + +@Implement +public class MoimFinder { + + private final MoimRepository moimRepository; + + public MoimFinder(final MoimRepository moimRepository) { + this.moimRepository = moimRepository; + } + + @Transactional(readOnly = true) + public MoimJpaEntity getById(final long moimId) { + return moimRepository.getById(moimId); + } +} diff --git a/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepository.java b/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepository.java index 49fa52b7..20db69f0 100644 --- a/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepository.java +++ b/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepository.java @@ -4,7 +4,9 @@ public interface MoimRepository { - MoimJpaEntity save(MoimJpaEntity moimJpaEntity); + MoimJpaEntity save(final MoimJpaEntity moimJpaEntity); long count(); + + MoimJpaEntity getById(final long moimId); } diff --git a/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepositoryImpl.java b/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepositoryImpl.java index cdc4c950..29bc755a 100644 --- a/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepositoryImpl.java +++ b/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepositoryImpl.java @@ -1,8 +1,11 @@ package moim_today.persistence.repository.moim.moim; +import moim_today.global.error.NotFoundException; import moim_today.persistence.entity.moim.moim.MoimJpaEntity; import org.springframework.stereotype.Repository; +import static moim_today.global.constant.exception.MoimExceptionConstant.MOIM_NOT_FOUND_ERROR; + @Repository public class MoimRepositoryImpl implements MoimRepository { @@ -21,4 +24,10 @@ public MoimJpaEntity save(final MoimJpaEntity moimJpaEntity) { public long count() { return moimJpaRepository.count(); } + + @Override + public MoimJpaEntity getById(final long moimId) { + return moimJpaRepository.findById(moimId) + .orElseThrow(() -> new NotFoundException(MOIM_NOT_FOUND_ERROR.message())); + } } diff --git a/backend/src/main/java/moim_today/presentation/moim/MoimController.java b/backend/src/main/java/moim_today/presentation/moim/MoimController.java index 78534039..ec7faace 100644 --- a/backend/src/main/java/moim_today/presentation/moim/MoimController.java +++ b/backend/src/main/java/moim_today/presentation/moim/MoimController.java @@ -1,8 +1,8 @@ package moim_today.presentation.moim; import moim_today.application.moim.MoimService; -import moim_today.application.moim.MoimServiceImpl; import moim_today.domain.member.MemberSession; +import moim_today.dto.moim.MoimDetailResponse; import moim_today.dto.moim.PrivateMoimAppendRequest; import moim_today.dto.moim.PublicMoimAppendRequest; import moim_today.dto.moim.UploadMoimImageResponse; @@ -37,4 +37,9 @@ public UploadMoimImageResponse uploadMoimImage(@Login final MemberSession member @RequestPart final MultipartFile file) { return moimService.uploadMoimImage(file); } + + @GetMapping("/detail") + public MoimDetailResponse getMoimDetail(@RequestBody final long moimId) { + return moimService.getMoimDetail(moimId); + } } diff --git a/backend/src/test/java/moim_today/fake_class/moim/FakeMoimService.java b/backend/src/test/java/moim_today/fake_class/moim/FakeMoimService.java index 717f08a6..267c69f2 100644 --- a/backend/src/test/java/moim_today/fake_class/moim/FakeMoimService.java +++ b/backend/src/test/java/moim_today/fake_class/moim/FakeMoimService.java @@ -1,6 +1,7 @@ package moim_today.fake_class.moim; import moim_today.application.moim.MoimService; +import moim_today.dto.moim.MoimDetailResponse; import moim_today.dto.moim.PrivateMoimAppendRequest; import moim_today.dto.moim.PublicMoimAppendRequest; import moim_today.dto.moim.UploadMoimImageResponse; @@ -24,4 +25,9 @@ public void createPrivateMoim(final long memberId, final long universityId, fina public UploadMoimImageResponse uploadMoimImage(final MultipartFile file) { return UploadMoimImageResponse.from(MOIM_IMAGE_URL.value()); } + + @Override + public MoimDetailResponse getMoimDetail(final long moimId) { + return null; + } } From 2f9247ae6843160170a2beab5f456936c9d27caf Mon Sep 17 00:00:00 2001 From: Yang JiWoong Date: Sun, 28 Apr 2024 05:05:33 +0900 Subject: [PATCH 25/52] =?UTF-8?q?[BE]=20test=20:=20=EB=AA=A8=EC=9E=84=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=20=EC=A1=B0=ED=9A=8C=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/moim/MoimDetailRequest.java | 6 +++ .../dto/moim/MoimDetailResponse.java | 3 ++ .../presentation/moim/MoimController.java | 9 ++-- .../fake_class/moim/FakeMoimService.java | 19 +++++++- .../implement/moim/MoimFinderTest.java | 47 +++++++++++++++++++ .../presentation/moim/MoimControllerTest.java | 42 +++++++++++++++-- .../java/moim_today/util/TestConstant.java | 4 +- 7 files changed, 116 insertions(+), 14 deletions(-) create mode 100644 backend/src/main/java/moim_today/dto/moim/MoimDetailRequest.java create mode 100644 backend/src/test/java/moim_today/implement/moim/MoimFinderTest.java diff --git a/backend/src/main/java/moim_today/dto/moim/MoimDetailRequest.java b/backend/src/main/java/moim_today/dto/moim/MoimDetailRequest.java new file mode 100644 index 00000000..39917326 --- /dev/null +++ b/backend/src/main/java/moim_today/dto/moim/MoimDetailRequest.java @@ -0,0 +1,6 @@ +package moim_today.dto.moim; + +public record MoimDetailRequest( + long moimId +) { +} diff --git a/backend/src/main/java/moim_today/dto/moim/MoimDetailResponse.java b/backend/src/main/java/moim_today/dto/moim/MoimDetailResponse.java index 9930ae86..419b506a 100644 --- a/backend/src/main/java/moim_today/dto/moim/MoimDetailResponse.java +++ b/backend/src/main/java/moim_today/dto/moim/MoimDetailResponse.java @@ -1,5 +1,6 @@ package moim_today.dto.moim; +import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Builder; import moim_today.domain.moim.DisplayStatus; import moim_today.domain.moim.enums.MoimCategory; @@ -17,7 +18,9 @@ public record MoimDetailResponse( MoimCategory moimCategory, DisplayStatus displayStatus, int views, + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "Asia/Seoul") LocalDate startDate, + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "Asia/Seoul") LocalDate endDate ) { diff --git a/backend/src/main/java/moim_today/presentation/moim/MoimController.java b/backend/src/main/java/moim_today/presentation/moim/MoimController.java index ec7faace..63611a74 100644 --- a/backend/src/main/java/moim_today/presentation/moim/MoimController.java +++ b/backend/src/main/java/moim_today/presentation/moim/MoimController.java @@ -2,10 +2,7 @@ import moim_today.application.moim.MoimService; import moim_today.domain.member.MemberSession; -import moim_today.dto.moim.MoimDetailResponse; -import moim_today.dto.moim.PrivateMoimAppendRequest; -import moim_today.dto.moim.PublicMoimAppendRequest; -import moim_today.dto.moim.UploadMoimImageResponse; +import moim_today.dto.moim.*; import moim_today.global.annotation.Login; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -39,7 +36,7 @@ public UploadMoimImageResponse uploadMoimImage(@Login final MemberSession member } @GetMapping("/detail") - public MoimDetailResponse getMoimDetail(@RequestBody final long moimId) { - return moimService.getMoimDetail(moimId); + public MoimDetailResponse getMoimDetail(@RequestBody final MoimDetailRequest moimDetailRequest) { + return moimService.getMoimDetail(moimDetailRequest.moimId()); } } diff --git a/backend/src/test/java/moim_today/fake_class/moim/FakeMoimService.java b/backend/src/test/java/moim_today/fake_class/moim/FakeMoimService.java index 267c69f2..8fc8c931 100644 --- a/backend/src/test/java/moim_today/fake_class/moim/FakeMoimService.java +++ b/backend/src/test/java/moim_today/fake_class/moim/FakeMoimService.java @@ -1,13 +1,17 @@ package moim_today.fake_class.moim; import moim_today.application.moim.MoimService; +import moim_today.domain.moim.DisplayStatus; +import moim_today.domain.moim.enums.MoimCategory; import moim_today.dto.moim.MoimDetailResponse; import moim_today.dto.moim.PrivateMoimAppendRequest; import moim_today.dto.moim.PublicMoimAppendRequest; import moim_today.dto.moim.UploadMoimImageResponse; import org.springframework.web.multipart.MultipartFile; -import static moim_today.util.TestConstant.MOIM_IMAGE_URL; +import java.time.LocalDate; + +import static moim_today.util.TestConstant.*; public class FakeMoimService implements MoimService { @@ -28,6 +32,17 @@ public UploadMoimImageResponse uploadMoimImage(final MultipartFile file) { @Override public MoimDetailResponse getMoimDetail(final long moimId) { - return null; + return MoimDetailResponse.builder() + .title(TITLE.value()) + .contents(CONTENTS.value()) + .capacity(Integer.parseInt((CAPACITY.value()))) + .currentCount(Integer.parseInt(CURRENT_COUNT.value())) + .imageUrl(MOIM_IMAGE_URL.value()) + .moimCategory(MoimCategory.STUDY) + .displayStatus(DisplayStatus.PUBLIC) + .views(Integer.parseInt(VIEWS.value())) + .startDate(LocalDate.of(2024,3,1)) + .endDate(LocalDate.of(2024,6,30)) + .build(); } } diff --git a/backend/src/test/java/moim_today/implement/moim/MoimFinderTest.java b/backend/src/test/java/moim_today/implement/moim/MoimFinderTest.java new file mode 100644 index 00000000..5d06a131 --- /dev/null +++ b/backend/src/test/java/moim_today/implement/moim/MoimFinderTest.java @@ -0,0 +1,47 @@ +package moim_today.implement.moim; + +import moim_today.global.error.NotFoundException; +import moim_today.persistence.entity.moim.moim.MoimJpaEntity; +import moim_today.util.ImplementTest; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import static moim_today.global.constant.exception.MoimExceptionConstant.MOIM_NOT_FOUND_ERROR; +import static moim_today.util.TestConstant.MOIM_ID; +import static moim_today.util.TestConstant.TITLE; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class MoimFinderTest extends ImplementTest { + + @Autowired + private MoimFinder moimFinder; + + @DisplayName("getById로 모임을 조회하면 모임 엔티티를 반환한다.") + @Test + void getByIdTest(){ + //given + MoimJpaEntity moimJpaEntity = MoimJpaEntity.builder() + .title(TITLE.value()) + .build(); + + moimRepository.save(moimJpaEntity); + + //when + MoimJpaEntity findMoimJpaEntity = moimFinder.getById(moimJpaEntity.getId()); + + //then + assertThat(findMoimJpaEntity).isExactlyInstanceOf(MoimJpaEntity.class); + assertThat(findMoimJpaEntity.getTitle()).isEqualTo(TITLE.value()); + } + + @DisplayName("getById로 모임을 조회할 때, 해당하는 모임이 없으면 예외를 발생시킨다.") + @Test + void getByIdThrowExceptionTest(){ + //when & then + assertThatThrownBy(() -> moimFinder.getById(Long.parseLong(MOIM_ID.value()))) + .isInstanceOf(NotFoundException.class) + .hasMessage(MOIM_NOT_FOUND_ERROR.message()); + } +} diff --git a/backend/src/test/java/moim_today/presentation/moim/MoimControllerTest.java b/backend/src/test/java/moim_today/presentation/moim/MoimControllerTest.java index 61b76592..5f94d361 100644 --- a/backend/src/test/java/moim_today/presentation/moim/MoimControllerTest.java +++ b/backend/src/test/java/moim_today/presentation/moim/MoimControllerTest.java @@ -2,6 +2,7 @@ import com.epages.restdocs.apispec.ResourceSnippetParameters; import moim_today.domain.moim.enums.MoimCategory; +import moim_today.dto.moim.MoimDetailRequest; import moim_today.dto.moim.PrivateMoimAppendRequest; import moim_today.dto.moim.PublicMoimAppendRequest; import moim_today.fake_class.moim.FakeMoimService; @@ -16,12 +17,10 @@ import static com.epages.restdocs.apispec.ResourceDocumentation.resource; import static moim_today.util.TestConstant.*; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.multipart; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; import static org.springframework.restdocs.payload.JsonFieldType.*; import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; -import static org.springframework.restdocs.request.RequestDocumentation.partWithName; -import static org.springframework.restdocs.request.RequestDocumentation.requestParts; +import static org.springframework.restdocs.request.RequestDocumentation.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; class MoimControllerTest extends ControllerTest { @@ -70,7 +69,7 @@ void createPublicMoimApiTest() throws Exception { .build() ))); } - + @DisplayName("비공개 모임 생성 테스트") @Test void createPrivateMoimApiTest() throws Exception { @@ -139,4 +138,37 @@ void uploadMoimImageTest() throws Exception { .build() ))); } + + @DisplayName("모임 상제 정보 조회 테스트") + @Test + void getMoimDetailTest() throws Exception { + MoimDetailRequest moimDetailRequest = new MoimDetailRequest(1L); + + mockMvc.perform(get("/api/moims/detail") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsBytes(moimDetailRequest)) + ) + .andExpect(status().isOk()) + .andDo(document("모임 상세 정보 조회", + resource(ResourceSnippetParameters.builder() + .tag("모임") + .summary("모임 상세 정보 조회 API") + .requestFields( + fieldWithPath("moimId").type(NUMBER).description("모임 ID") + ) + .responseFields( + fieldWithPath("title").type(STRING).description("모임명"), + fieldWithPath("contents").type(STRING).description("내용"), + fieldWithPath("capacity").type(NUMBER).description("모집 인원"), + fieldWithPath("currentCount").type(NUMBER).description("현재 인원"), + fieldWithPath("imageUrl").type(STRING).description("모임 사진 URL"), + fieldWithPath("moimCategory").type(VARIES).description("카테고리"), + fieldWithPath("displayStatus").type(VARIES).description("공개여부"), + fieldWithPath("views").type(NUMBER).description("조회수"), + fieldWithPath("startDate").type(STRING).description("시작 일자"), + fieldWithPath("endDate").type(STRING).description("종료 일자") + ) + .build() + ))); + } } diff --git a/backend/src/test/java/moim_today/util/TestConstant.java b/backend/src/test/java/moim_today/util/TestConstant.java index d2db320e..741ad97e 100644 --- a/backend/src/test/java/moim_today/util/TestConstant.java +++ b/backend/src/test/java/moim_today/util/TestConstant.java @@ -46,11 +46,13 @@ public enum TestConstant { // 모임 + MOIM_ID("1"), TITLE("title"), CONTENTS("contents"), CAPACITY("5"), MOIM_IMAGE_URL("moimImageUrl"), - + CURRENT_COUNT("0"), + VIEWS("10"), SCHEDULE_NAME("scheduleName"), NEW_SCHEDULE_NAME("new scheduleName"), From eb072ee1eff7a22ed5711f1bbbf41151701cf1bb Mon Sep 17 00:00:00 2001 From: Yang JiWoong Date: Sun, 28 Apr 2024 17:26:29 +0900 Subject: [PATCH 26/52] =?UTF-8?q?[BE]=20feat=20:=20=EB=AA=A8=EC=9E=84=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EC=88=98=EC=A0=95=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/moim/MoimService.java | 9 ++-- .../application/moim/MoimServiceImpl.java | 16 ++++--- .../dto/moim/MoimUpdateRequest.java | 27 ++++++++++++ .../exception/MoimExceptionConstant.java | 3 +- .../implement/moim/MoimUpdater.java | 24 +++++++++++ .../entity/moim/moim/MoimJpaEntity.java | 43 +++++++++++++++++++ .../presentation/moim/MoimController.java | 6 +++ .../fake_class/moim/FakeMoimService.java | 10 +++-- 8 files changed, 123 insertions(+), 15 deletions(-) create mode 100644 backend/src/main/java/moim_today/dto/moim/MoimUpdateRequest.java create mode 100644 backend/src/main/java/moim_today/implement/moim/MoimUpdater.java diff --git a/backend/src/main/java/moim_today/application/moim/MoimService.java b/backend/src/main/java/moim_today/application/moim/MoimService.java index c6005699..8f1fa17d 100644 --- a/backend/src/main/java/moim_today/application/moim/MoimService.java +++ b/backend/src/main/java/moim_today/application/moim/MoimService.java @@ -1,9 +1,6 @@ package moim_today.application.moim; -import moim_today.dto.moim.MoimDetailResponse; -import moim_today.dto.moim.PrivateMoimAppendRequest; -import moim_today.dto.moim.PublicMoimAppendRequest; -import moim_today.dto.moim.UploadMoimImageResponse; +import moim_today.dto.moim.*; import org.springframework.web.multipart.MultipartFile; public interface MoimService { @@ -16,5 +13,7 @@ void createPrivateMoim(final long memberId, final long universityId, UploadMoimImageResponse uploadMoimImage(final MultipartFile file); - MoimDetailResponse getMoimDetail(long moimId); + MoimDetailResponse getMoimDetail(final long moimId); + + void updateMoim(final long memberId, final MoimUpdateRequest moimUpdateRequest); } diff --git a/backend/src/main/java/moim_today/application/moim/MoimServiceImpl.java b/backend/src/main/java/moim_today/application/moim/MoimServiceImpl.java index 336f7981..fc584b2d 100644 --- a/backend/src/main/java/moim_today/application/moim/MoimServiceImpl.java +++ b/backend/src/main/java/moim_today/application/moim/MoimServiceImpl.java @@ -1,12 +1,10 @@ package moim_today.application.moim; -import moim_today.dto.moim.MoimDetailResponse; -import moim_today.dto.moim.PrivateMoimAppendRequest; -import moim_today.dto.moim.PublicMoimAppendRequest; -import moim_today.dto.moim.UploadMoimImageResponse; +import moim_today.dto.moim.*; import moim_today.implement.file.FileUploader; import moim_today.implement.moim.MoimAppender; import moim_today.implement.moim.MoimFinder; +import moim_today.implement.moim.MoimUpdater; import moim_today.persistence.entity.moim.moim.MoimJpaEntity; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; @@ -19,13 +17,16 @@ public class MoimServiceImpl implements MoimService{ private final MoimAppender moimAppender; private final FileUploader fileUploader; private final MoimFinder moimFinder; + private final MoimUpdater moimUpdater; public MoimServiceImpl(final MoimAppender moimAppender, final FileUploader fileUploader, - final MoimFinder moimFinder) { + final MoimFinder moimFinder, + final MoimUpdater moimUpdater) { this.moimAppender = moimAppender; this.fileUploader = fileUploader; this.moimFinder = moimFinder; + this.moimUpdater = moimUpdater; } @Override @@ -51,4 +52,9 @@ public MoimDetailResponse getMoimDetail(final long moimId) { MoimJpaEntity moimJpaEntity = moimFinder.getById(moimId); return MoimDetailResponse.from(moimJpaEntity); } + + @Override + public void updateMoim(final long memberId, final MoimUpdateRequest moimUpdateRequest) { + moimUpdater.updateMoim(memberId, moimUpdateRequest); + } } diff --git a/backend/src/main/java/moim_today/dto/moim/MoimUpdateRequest.java b/backend/src/main/java/moim_today/dto/moim/MoimUpdateRequest.java new file mode 100644 index 00000000..53550973 --- /dev/null +++ b/backend/src/main/java/moim_today/dto/moim/MoimUpdateRequest.java @@ -0,0 +1,27 @@ +package moim_today.dto.moim; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Builder; +import moim_today.domain.moim.DisplayStatus; +import moim_today.domain.moim.enums.MoimCategory; + +import java.time.LocalDate; + +@Builder +public record MoimUpdateRequest( + long moimId, + String title, + String contents, + int capacity, + //imageUrl null 허용 + String imageUrl, + //비밀번호 null 허용 + String password, + MoimCategory moimCategory, + DisplayStatus displayStatus, + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "Asia/Seoul") + LocalDate startDate, + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "Asia/Seoul") + LocalDate endDate +) { +} diff --git a/backend/src/main/java/moim_today/global/constant/exception/MoimExceptionConstant.java b/backend/src/main/java/moim_today/global/constant/exception/MoimExceptionConstant.java index 831432cc..b3054bec 100644 --- a/backend/src/main/java/moim_today/global/constant/exception/MoimExceptionConstant.java +++ b/backend/src/main/java/moim_today/global/constant/exception/MoimExceptionConstant.java @@ -2,7 +2,8 @@ public enum MoimExceptionConstant { - MOIM_NOT_FOUND_ERROR("존재하지 않거나 삭제된 모임입니다."); + MOIM_NOT_FOUND_ERROR("존재하지 않거나 삭제된 모임입니다."), + MOIM_FORBIDDEN("해당 모임에 대한 접근 권한이 없습니다."); private final String message; diff --git a/backend/src/main/java/moim_today/implement/moim/MoimUpdater.java b/backend/src/main/java/moim_today/implement/moim/MoimUpdater.java new file mode 100644 index 00000000..571ecff4 --- /dev/null +++ b/backend/src/main/java/moim_today/implement/moim/MoimUpdater.java @@ -0,0 +1,24 @@ +package moim_today.implement.moim; + +import moim_today.dto.moim.MoimUpdateRequest; +import moim_today.global.annotation.Implement; +import moim_today.persistence.entity.moim.moim.MoimJpaEntity; +import moim_today.persistence.repository.moim.moim.MoimRepository; +import org.springframework.transaction.annotation.Transactional; + +@Implement +public class MoimUpdater { + + private final MoimRepository moimRepository; + + public MoimUpdater(final MoimRepository moimRepository) { + this.moimRepository = moimRepository; + } + + @Transactional + public void updateMoim(final long memberId, final MoimUpdateRequest moimUpdateRequest) { + MoimJpaEntity moimJpaEntity = moimRepository.getById(moimUpdateRequest.moimId()); + moimJpaEntity.validateMember(memberId); + moimJpaEntity.updateMoim(moimUpdateRequest); + } +} diff --git a/backend/src/main/java/moim_today/persistence/entity/moim/moim/MoimJpaEntity.java b/backend/src/main/java/moim_today/persistence/entity/moim/moim/MoimJpaEntity.java index b6a4a883..83737046 100644 --- a/backend/src/main/java/moim_today/persistence/entity/moim/moim/MoimJpaEntity.java +++ b/backend/src/main/java/moim_today/persistence/entity/moim/moim/MoimJpaEntity.java @@ -5,11 +5,17 @@ import lombok.Getter; import moim_today.domain.moim.DisplayStatus; import moim_today.domain.moim.enums.MoimCategory; +import moim_today.dto.moim.MoimUpdateRequest; import moim_today.global.annotation.Association; import moim_today.global.base_entity.BaseTimeEntity; +import moim_today.global.error.ForbiddenException; import java.time.LocalDate; +import static moim_today.global.constant.MoimConstant.DEFAULT_MOIM_IMAGE_URL; +import static moim_today.global.constant.MoimConstant.DEFAULT_MOIM_PASSWORD; +import static moim_today.global.constant.exception.MoimExceptionConstant.MOIM_FORBIDDEN; + @Getter @Table(name = "moim") @Entity @@ -72,4 +78,41 @@ private MoimJpaEntity(final long universityId, final long memberId, final String this.startDate = startDate; this.endDate = endDate; } + + public void validateMember(final long memberId) { + if (this.memberId != memberId) { + throw new ForbiddenException(MOIM_FORBIDDEN.message()); + } + } + + public void updateMoim(final MoimUpdateRequest moimUpdateRequest) { + this.title = moimUpdateRequest.title(); + this.contents = moimUpdateRequest.contents(); + this.capacity = moimUpdateRequest.capacity(); + this.moimCategory = moimUpdateRequest.moimCategory(); + this.startDate = moimUpdateRequest.startDate(); + this.endDate = moimUpdateRequest.endDate(); + this.displayStatus = moimUpdateRequest.displayStatus(); + + updatePasswordByDisplayStatus(moimUpdateRequest.password()); + updateImageUrl(moimUpdateRequest.imageUrl()); + } + + private void updateImageUrl(final String updateImageUrl) { + if (updateImageUrl == null) { + this.imageUrl = DEFAULT_MOIM_IMAGE_URL.value(); + } else { + this.imageUrl = updateImageUrl; + } + } + + private void updatePasswordByDisplayStatus(final String updatePassword) { + if (displayStatus.equals(DisplayStatus.PUBLIC)) { + this.password = DEFAULT_MOIM_PASSWORD.value(); + } else { + if (updatePassword != null) { + this.password = updatePassword; + } + } + } } diff --git a/backend/src/main/java/moim_today/presentation/moim/MoimController.java b/backend/src/main/java/moim_today/presentation/moim/MoimController.java index 63611a74..8330ef94 100644 --- a/backend/src/main/java/moim_today/presentation/moim/MoimController.java +++ b/backend/src/main/java/moim_today/presentation/moim/MoimController.java @@ -39,4 +39,10 @@ public UploadMoimImageResponse uploadMoimImage(@Login final MemberSession member public MoimDetailResponse getMoimDetail(@RequestBody final MoimDetailRequest moimDetailRequest) { return moimService.getMoimDetail(moimDetailRequest.moimId()); } + + @PatchMapping + public void updateMoim(@Login final MemberSession memberSession, + @RequestBody final MoimUpdateRequest moimUpdateRequest) { + moimService.updateMoim(memberSession.id(), moimUpdateRequest); + } } diff --git a/backend/src/test/java/moim_today/fake_class/moim/FakeMoimService.java b/backend/src/test/java/moim_today/fake_class/moim/FakeMoimService.java index 8fc8c931..f3a55ffd 100644 --- a/backend/src/test/java/moim_today/fake_class/moim/FakeMoimService.java +++ b/backend/src/test/java/moim_today/fake_class/moim/FakeMoimService.java @@ -3,10 +3,7 @@ import moim_today.application.moim.MoimService; import moim_today.domain.moim.DisplayStatus; import moim_today.domain.moim.enums.MoimCategory; -import moim_today.dto.moim.MoimDetailResponse; -import moim_today.dto.moim.PrivateMoimAppendRequest; -import moim_today.dto.moim.PublicMoimAppendRequest; -import moim_today.dto.moim.UploadMoimImageResponse; +import moim_today.dto.moim.*; import org.springframework.web.multipart.MultipartFile; import java.time.LocalDate; @@ -45,4 +42,9 @@ public MoimDetailResponse getMoimDetail(final long moimId) { .endDate(LocalDate.of(2024,6,30)) .build(); } + + @Override + public void updateMoim(final long memberId, final MoimUpdateRequest moimUpdateRequest) { + + } } From 7c309225156872da705c84f1cd93e7cb97c521e4 Mon Sep 17 00:00:00 2001 From: Yang JiWoong Date: Mon, 29 Apr 2024 14:38:27 +0900 Subject: [PATCH 27/52] =?UTF-8?q?[BE]=20test=20:=20=EB=AA=A8=EC=9E=84=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EC=88=98=EC=A0=95=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../moim_today/global/config/WebConfig.java | 2 +- .../implement/moim/MoimUpdaterTest.java | 95 ++++++++ .../entity/moim/moim/MoimJpaEntityTest.java | 208 ++++++++++++++++++ .../presentation/moim/MoimControllerTest.java | 43 ++++ 4 files changed, 347 insertions(+), 1 deletion(-) create mode 100644 backend/src/test/java/moim_today/implement/moim/MoimUpdaterTest.java create mode 100644 backend/src/test/java/moim_today/persistence/entity/moim/moim/MoimJpaEntityTest.java diff --git a/backend/src/main/java/moim_today/global/config/WebConfig.java b/backend/src/main/java/moim_today/global/config/WebConfig.java index 599718f1..773f3067 100644 --- a/backend/src/main/java/moim_today/global/config/WebConfig.java +++ b/backend/src/main/java/moim_today/global/config/WebConfig.java @@ -27,7 +27,7 @@ public void addInterceptors(final InterceptorRegistry registry) { .excludePathPatterns( "/api/login", "/api/certification/**", - "/api/moims/detail/**" + "/api/moims/detail" ); } diff --git a/backend/src/test/java/moim_today/implement/moim/MoimUpdaterTest.java b/backend/src/test/java/moim_today/implement/moim/MoimUpdaterTest.java new file mode 100644 index 00000000..22392cf4 --- /dev/null +++ b/backend/src/test/java/moim_today/implement/moim/MoimUpdaterTest.java @@ -0,0 +1,95 @@ +package moim_today.implement.moim; + +import moim_today.domain.moim.DisplayStatus; +import moim_today.domain.moim.enums.MoimCategory; +import moim_today.dto.moim.MoimUpdateRequest; +import moim_today.global.error.ForbiddenException; +import moim_today.persistence.entity.moim.moim.MoimJpaEntity; +import moim_today.util.ImplementTest; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.time.LocalDate; + +import static moim_today.global.constant.exception.MoimExceptionConstant.MOIM_FORBIDDEN; +import static moim_today.util.TestConstant.*; +import static org.assertj.core.api.Assertions.*; + +class MoimUpdaterTest extends ImplementTest { + + @Autowired + private MoimUpdater moimUpdater; + + @DisplayName("자신이 만든 모임을 수정하려고 시도하면 수정에 성공한다.") + @Test + void updateMoimTest(){ + + //given + long memberId = Long.parseLong(MEMBER_ID.value()); + + MoimJpaEntity moimJpaEntity = MoimJpaEntity.builder() + .memberId(memberId) + .build(); + + moimRepository.save(moimJpaEntity); + long moimId = moimJpaEntity.getId(); + + int capacity = Integer.parseInt(CAPACITY.value()); + LocalDate startDate = LocalDate.of(2024, 3, 1); + LocalDate endDate = LocalDate.of(2024, 6, 30); + + MoimUpdateRequest moimUpdateRequest = MoimUpdateRequest.builder() + .moimId(moimId) + .title(TITLE.value()) + .contents(CONTENTS.value()) + .capacity(capacity) + .imageUrl(MOIM_IMAGE_URL.value()) + .password(PASSWORD.value()) + .moimCategory(MoimCategory.STUDY) + .displayStatus(DisplayStatus.PRIVATE) + .startDate(startDate) + .endDate(endDate) + .build(); + + //when & //then + assertThatCode(() -> moimUpdater.updateMoim(memberId, moimUpdateRequest)) + .doesNotThrowAnyException(); + + MoimJpaEntity updatedMoim = moimRepository.getById(moimId); + assertThat(updatedMoim.getTitle()).isEqualTo(TITLE.value()); + assertThat(updatedMoim.getContents()).isEqualTo(CONTENTS.value()); + assertThat(updatedMoim.getCapacity()).isEqualTo(capacity); + assertThat(updatedMoim.getImageUrl()).isEqualTo(MOIM_IMAGE_URL.value()); + assertThat(updatedMoim.getPassword()).isEqualTo(PASSWORD.value()); + assertThat(updatedMoim.getMoimCategory()).isEqualTo(MoimCategory.STUDY); + assertThat(updatedMoim.getDisplayStatus()).isEqualTo(DisplayStatus.PRIVATE); + assertThat(updatedMoim.getStartDate()).isEqualTo(startDate); + assertThat(updatedMoim.getEndDate()).isEqualTo(endDate); + } + + @DisplayName("수정 권한이 없는 모임을 수정하려고 시도하면 예외가 발생한다.") + @Test + void updateMoimFailureTest(){ + + //given + long memberId = Long.parseLong(MEMBER_ID.value()); + long forbiddenMemberId = memberId + 1; + + MoimJpaEntity moimJpaEntity = MoimJpaEntity.builder() + .memberId(forbiddenMemberId) + .build(); + + moimRepository.save(moimJpaEntity); + long moimId = moimJpaEntity.getId(); + + MoimUpdateRequest forbiddenMoimUpdateRequest = MoimUpdateRequest.builder() + .moimId(moimId) + .build(); + + //expected + assertThatThrownBy(() -> moimUpdater.updateMoim(memberId, forbiddenMoimUpdateRequest)) + .isInstanceOf(ForbiddenException.class) + .hasMessage(MOIM_FORBIDDEN.message()); + } +} diff --git a/backend/src/test/java/moim_today/persistence/entity/moim/moim/MoimJpaEntityTest.java b/backend/src/test/java/moim_today/persistence/entity/moim/moim/MoimJpaEntityTest.java new file mode 100644 index 00000000..d38dbbb7 --- /dev/null +++ b/backend/src/test/java/moim_today/persistence/entity/moim/moim/MoimJpaEntityTest.java @@ -0,0 +1,208 @@ +package moim_today.persistence.entity.moim.moim; + +import moim_today.domain.moim.DisplayStatus; +import moim_today.domain.moim.enums.MoimCategory; +import moim_today.dto.moim.MoimUpdateRequest; +import moim_today.global.error.ForbiddenException; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.time.LocalDate; + +import static moim_today.global.constant.MoimConstant.DEFAULT_MOIM_IMAGE_URL; +import static moim_today.global.constant.MoimConstant.DEFAULT_MOIM_PASSWORD; +import static moim_today.global.constant.exception.MoimExceptionConstant.MOIM_FORBIDDEN; +import static moim_today.util.TestConstant.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; + +class MoimJpaEntityTest { + + @DisplayName("회원 id가 일치하면 검증에 성공한다.") + @Test + void validateMemberTest(){ + + //given + long memberId = Long.parseLong(MEMBER_ID.value()); + + MoimJpaEntity moimJpaEntity = MoimJpaEntity.builder() + .memberId(memberId) + .build(); + + //expected + assertThatCode(() -> moimJpaEntity.validateMember(memberId)) + .doesNotThrowAnyException(); + } + + @DisplayName("회원 id가 일치하지 않으면 예외가 발생한다") + @Test + void validateMemberThrowsExceptionTest(){ + + //given + long memberId = Long.parseLong(MEMBER_ID.value()); + long forbiddenMemberId = Long.parseLong(MEMBER_ID.value()) + 1L; + + MoimJpaEntity moimJpaEntity = MoimJpaEntity.builder() + .memberId(memberId) + .build(); + + //expected + assertThatCode(() -> moimJpaEntity.validateMember(forbiddenMemberId)) + .isInstanceOf(ForbiddenException.class) + .hasMessage(MOIM_FORBIDDEN.message()); + } + + @DisplayName("수정시 공개 여부가 PUBLIC이라면 default password가 설정된다.") + @Test + void updateMoimDisplayStatusPublicTest(){ + + //given + MoimJpaEntity moimJpaEntity = MoimJpaEntity.builder() + .build(); + + int capacity = Integer.parseInt(CAPACITY.value()); + LocalDate startDate = LocalDate.of(2024, 3, 1); + LocalDate endDate = LocalDate.of(2024, 6, 30); + + MoimUpdateRequest moimUpdateRequest = MoimUpdateRequest.builder() + .title(TITLE.value()) + .contents(CONTENTS.value()) + .capacity(capacity) + .imageUrl(MOIM_IMAGE_URL.value()) + .moimCategory(MoimCategory.STUDY) + .displayStatus(DisplayStatus.PUBLIC) + .startDate(startDate) + .endDate(endDate) + .build(); + + //expected + assertThatCode(() -> moimJpaEntity.updateMoim(moimUpdateRequest)) + .doesNotThrowAnyException(); + + assertThat(moimJpaEntity.getTitle()).isEqualTo(TITLE.value()); + assertThat(moimJpaEntity.getContents()).isEqualTo(CONTENTS.value()); + assertThat(moimJpaEntity.getCapacity()).isEqualTo(capacity); + assertThat(moimJpaEntity.getImageUrl()).isEqualTo(MOIM_IMAGE_URL.value()); + assertThat(moimJpaEntity.getPassword()).isEqualTo(DEFAULT_MOIM_PASSWORD.value()); + assertThat(moimJpaEntity.getMoimCategory()).isEqualTo(MoimCategory.STUDY); + assertThat(moimJpaEntity.getDisplayStatus()).isEqualTo(DisplayStatus.PUBLIC); + assertThat(moimJpaEntity.getStartDate()).isEqualTo(startDate); + assertThat(moimJpaEntity.getEndDate()).isEqualTo(endDate); + } + + @DisplayName("수정시 공개 여부가 PRIVATE이라면 입력한 password가 설정된다.") + @Test + void updateMoimDisplayStatusPrivateTest(){ + + //given + MoimJpaEntity moimJpaEntity = MoimJpaEntity.builder() + .build(); + + int capacity = Integer.parseInt(CAPACITY.value()); + LocalDate startDate = LocalDate.of(2024, 3, 1); + LocalDate endDate = LocalDate.of(2024, 6, 30); + + MoimUpdateRequest moimUpdateRequest = MoimUpdateRequest.builder() + .title(TITLE.value()) + .contents(CONTENTS.value()) + .capacity(capacity) + .password(PASSWORD.value()) + .imageUrl(MOIM_IMAGE_URL.value()) + .moimCategory(MoimCategory.STUDY) + .displayStatus(DisplayStatus.PRIVATE) + .startDate(startDate) + .endDate(endDate) + .build(); + + //expected + assertThatCode(() -> moimJpaEntity.updateMoim(moimUpdateRequest)) + .doesNotThrowAnyException(); + + assertThat(moimJpaEntity.getTitle()).isEqualTo(TITLE.value()); + assertThat(moimJpaEntity.getContents()).isEqualTo(CONTENTS.value()); + assertThat(moimJpaEntity.getCapacity()).isEqualTo(capacity); + assertThat(moimJpaEntity.getImageUrl()).isEqualTo(MOIM_IMAGE_URL.value()); + assertThat(moimJpaEntity.getPassword()).isEqualTo(PASSWORD.value()); + assertThat(moimJpaEntity.getMoimCategory()).isEqualTo(MoimCategory.STUDY); + assertThat(moimJpaEntity.getDisplayStatus()).isEqualTo(DisplayStatus.PRIVATE); + assertThat(moimJpaEntity.getStartDate()).isEqualTo(startDate); + assertThat(moimJpaEntity.getEndDate()).isEqualTo(endDate); + } + + @DisplayName("수정시 imageUrl값이 없다면 default imageURL 값이 들어간다.") + @Test + void updateMoimImageUrlIsNullTest(){ + + //given + MoimJpaEntity moimJpaEntity = MoimJpaEntity.builder() + .build(); + + int capacity = Integer.parseInt(CAPACITY.value()); + LocalDate startDate = LocalDate.of(2024, 3, 1); + LocalDate endDate = LocalDate.of(2024, 6, 30); + + MoimUpdateRequest moimUpdateRequest = MoimUpdateRequest.builder() + .title(TITLE.value()) + .contents(CONTENTS.value()) + .capacity(capacity) + .password(PASSWORD.value()) + .moimCategory(MoimCategory.STUDY) + .displayStatus(DisplayStatus.PRIVATE) + .startDate(startDate) + .endDate(endDate) + .build(); + + //expected + assertThatCode(() -> moimJpaEntity.updateMoim(moimUpdateRequest)) + .doesNotThrowAnyException(); + + assertThat(moimJpaEntity.getTitle()).isEqualTo(TITLE.value()); + assertThat(moimJpaEntity.getContents()).isEqualTo(CONTENTS.value()); + assertThat(moimJpaEntity.getCapacity()).isEqualTo(capacity); + assertThat(moimJpaEntity.getImageUrl()).isEqualTo(DEFAULT_MOIM_IMAGE_URL.value()); + assertThat(moimJpaEntity.getPassword()).isEqualTo(PASSWORD.value()); + assertThat(moimJpaEntity.getMoimCategory()).isEqualTo(MoimCategory.STUDY); + assertThat(moimJpaEntity.getDisplayStatus()).isEqualTo(DisplayStatus.PRIVATE); + assertThat(moimJpaEntity.getStartDate()).isEqualTo(startDate); + assertThat(moimJpaEntity.getEndDate()).isEqualTo(endDate); + } + + @DisplayName("수정시 imageUrl값이 있다면 값이 그대로 들어간다.") + @Test + void updateMoimImageUrlIsNotNullTest(){ + + //given + MoimJpaEntity moimJpaEntity = MoimJpaEntity.builder() + .build(); + + int capacity = Integer.parseInt(CAPACITY.value()); + LocalDate startDate = LocalDate.of(2024, 3, 1); + LocalDate endDate = LocalDate.of(2024, 6, 30); + + MoimUpdateRequest moimUpdateRequest = MoimUpdateRequest.builder() + .title(TITLE.value()) + .contents(CONTENTS.value()) + .capacity(capacity) + .password(PASSWORD.value()) + .imageUrl(MOIM_IMAGE_URL.value()) + .moimCategory(MoimCategory.STUDY) + .displayStatus(DisplayStatus.PRIVATE) + .startDate(startDate) + .endDate(endDate) + .build(); + + //expected + assertThatCode(() -> moimJpaEntity.updateMoim(moimUpdateRequest)) + .doesNotThrowAnyException(); + + assertThat(moimJpaEntity.getTitle()).isEqualTo(TITLE.value()); + assertThat(moimJpaEntity.getContents()).isEqualTo(CONTENTS.value()); + assertThat(moimJpaEntity.getCapacity()).isEqualTo(capacity); + assertThat(moimJpaEntity.getImageUrl()).isEqualTo(MOIM_IMAGE_URL.value()); + assertThat(moimJpaEntity.getPassword()).isEqualTo(PASSWORD.value()); + assertThat(moimJpaEntity.getMoimCategory()).isEqualTo(MoimCategory.STUDY); + assertThat(moimJpaEntity.getDisplayStatus()).isEqualTo(DisplayStatus.PRIVATE); + assertThat(moimJpaEntity.getStartDate()).isEqualTo(startDate); + assertThat(moimJpaEntity.getEndDate()).isEqualTo(endDate); + } +} diff --git a/backend/src/test/java/moim_today/presentation/moim/MoimControllerTest.java b/backend/src/test/java/moim_today/presentation/moim/MoimControllerTest.java index 5f94d361..f08f15a2 100644 --- a/backend/src/test/java/moim_today/presentation/moim/MoimControllerTest.java +++ b/backend/src/test/java/moim_today/presentation/moim/MoimControllerTest.java @@ -1,8 +1,12 @@ package moim_today.presentation.moim; import com.epages.restdocs.apispec.ResourceSnippetParameters; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.core.JsonProcessingException; +import moim_today.domain.moim.DisplayStatus; import moim_today.domain.moim.enums.MoimCategory; import moim_today.dto.moim.MoimDetailRequest; +import moim_today.dto.moim.MoimUpdateRequest; import moim_today.dto.moim.PrivateMoimAppendRequest; import moim_today.dto.moim.PublicMoimAppendRequest; import moim_today.fake_class.moim.FakeMoimService; @@ -171,4 +175,43 @@ void getMoimDetailTest() throws Exception { .build() ))); } + + @DisplayName("모임 정보 업데이트 테스트") + @Test + void updateMoimTest() throws Exception { + MoimUpdateRequest moimUpdateRequest = MoimUpdateRequest.builder() + .moimId(Long.parseLong(MOIM_ID.value())) + .title(TITLE.value()) + .contents(CONTENTS.value()) + .capacity(Integer.parseInt(CAPACITY.value())) + .imageUrl(MOIM_IMAGE_URL.value()) + .password(PASSWORD.value()) + .moimCategory(MoimCategory.STUDY) + .displayStatus(DisplayStatus.PRIVATE) + .startDate(LocalDate.of(2024,3,1)) + .endDate(LocalDate.of(2024,6,30)) + .build(); + + mockMvc.perform(patch("/api/moims") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(moimUpdateRequest))) + .andExpect(status().isOk()) + .andDo(document("모임 정보 업데이트 테스트", + resource(ResourceSnippetParameters.builder() + .tag("모임") + .summary("모임 정보를 업데이트(수정)하는 테스트 입니다.") + .requestFields( + fieldWithPath("moimId").type(NUMBER).description("수정할 모임의 ID"), + fieldWithPath("title").type(STRING).description("수정한 모임명"), + fieldWithPath("contents").type(STRING).description("수정한 내용"), + fieldWithPath("capacity").type(NUMBER).description("수정한 모집 인원"), + fieldWithPath("imageUrl").type(STRING).description("수정한 모임 사진 URL"), + fieldWithPath("password").type(STRING).description("수정한 비밀번호"), + fieldWithPath("moimCategory").type(VARIES).description("수정한 카테고리"), + fieldWithPath("displayStatus").type(VARIES).description("수정한 공개여부"), + fieldWithPath("startDate").type(STRING).description("수정한 시작일자"), + fieldWithPath("endDate").type(STRING).description("수정한 종료일자") + ).build() + ))); + } } From e795ceecfcc3f353192415a02bde4117f73d1d5e Mon Sep 17 00:00:00 2001 From: Yang JiWoong Date: Mon, 29 Apr 2024 16:39:58 +0900 Subject: [PATCH 28/52] =?UTF-8?q?[BE]=20fix=20:=20=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=EA=B0=80=EC=9E=85=20URL=20excludePathPatterns=EC=97=90=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/main/java/moim_today/global/config/WebConfig.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/moim_today/global/config/WebConfig.java b/backend/src/main/java/moim_today/global/config/WebConfig.java index 773f3067..beb8563f 100644 --- a/backend/src/main/java/moim_today/global/config/WebConfig.java +++ b/backend/src/main/java/moim_today/global/config/WebConfig.java @@ -27,7 +27,8 @@ public void addInterceptors(final InterceptorRegistry registry) { .excludePathPatterns( "/api/login", "/api/certification/**", - "/api/moims/detail" + "/api/moims/detail", + "/api/register" ); } From 3b803705d61ad9bf970f4cbd4ad1a723583f030e Mon Sep 17 00:00:00 2001 From: Yang JiWoong Date: Mon, 29 Apr 2024 16:57:19 +0900 Subject: [PATCH 29/52] =?UTF-8?q?[BE]=20refactor=20:=20=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=EA=B0=80=EC=9E=85=20API=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/moim_today/application/auth/AuthService.java | 2 +- .../java/moim_today/application/auth/AuthServiceImpl.java | 6 +++--- .../java/moim_today/implement/member/AuthManager.java | 2 +- .../java/moim_today/presentation/auth/AuthController.java | 8 ++++---- .../java/moim_today/fake_class/auth/FakeAuthService.java | 2 +- .../java/moim_today/implement/member/AuthManagerTest.java | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/backend/src/main/java/moim_today/application/auth/AuthService.java b/backend/src/main/java/moim_today/application/auth/AuthService.java index 1ccf618b..da2e4400 100644 --- a/backend/src/main/java/moim_today/application/auth/AuthService.java +++ b/backend/src/main/java/moim_today/application/auth/AuthService.java @@ -8,7 +8,7 @@ public interface AuthService { void login(final MemberLoginRequest memberLoginRequest, final HttpServletRequest request); - void register(final MemberRegisterRequest memberRegisterRequest, final HttpServletRequest request); + void signUp(final MemberRegisterRequest memberRegisterRequest, final HttpServletRequest request); void logout(final HttpServletRequest request); } diff --git a/backend/src/main/java/moim_today/application/auth/AuthServiceImpl.java b/backend/src/main/java/moim_today/application/auth/AuthServiceImpl.java index 24e74a0f..0a0198e2 100644 --- a/backend/src/main/java/moim_today/application/auth/AuthServiceImpl.java +++ b/backend/src/main/java/moim_today/application/auth/AuthServiceImpl.java @@ -39,11 +39,11 @@ public void logout(final HttpServletRequest request) { } @Override - public void register(final MemberRegisterRequest memberRegisterRequest, - final HttpServletRequest request) { + public void signUp(final MemberRegisterRequest memberRegisterRequest, + final HttpServletRequest request) { universityFinder.checkUniversityIdIsPresent(memberRegisterRequest.universityId()); departmentFinder.isDepartmentAssociatedWithUniversity(memberRegisterRequest.universityId(), memberRegisterRequest.departmentId()); memberFinder.validateEmailNotExists(memberRegisterRequest.email()); - authManager.register(memberRegisterRequest, request); + authManager.signUp(memberRegisterRequest, request); } } diff --git a/backend/src/main/java/moim_today/implement/member/AuthManager.java b/backend/src/main/java/moim_today/implement/member/AuthManager.java index 57295129..9dff87bd 100644 --- a/backend/src/main/java/moim_today/implement/member/AuthManager.java +++ b/backend/src/main/java/moim_today/implement/member/AuthManager.java @@ -50,7 +50,7 @@ public void logout(final HttpServletRequest request) { } } - public void register(final MemberRegisterRequest memberRegisterRequest, final HttpServletRequest request) { + public void signUp(final MemberRegisterRequest memberRegisterRequest, final HttpServletRequest request) { String encodedPassword = passwordEncode(memberRegisterRequest.password()); MemberJpaEntity saveMember = memberRepository.save(memberRegisterRequest.toEntity(encodedPassword)); setSessionByMemberSession(saveMember, request); diff --git a/backend/src/main/java/moim_today/presentation/auth/AuthController.java b/backend/src/main/java/moim_today/presentation/auth/AuthController.java index b8f0ecb5..0cf87182 100644 --- a/backend/src/main/java/moim_today/presentation/auth/AuthController.java +++ b/backend/src/main/java/moim_today/presentation/auth/AuthController.java @@ -33,9 +33,9 @@ public void logout(@Login final MemberSession memberSession, final HttpServletRe authService.logout(request); } - @PostMapping("/register") - public void register(@Valid @RequestBody final MemberRegisterRequest memberRegisterRequest, - final HttpServletRequest request){ - authService.register(memberRegisterRequest, request); + @PostMapping("/sign-up") + public void signUp(@Valid @RequestBody final MemberRegisterRequest memberRegisterRequest, + final HttpServletRequest request){ + authService.signUp(memberRegisterRequest, request); } } diff --git a/backend/src/test/java/moim_today/fake_class/auth/FakeAuthService.java b/backend/src/test/java/moim_today/fake_class/auth/FakeAuthService.java index 20760f41..039a9e0b 100644 --- a/backend/src/test/java/moim_today/fake_class/auth/FakeAuthService.java +++ b/backend/src/test/java/moim_today/fake_class/auth/FakeAuthService.java @@ -36,7 +36,7 @@ public void login(final MemberLoginRequest memberLoginRequest, final HttpServlet } @Override - public void register(final MemberRegisterRequest memberRegisterRequest, final HttpServletRequest request) { + public void signUp(final MemberRegisterRequest memberRegisterRequest, final HttpServletRequest request) { } diff --git a/backend/src/test/java/moim_today/implement/member/AuthManagerTest.java b/backend/src/test/java/moim_today/implement/member/AuthManagerTest.java index cb26ecdd..12c585d7 100644 --- a/backend/src/test/java/moim_today/implement/member/AuthManagerTest.java +++ b/backend/src/test/java/moim_today/implement/member/AuthManagerTest.java @@ -100,7 +100,7 @@ void register() throws JsonProcessingException { .build(); // when - authManager.register(memberRegisterRequest, mockHttpServletRequest); + authManager.signUp(memberRegisterRequest, mockHttpServletRequest); // then HttpSession session = mockHttpServletRequest.getSession(false); From ef13090249f9224d5ddfb5d33e0d93a6f5131a61 Mon Sep 17 00:00:00 2001 From: Yang JiWoong Date: Mon, 29 Apr 2024 16:57:19 +0900 Subject: [PATCH 30/52] =?UTF-8?q?[BE]=20refactor=20:=20=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=EA=B0=80=EC=9E=85=20API=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/moim_today/application/auth/AuthService.java | 2 +- .../java/moim_today/application/auth/AuthServiceImpl.java | 6 +++--- .../java/moim_today/implement/member/AuthManager.java | 2 +- .../java/moim_today/presentation/auth/AuthController.java | 8 ++++---- .../java/moim_today/fake_class/auth/FakeAuthService.java | 2 +- .../java/moim_today/implement/member/AuthManagerTest.java | 2 +- .../moim_today/presentation/auth/AuthControllerTest.java | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/backend/src/main/java/moim_today/application/auth/AuthService.java b/backend/src/main/java/moim_today/application/auth/AuthService.java index 1ccf618b..da2e4400 100644 --- a/backend/src/main/java/moim_today/application/auth/AuthService.java +++ b/backend/src/main/java/moim_today/application/auth/AuthService.java @@ -8,7 +8,7 @@ public interface AuthService { void login(final MemberLoginRequest memberLoginRequest, final HttpServletRequest request); - void register(final MemberRegisterRequest memberRegisterRequest, final HttpServletRequest request); + void signUp(final MemberRegisterRequest memberRegisterRequest, final HttpServletRequest request); void logout(final HttpServletRequest request); } diff --git a/backend/src/main/java/moim_today/application/auth/AuthServiceImpl.java b/backend/src/main/java/moim_today/application/auth/AuthServiceImpl.java index 24e74a0f..0a0198e2 100644 --- a/backend/src/main/java/moim_today/application/auth/AuthServiceImpl.java +++ b/backend/src/main/java/moim_today/application/auth/AuthServiceImpl.java @@ -39,11 +39,11 @@ public void logout(final HttpServletRequest request) { } @Override - public void register(final MemberRegisterRequest memberRegisterRequest, - final HttpServletRequest request) { + public void signUp(final MemberRegisterRequest memberRegisterRequest, + final HttpServletRequest request) { universityFinder.checkUniversityIdIsPresent(memberRegisterRequest.universityId()); departmentFinder.isDepartmentAssociatedWithUniversity(memberRegisterRequest.universityId(), memberRegisterRequest.departmentId()); memberFinder.validateEmailNotExists(memberRegisterRequest.email()); - authManager.register(memberRegisterRequest, request); + authManager.signUp(memberRegisterRequest, request); } } diff --git a/backend/src/main/java/moim_today/implement/member/AuthManager.java b/backend/src/main/java/moim_today/implement/member/AuthManager.java index 57295129..9dff87bd 100644 --- a/backend/src/main/java/moim_today/implement/member/AuthManager.java +++ b/backend/src/main/java/moim_today/implement/member/AuthManager.java @@ -50,7 +50,7 @@ public void logout(final HttpServletRequest request) { } } - public void register(final MemberRegisterRequest memberRegisterRequest, final HttpServletRequest request) { + public void signUp(final MemberRegisterRequest memberRegisterRequest, final HttpServletRequest request) { String encodedPassword = passwordEncode(memberRegisterRequest.password()); MemberJpaEntity saveMember = memberRepository.save(memberRegisterRequest.toEntity(encodedPassword)); setSessionByMemberSession(saveMember, request); diff --git a/backend/src/main/java/moim_today/presentation/auth/AuthController.java b/backend/src/main/java/moim_today/presentation/auth/AuthController.java index b8f0ecb5..0cf87182 100644 --- a/backend/src/main/java/moim_today/presentation/auth/AuthController.java +++ b/backend/src/main/java/moim_today/presentation/auth/AuthController.java @@ -33,9 +33,9 @@ public void logout(@Login final MemberSession memberSession, final HttpServletRe authService.logout(request); } - @PostMapping("/register") - public void register(@Valid @RequestBody final MemberRegisterRequest memberRegisterRequest, - final HttpServletRequest request){ - authService.register(memberRegisterRequest, request); + @PostMapping("/sign-up") + public void signUp(@Valid @RequestBody final MemberRegisterRequest memberRegisterRequest, + final HttpServletRequest request){ + authService.signUp(memberRegisterRequest, request); } } diff --git a/backend/src/test/java/moim_today/fake_class/auth/FakeAuthService.java b/backend/src/test/java/moim_today/fake_class/auth/FakeAuthService.java index 20760f41..039a9e0b 100644 --- a/backend/src/test/java/moim_today/fake_class/auth/FakeAuthService.java +++ b/backend/src/test/java/moim_today/fake_class/auth/FakeAuthService.java @@ -36,7 +36,7 @@ public void login(final MemberLoginRequest memberLoginRequest, final HttpServlet } @Override - public void register(final MemberRegisterRequest memberRegisterRequest, final HttpServletRequest request) { + public void signUp(final MemberRegisterRequest memberRegisterRequest, final HttpServletRequest request) { } diff --git a/backend/src/test/java/moim_today/implement/member/AuthManagerTest.java b/backend/src/test/java/moim_today/implement/member/AuthManagerTest.java index cb26ecdd..12c585d7 100644 --- a/backend/src/test/java/moim_today/implement/member/AuthManagerTest.java +++ b/backend/src/test/java/moim_today/implement/member/AuthManagerTest.java @@ -100,7 +100,7 @@ void register() throws JsonProcessingException { .build(); // when - authManager.register(memberRegisterRequest, mockHttpServletRequest); + authManager.signUp(memberRegisterRequest, mockHttpServletRequest); // then HttpSession session = mockHttpServletRequest.getSession(false); diff --git a/backend/src/test/java/moim_today/presentation/auth/AuthControllerTest.java b/backend/src/test/java/moim_today/presentation/auth/AuthControllerTest.java index 95036b15..12f296d0 100644 --- a/backend/src/test/java/moim_today/presentation/auth/AuthControllerTest.java +++ b/backend/src/test/java/moim_today/presentation/auth/AuthControllerTest.java @@ -112,7 +112,7 @@ void registerTest() throws Exception { String json = objectMapper.writeValueAsString(memberRegisterRequest); - mockMvc.perform(post("/api/register") + mockMvc.perform(post("/api/sign-up") .contentType(APPLICATION_JSON) .accept(APPLICATION_JSON) .content(json)) From 14ae9fc985bc3ddee2fe34e3f2e4f283cc890d06 Mon Sep 17 00:00:00 2001 From: Yang JiWoong Date: Mon, 29 Apr 2024 17:08:59 +0900 Subject: [PATCH 31/52] =?UTF-8?q?[BE]=20fix=20:=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=EB=90=9C=20API=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EB=B0=98?= =?UTF-8?q?=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/moim_today/presentation/auth/AuthControllerTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/test/java/moim_today/presentation/auth/AuthControllerTest.java b/backend/src/test/java/moim_today/presentation/auth/AuthControllerTest.java index 12f296d0..1ce1d9a6 100644 --- a/backend/src/test/java/moim_today/presentation/auth/AuthControllerTest.java +++ b/backend/src/test/java/moim_today/presentation/auth/AuthControllerTest.java @@ -134,4 +134,4 @@ void registerTest() throws Exception { .build()) )); } -} \ No newline at end of file +} From d3ffdcde047201a01c3df51f511f677ed0244eed Mon Sep 17 00:00:00 2001 From: Yang JiWoong Date: Mon, 29 Apr 2024 18:43:11 +0900 Subject: [PATCH 32/52] =?UTF-8?q?[BE]=20refactor=20:=20=EB=AA=A8=EC=9E=84?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=20API=20=ED=8C=8C=EB=9D=BC=EB=AF=B8?= =?UTF-8?q?=ED=84=B0=20=EB=B0=A9=EC=8B=9D=EC=9C=BC=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/moim_today/dto/moim/MoimDetailRequest.java | 6 ------ .../moim_today/presentation/moim/MoimController.java | 4 ++-- .../presentation/moim/MoimControllerTest.java | 11 +++-------- 3 files changed, 5 insertions(+), 16 deletions(-) delete mode 100644 backend/src/main/java/moim_today/dto/moim/MoimDetailRequest.java diff --git a/backend/src/main/java/moim_today/dto/moim/MoimDetailRequest.java b/backend/src/main/java/moim_today/dto/moim/MoimDetailRequest.java deleted file mode 100644 index 39917326..00000000 --- a/backend/src/main/java/moim_today/dto/moim/MoimDetailRequest.java +++ /dev/null @@ -1,6 +0,0 @@ -package moim_today.dto.moim; - -public record MoimDetailRequest( - long moimId -) { -} diff --git a/backend/src/main/java/moim_today/presentation/moim/MoimController.java b/backend/src/main/java/moim_today/presentation/moim/MoimController.java index 8330ef94..67453e0b 100644 --- a/backend/src/main/java/moim_today/presentation/moim/MoimController.java +++ b/backend/src/main/java/moim_today/presentation/moim/MoimController.java @@ -36,8 +36,8 @@ public UploadMoimImageResponse uploadMoimImage(@Login final MemberSession member } @GetMapping("/detail") - public MoimDetailResponse getMoimDetail(@RequestBody final MoimDetailRequest moimDetailRequest) { - return moimService.getMoimDetail(moimDetailRequest.moimId()); + public MoimDetailResponse getMoimDetail(@RequestParam final long moimId) { + return moimService.getMoimDetail(moimId); } @PatchMapping diff --git a/backend/src/test/java/moim_today/presentation/moim/MoimControllerTest.java b/backend/src/test/java/moim_today/presentation/moim/MoimControllerTest.java index f08f15a2..6140fc43 100644 --- a/backend/src/test/java/moim_today/presentation/moim/MoimControllerTest.java +++ b/backend/src/test/java/moim_today/presentation/moim/MoimControllerTest.java @@ -1,11 +1,8 @@ package moim_today.presentation.moim; import com.epages.restdocs.apispec.ResourceSnippetParameters; -import com.fasterxml.jackson.annotation.JsonFormat; -import com.fasterxml.jackson.core.JsonProcessingException; import moim_today.domain.moim.DisplayStatus; import moim_today.domain.moim.enums.MoimCategory; -import moim_today.dto.moim.MoimDetailRequest; import moim_today.dto.moim.MoimUpdateRequest; import moim_today.dto.moim.PrivateMoimAppendRequest; import moim_today.dto.moim.PublicMoimAppendRequest; @@ -146,19 +143,17 @@ void uploadMoimImageTest() throws Exception { @DisplayName("모임 상제 정보 조회 테스트") @Test void getMoimDetailTest() throws Exception { - MoimDetailRequest moimDetailRequest = new MoimDetailRequest(1L); mockMvc.perform(get("/api/moims/detail") - .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsBytes(moimDetailRequest)) + .param("moimId", "1") ) .andExpect(status().isOk()) .andDo(document("모임 상세 정보 조회", resource(ResourceSnippetParameters.builder() .tag("모임") .summary("모임 상세 정보 조회 API") - .requestFields( - fieldWithPath("moimId").type(NUMBER).description("모임 ID") + .queryParameters( + parameterWithName("moimId").description("모임 ID") ) .responseFields( fieldWithPath("title").type(STRING).description("모임명"), From c4db091b3ec83442eae2e08b8c47935a04e94daf Mon Sep 17 00:00:00 2001 From: Yang JiWoong Date: Mon, 29 Apr 2024 18:46:41 +0900 Subject: [PATCH 33/52] =?UTF-8?q?[BE]=20refactor=20:=20=EB=AC=B8=EC=84=9C?= =?UTF-8?q?=ED=99=94=20=EC=9D=B8=EC=A6=9D=20Tag=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../moim_today/presentation/auth/AuthControllerTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/src/test/java/moim_today/presentation/auth/AuthControllerTest.java b/backend/src/test/java/moim_today/presentation/auth/AuthControllerTest.java index 1ce1d9a6..c560882b 100644 --- a/backend/src/test/java/moim_today/presentation/auth/AuthControllerTest.java +++ b/backend/src/test/java/moim_today/presentation/auth/AuthControllerTest.java @@ -67,7 +67,7 @@ void loginTestFail() throws Exception { .andExpect(status().isNotFound()) .andDo(document("로그인 실패", resource(ResourceSnippetParameters.builder() - .tag("로그인") + .tag("인증") .summary("로그인") .requestFields( fieldWithPath("email").type(STRING).description("이메일"), @@ -89,7 +89,7 @@ void logoutTest() throws Exception { .andExpect(status().isOk()) .andDo(document("로그아웃 성공", resource(ResourceSnippetParameters.builder() - .tag("로그아웃") + .tag("인증") .summary("로그아웃") .build() ) @@ -119,7 +119,7 @@ void registerTest() throws Exception { .andExpect(status().isOk()) .andDo(document("회원가입 성공", resource(ResourceSnippetParameters.builder() - .tag("회원") + .tag("인증") .summary("회원가입") .requestFields( fieldWithPath("email").type(STRING).description("학교 이메일"), From 89295ce15d31445a9cd5fefa82c91d1c1a4bc670 Mon Sep 17 00:00:00 2001 From: Jung-YouHwan Date: Mon, 29 Apr 2024 14:21:17 +0900 Subject: [PATCH 34/52] =?UTF-8?q?[BE]=20feat=20:=20=EC=BA=98=EB=A6=B0?= =?UTF-8?q?=EB=8D=94=20=EC=8A=A4=EC=BC=80=EC=A4=84=20=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/schedule/ScheduleService.java | 6 ++++ .../schedule/ScheduleServiceImpl.java | 19 +++++++---- .../dto/schedule/ScheduleResponse.java | 22 +++++++++++++ .../implement/schedule/ScheduleFinder.java | 33 +++++++++++++++++++ .../schedule/ScheduleRepository.java | 6 ++++ .../schedule/ScheduleRepositoryImpl.java | 25 ++++++++++++++ .../schedule/ScheduleController.java | 16 ++++++--- .../schedule/FakeScheduleService.java | 8 +++++ 8 files changed, 125 insertions(+), 10 deletions(-) create mode 100644 backend/src/main/java/moim_today/dto/schedule/ScheduleResponse.java create mode 100644 backend/src/main/java/moim_today/implement/schedule/ScheduleFinder.java diff --git a/backend/src/main/java/moim_today/application/schedule/ScheduleService.java b/backend/src/main/java/moim_today/application/schedule/ScheduleService.java index 219d10c8..3d42529b 100644 --- a/backend/src/main/java/moim_today/application/schedule/ScheduleService.java +++ b/backend/src/main/java/moim_today/application/schedule/ScheduleService.java @@ -1,12 +1,18 @@ package moim_today.application.schedule; import moim_today.dto.schedule.ScheduleCreateRequest; +import moim_today.dto.schedule.ScheduleResponse; import moim_today.dto.schedule.ScheduleUpdateRequest; import moim_today.dto.schedule.TimeTableRequest; +import java.time.YearMonth; +import java.util.List; + public interface ScheduleService { + List findAllByMonthly(final long memberId, final YearMonth yearMonth); + void fetchTimeTable(final long memberId, final TimeTableRequest timeTableRequest); void createSchedule(final long memberId, final ScheduleCreateRequest scheduleCreateRequest); diff --git a/backend/src/main/java/moim_today/application/schedule/ScheduleServiceImpl.java b/backend/src/main/java/moim_today/application/schedule/ScheduleServiceImpl.java index ca02c0f0..af90d25e 100644 --- a/backend/src/main/java/moim_today/application/schedule/ScheduleServiceImpl.java +++ b/backend/src/main/java/moim_today/application/schedule/ScheduleServiceImpl.java @@ -2,33 +2,40 @@ import moim_today.domain.schedule.Schedule; import moim_today.dto.schedule.ScheduleCreateRequest; +import moim_today.dto.schedule.ScheduleResponse; import moim_today.dto.schedule.ScheduleUpdateRequest; import moim_today.dto.schedule.TimeTableRequest; -import moim_today.implement.schedule.ScheduleAppender; -import moim_today.implement.schedule.ScheduleDeleter; -import moim_today.implement.schedule.ScheduleManager; -import moim_today.implement.schedule.ScheduleUpdater; +import moim_today.implement.schedule.*; import moim_today.persistence.entity.schedule.ScheduleJpaEntity; import org.springframework.stereotype.Service; +import java.time.YearMonth; import java.util.List; @Service public class ScheduleServiceImpl implements ScheduleService { private final ScheduleManager scheduleManager; + private final ScheduleFinder scheduleFinder; private final ScheduleAppender scheduleAppender; private final ScheduleUpdater scheduleUpdater; private final ScheduleDeleter scheduleDeleter; - public ScheduleServiceImpl(final ScheduleManager scheduleManager, final ScheduleAppender scheduleAppender, - final ScheduleUpdater scheduleUpdater, final ScheduleDeleter scheduleDeleter) { + public ScheduleServiceImpl(final ScheduleManager scheduleManager, final ScheduleFinder scheduleFinder, + final ScheduleAppender scheduleAppender, final ScheduleUpdater scheduleUpdater, + final ScheduleDeleter scheduleDeleter) { this.scheduleManager = scheduleManager; + this.scheduleFinder = scheduleFinder; this.scheduleAppender = scheduleAppender; this.scheduleUpdater = scheduleUpdater; this.scheduleDeleter = scheduleDeleter; } + @Override + public List findAllByMonthly(final long memberId, final YearMonth yearMonth) { + return scheduleFinder.findAllByMonthly(memberId, yearMonth); + } + @Override public void fetchTimeTable(final long memberId, final TimeTableRequest timeTableRequest) { String timeTableXML = scheduleManager.fetchTimetable(timeTableRequest.everytimeId()); diff --git a/backend/src/main/java/moim_today/dto/schedule/ScheduleResponse.java b/backend/src/main/java/moim_today/dto/schedule/ScheduleResponse.java new file mode 100644 index 00000000..49143ec5 --- /dev/null +++ b/backend/src/main/java/moim_today/dto/schedule/ScheduleResponse.java @@ -0,0 +1,22 @@ +package moim_today.dto.schedule; + +import com.querydsl.core.annotations.QueryProjection; +import lombok.Builder; + +import java.time.DayOfWeek; +import java.time.LocalDateTime; + +@Builder +public record ScheduleResponse( + long scheduleId, + long meetingId, + String scheduleName, + DayOfWeek dayOfWeek, + LocalDateTime startDateTime, + LocalDateTime endDateTime +) { + + @QueryProjection + public ScheduleResponse { + } +} diff --git a/backend/src/main/java/moim_today/implement/schedule/ScheduleFinder.java b/backend/src/main/java/moim_today/implement/schedule/ScheduleFinder.java new file mode 100644 index 00000000..502ef794 --- /dev/null +++ b/backend/src/main/java/moim_today/implement/schedule/ScheduleFinder.java @@ -0,0 +1,33 @@ +package moim_today.implement.schedule; + +import moim_today.dto.schedule.ScheduleResponse; +import moim_today.global.annotation.Implement; +import moim_today.persistence.repository.schedule.ScheduleRepository; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.time.YearMonth; +import java.util.List; + +@Implement +public class ScheduleFinder { + + private final ScheduleRepository scheduleRepository; + + public ScheduleFinder(final ScheduleRepository scheduleRepository) { + this.scheduleRepository = scheduleRepository; + } + + @Transactional(readOnly = true) + public List findAllByMonthly(final long memberId, final YearMonth yearMonth) { + // 1일 자정 + LocalDateTime startDateTime = + yearMonth.atDay(1).atStartOfDay(); + + // 다음달 1일 자정전 + LocalDateTime endDateTime = + yearMonth.atEndOfMonth().atTime(23, 59, 59, 999999999); + + return scheduleRepository.findAllByMonthly(memberId, startDateTime, endDateTime); + } +} diff --git a/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepository.java b/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepository.java index dc95862a..bd52214d 100644 --- a/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepository.java +++ b/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepository.java @@ -1,14 +1,20 @@ package moim_today.persistence.repository.schedule; +import moim_today.dto.schedule.ScheduleResponse; import moim_today.dto.schedule.ScheduleUpdateRequest; import moim_today.dto.schedule.TimeTableSchedulingTask; import moim_today.persistence.entity.schedule.ScheduleJpaEntity; +import java.time.LocalDateTime; +import java.util.List; + public interface ScheduleRepository { ScheduleJpaEntity getById(final long scheduleId); + List findAllByMonthly(final long memberId, final LocalDateTime startDateTime, final LocalDateTime endDateTime); + void save(final ScheduleJpaEntity scheduleJpaEntity); void batchUpdate(final TimeTableSchedulingTask timeTableSchedulingTask); diff --git a/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepositoryImpl.java b/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepositoryImpl.java index 1a08cf3b..f2439ade 100644 --- a/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepositoryImpl.java +++ b/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepositoryImpl.java @@ -2,6 +2,8 @@ import com.querydsl.jpa.impl.JPAQueryFactory; import moim_today.domain.schedule.Schedule; +import moim_today.dto.schedule.QScheduleResponse; +import moim_today.dto.schedule.ScheduleResponse; import moim_today.dto.schedule.ScheduleUpdateRequest; import moim_today.dto.schedule.TimeTableSchedulingTask; import moim_today.global.error.NotFoundException; @@ -43,6 +45,29 @@ public ScheduleJpaEntity getById(final long scheduleId) { .orElseThrow(() -> new NotFoundException(SCHEDULE_NOT_FOUND.message())); } + @Override + public List findAllByMonthly(final long memberId, final LocalDateTime startDateTime, + final LocalDateTime endDateTime) { + return queryFactory.select( + new QScheduleResponse( + scheduleJpaEntity.id, + scheduleJpaEntity.meetingId, + scheduleJpaEntity.scheduleName, + scheduleJpaEntity.dayOfWeek, + scheduleJpaEntity.startDateTime, + scheduleJpaEntity.endDateTime + )) + .from(scheduleJpaEntity) + .where( + scheduleJpaEntity.memberId.eq(memberId) + .and(scheduleJpaEntity.startDateTime.after(startDateTime)) + .and(scheduleJpaEntity.startDateTime.before(endDateTime)) + .and(scheduleJpaEntity.endDateTime.after(startDateTime)) + .and(scheduleJpaEntity.endDateTime.before(endDateTime)) + ) + .fetch(); + } + @Override public void save(final ScheduleJpaEntity scheduleJpaEntity) { scheduleJpaRepository.save(scheduleJpaEntity); diff --git a/backend/src/main/java/moim_today/presentation/schedule/ScheduleController.java b/backend/src/main/java/moim_today/presentation/schedule/ScheduleController.java index 072de068..c8d44c0d 100644 --- a/backend/src/main/java/moim_today/presentation/schedule/ScheduleController.java +++ b/backend/src/main/java/moim_today/presentation/schedule/ScheduleController.java @@ -2,13 +2,14 @@ import moim_today.application.schedule.ScheduleService; import moim_today.domain.member.MemberSession; -import moim_today.dto.schedule.ScheduleCreateRequest; -import moim_today.dto.schedule.ScheduleDeleteRequest; -import moim_today.dto.schedule.ScheduleUpdateRequest; -import moim_today.dto.schedule.TimeTableRequest; +import moim_today.dto.schedule.*; import moim_today.global.annotation.Login; +import moim_today.global.response.CollectionResponse; import org.springframework.web.bind.annotation.*; +import java.time.YearMonth; +import java.util.List; + @RequestMapping("/api/schedules") @RestController @@ -20,6 +21,13 @@ public ScheduleController(final ScheduleService scheduleService) { this.scheduleService = scheduleService; } + @GetMapping + public CollectionResponse> findAllByMonthly(@Login final MemberSession memberSession, + @RequestParam final YearMonth yearMonth) { + List scheduleResponses = scheduleService.findAllByMonthly(memberSession.id(), yearMonth); + return CollectionResponse.of(scheduleResponses); + } + @PostMapping("/timetable") public void fetchTimeTable(@Login final MemberSession memberSession, @RequestBody final TimeTableRequest timeTableRequest) { diff --git a/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java b/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java index d9e56172..ae4f1a31 100644 --- a/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java +++ b/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java @@ -2,6 +2,7 @@ import moim_today.application.schedule.ScheduleService; import moim_today.dto.schedule.ScheduleCreateRequest; +import moim_today.dto.schedule.ScheduleResponse; import moim_today.dto.schedule.ScheduleUpdateRequest; import moim_today.dto.schedule.TimeTableRequest; import moim_today.global.error.BadRequestException; @@ -9,6 +10,8 @@ import moim_today.global.error.NotFoundException; import java.time.LocalDateTime; +import java.time.YearMonth; +import java.util.List; import static moim_today.global.constant.exception.EveryTimeExceptionConstant.TIME_INPUT_ERROR; import static moim_today.global.constant.exception.ScheduleExceptionConstant.*; @@ -16,6 +19,11 @@ public class FakeScheduleService implements ScheduleService { + @Override + public List findAllByMonthly(final long memberId, final YearMonth yearMonth) { + return List.of(); + } + @Override public void fetchTimeTable(final long memberId, final TimeTableRequest timeTableRequest) { if (!timeTableRequest.everytimeId().equals(EVERY_TIME_ID.value())) { From 758a0067b9b8e0809d15ccb099e0cc1eb40f83fa Mon Sep 17 00:00:00 2001 From: Jung-YouHwan Date: Mon, 29 Apr 2024 15:48:02 +0900 Subject: [PATCH 35/52] =?UTF-8?q?[BE]=20test=20:=20=EC=BA=98=EB=A6=B0?= =?UTF-8?q?=EB=8D=94=20=EC=8A=A4=EC=BC=80=EC=A4=84=20=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/schedule/ScheduleResponse.java | 4 + .../schedule/ScheduleRepositoryImpl.java | 8 +- .../schedule/FakeScheduleService.java | 30 +++- .../schedule/ScheduleAppenderTest.java | 8 +- .../schedule/ScheduleFinderTest.java | 145 ++++++++++++++++++ .../schedule/ScheduleControllerTest.java | 27 ++++ 6 files changed, 213 insertions(+), 9 deletions(-) create mode 100644 backend/src/test/java/moim_today/implement/schedule/ScheduleFinderTest.java diff --git a/backend/src/main/java/moim_today/dto/schedule/ScheduleResponse.java b/backend/src/main/java/moim_today/dto/schedule/ScheduleResponse.java index 49143ec5..8fd2beff 100644 --- a/backend/src/main/java/moim_today/dto/schedule/ScheduleResponse.java +++ b/backend/src/main/java/moim_today/dto/schedule/ScheduleResponse.java @@ -1,5 +1,6 @@ package moim_today.dto.schedule; +import com.fasterxml.jackson.annotation.JsonFormat; import com.querydsl.core.annotations.QueryProjection; import lombok.Builder; @@ -12,7 +13,10 @@ public record ScheduleResponse( long meetingId, String scheduleName, DayOfWeek dayOfWeek, + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul") LocalDateTime startDateTime, + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul") LocalDateTime endDateTime ) { diff --git a/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepositoryImpl.java b/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepositoryImpl.java index f2439ade..a2735b3b 100644 --- a/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepositoryImpl.java +++ b/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepositoryImpl.java @@ -60,10 +60,10 @@ public List findAllByMonthly(final long memberId, final LocalD .from(scheduleJpaEntity) .where( scheduleJpaEntity.memberId.eq(memberId) - .and(scheduleJpaEntity.startDateTime.after(startDateTime)) - .and(scheduleJpaEntity.startDateTime.before(endDateTime)) - .and(scheduleJpaEntity.endDateTime.after(startDateTime)) - .and(scheduleJpaEntity.endDateTime.before(endDateTime)) + .and(scheduleJpaEntity.startDateTime.goe(startDateTime)) + .and(scheduleJpaEntity.startDateTime.loe(endDateTime)) + .and(scheduleJpaEntity.endDateTime.goe(startDateTime)) + .and(scheduleJpaEntity.endDateTime.loe(endDateTime)) ) .fetch(); } diff --git a/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java b/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java index ae4f1a31..1bff64f4 100644 --- a/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java +++ b/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java @@ -9,6 +9,7 @@ import moim_today.global.error.ForbiddenException; import moim_today.global.error.NotFoundException; +import java.time.DayOfWeek; import java.time.LocalDateTime; import java.time.YearMonth; import java.util.List; @@ -21,7 +22,34 @@ public class FakeScheduleService implements ScheduleService { @Override public List findAllByMonthly(final long memberId, final YearMonth yearMonth) { - return List.of(); + ScheduleResponse scheduleResponse1 = ScheduleResponse.builder() + .scheduleId(1L) + .meetingId(0L) + .scheduleName("스케줄명 1") + .dayOfWeek(DayOfWeek.MONDAY) + .startDateTime(LocalDateTime.of(2024, 03, 04, 10, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 03, 04, 12, 0, 0)) + .build(); + + ScheduleResponse scheduleResponse2 = ScheduleResponse.builder() + .scheduleId(2L) + .meetingId(0L) + .scheduleName("스케줄명 2") + .dayOfWeek(DayOfWeek.TUESDAY) + .startDateTime(LocalDateTime.of(2024, 03, 05, 12, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 03, 05, 13, 15, 0)) + .build(); + + ScheduleResponse scheduleResponse3 = ScheduleResponse.builder() + .scheduleId(3L) + .meetingId(1L) + .scheduleName("스케줄명 3") + .dayOfWeek(DayOfWeek.WEDNESDAY) + .startDateTime(LocalDateTime.of(2024, 03, 06, 12, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 03, 06, 13, 15, 0)) + .build(); + + return List.of(scheduleResponse1, scheduleResponse2, scheduleResponse3); } @Override diff --git a/backend/src/test/java/moim_today/implement/schedule/ScheduleAppenderTest.java b/backend/src/test/java/moim_today/implement/schedule/ScheduleAppenderTest.java index 2a7c1dd5..4596ecef 100644 --- a/backend/src/test/java/moim_today/implement/schedule/ScheduleAppenderTest.java +++ b/backend/src/test/java/moim_today/implement/schedule/ScheduleAppenderTest.java @@ -143,8 +143,8 @@ void createScheduleBetweenOtherSchedules() { .build(); ScheduleJpaEntity afterScheduleJpaEntity = ScheduleJpaEntity.builder() - .startDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) - .endDateTime(LocalDateTime.of(2024, 1, 1, 14, 0, 0)) + .startDateTime(LocalDateTime.of(2024, 1, 1, 14, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 16, 0, 0)) .build(); scheduleRepository.save(BeforeScheduleJpaEntity); @@ -152,8 +152,8 @@ void createScheduleBetweenOtherSchedules() { // given 2 ScheduleJpaEntity newScheduleJpaEntity = ScheduleJpaEntity.builder() - .startDateTime(LocalDateTime.of(2024, 1, 1, 14, 0, 0)) - .endDateTime(LocalDateTime.of(2024, 1, 1, 16, 0, 0)) + .startDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 14, 0, 0)) .build(); // then diff --git a/backend/src/test/java/moim_today/implement/schedule/ScheduleFinderTest.java b/backend/src/test/java/moim_today/implement/schedule/ScheduleFinderTest.java new file mode 100644 index 00000000..f4f3a1ae --- /dev/null +++ b/backend/src/test/java/moim_today/implement/schedule/ScheduleFinderTest.java @@ -0,0 +1,145 @@ +package moim_today.implement.schedule; + +import moim_today.dto.schedule.ScheduleResponse; +import moim_today.persistence.entity.schedule.ScheduleJpaEntity; +import moim_today.util.ImplementTest; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.time.LocalDateTime; +import java.time.YearMonth; +import java.util.List; + +import static org.assertj.core.api.Assertions.*; + +class ScheduleFinderTest extends ImplementTest { + + @Autowired + private ScheduleFinder scheduleFinder; + + @DisplayName("다른 회원의 스케줄은 조회되지 않는다.") + @Test + void findAllByMonthlyOnlyMember() { + // given + long memberId = 1L; + long otherMemberId = 9999L; + YearMonth yearMonth = YearMonth.of(2024, 3); + + ScheduleJpaEntity scheduleJpaEntity1 = ScheduleJpaEntity.builder() + .memberId(memberId) + .scheduleName("스케줄명 1") + .startDateTime(LocalDateTime.of(2024, 3, 2, 10, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 3, 2, 12, 0, 0)) + .build(); + + ScheduleJpaEntity scheduleJpaEntity2 = ScheduleJpaEntity.builder() + .memberId(memberId) + .scheduleName("스케줄명 2") + .startDateTime(LocalDateTime.of(2024, 3, 3, 10, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 3, 3, 12, 0, 0)) + .build(); + + ScheduleJpaEntity scheduleJpaEntity3 = ScheduleJpaEntity.builder() + .memberId(otherMemberId) + .scheduleName("스케줄명 3") + .startDateTime(LocalDateTime.of(2024, 3, 4, 0, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 3, 4, 2, 0, 0)) + .build(); + + scheduleRepository.save(scheduleJpaEntity1); + scheduleRepository.save(scheduleJpaEntity2); + scheduleRepository.save(scheduleJpaEntity3); + + // when + List scheduleResponses = scheduleFinder.findAllByMonthly(memberId, yearMonth); + + // then + assertThat(scheduleResponses.size()).isEqualTo(2); + } + + @DisplayName("한 달 스케줄 조회는 당월 1일 자정부터 조회된다.") + @Test + void findAllByMonthlyStartWithMidNight() { + // given + long memberId = 1L; + YearMonth yearMonth = YearMonth.of(2024, 3); + + ScheduleJpaEntity scheduleJpaEntity = ScheduleJpaEntity.builder() + .memberId(memberId) + .scheduleName("스케줄명 1") + .startDateTime(LocalDateTime.of(2024, 3, 1, 0, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 3, 1, 2, 0, 0)) + .build(); + + scheduleRepository.save(scheduleJpaEntity); + + // when + List scheduleResponses = scheduleFinder.findAllByMonthly(memberId, yearMonth); + + // then + assertThat(scheduleResponses.size()).isEqualTo(1); + } + + @DisplayName("한 달 스케줄 조회는 다음달 1일 자정전까지 조회된다.") + @Test + void findAllByMonthlyUntilNextMonthMidNight() { + // given + long memberId = 1L; + YearMonth yearMonth = YearMonth.of(2024, 3); + + ScheduleJpaEntity scheduleJpaEntity = ScheduleJpaEntity.builder() + .memberId(memberId) + .scheduleName("스케줄명 1") + .startDateTime(LocalDateTime.of(2024, 4, 1, 0, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 4, 1, 2, 0, 0)) + .build(); + + scheduleRepository.save(scheduleJpaEntity); + + // when + List scheduleResponses = scheduleFinder.findAllByMonthly(memberId, yearMonth); + + // then + assertThat(scheduleResponses.size()).isEqualTo(0); + } + + @DisplayName("캘린더에 나타낼 한 달 스케줄을 조회한다.") + @Test + void findAllByMonthly() { + // given + long memberId = 1L; + YearMonth yearMonth = YearMonth.of(2024, 3); + + ScheduleJpaEntity scheduleJpaEntity1 = ScheduleJpaEntity.builder() + .memberId(memberId) + .scheduleName("스케줄명 1") + .startDateTime(LocalDateTime.of(2024, 3, 1, 0, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 3, 1, 2, 0, 0)) + .build(); + + ScheduleJpaEntity scheduleJpaEntity2 = ScheduleJpaEntity.builder() + .memberId(memberId) + .scheduleName("스케줄명 2") + .startDateTime(LocalDateTime.of(2024, 3, 15, 10, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 3, 15, 12, 0, 0)) + .build(); + + ScheduleJpaEntity scheduleJpaEntity3 = ScheduleJpaEntity.builder() + .memberId(memberId) + .scheduleName("스케줄명 3") + .startDateTime(LocalDateTime.of(2024, 3, 31, 23, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 3, 31, 23, 59, 29)) + .build(); + + scheduleRepository.save(scheduleJpaEntity1); + scheduleRepository.save(scheduleJpaEntity2); + scheduleRepository.save(scheduleJpaEntity3); + + // when + List scheduleResponses = scheduleFinder.findAllByMonthly(memberId, yearMonth); + + // then + assertThat(scheduleResponses.size()).isEqualTo(3); + } +} \ No newline at end of file diff --git a/backend/src/test/java/moim_today/presentation/schedule/ScheduleControllerTest.java b/backend/src/test/java/moim_today/presentation/schedule/ScheduleControllerTest.java index 36ba1169..b4017c6d 100644 --- a/backend/src/test/java/moim_today/presentation/schedule/ScheduleControllerTest.java +++ b/backend/src/test/java/moim_today/presentation/schedule/ScheduleControllerTest.java @@ -16,6 +16,7 @@ import java.time.LocalDateTime; import static com.epages.restdocs.apispec.MockMvcRestDocumentationWrapper.document; +import static com.epages.restdocs.apispec.ResourceDocumentation.parameterWithName; import static com.epages.restdocs.apispec.ResourceDocumentation.resource; import static moim_today.util.TestConstant.*; import static moim_today.util.TestConstant.EVERY_TIME_ID; @@ -36,6 +37,32 @@ protected Object initController() { return new ScheduleController(scheduleService); } + @DisplayName("캘린더에 나타낼 한 달 스케줄을 조회한다.") + @Test + void findAllByMonthly() throws Exception { + mockMvc.perform(get("/api/schedules") + .param("yearMonth", "2024-03") + ) + .andExpect(status().isOk()) + .andDo(document("캘린더에 나타낼 한 달 스케줄 조회", + resource(ResourceSnippetParameters.builder() + .tag("스케줄") + .summary("스케줄 조회") + .queryParameters( + parameterWithName("yearMonth").description("연도 - 월 정보, ex) 2024-03") + ) + .responseFields( + fieldWithPath("data[0].scheduleId").type(NUMBER).description("스케줄 id"), + fieldWithPath("data[0].meetingId").type(NUMBER).description("미팅 id"), + fieldWithPath("data[0].scheduleName").type(STRING).description("스케줄명"), + fieldWithPath("data[0].dayOfWeek").type(STRING).description("요일"), + fieldWithPath("data[0].startDateTime").type(STRING).description("시작 시간"), + fieldWithPath("data[0].endDateTime").type(STRING).description("종료 시간") + ) + .build() + ))); + } + @DisplayName("요청 URL로 시간표 정보를 스케줄로 등록한다.") @Test void fetchTimeTable() throws Exception { From b67eba0d3e9826dea2c5d21fab98e706eae48a7f Mon Sep 17 00:00:00 2001 From: Jung-YouHwan Date: Mon, 29 Apr 2024 16:07:28 +0900 Subject: [PATCH 36/52] =?UTF-8?q?[BE]=20feat=20:=20=EC=8B=9C=EA=B0=84?= =?UTF-8?q?=ED=91=9C=20=EB=93=B1=EB=A1=9D=20=EC=8A=A4=EC=BC=80=EC=A4=84=20?= =?UTF-8?q?=EC=A4=91=EB=B3=B5=20=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../moim_today/domain/schedule/Schedule.java | 5 ++ .../implement/schedule/ScheduleAppender.java | 5 ++ .../schedule/ScheduleJpaRepository.java | 4 ++ .../schedule/ScheduleRepository.java | 2 + .../schedule/ScheduleRepositoryImpl.java | 5 ++ .../schedule/ScheduleAppenderTest.java | 49 ++++++++++++++++++- 6 files changed, 68 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/moim_today/domain/schedule/Schedule.java b/backend/src/main/java/moim_today/domain/schedule/Schedule.java index 7f710d08..3b939695 100644 --- a/backend/src/main/java/moim_today/domain/schedule/Schedule.java +++ b/backend/src/main/java/moim_today/domain/schedule/Schedule.java @@ -36,4 +36,9 @@ public ScheduleJpaEntity toEntity(final long memberId, final long meetingId) { .endDateTime(endDateTime) .build(); } + + public boolean isExist(final ScheduleJpaEntity scheduleJpaEntity) { + return startDateTime.isAfter(scheduleJpaEntity.getEndDateTime()) && + endDateTime.isBefore(scheduleJpaEntity.getStartDateTime()); + } } diff --git a/backend/src/main/java/moim_today/implement/schedule/ScheduleAppender.java b/backend/src/main/java/moim_today/implement/schedule/ScheduleAppender.java index b0f9358b..c4d0a875 100644 --- a/backend/src/main/java/moim_today/implement/schedule/ScheduleAppender.java +++ b/backend/src/main/java/moim_today/implement/schedule/ScheduleAppender.java @@ -24,6 +24,11 @@ public ScheduleAppender(final ScheduleRepository scheduleRepository) { @Transactional public void batchUpdateSchedules(final List schedules, final long memberId) { + List scheduleJpaEntities = scheduleRepository.findAllByMemberId(memberId); + for (ScheduleJpaEntity scheduleJpaEntity : scheduleJpaEntities) { + schedules.removeIf(schedule -> schedule.isExist(scheduleJpaEntity)); + } + TimeTableSchedulingTask timeTableSchedulingTask = TimeTableSchedulingTask.of(schedules, memberId); scheduleRepository.batchUpdate(timeTableSchedulingTask); } diff --git a/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleJpaRepository.java b/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleJpaRepository.java index 1eea730f..f9cde4f5 100644 --- a/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleJpaRepository.java +++ b/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleJpaRepository.java @@ -3,5 +3,9 @@ import moim_today.persistence.entity.schedule.ScheduleJpaEntity; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.List; + public interface ScheduleJpaRepository extends JpaRepository { + + List findAllByMemberId(final long memberId); } diff --git a/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepository.java b/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepository.java index bd52214d..1e064cdb 100644 --- a/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepository.java +++ b/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepository.java @@ -13,6 +13,8 @@ public interface ScheduleRepository { ScheduleJpaEntity getById(final long scheduleId); + List findAllByMemberId(final long memberId); + List findAllByMonthly(final long memberId, final LocalDateTime startDateTime, final LocalDateTime endDateTime); void save(final ScheduleJpaEntity scheduleJpaEntity); diff --git a/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepositoryImpl.java b/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepositoryImpl.java index a2735b3b..244d3609 100644 --- a/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepositoryImpl.java +++ b/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepositoryImpl.java @@ -45,6 +45,11 @@ public ScheduleJpaEntity getById(final long scheduleId) { .orElseThrow(() -> new NotFoundException(SCHEDULE_NOT_FOUND.message())); } + @Override + public List findAllByMemberId(final long memberId) { + return scheduleJpaRepository.findAllByMemberId(memberId); + } + @Override public List findAllByMonthly(final long memberId, final LocalDateTime startDateTime, final LocalDateTime endDateTime) { diff --git a/backend/src/test/java/moim_today/implement/schedule/ScheduleAppenderTest.java b/backend/src/test/java/moim_today/implement/schedule/ScheduleAppenderTest.java index 4596ecef..8103d6bb 100644 --- a/backend/src/test/java/moim_today/implement/schedule/ScheduleAppenderTest.java +++ b/backend/src/test/java/moim_today/implement/schedule/ScheduleAppenderTest.java @@ -35,19 +35,64 @@ void batchUpdateSchedules() { Schedule schedule2 = Schedule.builder() .scheduleName("스케줄 2") .dayOfWeek(DayOfWeek.THURSDAY) - .startDateTime(LocalDateTime.of(2024, 1, 1, 10, 0, 0)) - .endDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) + .startDateTime(LocalDateTime.of(2024, 1, 2, 10, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 2, 12, 0, 0)) .build(); Schedule schedule3 = Schedule.builder() .scheduleName("스케줄 3") .dayOfWeek(DayOfWeek.WEDNESDAY) + .startDateTime(LocalDateTime.of(2024, 1, 3, 10, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 3, 12, 0, 0)) + .build(); + + long memberId = 1L; + + // given 2 + List schedules = List.of(schedule1, schedule2, schedule3); + + // when + scheduleAppender.batchUpdateSchedules(schedules, memberId); + + // then + assertThat(scheduleRepository.count()).isEqualTo(3); + } + + @DisplayName("시간표 정보로 스케줄 정보를 저장할 때 이미 해당 시간에 스케줄이 존재하면 새롭게 저장하지 않는다.") + @Test + void batchUpdateSchedulesAlreadyExist() { + // given 1 + Schedule schedule1 = Schedule.builder() + .scheduleName("스케줄 1") + .dayOfWeek(DayOfWeek.MONDAY) .startDateTime(LocalDateTime.of(2024, 1, 1, 10, 0, 0)) .endDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) .build(); + Schedule schedule2 = Schedule.builder() + .scheduleName("스케줄 2") + .dayOfWeek(DayOfWeek.THURSDAY) + .startDateTime(LocalDateTime.of(2024, 1, 2, 10, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 2, 12, 0, 0)) + .build(); + + Schedule schedule3 = Schedule.builder() + .scheduleName("스케줄 3") + .dayOfWeek(DayOfWeek.WEDNESDAY) + .startDateTime(LocalDateTime.of(2024, 1, 3, 10, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 3, 12, 0, 0)) + .build(); + long memberId = 1L; + // given 2 + ScheduleJpaEntity scheduleJpaEntity = ScheduleJpaEntity.builder() + .startDateTime(LocalDateTime.of(2024, 1, 1, 11, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) + .build(); + + scheduleRepository.save(scheduleJpaEntity); + // given 2 List schedules = List.of(schedule1, schedule2, schedule3); From d608b1968d6e49bc9121710ccfead872fba15331 Mon Sep 17 00:00:00 2001 From: Jung-YouHwan Date: Mon, 29 Apr 2024 16:49:28 +0900 Subject: [PATCH 37/52] =?UTF-8?q?[BE]=20test=20:=20=EC=8B=9C=EA=B0=84?= =?UTF-8?q?=ED=91=9C=20=EB=93=B1=EB=A1=9D=20=EC=8A=A4=EC=BC=80=EC=A4=84=20?= =?UTF-8?q?=EC=A4=91=EB=B3=B5=20=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../moim_today/domain/schedule/Schedule.java | 4 +- .../domain/schedule/ScheduleTest.java | 97 +++++++++++++++++++ .../schedule/ScheduleAppenderTest.java | 34 ++++--- 3 files changed, 120 insertions(+), 15 deletions(-) create mode 100644 backend/src/test/java/moim_today/domain/schedule/ScheduleTest.java diff --git a/backend/src/main/java/moim_today/domain/schedule/Schedule.java b/backend/src/main/java/moim_today/domain/schedule/Schedule.java index 3b939695..f8bec472 100644 --- a/backend/src/main/java/moim_today/domain/schedule/Schedule.java +++ b/backend/src/main/java/moim_today/domain/schedule/Schedule.java @@ -38,7 +38,7 @@ public ScheduleJpaEntity toEntity(final long memberId, final long meetingId) { } public boolean isExist(final ScheduleJpaEntity scheduleJpaEntity) { - return startDateTime.isAfter(scheduleJpaEntity.getEndDateTime()) && - endDateTime.isBefore(scheduleJpaEntity.getStartDateTime()); + return scheduleJpaEntity.getEndDateTime().isAfter(startDateTime) && + scheduleJpaEntity.getStartDateTime().isBefore(endDateTime); } } diff --git a/backend/src/test/java/moim_today/domain/schedule/ScheduleTest.java b/backend/src/test/java/moim_today/domain/schedule/ScheduleTest.java new file mode 100644 index 00000000..3a96f312 --- /dev/null +++ b/backend/src/test/java/moim_today/domain/schedule/ScheduleTest.java @@ -0,0 +1,97 @@ +package moim_today.domain.schedule; + +import moim_today.persistence.entity.schedule.ScheduleJpaEntity; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.time.LocalDateTime; + +import static org.assertj.core.api.Assertions.*; + + +class ScheduleTest { + + @DisplayName("새롭게 등록하는 스케줄 시작시간과 겹치는 스케줄이 있으면 true를 반환한다.") + @Test + void beforeScheduleAlreadyExist() { + // given + Schedule schedule = Schedule.builder() + .startDateTime(LocalDateTime.of(2024, 1, 1, 10, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) + .build(); + + ScheduleJpaEntity beforeScheduleJpaEntity = ScheduleJpaEntity.builder() + .startDateTime(LocalDateTime.of(2024, 1, 1, 8, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 10, 0, 1)) + .build(); + + // when + boolean exist = schedule.isExist(beforeScheduleJpaEntity); + + // then + assertThat(exist).isTrue(); + } + + @DisplayName("새롭게 등록하는 스케줄 시작시간과 겹치지 않으면 false를 반환한다.") + @Test + void beforeScheduleNotExist() { + // given + Schedule schedule = Schedule.builder() + .startDateTime(LocalDateTime.of(2024, 1, 1, 10, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) + .build(); + + ScheduleJpaEntity beforeScheduleJpaEntity = ScheduleJpaEntity.builder() + .startDateTime(LocalDateTime.of(2024, 1, 1, 8, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 10, 0, 0)) + .build(); + + // when + boolean exist = schedule.isExist(beforeScheduleJpaEntity); + + // then + assertThat(exist).isFalse(); + } + + @DisplayName("새롭게 등록하는 스케줄 시작시간과 겹치는 스케줄이 있으면 true를 반환한다.") + @Test + void afterScheduleAlreadyExist() { + // given + Schedule schedule = Schedule.builder() + .startDateTime(LocalDateTime.of(2024, 1, 1, 10, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) + .build(); + + ScheduleJpaEntity afterScheduleJpaEntity = ScheduleJpaEntity.builder() + .startDateTime(LocalDateTime.of(2024, 1, 1, 11, 59, 59)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 14, 0, 0)) + .build(); + + // when + boolean exist = schedule.isExist(afterScheduleJpaEntity); + + // then + assertThat(exist).isTrue(); + } + + @DisplayName("새롭게 등록하는 스케줄 시작시간과 겹치지 않으면 false를 반환한다.") + @Test + void afterScheduleNotExist() { + // given + Schedule schedule = Schedule.builder() + .startDateTime(LocalDateTime.of(2024, 1, 1, 10, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) + .build(); + + ScheduleJpaEntity afterScheduleJpaEntity = ScheduleJpaEntity.builder() + .startDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 14, 0, 0)) + .build(); + + // when + boolean exist = schedule.isExist(afterScheduleJpaEntity); + + // then + assertThat(exist).isFalse(); + } +} \ No newline at end of file diff --git a/backend/src/test/java/moim_today/implement/schedule/ScheduleAppenderTest.java b/backend/src/test/java/moim_today/implement/schedule/ScheduleAppenderTest.java index 8103d6bb..b0cf5ba4 100644 --- a/backend/src/test/java/moim_today/implement/schedule/ScheduleAppenderTest.java +++ b/backend/src/test/java/moim_today/implement/schedule/ScheduleAppenderTest.java @@ -10,6 +10,7 @@ import java.time.DayOfWeek; import java.time.LocalDateTime; +import java.util.ArrayList; import java.util.List; import static moim_today.global.constant.exception.ScheduleExceptionConstant.*; @@ -49,7 +50,10 @@ void batchUpdateSchedules() { long memberId = 1L; // given 2 - List schedules = List.of(schedule1, schedule2, schedule3); + List schedules = new ArrayList<>(); + schedules.add(schedule1); + schedules.add(schedule2); + schedules.add(schedule3); // when scheduleAppender.batchUpdateSchedules(schedules, memberId); @@ -62,6 +66,17 @@ void batchUpdateSchedules() { @Test void batchUpdateSchedulesAlreadyExist() { // given 1 + long memberId = 1L; + + ScheduleJpaEntity scheduleJpaEntity = ScheduleJpaEntity.builder() + .memberId(memberId) + .startDateTime(LocalDateTime.of(2024, 1, 1, 11, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) + .build(); + + scheduleRepository.save(scheduleJpaEntity); + + // given 2 Schedule schedule1 = Schedule.builder() .scheduleName("스케줄 1") .dayOfWeek(DayOfWeek.MONDAY) @@ -83,18 +98,11 @@ void batchUpdateSchedulesAlreadyExist() { .endDateTime(LocalDateTime.of(2024, 1, 3, 12, 0, 0)) .build(); - long memberId = 1L; - - // given 2 - ScheduleJpaEntity scheduleJpaEntity = ScheduleJpaEntity.builder() - .startDateTime(LocalDateTime.of(2024, 1, 1, 11, 0, 0)) - .endDateTime(LocalDateTime.of(2024, 1, 1, 12, 0, 0)) - .build(); - - scheduleRepository.save(scheduleJpaEntity); - - // given 2 - List schedules = List.of(schedule1, schedule2, schedule3); + // given 3 + List schedules = new ArrayList<>(); + schedules.add(schedule1); + schedules.add(schedule2); + schedules.add(schedule3); // when scheduleAppender.batchUpdateSchedules(schedules, memberId); From d3de165232efc429773fc97668c43d3384fc2015 Mon Sep 17 00:00:00 2001 From: Jung-YouHwan Date: Mon, 29 Apr 2024 17:35:35 +0900 Subject: [PATCH 38/52] =?UTF-8?q?[BE]=20feat=20:=20weekly=20=EC=BA=98?= =?UTF-8?q?=EB=A6=B0=EB=8D=94=20=EC=8A=A4=EC=BC=80=EC=A4=84=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/schedule/ScheduleService.java | 3 +++ .../schedule/ScheduleServiceImpl.java | 6 +++++ .../global/constant/TimeConstant.java | 1 + .../implement/schedule/ScheduleFinder.java | 19 +++++++++++++++- .../schedule/ScheduleRepository.java | 2 +- .../schedule/ScheduleRepositoryImpl.java | 4 ++-- .../schedule/ScheduleController.java | 22 +++++++++++++------ .../schedule/FakeScheduleService.java | 9 +++++--- .../schedule/ScheduleControllerTest.java | 2 +- 9 files changed, 53 insertions(+), 15 deletions(-) diff --git a/backend/src/main/java/moim_today/application/schedule/ScheduleService.java b/backend/src/main/java/moim_today/application/schedule/ScheduleService.java index 3d42529b..53aa6338 100644 --- a/backend/src/main/java/moim_today/application/schedule/ScheduleService.java +++ b/backend/src/main/java/moim_today/application/schedule/ScheduleService.java @@ -5,12 +5,15 @@ import moim_today.dto.schedule.ScheduleUpdateRequest; import moim_today.dto.schedule.TimeTableRequest; +import java.time.LocalDate; import java.time.YearMonth; import java.util.List; public interface ScheduleService { + List findAllByWeekly(final long memberId, final LocalDate startDate); + List findAllByMonthly(final long memberId, final YearMonth yearMonth); void fetchTimeTable(final long memberId, final TimeTableRequest timeTableRequest); diff --git a/backend/src/main/java/moim_today/application/schedule/ScheduleServiceImpl.java b/backend/src/main/java/moim_today/application/schedule/ScheduleServiceImpl.java index af90d25e..25f181da 100644 --- a/backend/src/main/java/moim_today/application/schedule/ScheduleServiceImpl.java +++ b/backend/src/main/java/moim_today/application/schedule/ScheduleServiceImpl.java @@ -9,6 +9,7 @@ import moim_today.persistence.entity.schedule.ScheduleJpaEntity; import org.springframework.stereotype.Service; +import java.time.LocalDate; import java.time.YearMonth; import java.util.List; @@ -31,6 +32,11 @@ public ScheduleServiceImpl(final ScheduleManager scheduleManager, final Schedule this.scheduleDeleter = scheduleDeleter; } + @Override + public List findAllByWeekly(final long memberId, final LocalDate startDate) { + return scheduleFinder.findAllByWeekly(memberId, startDate); + } + @Override public List findAllByMonthly(final long memberId, final YearMonth yearMonth) { return scheduleFinder.findAllByMonthly(memberId, yearMonth); diff --git a/backend/src/main/java/moim_today/global/constant/TimeConstant.java b/backend/src/main/java/moim_today/global/constant/TimeConstant.java index faa80bcc..da0eedc7 100644 --- a/backend/src/main/java/moim_today/global/constant/TimeConstant.java +++ b/backend/src/main/java/moim_today/global/constant/TimeConstant.java @@ -4,6 +4,7 @@ public enum TimeConstant { TEN_MINUTES(10), ONE_WEEK(1), + SIX_DAY(6), DAYS_PER_WEEK(7), WEEK_START_POINT(1), diff --git a/backend/src/main/java/moim_today/implement/schedule/ScheduleFinder.java b/backend/src/main/java/moim_today/implement/schedule/ScheduleFinder.java index 502ef794..b864ac7e 100644 --- a/backend/src/main/java/moim_today/implement/schedule/ScheduleFinder.java +++ b/backend/src/main/java/moim_today/implement/schedule/ScheduleFinder.java @@ -5,10 +5,13 @@ import moim_today.persistence.repository.schedule.ScheduleRepository; import org.springframework.transaction.annotation.Transactional; +import java.time.LocalDate; import java.time.LocalDateTime; import java.time.YearMonth; import java.util.List; +import static moim_today.global.constant.TimeConstant.SIX_DAY; + @Implement public class ScheduleFinder { @@ -18,6 +21,20 @@ public ScheduleFinder(final ScheduleRepository scheduleRepository) { this.scheduleRepository = scheduleRepository; } + @Transactional(readOnly = true) + public List findAllByWeekly(final long memberId, final LocalDate startDate) { + // 시작 날짜의 자정 + LocalDateTime startDateTime = startDate.atStartOfDay(); + + // 시작 날짜로부터 7일 후의 자정 전 + LocalDateTime endDateTime + = startDate.plusDays(SIX_DAY.time()) + .atTime(23, 59, 59, 999999999); + + return scheduleRepository.findAllByDateTime(memberId, startDateTime, endDateTime); + } + + @Transactional(readOnly = true) public List findAllByMonthly(final long memberId, final YearMonth yearMonth) { // 1일 자정 @@ -28,6 +45,6 @@ public List findAllByMonthly(final long memberId, final YearMo LocalDateTime endDateTime = yearMonth.atEndOfMonth().atTime(23, 59, 59, 999999999); - return scheduleRepository.findAllByMonthly(memberId, startDateTime, endDateTime); + return scheduleRepository.findAllByDateTime(memberId, startDateTime, endDateTime); } } diff --git a/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepository.java b/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepository.java index 1e064cdb..8af9a497 100644 --- a/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepository.java +++ b/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepository.java @@ -15,7 +15,7 @@ public interface ScheduleRepository { List findAllByMemberId(final long memberId); - List findAllByMonthly(final long memberId, final LocalDateTime startDateTime, final LocalDateTime endDateTime); + List findAllByDateTime(final long memberId, final LocalDateTime startDateTime, final LocalDateTime endDateTime); void save(final ScheduleJpaEntity scheduleJpaEntity); diff --git a/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepositoryImpl.java b/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepositoryImpl.java index 244d3609..5a295069 100644 --- a/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepositoryImpl.java +++ b/backend/src/main/java/moim_today/persistence/repository/schedule/ScheduleRepositoryImpl.java @@ -51,8 +51,8 @@ public List findAllByMemberId(final long memberId) { } @Override - public List findAllByMonthly(final long memberId, final LocalDateTime startDateTime, - final LocalDateTime endDateTime) { + public List findAllByDateTime(final long memberId, final LocalDateTime startDateTime, + final LocalDateTime endDateTime) { return queryFactory.select( new QScheduleResponse( scheduleJpaEntity.id, diff --git a/backend/src/main/java/moim_today/presentation/schedule/ScheduleController.java b/backend/src/main/java/moim_today/presentation/schedule/ScheduleController.java index c8d44c0d..dc72b083 100644 --- a/backend/src/main/java/moim_today/presentation/schedule/ScheduleController.java +++ b/backend/src/main/java/moim_today/presentation/schedule/ScheduleController.java @@ -7,11 +7,12 @@ import moim_today.global.response.CollectionResponse; import org.springframework.web.bind.annotation.*; +import java.time.LocalDate; import java.time.YearMonth; import java.util.List; -@RequestMapping("/api/schedules") +@RequestMapping("/api") @RestController public class ScheduleController { @@ -21,32 +22,39 @@ public ScheduleController(final ScheduleService scheduleService) { this.scheduleService = scheduleService; } - @GetMapping + @GetMapping("/schedules-weekly") + public CollectionResponse> findAllByWeekly(@Login final MemberSession memberSession, + @RequestParam final LocalDate startDate) { + List scheduleResponses = scheduleService.findAllByWeekly(memberSession.id(), startDate); + return CollectionResponse.of(scheduleResponses); + } + + @GetMapping("/schedules-monthly") public CollectionResponse> findAllByMonthly(@Login final MemberSession memberSession, - @RequestParam final YearMonth yearMonth) { + @RequestParam final YearMonth yearMonth) { List scheduleResponses = scheduleService.findAllByMonthly(memberSession.id(), yearMonth); return CollectionResponse.of(scheduleResponses); } - @PostMapping("/timetable") + @PostMapping("/schedules/timetable") public void fetchTimeTable(@Login final MemberSession memberSession, @RequestBody final TimeTableRequest timeTableRequest) { scheduleService.fetchTimeTable(memberSession.id(), timeTableRequest); } - @PostMapping + @PostMapping("/schedules") public void createSchedule(@Login final MemberSession memberSession, @RequestBody final ScheduleCreateRequest scheduleCreateRequest) { scheduleService.createSchedule(memberSession.id(), scheduleCreateRequest); } - @PatchMapping + @PatchMapping("/schedules") public void updateSchedule(@Login final MemberSession memberSession, @RequestBody final ScheduleUpdateRequest scheduleUpdateRequest) { scheduleService.updateSchedule(memberSession.id(), scheduleUpdateRequest); } - @DeleteMapping + @DeleteMapping("/schedules") public void deleteSchedule(@Login final MemberSession memberSession, @RequestBody final ScheduleDeleteRequest scheduleDeleteRequest) { scheduleService.deleteSchedule(memberSession.id(), scheduleDeleteRequest.scheduleId()); diff --git a/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java b/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java index 1bff64f4..49ced537 100644 --- a/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java +++ b/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java @@ -9,9 +9,7 @@ import moim_today.global.error.ForbiddenException; import moim_today.global.error.NotFoundException; -import java.time.DayOfWeek; -import java.time.LocalDateTime; -import java.time.YearMonth; +import java.time.*; import java.util.List; import static moim_today.global.constant.exception.EveryTimeExceptionConstant.TIME_INPUT_ERROR; @@ -20,6 +18,11 @@ public class FakeScheduleService implements ScheduleService { + @Override + public List findAllByWeekly(final long memberId, final LocalDate localDate) { + return List.of(); + } + @Override public List findAllByMonthly(final long memberId, final YearMonth yearMonth) { ScheduleResponse scheduleResponse1 = ScheduleResponse.builder() diff --git a/backend/src/test/java/moim_today/presentation/schedule/ScheduleControllerTest.java b/backend/src/test/java/moim_today/presentation/schedule/ScheduleControllerTest.java index b4017c6d..c31be36a 100644 --- a/backend/src/test/java/moim_today/presentation/schedule/ScheduleControllerTest.java +++ b/backend/src/test/java/moim_today/presentation/schedule/ScheduleControllerTest.java @@ -40,7 +40,7 @@ protected Object initController() { @DisplayName("캘린더에 나타낼 한 달 스케줄을 조회한다.") @Test void findAllByMonthly() throws Exception { - mockMvc.perform(get("/api/schedules") + mockMvc.perform(get("/api/schedules-monthly") .param("yearMonth", "2024-03") ) .andExpect(status().isOk()) From 5e5e4e42ce179a6852583332597bb5627b880088 Mon Sep 17 00:00:00 2001 From: Jung-YouHwan Date: Mon, 29 Apr 2024 19:12:29 +0900 Subject: [PATCH 39/52] =?UTF-8?q?[BE]=20test=20:=20weekly=20=EC=BA=98?= =?UTF-8?q?=EB=A6=B0=EB=8D=94=20=EC=8A=A4=EC=BC=80=EC=A4=84=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../implement/schedule/ScheduleFinder.java | 2 +- .../schedule/FakeScheduleService.java | 29 ++- .../schedule/ScheduleFinderTest.java | 168 +++++++++++++++++- .../schedule/ScheduleControllerTest.java | 32 +++- 4 files changed, 221 insertions(+), 10 deletions(-) diff --git a/backend/src/main/java/moim_today/implement/schedule/ScheduleFinder.java b/backend/src/main/java/moim_today/implement/schedule/ScheduleFinder.java index b864ac7e..1e74eb0d 100644 --- a/backend/src/main/java/moim_today/implement/schedule/ScheduleFinder.java +++ b/backend/src/main/java/moim_today/implement/schedule/ScheduleFinder.java @@ -26,7 +26,7 @@ public List findAllByWeekly(final long memberId, final LocalDa // 시작 날짜의 자정 LocalDateTime startDateTime = startDate.atStartOfDay(); - // 시작 날짜로부터 7일 후의 자정 전 + // 시작 날짜로부터 8일 후의 자정 전 LocalDateTime endDateTime = startDate.plusDays(SIX_DAY.time()) .atTime(23, 59, 59, 999999999); diff --git a/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java b/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java index 49ced537..f84bd3a5 100644 --- a/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java +++ b/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java @@ -20,7 +20,34 @@ public class FakeScheduleService implements ScheduleService { @Override public List findAllByWeekly(final long memberId, final LocalDate localDate) { - return List.of(); + ScheduleResponse scheduleResponse1 = ScheduleResponse.builder() + .scheduleId(1L) + .meetingId(0L) + .scheduleName("스케줄명 1") + .dayOfWeek(DayOfWeek.MONDAY) + .startDateTime(LocalDateTime.of(2024, 03, 04, 10, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 03, 04, 12, 0, 0)) + .build(); + + ScheduleResponse scheduleResponse2 = ScheduleResponse.builder() + .scheduleId(2L) + .meetingId(0L) + .scheduleName("스케줄명 2") + .dayOfWeek(DayOfWeek.TUESDAY) + .startDateTime(LocalDateTime.of(2024, 03, 05, 12, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 03, 05, 13, 15, 0)) + .build(); + + ScheduleResponse scheduleResponse3 = ScheduleResponse.builder() + .scheduleId(3L) + .meetingId(1L) + .scheduleName("스케줄명 3") + .dayOfWeek(DayOfWeek.WEDNESDAY) + .startDateTime(LocalDateTime.of(2024, 03, 06, 12, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 03, 06, 13, 15, 0)) + .build(); + + return List.of(scheduleResponse1, scheduleResponse2, scheduleResponse3); } @Override diff --git a/backend/src/test/java/moim_today/implement/schedule/ScheduleFinderTest.java b/backend/src/test/java/moim_today/implement/schedule/ScheduleFinderTest.java index f4f3a1ae..41ecf7db 100644 --- a/backend/src/test/java/moim_today/implement/schedule/ScheduleFinderTest.java +++ b/backend/src/test/java/moim_today/implement/schedule/ScheduleFinderTest.java @@ -7,6 +7,7 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import java.time.LocalDate; import java.time.LocalDateTime; import java.time.YearMonth; import java.util.List; @@ -18,7 +19,147 @@ class ScheduleFinderTest extends ImplementTest { @Autowired private ScheduleFinder scheduleFinder; - @DisplayName("다른 회원의 스케줄은 조회되지 않는다.") + @DisplayName("다른 회원의 Weekly 스케줄은 조회되지 않는다.") + @Test + void findAllByWeeklyOnlyMember() { + // given + long memberId = 1L; + long otherMemberId = 9999L; + LocalDate startDate = LocalDate.of(2024, 3, 1); + + ScheduleJpaEntity scheduleJpaEntity1 = ScheduleJpaEntity.builder() + .memberId(memberId) + .scheduleName("스케줄명 1") + .startDateTime(LocalDateTime.of(2024, 3, 2, 10, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 3, 2, 12, 0, 0)) + .build(); + + ScheduleJpaEntity scheduleJpaEntity2 = ScheduleJpaEntity.builder() + .memberId(memberId) + .scheduleName("스케줄명 2") + .startDateTime(LocalDateTime.of(2024, 3, 3, 10, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 3, 3, 12, 0, 0)) + .build(); + + ScheduleJpaEntity scheduleJpaEntity3 = ScheduleJpaEntity.builder() + .memberId(otherMemberId) + .scheduleName("스케줄명 3") + .startDateTime(LocalDateTime.of(2024, 3, 4, 0, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 3, 4, 2, 0, 0)) + .build(); + + scheduleRepository.save(scheduleJpaEntity1); + scheduleRepository.save(scheduleJpaEntity2); + scheduleRepository.save(scheduleJpaEntity3); + + // when + List scheduleResponses = scheduleFinder.findAllByWeekly(memberId, startDate); + + // then + assertThat(scheduleResponses.size()).isEqualTo(2); + } + + @DisplayName("Weekly 스케줄 조회는 시작 날짜의 자정부터 조회된다.") + @Test + void findAllByWeeklyStartWithMidNight() { + // given + long memberId = 1L; + LocalDate startDate = LocalDate.of(2024, 3, 1); + + ScheduleJpaEntity beforeScheduleJpaEntity = ScheduleJpaEntity.builder() + .memberId(memberId) + .scheduleName("스케줄명 1") + .startDateTime(LocalDateTime.of(2024, 2, 29, 22, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 2, 29, 23, 59, 59)) + .build(); + + ScheduleJpaEntity scheduleJpaEntity = ScheduleJpaEntity.builder() + .memberId(memberId) + .scheduleName("스케줄명 2") + .startDateTime(LocalDateTime.of(2024, 3, 1, 0, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 3, 1, 2, 0, 0)) + .build(); + + scheduleRepository.save(beforeScheduleJpaEntity); + scheduleRepository.save(scheduleJpaEntity); + + // when + List scheduleResponses = scheduleFinder.findAllByWeekly(memberId, startDate); + + // then + assertThat(scheduleResponses.size()).isEqualTo(1); + } + + @DisplayName("Weekly 스케줄 조회는 시작 날짜의 7일 후 자정전까지 조회된다.") + @Test + void findAllByWeeklyUntilNextMonthMidNight() { + // given + long memberId = 1L; + LocalDate startDate = LocalDate.of(2024, 3, 1); + + ScheduleJpaEntity scheduleJpaEntity = ScheduleJpaEntity.builder() + .memberId(memberId) + .scheduleName("스케줄명 1") + .startDateTime(LocalDateTime.of(2024, 3, 6, 22, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 3, 6, 23, 59, 59)) + .build(); + + ScheduleJpaEntity afterScheduleJpaEntity = ScheduleJpaEntity.builder() + .memberId(memberId) + .scheduleName("스케줄명 2") + .startDateTime(LocalDateTime.of(2024, 3, 7, 0, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 3, 7, 2, 0, 0)) + .build(); + + scheduleRepository.save(scheduleJpaEntity); + + // when + List scheduleResponses = scheduleFinder.findAllByWeekly(memberId, startDate); + + // then + assertThat(scheduleResponses.size()).isEqualTo(1); + } + + @DisplayName("캘린더에 나타낼 Weekly 스케줄을 조회한다.") + @Test + void findAllByWeekly() { + // given + long memberId = 1L; + LocalDate startDate = LocalDate.of(2024, 3, 1); + + ScheduleJpaEntity scheduleJpaEntity1 = ScheduleJpaEntity.builder() + .memberId(memberId) + .scheduleName("스케줄명 1") + .startDateTime(LocalDateTime.of(2024, 3, 1, 0, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 3, 1, 2, 0, 0)) + .build(); + + ScheduleJpaEntity scheduleJpaEntity2 = ScheduleJpaEntity.builder() + .memberId(memberId) + .scheduleName("스케줄명 2") + .startDateTime(LocalDateTime.of(2024, 3, 3, 10, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 3, 3, 12, 0, 0)) + .build(); + + ScheduleJpaEntity scheduleJpaEntity3 = ScheduleJpaEntity.builder() + .memberId(memberId) + .scheduleName("스케줄명 3") + .startDateTime(LocalDateTime.of(2024, 3, 6, 22, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 3, 6, 23, 59, 29)) + .build(); + + scheduleRepository.save(scheduleJpaEntity1); + scheduleRepository.save(scheduleJpaEntity2); + scheduleRepository.save(scheduleJpaEntity3); + + // when + List scheduleResponses = scheduleFinder.findAllByWeekly(memberId, startDate); + + // then + assertThat(scheduleResponses.size()).isEqualTo(3); + } + + @DisplayName("다른 회원의 Monthly 스케줄은 조회되지 않는다.") @Test void findAllByMonthlyOnlyMember() { // given @@ -58,20 +199,28 @@ void findAllByMonthlyOnlyMember() { assertThat(scheduleResponses.size()).isEqualTo(2); } - @DisplayName("한 달 스케줄 조회는 당월 1일 자정부터 조회된다.") + @DisplayName("Monthly 스케줄 조회는 당월 1일 자정부터 조회된다.") @Test void findAllByMonthlyStartWithMidNight() { // given long memberId = 1L; YearMonth yearMonth = YearMonth.of(2024, 3); - ScheduleJpaEntity scheduleJpaEntity = ScheduleJpaEntity.builder() + ScheduleJpaEntity befroeScheduleJpaEntity = ScheduleJpaEntity.builder() .memberId(memberId) .scheduleName("스케줄명 1") + .startDateTime(LocalDateTime.of(2024, 2, 29, 22, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 2, 29, 23, 59, 59)) + .build(); + + ScheduleJpaEntity scheduleJpaEntity = ScheduleJpaEntity.builder() + .memberId(memberId) + .scheduleName("스케줄명 2") .startDateTime(LocalDateTime.of(2024, 3, 1, 0, 0, 0)) .endDateTime(LocalDateTime.of(2024, 3, 1, 2, 0, 0)) .build(); + scheduleRepository.save(befroeScheduleJpaEntity); scheduleRepository.save(scheduleJpaEntity); // when @@ -88,6 +237,13 @@ void findAllByMonthlyUntilNextMonthMidNight() { long memberId = 1L; YearMonth yearMonth = YearMonth.of(2024, 3); + ScheduleJpaEntity afterScheduleJpaEntity = ScheduleJpaEntity.builder() + .memberId(memberId) + .scheduleName("스케줄명 1") + .startDateTime(LocalDateTime.of(2024, 3, 31, 22, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 3, 31, 23, 59, 59)) + .build(); + ScheduleJpaEntity scheduleJpaEntity = ScheduleJpaEntity.builder() .memberId(memberId) .scheduleName("스케줄명 1") @@ -95,16 +251,18 @@ void findAllByMonthlyUntilNextMonthMidNight() { .endDateTime(LocalDateTime.of(2024, 4, 1, 2, 0, 0)) .build(); + + scheduleRepository.save(afterScheduleJpaEntity); scheduleRepository.save(scheduleJpaEntity); // when List scheduleResponses = scheduleFinder.findAllByMonthly(memberId, yearMonth); // then - assertThat(scheduleResponses.size()).isEqualTo(0); + assertThat(scheduleResponses.size()).isEqualTo(1); } - @DisplayName("캘린더에 나타낼 한 달 스케줄을 조회한다.") + @DisplayName("캘린더에 나타낼 Monthly 스케줄을 조회한다.") @Test void findAllByMonthly() { // given diff --git a/backend/src/test/java/moim_today/presentation/schedule/ScheduleControllerTest.java b/backend/src/test/java/moim_today/presentation/schedule/ScheduleControllerTest.java index c31be36a..d3a4f696 100644 --- a/backend/src/test/java/moim_today/presentation/schedule/ScheduleControllerTest.java +++ b/backend/src/test/java/moim_today/presentation/schedule/ScheduleControllerTest.java @@ -37,17 +37,43 @@ protected Object initController() { return new ScheduleController(scheduleService); } - @DisplayName("캘린더에 나타낼 한 달 스케줄을 조회한다.") + @DisplayName("캘린더에 나타낼 Weekly 스케줄을 조회한다.") + @Test + void findAllByWeekly() throws Exception { + mockMvc.perform(get("/api/schedules-weekly") + .param("startDate", "2024-03-04") + ) + .andExpect(status().isOk()) + .andDo(document("캘린더에 나타낼 Weekly 스케줄 조회", + resource(ResourceSnippetParameters.builder() + .tag("스케줄") + .summary("Weekly 스케줄 조회") + .queryParameters( + parameterWithName("startDate").description("연도 - 월 - 일 정보, ex) 2024-03-04") + ) + .responseFields( + fieldWithPath("data[0].scheduleId").type(NUMBER).description("스케줄 id"), + fieldWithPath("data[0].meetingId").type(NUMBER).description("미팅 id"), + fieldWithPath("data[0].scheduleName").type(STRING).description("스케줄명"), + fieldWithPath("data[0].dayOfWeek").type(STRING).description("요일"), + fieldWithPath("data[0].startDateTime").type(STRING).description("시작 시간"), + fieldWithPath("data[0].endDateTime").type(STRING).description("종료 시간") + ) + .build() + ))); + } + + @DisplayName("캘린더에 나타낼 Monthly 스케줄을 조회한다.") @Test void findAllByMonthly() throws Exception { mockMvc.perform(get("/api/schedules-monthly") .param("yearMonth", "2024-03") ) .andExpect(status().isOk()) - .andDo(document("캘린더에 나타낼 한 달 스케줄 조회", + .andDo(document("캘린더에 나타낼 Monthly 스케줄 조회", resource(ResourceSnippetParameters.builder() .tag("스케줄") - .summary("스케줄 조회") + .summary("Monthly 스케줄 조회") .queryParameters( parameterWithName("yearMonth").description("연도 - 월 정보, ex) 2024-03") ) From 6478df2e6cf74e78796ecaf7bf5b88a2833da167 Mon Sep 17 00:00:00 2001 From: Jung-YouHwan Date: Wed, 1 May 2024 09:38:31 +0900 Subject: [PATCH 40/52] =?UTF-8?q?[BE]=20style=20:=20=EC=A3=BC=EC=84=9D/?= =?UTF-8?q?=EB=A9=94=EC=86=8C=EB=93=9C=EB=AA=85/url=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/moim_today/domain/schedule/Schedule.java | 2 +- .../moim_today/implement/schedule/ScheduleAppender.java | 2 +- .../moim_today/implement/schedule/ScheduleFinder.java | 2 +- .../presentation/schedule/ScheduleController.java | 4 ++-- .../java/moim_today/domain/schedule/ScheduleTest.java | 8 ++++---- .../presentation/schedule/ScheduleControllerTest.java | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/backend/src/main/java/moim_today/domain/schedule/Schedule.java b/backend/src/main/java/moim_today/domain/schedule/Schedule.java index f8bec472..8585e3cb 100644 --- a/backend/src/main/java/moim_today/domain/schedule/Schedule.java +++ b/backend/src/main/java/moim_today/domain/schedule/Schedule.java @@ -37,7 +37,7 @@ public ScheduleJpaEntity toEntity(final long memberId, final long meetingId) { .build(); } - public boolean isExist(final ScheduleJpaEntity scheduleJpaEntity) { + public boolean exists(final ScheduleJpaEntity scheduleJpaEntity) { return scheduleJpaEntity.getEndDateTime().isAfter(startDateTime) && scheduleJpaEntity.getStartDateTime().isBefore(endDateTime); } diff --git a/backend/src/main/java/moim_today/implement/schedule/ScheduleAppender.java b/backend/src/main/java/moim_today/implement/schedule/ScheduleAppender.java index c4d0a875..6db1526a 100644 --- a/backend/src/main/java/moim_today/implement/schedule/ScheduleAppender.java +++ b/backend/src/main/java/moim_today/implement/schedule/ScheduleAppender.java @@ -26,7 +26,7 @@ public ScheduleAppender(final ScheduleRepository scheduleRepository) { public void batchUpdateSchedules(final List schedules, final long memberId) { List scheduleJpaEntities = scheduleRepository.findAllByMemberId(memberId); for (ScheduleJpaEntity scheduleJpaEntity : scheduleJpaEntities) { - schedules.removeIf(schedule -> schedule.isExist(scheduleJpaEntity)); + schedules.removeIf(schedule -> schedule.exists(scheduleJpaEntity)); } TimeTableSchedulingTask timeTableSchedulingTask = TimeTableSchedulingTask.of(schedules, memberId); diff --git a/backend/src/main/java/moim_today/implement/schedule/ScheduleFinder.java b/backend/src/main/java/moim_today/implement/schedule/ScheduleFinder.java index 1e74eb0d..b864ac7e 100644 --- a/backend/src/main/java/moim_today/implement/schedule/ScheduleFinder.java +++ b/backend/src/main/java/moim_today/implement/schedule/ScheduleFinder.java @@ -26,7 +26,7 @@ public List findAllByWeekly(final long memberId, final LocalDa // 시작 날짜의 자정 LocalDateTime startDateTime = startDate.atStartOfDay(); - // 시작 날짜로부터 8일 후의 자정 전 + // 시작 날짜로부터 7일 후의 자정 전 LocalDateTime endDateTime = startDate.plusDays(SIX_DAY.time()) .atTime(23, 59, 59, 999999999); diff --git a/backend/src/main/java/moim_today/presentation/schedule/ScheduleController.java b/backend/src/main/java/moim_today/presentation/schedule/ScheduleController.java index dc72b083..65dc4e9b 100644 --- a/backend/src/main/java/moim_today/presentation/schedule/ScheduleController.java +++ b/backend/src/main/java/moim_today/presentation/schedule/ScheduleController.java @@ -22,14 +22,14 @@ public ScheduleController(final ScheduleService scheduleService) { this.scheduleService = scheduleService; } - @GetMapping("/schedules-weekly") + @GetMapping("/schedules/weekly") public CollectionResponse> findAllByWeekly(@Login final MemberSession memberSession, @RequestParam final LocalDate startDate) { List scheduleResponses = scheduleService.findAllByWeekly(memberSession.id(), startDate); return CollectionResponse.of(scheduleResponses); } - @GetMapping("/schedules-monthly") + @GetMapping("/schedules/monthly") public CollectionResponse> findAllByMonthly(@Login final MemberSession memberSession, @RequestParam final YearMonth yearMonth) { List scheduleResponses = scheduleService.findAllByMonthly(memberSession.id(), yearMonth); diff --git a/backend/src/test/java/moim_today/domain/schedule/ScheduleTest.java b/backend/src/test/java/moim_today/domain/schedule/ScheduleTest.java index 3a96f312..5faf0615 100644 --- a/backend/src/test/java/moim_today/domain/schedule/ScheduleTest.java +++ b/backend/src/test/java/moim_today/domain/schedule/ScheduleTest.java @@ -26,7 +26,7 @@ void beforeScheduleAlreadyExist() { .build(); // when - boolean exist = schedule.isExist(beforeScheduleJpaEntity); + boolean exist = schedule.exists(beforeScheduleJpaEntity); // then assertThat(exist).isTrue(); @@ -47,7 +47,7 @@ void beforeScheduleNotExist() { .build(); // when - boolean exist = schedule.isExist(beforeScheduleJpaEntity); + boolean exist = schedule.exists(beforeScheduleJpaEntity); // then assertThat(exist).isFalse(); @@ -68,7 +68,7 @@ void afterScheduleAlreadyExist() { .build(); // when - boolean exist = schedule.isExist(afterScheduleJpaEntity); + boolean exist = schedule.exists(afterScheduleJpaEntity); // then assertThat(exist).isTrue(); @@ -89,7 +89,7 @@ void afterScheduleNotExist() { .build(); // when - boolean exist = schedule.isExist(afterScheduleJpaEntity); + boolean exist = schedule.exists(afterScheduleJpaEntity); // then assertThat(exist).isFalse(); diff --git a/backend/src/test/java/moim_today/presentation/schedule/ScheduleControllerTest.java b/backend/src/test/java/moim_today/presentation/schedule/ScheduleControllerTest.java index d3a4f696..e7ea4260 100644 --- a/backend/src/test/java/moim_today/presentation/schedule/ScheduleControllerTest.java +++ b/backend/src/test/java/moim_today/presentation/schedule/ScheduleControllerTest.java @@ -40,7 +40,7 @@ protected Object initController() { @DisplayName("캘린더에 나타낼 Weekly 스케줄을 조회한다.") @Test void findAllByWeekly() throws Exception { - mockMvc.perform(get("/api/schedules-weekly") + mockMvc.perform(get("/api/schedules/weekly") .param("startDate", "2024-03-04") ) .andExpect(status().isOk()) @@ -66,7 +66,7 @@ void findAllByWeekly() throws Exception { @DisplayName("캘린더에 나타낼 Monthly 스케줄을 조회한다.") @Test void findAllByMonthly() throws Exception { - mockMvc.perform(get("/api/schedules-monthly") + mockMvc.perform(get("/api/schedules/monthly") .param("yearMonth", "2024-03") ) .andExpect(status().isOk()) From c18add821a9f3683b148e22a4b7bbd2ca1706661 Mon Sep 17 00:00:00 2001 From: Donghyun Kim Date: Tue, 30 Apr 2024 18:35:29 +0900 Subject: [PATCH 41/52] =?UTF-8?q?[BE]=20refactor=20:=20university=20?= =?UTF-8?q?=ED=81=AC=EB=A1=A4=EB=A7=81=20appender=20=EC=97=AD=ED=95=A0=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../university/UniversityServiceImpl.java | 10 ++--- .../department/DepartmentAppender.java | 13 ++++-- .../university/UniversityAppender.java | 39 ----------------- .../university/UniversityFinder.java | 2 +- .../university/UniversityUpdater.java | 43 ++++++++++++++++++- .../department/DepartmentJpaEntity.java | 2 + .../department/DepartmentRepository.java | 2 + .../department/DepartmentRepositoryImpl.java | 28 +++++++++++- .../university/UniversityRepository.java | 2 +- .../university/UniversityRepositoryImpl.java | 2 +- .../fake_class/moim/FakeMoimService.java | 5 +++ 11 files changed, 96 insertions(+), 52 deletions(-) diff --git a/backend/src/main/java/moim_today/application/university/UniversityServiceImpl.java b/backend/src/main/java/moim_today/application/university/UniversityServiceImpl.java index ab3c3827..ebfd3710 100644 --- a/backend/src/main/java/moim_today/application/university/UniversityServiceImpl.java +++ b/backend/src/main/java/moim_today/application/university/UniversityServiceImpl.java @@ -1,7 +1,7 @@ package moim_today.application.university; import moim_today.dto.university.UniversityInfoResponse; -import moim_today.implement.university.UniversityAppender; +import moim_today.implement.university.UniversityUpdater; import moim_today.implement.university.UniversityFinder; import org.springframework.stereotype.Service; @@ -10,17 +10,17 @@ @Service public class UniversityServiceImpl implements UniversityService{ - private final UniversityAppender universityAppender; + private final UniversityUpdater universityUpdater; private final UniversityFinder universityFinder; - public UniversityServiceImpl(final UniversityAppender universityAppender, final UniversityFinder universityFinder) { - this.universityAppender = universityAppender; + public UniversityServiceImpl(final UniversityUpdater universityUpdater, final UniversityFinder universityFinder) { + this.universityUpdater = universityUpdater; this.universityFinder = universityFinder; } @Override public void putAllUniversity() { - universityAppender.fetchAllUniversity(); + universityUpdater.fetchAllUniversity(); } @Override diff --git a/backend/src/main/java/moim_today/implement/department/DepartmentAppender.java b/backend/src/main/java/moim_today/implement/department/DepartmentAppender.java index 3a9f4702..c56297a6 100644 --- a/backend/src/main/java/moim_today/implement/department/DepartmentAppender.java +++ b/backend/src/main/java/moim_today/implement/department/DepartmentAppender.java @@ -43,11 +43,10 @@ public DepartmentAppender(final RestTemplate restTemplate, final ObjectMapper ob public void putAllDepartment(){ List allDepartment = fetchAllDepartment(); for(String eachDepartment : allDepartment){ - fetchUniversitiesByDepartment(eachDepartment); + queryUniversitiesByDepartment(eachDepartment); } } - @Transactional public List fetchAllDepartment(){ String url = UNIVERSITY_API_URL.value()+apiKey+FETCH_ALL_DEPARTMENT_URL.value(); String response = restTemplate.getForObject(url, String.class); @@ -69,9 +68,10 @@ public List fetchAllDepartment(){ } @Transactional - public void fetchUniversitiesByDepartment(final String majorSeq){ + public List queryUniversitiesByDepartment(final String majorSeq){ String url = UNIVERSITY_API_URL.value()+apiKey+FETCH_ALL_UNIVERSITY_BY_DEPARTMENT_URL.value()+majorSeq; String response = restTemplate.getForObject(url, String.class); + List returnDepartmentJpaEntity = new ArrayList<>(); try { JsonNode root = objectMapper.readTree(response); @@ -92,6 +92,13 @@ public void fetchUniversitiesByDepartment(final String majorSeq){ }catch (JsonProcessingException e){ throw new InternalServerException(CRAWLING_PARSE_ERROR.message()); } + + return returnDepartmentJpaEntity; + } + + @Transactional + public void batchUpdate(List departmentJpaEntities){ + departmentRepository.batchUpdate(departmentJpaEntities); } @Transactional diff --git a/backend/src/main/java/moim_today/implement/university/UniversityAppender.java b/backend/src/main/java/moim_today/implement/university/UniversityAppender.java index 13cbe6f9..aaa8729c 100644 --- a/backend/src/main/java/moim_today/implement/university/UniversityAppender.java +++ b/backend/src/main/java/moim_today/implement/university/UniversityAppender.java @@ -1,54 +1,15 @@ package moim_today.implement.university; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import moim_today.domain.university.ExtractUniversity; import moim_today.global.annotation.Implement; -import moim_today.global.error.InternalServerException; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.transaction.annotation.Transactional; import org.springframework.web.client.RestTemplate; -import static moim_today.global.constant.UniversityConstant.*; -import static moim_today.global.constant.exception.CrawlingExceptionConstant.CRAWLING_PARSE_ERROR; - @Implement public class UniversityAppender { - private final RestTemplate restTemplate; - private final ObjectMapper objectMapper; private final UniversityUpdater universityUpdater; - @Value("${university.api.key}") - private String apiKey; - public UniversityAppender(final RestTemplate restTemplate, final ObjectMapper objectMapper, final UniversityUpdater universityUpdater) { - this.restTemplate = restTemplate; - this.objectMapper = objectMapper; this.universityUpdater = universityUpdater; } - - @Transactional - public void fetchAllUniversity(){ - String url = UNIVERSITY_API_URL.value()+apiKey+FETCH_ALL_UNIVERSITY_URL.value(); - String response = restTemplate.getForObject(url, String.class); - - try{ - JsonNode root = objectMapper.readTree(response); - JsonNode content = root.path(DATA_SEARCH.value()).path(CONTENT.value()); - - for (JsonNode item : content) { - ExtractUniversity extractUniversity = objectMapper.readValue(item.toPrettyString(), ExtractUniversity.class); - if(!extractUniversity.checkUniversityType()){ - continue; - } - extractUniversity.extractEmailExtension(); - universityUpdater.putUniversity(extractUniversity.toEntity()); - } - } catch (JsonProcessingException e){ - e.printStackTrace(); - throw new InternalServerException(CRAWLING_PARSE_ERROR.message()); - } - } } diff --git a/backend/src/main/java/moim_today/implement/university/UniversityFinder.java b/backend/src/main/java/moim_today/implement/university/UniversityFinder.java index 21a476af..f886b933 100644 --- a/backend/src/main/java/moim_today/implement/university/UniversityFinder.java +++ b/backend/src/main/java/moim_today/implement/university/UniversityFinder.java @@ -41,7 +41,7 @@ public UniversityJpaEntity getByUniversityEmail(final String emailDomain) { @Transactional(readOnly = true) public void validateExists(final String emailDomain) { - if (!universityRepository.existsByUniversityEmail(emailDomain)) { + if (!universityRepository.validateUniversityEmail(emailDomain)) { throw new NotFoundException(UNIVERSITY_EMAIL_NOT_FOUND.message()); } } diff --git a/backend/src/main/java/moim_today/implement/university/UniversityUpdater.java b/backend/src/main/java/moim_today/implement/university/UniversityUpdater.java index 9564f28f..f0599165 100644 --- a/backend/src/main/java/moim_today/implement/university/UniversityUpdater.java +++ b/backend/src/main/java/moim_today/implement/university/UniversityUpdater.java @@ -1,19 +1,60 @@ package moim_today.implement.university; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import moim_today.domain.university.ExtractUniversity; import moim_today.global.annotation.Implement; +import moim_today.global.error.InternalServerException; import moim_today.persistence.entity.university.UniversityJpaEntity; import moim_today.persistence.repository.university.UniversityRepository; +import org.springframework.beans.factory.annotation.Value; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.client.RestTemplate; import java.util.Optional; +import static moim_today.global.constant.UniversityConstant.*; +import static moim_today.global.constant.exception.CrawlingExceptionConstant.CRAWLING_PARSE_ERROR; + @Implement public class UniversityUpdater { private final UniversityRepository universityRepository; + private final ObjectMapper objectMapper; + private final RestTemplate restTemplate; + + @Value("${university.api.key}") + private String apiKey; - public UniversityUpdater(final UniversityRepository universityRepository) { + public UniversityUpdater(final UniversityRepository universityRepository, + ObjectMapper objectMapper, RestTemplate restTemplate) { this.universityRepository = universityRepository; + this.objectMapper = objectMapper; + this.restTemplate = restTemplate; + } + + @Transactional + public void fetchAllUniversity() { + String url = UNIVERSITY_API_URL.value() + apiKey + FETCH_ALL_UNIVERSITY_URL.value(); + String response = restTemplate.getForObject(url, String.class); + + try { + JsonNode root = objectMapper.readTree(response); + JsonNode content = root.path(DATA_SEARCH.value()).path(CONTENT.value()); + + for (JsonNode item : content) { + ExtractUniversity extractUniversity = objectMapper.readValue(item.toPrettyString(), ExtractUniversity.class); + if (!extractUniversity.checkUniversityType()) { + continue; + } + extractUniversity.extractEmailExtension(); + putUniversity(extractUniversity.toEntity()); + } + } catch (JsonProcessingException e) { + e.printStackTrace(); + throw new InternalServerException(CRAWLING_PARSE_ERROR.message()); + } } @Transactional diff --git a/backend/src/main/java/moim_today/persistence/entity/department/DepartmentJpaEntity.java b/backend/src/main/java/moim_today/persistence/entity/department/DepartmentJpaEntity.java index 0baa986b..2e442bbd 100644 --- a/backend/src/main/java/moim_today/persistence/entity/department/DepartmentJpaEntity.java +++ b/backend/src/main/java/moim_today/persistence/entity/department/DepartmentJpaEntity.java @@ -28,4 +28,6 @@ private DepartmentJpaEntity(final long universityId, final String departmentName this.universityId = universityId; this.departmentName = departmentName; } + + } diff --git a/backend/src/main/java/moim_today/persistence/repository/department/DepartmentRepository.java b/backend/src/main/java/moim_today/persistence/repository/department/DepartmentRepository.java index 1ee1024e..c59f15a9 100644 --- a/backend/src/main/java/moim_today/persistence/repository/department/DepartmentRepository.java +++ b/backend/src/main/java/moim_today/persistence/repository/department/DepartmentRepository.java @@ -12,4 +12,6 @@ public interface DepartmentRepository { DepartmentJpaEntity getById(final long departmentId); List findAllDepartmentOfUniversity(final long universityId); + + void batchUpdate(List departmentJpaEntities); } diff --git a/backend/src/main/java/moim_today/persistence/repository/department/DepartmentRepositoryImpl.java b/backend/src/main/java/moim_today/persistence/repository/department/DepartmentRepositoryImpl.java index b8e2701c..8e83c9b1 100644 --- a/backend/src/main/java/moim_today/persistence/repository/department/DepartmentRepositoryImpl.java +++ b/backend/src/main/java/moim_today/persistence/repository/department/DepartmentRepositoryImpl.java @@ -3,8 +3,12 @@ import moim_today.dto.department.DepartmentInfoResponse; import moim_today.global.error.NotFoundException; import moim_today.persistence.entity.department.DepartmentJpaEntity; +import org.springframework.jdbc.core.BatchPreparedStatementSetter; +import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; +import java.sql.PreparedStatement; +import java.sql.SQLException; import java.util.List; import static moim_today.global.constant.exception.DepartmentExceptionConstant.DEPARTMENT_NOT_FOUND_ERROR; @@ -13,9 +17,11 @@ public class DepartmentRepositoryImpl implements DepartmentRepository { private final DepartmentJpaRepository departmentJpaRepository; + private final JdbcTemplate jdbcTemplate; - public DepartmentRepositoryImpl(final DepartmentJpaRepository departmentJpaRepository) { + public DepartmentRepositoryImpl(final DepartmentJpaRepository departmentJpaRepository, JdbcTemplate jdbcTemplate) { this.departmentJpaRepository = departmentJpaRepository; + this.jdbcTemplate = jdbcTemplate; } @Override @@ -30,6 +36,26 @@ public List findAllDepartmentOfUniversity(final long uni .toList(); } + @Override + public void batchUpdate(final List departmentJpaEntities) { + String sql = "INSERT INTO department (university_id, department_name) VALUES (?, ?)"; + + this.jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() { + + @Override + public void setValues(PreparedStatement ps, int i) throws SQLException { + DepartmentJpaEntity department = departmentJpaEntities.get(i); + ps.setLong(1, department.getUniversityId()); + ps.setString(2, department.getDepartmentName()); + } + + @Override + public int getBatchSize() { + return departmentJpaEntities.size(); + } + }); + } + @Override public DepartmentJpaEntity getById(final long departmentId) { return departmentJpaRepository.findById(departmentId) diff --git a/backend/src/main/java/moim_today/persistence/repository/university/UniversityRepository.java b/backend/src/main/java/moim_today/persistence/repository/university/UniversityRepository.java index 2938a318..4c3eae7c 100644 --- a/backend/src/main/java/moim_today/persistence/repository/university/UniversityRepository.java +++ b/backend/src/main/java/moim_today/persistence/repository/university/UniversityRepository.java @@ -13,7 +13,7 @@ public interface UniversityRepository { UniversityJpaEntity getByEmail(final String email); - boolean existsByUniversityEmail(final String universityEmail); + boolean validateUniversityEmail(final String universityEmail); Optional findByName(final String name); diff --git a/backend/src/main/java/moim_today/persistence/repository/university/UniversityRepositoryImpl.java b/backend/src/main/java/moim_today/persistence/repository/university/UniversityRepositoryImpl.java index 881304dd..00800fad 100644 --- a/backend/src/main/java/moim_today/persistence/repository/university/UniversityRepositoryImpl.java +++ b/backend/src/main/java/moim_today/persistence/repository/university/UniversityRepositoryImpl.java @@ -37,7 +37,7 @@ public UniversityJpaEntity getByEmail(final String email) { } @Override - public boolean existsByUniversityEmail(final String universityEmail) { + public boolean validateUniversityEmail(final String universityEmail) { return universityJpaRepository.existsByUniversityEmail(universityEmail); } diff --git a/backend/src/test/java/moim_today/fake_class/moim/FakeMoimService.java b/backend/src/test/java/moim_today/fake_class/moim/FakeMoimService.java index f3a55ffd..7d26b391 100644 --- a/backend/src/test/java/moim_today/fake_class/moim/FakeMoimService.java +++ b/backend/src/test/java/moim_today/fake_class/moim/FakeMoimService.java @@ -47,4 +47,9 @@ public MoimDetailResponse getMoimDetail(final long moimId) { public void updateMoim(final long memberId, final MoimUpdateRequest moimUpdateRequest) { } + + @Override + public MoimMembersResponse findMoimMembers(final long memberId, final long moimId) { + return null; + } } From 8a083b14fd5dfd68f5363c6582db5d75307fd26a Mon Sep 17 00:00:00 2001 From: Donghyun Kim Date: Tue, 30 Apr 2024 19:38:07 +0900 Subject: [PATCH 42/52] =?UTF-8?q?[BE]=20refactor=20:=20=EB=8C=80=ED=95=99?= =?UTF-8?q?=EA=B5=90=20=EC=9D=B4=EB=A6=84=20=EC=BB=AC=EB=A0=89=EC=85=98=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EC=B5=9C=EC=A0=81=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/constant/UniversityConstant.java | 3 ++ .../department/DepartmentAppender.java | 10 ++++- .../university/UniversityFinder.java | 4 ++ .../university/UniversityRepository.java | 2 + .../university/UniversityRepositoryImpl.java | 31 +++++++++++++++- .../fake_class/moim/FakeMoimService.java | 5 --- .../university/UniversityFinderTest.java | 37 ++++++++++++++++--- 7 files changed, 79 insertions(+), 13 deletions(-) diff --git a/backend/src/main/java/moim_today/global/constant/UniversityConstant.java b/backend/src/main/java/moim_today/global/constant/UniversityConstant.java index 9ba5b442..6f6d018d 100644 --- a/backend/src/main/java/moim_today/global/constant/UniversityConstant.java +++ b/backend/src/main/java/moim_today/global/constant/UniversityConstant.java @@ -2,6 +2,9 @@ public enum UniversityConstant { + UNIVERSITY_NAME("university_name"), + UNIVERSITY_EMAIL("university_email"), + ASSOCIATE_DEGREE("전문대학"), GRADUATE_DEGREE("대학교"), DATA_SEARCH("dataSearch"), diff --git a/backend/src/main/java/moim_today/implement/department/DepartmentAppender.java b/backend/src/main/java/moim_today/implement/department/DepartmentAppender.java index c56297a6..6b1b277e 100644 --- a/backend/src/main/java/moim_today/implement/department/DepartmentAppender.java +++ b/backend/src/main/java/moim_today/implement/department/DepartmentAppender.java @@ -71,6 +71,7 @@ public List fetchAllDepartment(){ public List queryUniversitiesByDepartment(final String majorSeq){ String url = UNIVERSITY_API_URL.value()+apiKey+FETCH_ALL_UNIVERSITY_BY_DEPARTMENT_URL.value()+majorSeq; String response = restTemplate.getForObject(url, String.class); + List returnDepartmentJpaEntity = new ArrayList<>(); try { @@ -81,9 +82,9 @@ public List queryUniversitiesByDepartment(final String majo JsonNode universities = item.path(UNIVERSITY.value()); for (JsonNode university : universities) { String departmentName = university.path(MAJOR_NAME.value()).asText(); - String schoolName = university.path(SCHOOL_NAME.value()).asText(); + String universityName = university.path(SCHOOL_NAME.value()).asText(); - Optional universityJpaEntity = universityFinder.findByName(schoolName); + Optional universityJpaEntity = universityFinder.findByName(universityName); if(universityJpaEntity.isPresent()){ saveDepartment(universityJpaEntity.get(), departmentName); } @@ -96,6 +97,11 @@ public List queryUniversitiesByDepartment(final String majo return returnDepartmentJpaEntity; } + @Transactional + public List findUniversitiesByName(final List universityName){ + return universityFinder.findUniversitiesByName(universityName); + } + @Transactional public void batchUpdate(List departmentJpaEntities){ departmentRepository.batchUpdate(departmentJpaEntities); diff --git a/backend/src/main/java/moim_today/implement/university/UniversityFinder.java b/backend/src/main/java/moim_today/implement/university/UniversityFinder.java index f886b933..2244dab9 100644 --- a/backend/src/main/java/moim_today/implement/university/UniversityFinder.java +++ b/backend/src/main/java/moim_today/implement/university/UniversityFinder.java @@ -51,4 +51,8 @@ public boolean checkUniversityIdIsPresent(final long universityId){ Optional findUniversity = universityRepository.findById(universityId); return findUniversity.isPresent(); } + + public List findUniversitiesByName(final List universityNames) { + return universityRepository.findExistingUniversities(universityNames); + } } diff --git a/backend/src/main/java/moim_today/persistence/repository/university/UniversityRepository.java b/backend/src/main/java/moim_today/persistence/repository/university/UniversityRepository.java index 4c3eae7c..800644bf 100644 --- a/backend/src/main/java/moim_today/persistence/repository/university/UniversityRepository.java +++ b/backend/src/main/java/moim_today/persistence/repository/university/UniversityRepository.java @@ -20,4 +20,6 @@ public interface UniversityRepository { Optional findById(final long id); List findAll(); + + List findExistingUniversities(List universityNames); } diff --git a/backend/src/main/java/moim_today/persistence/repository/university/UniversityRepositoryImpl.java b/backend/src/main/java/moim_today/persistence/repository/university/UniversityRepositoryImpl.java index 00800fad..c407a30f 100644 --- a/backend/src/main/java/moim_today/persistence/repository/university/UniversityRepositoryImpl.java +++ b/backend/src/main/java/moim_today/persistence/repository/university/UniversityRepositoryImpl.java @@ -2,11 +2,17 @@ import moim_today.global.error.NotFoundException; import moim_today.persistence.entity.university.UniversityJpaEntity; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; import org.springframework.stereotype.Repository; +import java.util.ArrayList; import java.util.List; import java.util.Optional; +import static java.util.Collections.nCopies; +import static moim_today.global.constant.UniversityConstant.UNIVERSITY_EMAIL; +import static moim_today.global.constant.UniversityConstant.UNIVERSITY_NAME; import static moim_today.global.constant.exception.UniversityExceptionConstant.UNIVERSITY_EMAIL_NOT_FOUND; import static moim_today.global.constant.exception.UniversityExceptionConstant.UNIVERSITY_NOT_FOUND; @@ -14,9 +20,11 @@ public class UniversityRepositoryImpl implements UniversityRepository { private final UniversityJpaRepository universityJpaRepository; + private final JdbcTemplate jdbcTemplate; - public UniversityRepositoryImpl(final UniversityJpaRepository universityJpaRepository) { + public UniversityRepositoryImpl(final UniversityJpaRepository universityJpaRepository, JdbcTemplate jdbcTemplate) { this.universityJpaRepository = universityJpaRepository; + this.jdbcTemplate = jdbcTemplate; } @Override @@ -51,8 +59,29 @@ public List findAll() { return universityJpaRepository.findAll(); } + @Override + public List findExistingUniversities(final List universityNames) { + if (universityNames == null || universityNames.isEmpty()) { + return new ArrayList<>(); + } + + String inSql = String.join(",", nCopies(universityNames.size(), "?")); + String sql = "SELECT * FROM university WHERE "+UNIVERSITY_NAME.value()+" IN (" + inSql + ")"; + + return jdbcTemplate.query(sql, universityNames.toArray(new Object[0]), universityJpaEntityRowMapper()); + } + @Override public Optional findById(final long id) { return universityJpaRepository.findById(id); } + + private RowMapper universityJpaEntityRowMapper() { + return (rs, rowNum) -> { + return UniversityJpaEntity.builder() + .universityName(rs.getString(UNIVERSITY_NAME.value())) + .universityEmail(rs.getString(UNIVERSITY_EMAIL.value())) + .build(); + }; + } } diff --git a/backend/src/test/java/moim_today/fake_class/moim/FakeMoimService.java b/backend/src/test/java/moim_today/fake_class/moim/FakeMoimService.java index 7d26b391..f3a55ffd 100644 --- a/backend/src/test/java/moim_today/fake_class/moim/FakeMoimService.java +++ b/backend/src/test/java/moim_today/fake_class/moim/FakeMoimService.java @@ -47,9 +47,4 @@ public MoimDetailResponse getMoimDetail(final long moimId) { public void updateMoim(final long memberId, final MoimUpdateRequest moimUpdateRequest) { } - - @Override - public MoimMembersResponse findMoimMembers(final long memberId, final long moimId) { - return null; - } } diff --git a/backend/src/test/java/moim_today/implement/university/UniversityFinderTest.java b/backend/src/test/java/moim_today/implement/university/UniversityFinderTest.java index 7090712d..cf50dc5b 100644 --- a/backend/src/test/java/moim_today/implement/university/UniversityFinderTest.java +++ b/backend/src/test/java/moim_today/implement/university/UniversityFinderTest.java @@ -11,8 +11,7 @@ import java.util.List; import java.util.Optional; -import static moim_today.util.TestConstant.EMAIL; -import static moim_today.util.TestConstant.UNIVERSITY_NAME; +import static moim_today.util.TestConstant.*; import static org.assertj.core.api.Assertions.assertThat; class UniversityFinderTest extends ImplementTest { @@ -62,17 +61,45 @@ void findByName() { @DisplayName("대학교 이름이 없을 때 테스트") @Test - void 대학교_이름으로_찾았는데_대학교가_없을_때() { + void noUniversityFoundByUniversityNameTest() { // when - Optional findUniversity = universityRepository.findByName(UNIVERSITY_NAME.value()); + Optional findUniversity = universityFinder.findByName(UNIVERSITY_NAME.value()); // then assertThat(findUniversity.isEmpty()).isTrue(); } + @DisplayName("대학교 테이블에 존재하는 대학교 이름만 반환한다") + @Test + void findUniversitiesByUniversityNames(){ + // given + List universityNames = new ArrayList<>(); + String testUniversityName = UNIVERSITY_NAME.value(); + + for(int i = 0; i < 10; i++){ + UniversityJpaEntity universityJpaEntity = UniversityJpaEntity.builder() + .universityName(testUniversityName+i) + .universityEmail(AJOU_EMAIL.value()) + .build(); + universityRepository.save(universityJpaEntity); + + universityNames.add(testUniversityName+i); + } + + for(int i = 10; i < 20; i++){ + universityNames.add(testUniversityName+i); + } + + // when + List findUniversities = universityFinder.findUniversitiesByName(universityNames); + + // then + assertThat(findUniversities.size()).isEqualTo(10); + } + @DisplayName("대학교 ID가 있는지 없는지 검사한다") @Test - void 대학교_ID가_있는지_검사() { + void validateUniversityIdTest() { // given UniversityJpaEntity universityJpaEntity = UniversityJpaEntity.builder() .universityName(UNIVERSITY_NAME.value()) From 322185c69d125baa4e37d3234c05f62c969e6cf2 Mon Sep 17 00:00:00 2001 From: Donghyun Kim Date: Tue, 30 Apr 2024 21:21:03 +0900 Subject: [PATCH 43/52] =?UTF-8?q?[BE]=20refactor=20:=20=EB=8C=80=ED=95=99?= =?UTF-8?q?=EA=B5=90=20=ED=95=99=EA=B3=BC=20=EB=B0=B0=EC=B9=98=20=EC=97=85?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=8A=B8=EB=A1=9C=20=EC=B5=9C=EC=A0=81?= =?UTF-8?q?=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/department/Department.java | 38 +++++++++ .../department/DepartmentAppender.java | 80 +++++++++---------- .../university/UniversityFinder.java | 1 + .../department/DepartmentJpaEntity.java | 2 - .../department/DepartmentAppenderTest.java | 42 ++++++++++ 5 files changed, 121 insertions(+), 42 deletions(-) create mode 100644 backend/src/main/java/moim_today/domain/department/Department.java create mode 100644 backend/src/test/java/moim_today/implement/department/DepartmentAppenderTest.java diff --git a/backend/src/main/java/moim_today/domain/department/Department.java b/backend/src/main/java/moim_today/domain/department/Department.java new file mode 100644 index 00000000..98ed1968 --- /dev/null +++ b/backend/src/main/java/moim_today/domain/department/Department.java @@ -0,0 +1,38 @@ +package moim_today.domain.department; + +import moim_today.persistence.entity.department.DepartmentJpaEntity; +import moim_today.persistence.entity.university.UniversityJpaEntity; + +import java.util.*; + +public record Department( + long universityId, + String departmentName +) { + + public static List toEntities(Map> universityAndDepartments) { + List departmentJpaEntities = new ArrayList<>(); + + for (Map.Entry> entrySet : universityAndDepartments.entrySet()) { + for (String departmentName : entrySet.getValue()) { + departmentJpaEntities.add(DepartmentJpaEntity.builder() + .universityId(entrySet.getKey()) + .departmentName(departmentName) + .build()); + } + } + return departmentJpaEntities; + } + + public static Map> convertToUnivIdAndDepartments(final Map> universityAndDepartments, + final List universityJpaEntities) { + Map> existingUniversities = new HashMap<>(); + + universityJpaEntities.stream() + .forEach(universityJpaEntity -> { + existingUniversities.put(universityJpaEntity.getId(), universityAndDepartments.get(universityJpaEntity.getUniversityName())); + }); + + return existingUniversities; + } +} diff --git a/backend/src/main/java/moim_today/implement/department/DepartmentAppender.java b/backend/src/main/java/moim_today/implement/department/DepartmentAppender.java index 6b1b277e..c8bae7a9 100644 --- a/backend/src/main/java/moim_today/implement/department/DepartmentAppender.java +++ b/backend/src/main/java/moim_today/implement/department/DepartmentAppender.java @@ -3,6 +3,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import moim_today.domain.department.Department; import moim_today.global.annotation.Implement; import moim_today.global.error.InternalServerException; import moim_today.implement.university.UniversityFinder; @@ -13,9 +14,7 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.web.client.RestTemplate; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; +import java.util.*; import static moim_today.global.constant.UniversityConstant.*; import static moim_today.global.constant.exception.CrawlingExceptionConstant.CRAWLING_PARSE_ERROR; @@ -39,40 +38,57 @@ public DepartmentAppender(final RestTemplate restTemplate, final ObjectMapper ob @Value("${university.api.key}") private String apiKey; - @Transactional - public void putAllDepartment(){ - List allDepartment = fetchAllDepartment(); - for(String eachDepartment : allDepartment){ - queryUniversitiesByDepartment(eachDepartment); + public void putAllDepartment() { + List allMajor = findAllMajor(); + for (String eachMajor : allMajor) { + updateDepartments(eachMajor); } } - public List fetchAllDepartment(){ - String url = UNIVERSITY_API_URL.value()+apiKey+FETCH_ALL_DEPARTMENT_URL.value(); + @Transactional + public void batchUpdate(final List departmentJpaEntities) { + departmentRepository.batchUpdate(departmentJpaEntities); + } + + private void updateDepartments(final String eachMajor) { + Map> universityAndDepartments = getDepartmentsOfUniversity(eachMajor); + Map> universityIdAndDepartments = filterExistingUniversity(universityAndDepartments); + List departmentJpaEntities = Department.toEntities(universityIdAndDepartments); + batchUpdate(departmentJpaEntities); + } + + private Map> filterExistingUniversity(final Map> universityAndDepartments) { + List universityJpaEntities = universityFinder + .findUniversitiesByName(universityAndDepartments.keySet().stream().toList()); + + return Department.convertToUnivIdAndDepartments(universityAndDepartments, universityJpaEntities); + } + + private List findAllMajor() { + String url = UNIVERSITY_API_URL.value() + apiKey + FETCH_ALL_DEPARTMENT_URL.value(); String response = restTemplate.getForObject(url, String.class); List allMajor = new ArrayList<>(); - try{ + try { JsonNode root = objectMapper.readTree(response); JsonNode content = root.path(DATA_SEARCH.value()).path(CONTENT.value()); - for(JsonNode item : content){ + for (JsonNode item : content) { String majorSeq = item.get(MAJOR_SEQ.value()).asText(); allMajor.add(majorSeq); } return allMajor; - }catch(JsonProcessingException e){ + } catch (JsonProcessingException e) { throw new InternalServerException(CRAWLING_PARSE_ERROR.message()); } } - @Transactional - public List queryUniversitiesByDepartment(final String majorSeq){ - String url = UNIVERSITY_API_URL.value()+apiKey+FETCH_ALL_UNIVERSITY_BY_DEPARTMENT_URL.value()+majorSeq; + private Map> getDepartmentsOfUniversity(final String majorSeq) { + String url = UNIVERSITY_API_URL.value() + apiKey + FETCH_ALL_UNIVERSITY_BY_DEPARTMENT_URL.value() + majorSeq; String response = restTemplate.getForObject(url, String.class); - List returnDepartmentJpaEntity = new ArrayList<>(); + Map> universityAndDepartments = new HashMap<>(); try { JsonNode root = objectMapper.readTree(response); @@ -84,35 +100,19 @@ public List queryUniversitiesByDepartment(final String majo String departmentName = university.path(MAJOR_NAME.value()).asText(); String universityName = university.path(SCHOOL_NAME.value()).asText(); - Optional universityJpaEntity = universityFinder.findByName(universityName); - if(universityJpaEntity.isPresent()){ - saveDepartment(universityJpaEntity.get(), departmentName); - } + patchMap(universityAndDepartments, universityName, departmentName); } } - }catch (JsonProcessingException e){ + } catch (JsonProcessingException e) { throw new InternalServerException(CRAWLING_PARSE_ERROR.message()); } - return returnDepartmentJpaEntity; - } - - @Transactional - public List findUniversitiesByName(final List universityName){ - return universityFinder.findUniversitiesByName(universityName); - } - - @Transactional - public void batchUpdate(List departmentJpaEntities){ - departmentRepository.batchUpdate(departmentJpaEntities); + return universityAndDepartments; } - @Transactional - public void saveDepartment(UniversityJpaEntity universityJpaEntity, String departmentName){ - DepartmentJpaEntity saveDepartment = DepartmentJpaEntity.builder() - .universityId(universityJpaEntity.getId()) - .departmentName(departmentName) - .build(); - departmentRepository.save(saveDepartment); + private void patchMap(final Map> universityAndDepartments, final String universityName, final String departmentName) { + Set departments = universityAndDepartments + .computeIfAbsent(universityName, k -> new HashSet<>()); + departments.add(departmentName); } } diff --git a/backend/src/main/java/moim_today/implement/university/UniversityFinder.java b/backend/src/main/java/moim_today/implement/university/UniversityFinder.java index 2244dab9..9594e52f 100644 --- a/backend/src/main/java/moim_today/implement/university/UniversityFinder.java +++ b/backend/src/main/java/moim_today/implement/university/UniversityFinder.java @@ -52,6 +52,7 @@ public boolean checkUniversityIdIsPresent(final long universityId){ return findUniversity.isPresent(); } + @Transactional(readOnly = true) public List findUniversitiesByName(final List universityNames) { return universityRepository.findExistingUniversities(universityNames); } diff --git a/backend/src/main/java/moim_today/persistence/entity/department/DepartmentJpaEntity.java b/backend/src/main/java/moim_today/persistence/entity/department/DepartmentJpaEntity.java index 2e442bbd..0baa986b 100644 --- a/backend/src/main/java/moim_today/persistence/entity/department/DepartmentJpaEntity.java +++ b/backend/src/main/java/moim_today/persistence/entity/department/DepartmentJpaEntity.java @@ -28,6 +28,4 @@ private DepartmentJpaEntity(final long universityId, final String departmentName this.universityId = universityId; this.departmentName = departmentName; } - - } diff --git a/backend/src/test/java/moim_today/implement/department/DepartmentAppenderTest.java b/backend/src/test/java/moim_today/implement/department/DepartmentAppenderTest.java new file mode 100644 index 00000000..f39d18e5 --- /dev/null +++ b/backend/src/test/java/moim_today/implement/department/DepartmentAppenderTest.java @@ -0,0 +1,42 @@ +package moim_today.implement.department; + +import moim_today.dto.department.DepartmentInfoResponse; +import moim_today.persistence.entity.department.DepartmentJpaEntity; +import moim_today.util.ImplementTest; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +class DepartmentAppenderTest extends ImplementTest { + + @Autowired + private DepartmentAppender departmentAppender; + + @Autowired + private DepartmentFinder departmentFinder; + + @DisplayName("Department 정보 컬렉션을 한 번에 업데이트한다") + @Test + void batchUpdate() { + // given + List departmentJpaEntities = new ArrayList<>(); + for(int i = 0; i < 10; i++){ + departmentJpaEntities.add(DepartmentJpaEntity.builder() + .universityId(0) + .departmentName("departmentName"+i) + .build()); + } + + // when + departmentAppender.batchUpdate(departmentJpaEntities); + List allDepartment = departmentFinder.getAllDepartment(0, null); + + // then + assertThat(allDepartment.size()).isEqualTo(10); + } +} \ No newline at end of file From 0f4be8829d17cc06e8ec7f7dea5162f9cf3fed92 Mon Sep 17 00:00:00 2001 From: Donghyun Kim Date: Wed, 1 May 2024 01:26:52 +0900 Subject: [PATCH 44/52] =?UTF-8?q?[BE]=20refactor=20:=20=EB=8C=80=ED=95=99?= =?UTF-8?q?=EA=B5=90=20=ED=95=99=EA=B3=BC=20=EC=97=85=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=8A=B8=20=EB=A7=B5=EC=97=90=20=EC=8C=93=EC=9D=80=20=EB=92=A4?= =?UTF-8?q?=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../moim_today/global/config/WebConfig.java | 4 +- .../global/constant/DepartmentConstant.java | 19 +++++++++ .../global/constant/UniversityConstant.java | 1 + .../department/DepartmentAppender.java | 39 +++++++++++++++++-- .../university/UniversityJpaEntity.java | 3 +- .../university/UniversityRepositoryImpl.java | 14 +++---- .../department/DepartmentAppenderTest.java | 33 +++++++++++++++- .../university/UniversityFinderTest.java | 17 ++++++-- .../PasswordCertificationJpaEntityTest.java | 5 ++- .../java/moim_today/util/TestConstant.java | 4 ++ 10 files changed, 118 insertions(+), 21 deletions(-) create mode 100644 backend/src/main/java/moim_today/global/constant/DepartmentConstant.java diff --git a/backend/src/main/java/moim_today/global/config/WebConfig.java b/backend/src/main/java/moim_today/global/config/WebConfig.java index beb8563f..851ecd53 100644 --- a/backend/src/main/java/moim_today/global/config/WebConfig.java +++ b/backend/src/main/java/moim_today/global/config/WebConfig.java @@ -28,7 +28,9 @@ public void addInterceptors(final InterceptorRegistry registry) { "/api/login", "/api/certification/**", "/api/moims/detail", - "/api/register" + "/api/sign-up", + "/api/universities", + "/api/universities/departments/**" ); } diff --git a/backend/src/main/java/moim_today/global/constant/DepartmentConstant.java b/backend/src/main/java/moim_today/global/constant/DepartmentConstant.java new file mode 100644 index 00000000..bf413482 --- /dev/null +++ b/backend/src/main/java/moim_today/global/constant/DepartmentConstant.java @@ -0,0 +1,19 @@ +package moim_today.global.constant; + +public enum DepartmentConstant { + DEPARTMENT_UPDATE_BATCH_SIZE("1000"); + + private final String value; + + DepartmentConstant(final String value) { + this.value = value; + } + + public String value(){ + return value; + } + + public int intValue(){ + return Integer.parseInt(value); + } +} diff --git a/backend/src/main/java/moim_today/global/constant/UniversityConstant.java b/backend/src/main/java/moim_today/global/constant/UniversityConstant.java index 6f6d018d..5ce8d70a 100644 --- a/backend/src/main/java/moim_today/global/constant/UniversityConstant.java +++ b/backend/src/main/java/moim_today/global/constant/UniversityConstant.java @@ -4,6 +4,7 @@ public enum UniversityConstant { UNIVERSITY_NAME("university_name"), UNIVERSITY_EMAIL("university_email"), + UNIVERSITY_ID("university_id"), ASSOCIATE_DEGREE("전문대학"), GRADUATE_DEGREE("대학교"), diff --git a/backend/src/main/java/moim_today/implement/department/DepartmentAppender.java b/backend/src/main/java/moim_today/implement/department/DepartmentAppender.java index c8bae7a9..c5c0e075 100644 --- a/backend/src/main/java/moim_today/implement/department/DepartmentAppender.java +++ b/backend/src/main/java/moim_today/implement/department/DepartmentAppender.java @@ -16,6 +16,7 @@ import java.util.*; +import static moim_today.global.constant.DepartmentConstant.DEPARTMENT_UPDATE_BATCH_SIZE; import static moim_today.global.constant.UniversityConstant.*; import static moim_today.global.constant.exception.CrawlingExceptionConstant.CRAWLING_PARSE_ERROR; @@ -40,9 +41,13 @@ public DepartmentAppender(final RestTemplate restTemplate, final ObjectMapper ob public void putAllDepartment() { List allMajor = findAllMajor(); + Map> departmentUpdateQueue = new HashMap<>(); + for (String eachMajor : allMajor) { - updateDepartments(eachMajor); + patchMapAll(departmentUpdateQueue, getDepartments(eachMajor)); + updateDepartmentsIfSizeOver(departmentUpdateQueue, DEPARTMENT_UPDATE_BATCH_SIZE.intValue()); } + batchUpdate(getDepartmentJpaEntities(departmentUpdateQueue)); } @Transactional @@ -50,11 +55,30 @@ public void batchUpdate(final List departmentJpaEntities) { departmentRepository.batchUpdate(departmentJpaEntities); } - private void updateDepartments(final String eachMajor) { - Map> universityAndDepartments = getDepartmentsOfUniversity(eachMajor); + public void updateDepartmentsIfSizeOver(final Map> universityAndDepartments, final int size){ + if(getTotalMapSize(universityAndDepartments) > size){ + batchUpdate(getDepartmentJpaEntities(universityAndDepartments)); + universityAndDepartments.clear(); + } + } + + private int getTotalMapSize(final Map> mapWithSet){ + int totalSize = 0; + for(Map.Entry> entry : mapWithSet.entrySet()){ + totalSize += entry.getValue().size(); + } + return totalSize; + } + + private List getDepartmentJpaEntities(final Map> universityAndDepartments) { Map> universityIdAndDepartments = filterExistingUniversity(universityAndDepartments); List departmentJpaEntities = Department.toEntities(universityIdAndDepartments); - batchUpdate(departmentJpaEntities); + return departmentJpaEntities; + } + + private Map> getDepartments(final String eachMajor) { + Map> universityAndDepartments = getDepartmentsOfUniversity(eachMajor); + return universityAndDepartments; } private Map> filterExistingUniversity(final Map> universityAndDepartments) { @@ -115,4 +139,11 @@ private void patchMap(final Map> universityAndDepartments, f .computeIfAbsent(universityName, k -> new HashSet<>()); departments.add(departmentName); } + + private void patchMapAll(final Map> baseMap, + final Map> addingMap){ + for (Map.Entry> entry : addingMap.entrySet()) { + baseMap.computeIfAbsent(entry.getKey(), k -> new HashSet<>()).addAll(entry.getValue()); + } + } } diff --git a/backend/src/main/java/moim_today/persistence/entity/university/UniversityJpaEntity.java b/backend/src/main/java/moim_today/persistence/entity/university/UniversityJpaEntity.java index a4110aa2..c1b1ce7b 100644 --- a/backend/src/main/java/moim_today/persistence/entity/university/UniversityJpaEntity.java +++ b/backend/src/main/java/moim_today/persistence/entity/university/UniversityJpaEntity.java @@ -22,7 +22,8 @@ protected UniversityJpaEntity() { } @Builder - public UniversityJpaEntity(final String universityName, final String universityEmail) { + public UniversityJpaEntity(long id, final String universityName, final String universityEmail) { + this.id = id; this.universityName = universityName; this.universityEmail = universityEmail; } diff --git a/backend/src/main/java/moim_today/persistence/repository/university/UniversityRepositoryImpl.java b/backend/src/main/java/moim_today/persistence/repository/university/UniversityRepositoryImpl.java index c407a30f..aad594ae 100644 --- a/backend/src/main/java/moim_today/persistence/repository/university/UniversityRepositoryImpl.java +++ b/backend/src/main/java/moim_today/persistence/repository/university/UniversityRepositoryImpl.java @@ -11,8 +11,7 @@ import java.util.Optional; import static java.util.Collections.nCopies; -import static moim_today.global.constant.UniversityConstant.UNIVERSITY_EMAIL; -import static moim_today.global.constant.UniversityConstant.UNIVERSITY_NAME; +import static moim_today.global.constant.UniversityConstant.*; import static moim_today.global.constant.exception.UniversityExceptionConstant.UNIVERSITY_EMAIL_NOT_FOUND; import static moim_today.global.constant.exception.UniversityExceptionConstant.UNIVERSITY_NOT_FOUND; @@ -77,11 +76,10 @@ public Optional findById(final long id) { } private RowMapper universityJpaEntityRowMapper() { - return (rs, rowNum) -> { - return UniversityJpaEntity.builder() - .universityName(rs.getString(UNIVERSITY_NAME.value())) - .universityEmail(rs.getString(UNIVERSITY_EMAIL.value())) - .build(); - }; + return (rs, rowNum) -> UniversityJpaEntity.builder() + .id(Long.parseLong(rs.getString(UNIVERSITY_ID.value()))) + .universityName(rs.getString(UNIVERSITY_NAME.value())) + .universityEmail(rs.getString(UNIVERSITY_EMAIL.value())) + .build(); } } diff --git a/backend/src/test/java/moim_today/implement/department/DepartmentAppenderTest.java b/backend/src/test/java/moim_today/implement/department/DepartmentAppenderTest.java index f39d18e5..5b70bd36 100644 --- a/backend/src/test/java/moim_today/implement/department/DepartmentAppenderTest.java +++ b/backend/src/test/java/moim_today/implement/department/DepartmentAppenderTest.java @@ -2,14 +2,16 @@ import moim_today.dto.department.DepartmentInfoResponse; import moim_today.persistence.entity.department.DepartmentJpaEntity; +import moim_today.persistence.entity.university.UniversityJpaEntity; import moim_today.util.ImplementTest; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import java.util.ArrayList; -import java.util.List; +import java.util.*; +import static moim_today.global.constant.DepartmentConstant.DEPARTMENT_UPDATE_BATCH_SIZE; +import static moim_today.util.TestConstant.*; import static org.assertj.core.api.Assertions.assertThat; class DepartmentAppenderTest extends ImplementTest { @@ -20,6 +22,8 @@ class DepartmentAppenderTest extends ImplementTest { @Autowired private DepartmentFinder departmentFinder; + private final int MAX_SIZE = 1500; + @DisplayName("Department 정보 컬렉션을 한 번에 업데이트한다") @Test void batchUpdate() { @@ -39,4 +43,29 @@ void batchUpdate() { // then assertThat(allDepartment.size()).isEqualTo(10); } + + @DisplayName("Department 정보가 Size 값을 넘을 경우 batchUpdate를 실행한다") + @Test + void updateDepartmentsIfSizeOver() { + // given + Map> departmentJpaEntities = new HashMap<>(); + departmentJpaEntities.put(UNIVERSITY_NAME.value(), new HashSet<>()); + UniversityJpaEntity universityJpaEntity = UniversityJpaEntity.builder() + .universityName(UNIVERSITY_NAME.value()) + .universityEmail(AJOU_EMAIL_DOMAIN.value()) + .build(); + universityRepository.save(universityJpaEntity); + + for(int i = 0; i < MAX_SIZE; i++){ + departmentJpaEntities.get(UNIVERSITY_NAME.value()).add(DEPARTMENT_NAME.value()+i); + } + + // when + departmentAppender.updateDepartmentsIfSizeOver(departmentJpaEntities, DEPARTMENT_UPDATE_BATCH_SIZE.intValue()); + + // then + long universityId = universityRepository.getByName(UNIVERSITY_NAME.value()).getId(); + assertThat(departmentRepository.findAllDepartmentOfUniversity(universityId).size()) + .isEqualTo(MAX_SIZE); + } } \ No newline at end of file diff --git a/backend/src/test/java/moim_today/implement/university/UniversityFinderTest.java b/backend/src/test/java/moim_today/implement/university/UniversityFinderTest.java index cf50dc5b..6b5c557b 100644 --- a/backend/src/test/java/moim_today/implement/university/UniversityFinderTest.java +++ b/backend/src/test/java/moim_today/implement/university/UniversityFinderTest.java @@ -10,6 +10,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.Random; import static moim_today.util.TestConstant.*; import static org.assertj.core.api.Assertions.assertThat; @@ -73,10 +74,13 @@ void noUniversityFoundByUniversityNameTest() { @Test void findUniversitiesByUniversityNames(){ // given + final int MAX_UNIV = 5; + final int MAX_TEST_UNIV = 10; + Random random = new Random(); List universityNames = new ArrayList<>(); String testUniversityName = UNIVERSITY_NAME.value(); - for(int i = 0; i < 10; i++){ + for(int i = 0; i < MAX_UNIV; i++){ UniversityJpaEntity universityJpaEntity = UniversityJpaEntity.builder() .universityName(testUniversityName+i) .universityEmail(AJOU_EMAIL.value()) @@ -86,7 +90,7 @@ void findUniversitiesByUniversityNames(){ universityNames.add(testUniversityName+i); } - for(int i = 10; i < 20; i++){ + for(int i = MAX_UNIV; i < MAX_TEST_UNIV; i++){ universityNames.add(testUniversityName+i); } @@ -94,7 +98,14 @@ void findUniversitiesByUniversityNames(){ List findUniversities = universityFinder.findUniversitiesByName(universityNames); // then - assertThat(findUniversities.size()).isEqualTo(10); + UniversityJpaEntity randomUniversity = UniversityJpaEntity.builder() + .universityName(testUniversityName+(random.nextInt(MAX_UNIV))) + .universityEmail(AJOU_EMAIL.value()) + .build(); + assertThat(findUniversities.size()).isEqualTo(MAX_UNIV); + assertThat(findUniversities.stream().filter(u -> u.getUniversityName().equals(randomUniversity.getUniversityName())) + .findAny()) + .isPresent(); } @DisplayName("대학교 ID가 있는지 없는지 검사한다") diff --git a/backend/src/test/java/moim_today/persistence/entity/certification_token/PasswordCertificationJpaEntityTest.java b/backend/src/test/java/moim_today/persistence/entity/certification_token/PasswordCertificationJpaEntityTest.java index 9c4fda06..1aa235ee 100644 --- a/backend/src/test/java/moim_today/persistence/entity/certification_token/PasswordCertificationJpaEntityTest.java +++ b/backend/src/test/java/moim_today/persistence/entity/certification_token/PasswordCertificationJpaEntityTest.java @@ -6,8 +6,9 @@ import java.time.LocalDateTime; -import static moim_today.util.TestConstant.*; -import static org.assertj.core.api.Assertions.*; +import static moim_today.util.TestConstant.CERTIFICATION_TOKEN; +import static moim_today.util.TestConstant.NEW_CERTIFICATION_TOKEN; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; class PasswordCertificationJpaEntityTest { diff --git a/backend/src/test/java/moim_today/util/TestConstant.java b/backend/src/test/java/moim_today/util/TestConstant.java index 741ad97e..74dd71c8 100644 --- a/backend/src/test/java/moim_today/util/TestConstant.java +++ b/backend/src/test/java/moim_today/util/TestConstant.java @@ -74,4 +74,8 @@ public enum TestConstant { public String value() { return value; } + + public int intValue(){ + return Integer.parseInt(value); + } } From b8c5ed379d92a0e729a8480e13fd887920c54a0a Mon Sep 17 00:00:00 2001 From: Donghyun Kim Date: Wed, 1 May 2024 03:15:19 +0900 Subject: [PATCH 45/52] =?UTF-8?q?[BE]=20refactor=20:=20=EC=99=B8=EB=B6=80?= =?UTF-8?q?=20api=20=ED=8C=8C=EC=8B=B1,=20map=EC=97=90=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5=ED=95=98=EB=8A=94=20=EB=A1=9C=EC=A7=81=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../department/DepartmentService.java | 2 +- .../department/DepartmentServiceImpl.java | 2 +- .../university/UniversityService.java | 2 +- .../university/UniversityServiceImpl.java | 2 +- .../domain/department/Department.java | 9 +- .../department/DepartmentAppender.java | 118 +++--------------- .../department/DepartmentFetcher.java | 91 ++++++++++++++ .../university/UniversityController.java | 6 +- .../university/UniversityControllerTest.java | 20 +++ 9 files changed, 143 insertions(+), 109 deletions(-) create mode 100644 backend/src/main/java/moim_today/implement/department/DepartmentFetcher.java create mode 100644 backend/src/test/java/moim_today/presentation/university/UniversityControllerTest.java diff --git a/backend/src/main/java/moim_today/application/department/DepartmentService.java b/backend/src/main/java/moim_today/application/department/DepartmentService.java index fa386d31..de0016a9 100644 --- a/backend/src/main/java/moim_today/application/department/DepartmentService.java +++ b/backend/src/main/java/moim_today/application/department/DepartmentService.java @@ -6,7 +6,7 @@ public interface DepartmentService { - void putAllDepartment(); + void patchAllDepartment(); List getAllDepartment(final long universityId, String universityName); } diff --git a/backend/src/main/java/moim_today/application/department/DepartmentServiceImpl.java b/backend/src/main/java/moim_today/application/department/DepartmentServiceImpl.java index abbb342a..4d703051 100644 --- a/backend/src/main/java/moim_today/application/department/DepartmentServiceImpl.java +++ b/backend/src/main/java/moim_today/application/department/DepartmentServiceImpl.java @@ -19,7 +19,7 @@ public DepartmentServiceImpl(final DepartmentAppender departmentAppender, final } @Override - public void putAllDepartment() { + public void patchAllDepartment() { departmentAppender.putAllDepartment(); } diff --git a/backend/src/main/java/moim_today/application/university/UniversityService.java b/backend/src/main/java/moim_today/application/university/UniversityService.java index 5f9ef387..44428a06 100644 --- a/backend/src/main/java/moim_today/application/university/UniversityService.java +++ b/backend/src/main/java/moim_today/application/university/UniversityService.java @@ -6,7 +6,7 @@ public interface UniversityService { - void putAllUniversity(); + void patchAllUniversity(); List getUniversities(); } diff --git a/backend/src/main/java/moim_today/application/university/UniversityServiceImpl.java b/backend/src/main/java/moim_today/application/university/UniversityServiceImpl.java index ebfd3710..598e9f5c 100644 --- a/backend/src/main/java/moim_today/application/university/UniversityServiceImpl.java +++ b/backend/src/main/java/moim_today/application/university/UniversityServiceImpl.java @@ -19,7 +19,7 @@ public UniversityServiceImpl(final UniversityUpdater universityUpdater, final Un } @Override - public void putAllUniversity() { + public void patchAllUniversity() { universityUpdater.fetchAllUniversity(); } diff --git a/backend/src/main/java/moim_today/domain/department/Department.java b/backend/src/main/java/moim_today/domain/department/Department.java index 98ed1968..d8c912fc 100644 --- a/backend/src/main/java/moim_today/domain/department/Department.java +++ b/backend/src/main/java/moim_today/domain/department/Department.java @@ -10,10 +10,12 @@ public record Department( String departmentName ) { - public static List toEntities(Map> universityAndDepartments) { + public static List toEntities(final Map> universityAndDepartments, + final List universityJpaEntities) { + Map> existingUniversities = convertToUnivIdAndDepartments(universityAndDepartments, universityJpaEntities); List departmentJpaEntities = new ArrayList<>(); - for (Map.Entry> entrySet : universityAndDepartments.entrySet()) { + for (Map.Entry> entrySet : existingUniversities.entrySet()) { for (String departmentName : entrySet.getValue()) { departmentJpaEntities.add(DepartmentJpaEntity.builder() .universityId(entrySet.getKey()) @@ -24,7 +26,7 @@ public static List toEntities(Map> univer return departmentJpaEntities; } - public static Map> convertToUnivIdAndDepartments(final Map> universityAndDepartments, + private static Map> convertToUnivIdAndDepartments(final Map> universityAndDepartments, final List universityJpaEntities) { Map> existingUniversities = new HashMap<>(); @@ -35,4 +37,5 @@ public static Map> convertToUnivIdAndDepartments(final Map allMajor = findAllMajor(); + List allMajor = departmentFetcher.getAllMajor(); Map> departmentUpdateQueue = new HashMap<>(); for (String eachMajor : allMajor) { - patchMapAll(departmentUpdateQueue, getDepartments(eachMajor)); + departmentFetcher.patchDepartmentQueue(departmentUpdateQueue, eachMajor); updateDepartmentsIfSizeOver(departmentUpdateQueue, DEPARTMENT_UPDATE_BATCH_SIZE.intValue()); } - batchUpdate(getDepartmentJpaEntities(departmentUpdateQueue)); + batchUpdate(filterUniversityExistToDepartment(departmentUpdateQueue)); } @Transactional @@ -57,11 +48,17 @@ public void batchUpdate(final List departmentJpaEntities) { public void updateDepartmentsIfSizeOver(final Map> universityAndDepartments, final int size){ if(getTotalMapSize(universityAndDepartments) > size){ - batchUpdate(getDepartmentJpaEntities(universityAndDepartments)); + batchUpdate(filterUniversityExistToDepartment(universityAndDepartments)); universityAndDepartments.clear(); } } + private List filterUniversityExistToDepartment(final Map> universityAndDepartments) { + List universityIdAndDepartments = universityFinder + .findUniversitiesByName(universityAndDepartments.keySet().stream().toList()); + return Department.toEntities(universityAndDepartments, universityIdAndDepartments); + } + private int getTotalMapSize(final Map> mapWithSet){ int totalSize = 0; for(Map.Entry> entry : mapWithSet.entrySet()){ @@ -69,81 +66,4 @@ private int getTotalMapSize(final Map> mapWithSet){ } return totalSize; } - - private List getDepartmentJpaEntities(final Map> universityAndDepartments) { - Map> universityIdAndDepartments = filterExistingUniversity(universityAndDepartments); - List departmentJpaEntities = Department.toEntities(universityIdAndDepartments); - return departmentJpaEntities; - } - - private Map> getDepartments(final String eachMajor) { - Map> universityAndDepartments = getDepartmentsOfUniversity(eachMajor); - return universityAndDepartments; - } - - private Map> filterExistingUniversity(final Map> universityAndDepartments) { - List universityJpaEntities = universityFinder - .findUniversitiesByName(universityAndDepartments.keySet().stream().toList()); - - return Department.convertToUnivIdAndDepartments(universityAndDepartments, universityJpaEntities); - } - - private List findAllMajor() { - String url = UNIVERSITY_API_URL.value() + apiKey + FETCH_ALL_DEPARTMENT_URL.value(); - String response = restTemplate.getForObject(url, String.class); - - List allMajor = new ArrayList<>(); - try { - JsonNode root = objectMapper.readTree(response); - JsonNode content = root.path(DATA_SEARCH.value()).path(CONTENT.value()); - - for (JsonNode item : content) { - String majorSeq = item.get(MAJOR_SEQ.value()).asText(); - allMajor.add(majorSeq); - } - - return allMajor; - } catch (JsonProcessingException e) { - throw new InternalServerException(CRAWLING_PARSE_ERROR.message()); - } - } - - private Map> getDepartmentsOfUniversity(final String majorSeq) { - String url = UNIVERSITY_API_URL.value() + apiKey + FETCH_ALL_UNIVERSITY_BY_DEPARTMENT_URL.value() + majorSeq; - String response = restTemplate.getForObject(url, String.class); - - Map> universityAndDepartments = new HashMap<>(); - - try { - JsonNode root = objectMapper.readTree(response); - JsonNode content = root.path(DATA_SEARCH.value()).path(CONTENT.value()); - - for (JsonNode item : content) { - JsonNode universities = item.path(UNIVERSITY.value()); - for (JsonNode university : universities) { - String departmentName = university.path(MAJOR_NAME.value()).asText(); - String universityName = university.path(SCHOOL_NAME.value()).asText(); - - patchMap(universityAndDepartments, universityName, departmentName); - } - } - } catch (JsonProcessingException e) { - throw new InternalServerException(CRAWLING_PARSE_ERROR.message()); - } - - return universityAndDepartments; - } - - private void patchMap(final Map> universityAndDepartments, final String universityName, final String departmentName) { - Set departments = universityAndDepartments - .computeIfAbsent(universityName, k -> new HashSet<>()); - departments.add(departmentName); - } - - private void patchMapAll(final Map> baseMap, - final Map> addingMap){ - for (Map.Entry> entry : addingMap.entrySet()) { - baseMap.computeIfAbsent(entry.getKey(), k -> new HashSet<>()).addAll(entry.getValue()); - } - } } diff --git a/backend/src/main/java/moim_today/implement/department/DepartmentFetcher.java b/backend/src/main/java/moim_today/implement/department/DepartmentFetcher.java new file mode 100644 index 00000000..fb17059f --- /dev/null +++ b/backend/src/main/java/moim_today/implement/department/DepartmentFetcher.java @@ -0,0 +1,91 @@ +package moim_today.implement.department; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import moim_today.global.annotation.Implement; +import moim_today.global.error.InternalServerException; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.client.RestTemplate; + +import java.util.*; + +import static moim_today.global.constant.UniversityConstant.*; +import static moim_today.global.constant.exception.CrawlingExceptionConstant.CRAWLING_PARSE_ERROR; + +@Implement +public class DepartmentFetcher { + + private final RestTemplate restTemplate; + private final ObjectMapper objectMapper; + + public DepartmentFetcher(final RestTemplate restTemplate, final ObjectMapper objectMapper) { + this.restTemplate = restTemplate; + this.objectMapper = objectMapper; + } + + @Value("${university.api.key}") + private String apiKey; + + public List getAllMajor() { + String url = UNIVERSITY_API_URL.value() + apiKey + FETCH_ALL_DEPARTMENT_URL.value(); + String response = restTemplate.getForObject(url, String.class); + List allMajor = new ArrayList<>(); + fetchAllMajor(response, allMajor); + return allMajor; + } + + public void patchDepartmentQueue(final Map> baseMap, + final String majorSeq){ + Map> addingMap = getDepartmentsOfUniversity(majorSeq); + for (Map.Entry> entry : addingMap.entrySet()) { + baseMap.computeIfAbsent(entry.getKey(), k -> new HashSet<>()).addAll(entry.getValue()); + } + } + + private Map> getDepartmentsOfUniversity(final String majorSeq) { + String url = UNIVERSITY_API_URL.value() + apiKey + FETCH_ALL_UNIVERSITY_BY_DEPARTMENT_URL.value() + majorSeq; + String response = restTemplate.getForObject(url, String.class); + Map> universityAndDepartments = new HashMap<>(); + fetchAllDepartments(response, universityAndDepartments); + return universityAndDepartments; + } + + private void fetchAllMajor(final String response, final List allMajor) { + try { + JsonNode root = objectMapper.readTree(response); + JsonNode content = root.path(DATA_SEARCH.value()).path(CONTENT.value()); + + for (JsonNode item : content) { + String majorSeq = item.get(MAJOR_SEQ.value()).asText(); + allMajor.add(majorSeq); + } + } catch (JsonProcessingException e) { + throw new InternalServerException(CRAWLING_PARSE_ERROR.message()); + } + } + + private void fetchAllDepartments(final String response, final Map> universityAndDepartments) { + try { + JsonNode root = objectMapper.readTree(response); + JsonNode content = root.path(DATA_SEARCH.value()).path(CONTENT.value()); + + for (JsonNode item : content) { + JsonNode universities = item.path(UNIVERSITY.value()); + for (JsonNode university : universities) { + String departmentName = university.path(MAJOR_NAME.value()).asText(); + String universityName = university.path(SCHOOL_NAME.value()).asText(); + patchMap(universityAndDepartments, universityName, departmentName); + } + } + } catch (JsonProcessingException e) { + throw new InternalServerException(CRAWLING_PARSE_ERROR.message()); + } + } + + private void patchMap(final Map> universityAndDepartments, final String universityName, final String departmentName) { + Set departments = universityAndDepartments + .computeIfAbsent(universityName, k -> new HashSet<>()); + departments.add(departmentName); + } +} diff --git a/backend/src/main/java/moim_today/presentation/university/UniversityController.java b/backend/src/main/java/moim_today/presentation/university/UniversityController.java index 1a9d0008..16263841 100644 --- a/backend/src/main/java/moim_today/presentation/university/UniversityController.java +++ b/backend/src/main/java/moim_today/presentation/university/UniversityController.java @@ -25,13 +25,13 @@ public UniversityController(final UniversityService universityService, final Dep } @PostMapping - public void updateCollegeInfo(){ - universityService.putAllUniversity(); + public void updateUniversityInfo(){ + universityService.patchAllUniversity(); } @PostMapping("/departments") public void updateDepartmentInfo(){ - departmentService.putAllDepartment(); + departmentService.patchAllDepartment(); } @GetMapping diff --git a/backend/src/test/java/moim_today/presentation/university/UniversityControllerTest.java b/backend/src/test/java/moim_today/presentation/university/UniversityControllerTest.java new file mode 100644 index 00000000..725fff1f --- /dev/null +++ b/backend/src/test/java/moim_today/presentation/university/UniversityControllerTest.java @@ -0,0 +1,20 @@ +package moim_today.presentation.university; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class UniversityControllerTest { + + @DisplayName("모든 대학교 정보를 가져오는 API") + @Test + void getUniversity() { + } + + @DisplayName("한 대학교의 모든 학과를 가져오는 API") + @Test + void getDepartments() { + } + +} \ No newline at end of file From af4f0db082c57104331ae3ee36c06e588ed6ff00 Mon Sep 17 00:00:00 2001 From: Donghyun Kim Date: Wed, 1 May 2024 10:44:39 +0900 Subject: [PATCH 46/52] =?UTF-8?q?[BE]=20refator=20:=20=EB=8C=80=ED=95=99?= =?UTF-8?q?=EA=B5=90=20=ED=95=99=EA=B3=BC=20=EC=9A=94=EC=B2=AD=20API=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC=20=EB=B0=8F=20=EB=AC=B8=EC=84=9C=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../department/DepartmentService.java | 4 +- .../department/DepartmentServiceImpl.java | 11 ++- .../moim_today/global/config/WebConfig.java | 4 +- .../department/DepartmentFinder.java | 20 ++--- .../department/DepartmentController.java | 39 +++++++++ .../university/UniversityController.java | 26 ++---- .../department/FakeDepartmentService.java | 19 +++++ .../university/FakeUniversityService.java | 19 +++++ .../department/DepartmentControllerTest.java | 79 +++++++++++++++++++ .../university/UniversityControllerTest.java | 43 ++++++++-- .../java/moim_today/util/TestConstant.java | 2 + 11 files changed, 220 insertions(+), 46 deletions(-) create mode 100644 backend/src/main/java/moim_today/presentation/department/DepartmentController.java create mode 100644 backend/src/test/java/moim_today/fake_class/department/FakeDepartmentService.java create mode 100644 backend/src/test/java/moim_today/fake_class/university/FakeUniversityService.java create mode 100644 backend/src/test/java/moim_today/presentation/department/DepartmentControllerTest.java diff --git a/backend/src/main/java/moim_today/application/department/DepartmentService.java b/backend/src/main/java/moim_today/application/department/DepartmentService.java index de0016a9..d3f2429d 100644 --- a/backend/src/main/java/moim_today/application/department/DepartmentService.java +++ b/backend/src/main/java/moim_today/application/department/DepartmentService.java @@ -8,5 +8,7 @@ public interface DepartmentService { void patchAllDepartment(); - List getAllDepartment(final long universityId, String universityName); + List getAllDepartmentByUniversityName(final String universityName); + + List getAllDepartmentById(final long universityId); } diff --git a/backend/src/main/java/moim_today/application/department/DepartmentServiceImpl.java b/backend/src/main/java/moim_today/application/department/DepartmentServiceImpl.java index 4d703051..0cf776cb 100644 --- a/backend/src/main/java/moim_today/application/department/DepartmentServiceImpl.java +++ b/backend/src/main/java/moim_today/application/department/DepartmentServiceImpl.java @@ -8,7 +8,7 @@ import java.util.List; @Service -public class DepartmentServiceImpl implements DepartmentService{ +public class DepartmentServiceImpl implements DepartmentService { private final DepartmentAppender departmentAppender; private final DepartmentFinder departmentFinder; @@ -24,7 +24,12 @@ public void patchAllDepartment() { } @Override - public List getAllDepartment(final long universityId, final String universityName) { - return departmentFinder.getAllDepartment(universityId, universityName); + public List getAllDepartmentByUniversityName(final String universityName) { + return departmentFinder.getAllDepartmentByUniversityName(universityName); + } + + @Override + public List getAllDepartmentById(final long universityId) { + return departmentFinder.getAllDepartmentById(universityId); } } diff --git a/backend/src/main/java/moim_today/global/config/WebConfig.java b/backend/src/main/java/moim_today/global/config/WebConfig.java index 851ecd53..f0d2b477 100644 --- a/backend/src/main/java/moim_today/global/config/WebConfig.java +++ b/backend/src/main/java/moim_today/global/config/WebConfig.java @@ -30,7 +30,9 @@ public void addInterceptors(final InterceptorRegistry registry) { "/api/moims/detail", "/api/sign-up", "/api/universities", - "/api/universities/departments/**" + "/api/universities/departments/**", + "/api/departments/university-name", + "/api/departments/university-id" ); } diff --git a/backend/src/main/java/moim_today/implement/department/DepartmentFinder.java b/backend/src/main/java/moim_today/implement/department/DepartmentFinder.java index 3b38834e..f4ba1f12 100644 --- a/backend/src/main/java/moim_today/implement/department/DepartmentFinder.java +++ b/backend/src/main/java/moim_today/implement/department/DepartmentFinder.java @@ -32,22 +32,18 @@ public void isDepartmentAssociatedWithUniversity(final long universityId, final } } - public List getAllDepartment(final long universityId, final String universityName){ - if(universityId != Long.parseLong(NO_UNIVERSITY_ID)){ - return getAllDepartmentByUniversityId(universityId); - } + public List getAllDepartmentByUniversityName(final String universityName){ if(!universityName.isEmpty()){ - return getAllDepartmentByUniversityName(universityName); + long universityId = universityRepository.getByName(universityName).getId(); + return departmentRepository.findAllDepartmentOfUniversity(universityId); } throw new BadRequestException(UNIVERSITY_SEARCH_CONDITIONS_INSUFFICIENT.message()); } - private List getAllDepartmentByUniversityId(final long universityId) { - return departmentRepository.findAllDepartmentOfUniversity(universityId); - } - - private List getAllDepartmentByUniversityName(final String universityName) { - long universityId = universityRepository.getByName(universityName).getId(); - return departmentRepository.findAllDepartmentOfUniversity(universityId); + public List getAllDepartmentById(final long universityId){ + if(universityId != Long.parseLong(NO_UNIVERSITY_ID)){ + return departmentRepository.findAllDepartmentOfUniversity(universityId); + } + throw new BadRequestException(UNIVERSITY_SEARCH_CONDITIONS_INSUFFICIENT.message()); } } diff --git a/backend/src/main/java/moim_today/presentation/department/DepartmentController.java b/backend/src/main/java/moim_today/presentation/department/DepartmentController.java new file mode 100644 index 00000000..eefbd661 --- /dev/null +++ b/backend/src/main/java/moim_today/presentation/department/DepartmentController.java @@ -0,0 +1,39 @@ +package moim_today.presentation.department; + +import moim_today.application.department.DepartmentService; +import moim_today.dto.department.DepartmentInfoResponse; +import moim_today.global.response.CollectionResponse; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +import static moim_today.global.constant.StaticSymbolConstant.BLANK; +import static moim_today.global.constant.StaticSymbolConstant.NO_UNIVERSITY_ID; + +@RequestMapping("/api/departments") +@RestController +public class DepartmentController { + + private final DepartmentService departmentService; + + public DepartmentController(final DepartmentService departmentService) { + this.departmentService = departmentService; + } + + @PostMapping + public void updateDepartmentInfo() { + departmentService.patchAllDepartment(); + } + + @GetMapping("/university-name") + public CollectionResponse> getDepartmentsByUniversityName( + @RequestParam(defaultValue = BLANK) final String universityName) { + return CollectionResponse.of(departmentService.getAllDepartmentByUniversityName(universityName)); + } + + @GetMapping("/university-id") + public CollectionResponse> getDepartmentsByUniversityId( + @RequestParam(defaultValue = NO_UNIVERSITY_ID) final long universityId) { + return CollectionResponse.of(departmentService.getAllDepartmentById(universityId)); + } +} \ No newline at end of file diff --git a/backend/src/main/java/moim_today/presentation/university/UniversityController.java b/backend/src/main/java/moim_today/presentation/university/UniversityController.java index 16263841..d5150b86 100644 --- a/backend/src/main/java/moim_today/presentation/university/UniversityController.java +++ b/backend/src/main/java/moim_today/presentation/university/UniversityController.java @@ -1,27 +1,23 @@ package moim_today.presentation.university; -import moim_today.application.department.DepartmentService; import moim_today.application.university.UniversityService; -import moim_today.dto.department.DepartmentInfoResponse; import moim_today.dto.university.UniversityInfoResponse; import moim_today.global.response.CollectionResponse; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; import java.util.List; -import static moim_today.global.constant.StaticSymbolConstant.BLANK; -import static moim_today.global.constant.StaticSymbolConstant.NO_UNIVERSITY_ID; - @RequestMapping("/api/universities") @RestController public class UniversityController { private final UniversityService universityService; - private final DepartmentService departmentService; - public UniversityController(final UniversityService universityService, final DepartmentService departmentService) { + public UniversityController(final UniversityService universityService) { this.universityService = universityService; - this.departmentService = departmentService; } @PostMapping @@ -29,20 +25,8 @@ public void updateUniversityInfo(){ universityService.patchAllUniversity(); } - @PostMapping("/departments") - public void updateDepartmentInfo(){ - departmentService.patchAllDepartment(); - } - @GetMapping public CollectionResponse> getUniversity(){ return CollectionResponse.of(universityService.getUniversities()); } - - @GetMapping("/departments") - public CollectionResponse> getDepartments( - @RequestParam(defaultValue = NO_UNIVERSITY_ID, required = false) final long universityId, - @RequestParam(defaultValue = BLANK, required = false) final String universityName) { - return CollectionResponse.of(departmentService.getAllDepartment(universityId, universityName)); - } } diff --git a/backend/src/test/java/moim_today/fake_class/department/FakeDepartmentService.java b/backend/src/test/java/moim_today/fake_class/department/FakeDepartmentService.java new file mode 100644 index 00000000..adb1173c --- /dev/null +++ b/backend/src/test/java/moim_today/fake_class/department/FakeDepartmentService.java @@ -0,0 +1,19 @@ +package moim_today.fake_class.department; + +import moim_today.application.department.DepartmentService; +import moim_today.dto.department.DepartmentInfoResponse; + +import java.util.List; + +public class FakeDepartmentService implements DepartmentService { + + @Override + public void patchAllDepartment() { + + } + + @Override + public List getAllDepartment(final long universityId, final String universityName) { + return null; + } +} diff --git a/backend/src/test/java/moim_today/fake_class/university/FakeUniversityService.java b/backend/src/test/java/moim_today/fake_class/university/FakeUniversityService.java new file mode 100644 index 00000000..847b997a --- /dev/null +++ b/backend/src/test/java/moim_today/fake_class/university/FakeUniversityService.java @@ -0,0 +1,19 @@ +package moim_today.fake_class.university; + +import moim_today.application.university.UniversityService; +import moim_today.dto.university.UniversityInfoResponse; + +import java.util.List; + +public class FakeUniversityService implements UniversityService { + + @Override + public void patchAllUniversity() { + + } + + @Override + public List getUniversities() { + return null; + } +} diff --git a/backend/src/test/java/moim_today/presentation/department/DepartmentControllerTest.java b/backend/src/test/java/moim_today/presentation/department/DepartmentControllerTest.java new file mode 100644 index 00000000..685e83e8 --- /dev/null +++ b/backend/src/test/java/moim_today/presentation/department/DepartmentControllerTest.java @@ -0,0 +1,79 @@ +package moim_today.presentation.department; + +import com.epages.restdocs.apispec.ResourceSnippetParameters; +import moim_today.fake_class.department.FakeDepartmentService; +import moim_today.util.ControllerTest; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static com.epages.restdocs.apispec.ResourceDocumentation.resource; +import static javax.management.openmbean.SimpleType.STRING; +import static moim_today.global.constant.StaticSymbolConstant.BLANK; +import static moim_today.global.constant.StaticSymbolConstant.NO_UNIVERSITY_ID; +import static moim_today.util.TestConstant.*; +import static org.springframework.http.MediaType.APPLICATION_JSON; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.snippet.Attributes.key; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +class DepartmentControllerTest extends ControllerTest { + + private final FakeDepartmentService fakeDepartmentService = new FakeDepartmentService(); + + @Override + protected Object initController() { + return new DepartmentController(fakeDepartmentService); + } + + @DisplayName("한 대학교의 모든 학과를 대학교 ID로 가져오는 API") + @Test + void getDepartmentsById() throws Exception { + mockMvc.perform(get("/api/departments/university-id") + .param(UNIVERSITY_ID.value(), UNIV_ID.value()) + .contentType(APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(document("대학교 ID로 모든 학과 조회 성공", + resource(ResourceSnippetParameters.builder() + .tag("학과") + .summary("대학교 ID로 모든 학과 조회") + .requestFields( + fieldWithPath("universityId").type(STRING).description("대학교 ID") + .optional().attributes(key("defaultValue").value(NO_UNIVERSITY_ID)) + ) + .responseFields( + fieldWithPath("[]").description("대학교 내 모든 학과의 정보 리스트"), + fieldWithPath("[].departmentId").description("학과 ID"), + fieldWithPath("[].departmentName").description("학과 이름"), + fieldWithPath("[].universityId").description("대학교 ID").optional() + ) + .build()) + )); + } + + @DisplayName("한 대학교의 모든 학과를 대학교 이름으로 가져오는 API") + @Test + void getDepartmentsByUniversityName() throws Exception { + mockMvc.perform(get("/api/departments/university-name") + .param(UNIVERSITY_NAME.value(), AJOU_UNIVERSITY_NAME.value()) + .contentType(APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(document("대학교 이름으로 모든 학과 조회 성공", + resource(ResourceSnippetParameters.builder() + .tag("학과") + .summary("대학교 이름으로 모든 학과 조회") + .requestFields( + fieldWithPath("universityName").type(STRING).description("대학교 이름") + .optional().attributes(key("defaultValue").value(BLANK)) + ) + .responseFields( + fieldWithPath("[]").description("대학교 내 모든 학과의 정보 리스트"), + fieldWithPath("[].departmentId").description("학과 ID"), + fieldWithPath("[].departmentName").description("학과 이름"), + fieldWithPath("[].universityId").description("대학교 ID").optional() + ) + .build()) + )); + } +} \ No newline at end of file diff --git a/backend/src/test/java/moim_today/presentation/university/UniversityControllerTest.java b/backend/src/test/java/moim_today/presentation/university/UniversityControllerTest.java index 725fff1f..5dd170e7 100644 --- a/backend/src/test/java/moim_today/presentation/university/UniversityControllerTest.java +++ b/backend/src/test/java/moim_today/presentation/university/UniversityControllerTest.java @@ -1,20 +1,47 @@ package moim_today.presentation.university; +import com.epages.restdocs.apispec.ResourceSnippetParameters; +import moim_today.fake_class.university.FakeUniversityService; +import moim_today.util.ControllerTest; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import static com.epages.restdocs.apispec.ResourceDocumentation.resource; +import static org.springframework.http.MediaType.APPLICATION_JSON; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.restdocs.payload.JsonFieldType.STRING; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -class UniversityControllerTest { +class UniversityControllerTest extends ControllerTest { - @DisplayName("모든 대학교 정보를 가져오는 API") - @Test - void getUniversity() { + private final FakeUniversityService fakeScheduleService = new FakeUniversityService(); + + @Override + protected Object initController() { + return new UniversityController(fakeScheduleService); } - @DisplayName("한 대학교의 모든 학과를 가져오는 API") + @DisplayName("모든 대학교 정보를 가져오는 API") @Test - void getDepartments() { - } + void getUniversity() throws Exception{ + mockMvc.perform(get("/api/universities") + .contentType(APPLICATION_JSON) + ) + .andExpect(status().isOk()) + .andDo(document("모든 대학교 정보 조회 성공", + resource(ResourceSnippetParameters.builder() + .tag("대학교") + .summary("모든 대학교 정보 조회") + .responseFields( + fieldWithPath("[]").type(STRING).description("대학교 정보 리스트"), + fieldWithPath("[].universityId").type(STRING).description("대학교 ID"), + fieldWithPath("[].universityName").type(STRING).description("대학교 이름"), + fieldWithPath("[].universityEmail").type(STRING).description("대학교 이메일 도메인") + ) + .build() + ))); + } } \ No newline at end of file diff --git a/backend/src/test/java/moim_today/util/TestConstant.java b/backend/src/test/java/moim_today/util/TestConstant.java index 74dd71c8..63577cc3 100644 --- a/backend/src/test/java/moim_today/util/TestConstant.java +++ b/backend/src/test/java/moim_today/util/TestConstant.java @@ -31,8 +31,10 @@ public enum TestConstant { // 대학교 + UNIVERSITY_ID("universityID"), UNIV_ID("194"), UNIVERSITY_NAME("universityName"), + AJOU_UNIVERSITY_NAME("아주대학교"), // 학과 DEPARTMENT_ID("9369"), From 395f44494dec6ac72253a8fcb7dd1b6802d4ac63 Mon Sep 17 00:00:00 2001 From: Donghyun Kim Date: Wed, 1 May 2024 10:46:03 +0900 Subject: [PATCH 47/52] =?UTF-8?q?[BE]=20fix=20:=20fake=20department=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fake_class/department/FakeDepartmentService.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/backend/src/test/java/moim_today/fake_class/department/FakeDepartmentService.java b/backend/src/test/java/moim_today/fake_class/department/FakeDepartmentService.java index adb1173c..c5aa308d 100644 --- a/backend/src/test/java/moim_today/fake_class/department/FakeDepartmentService.java +++ b/backend/src/test/java/moim_today/fake_class/department/FakeDepartmentService.java @@ -13,7 +13,12 @@ public void patchAllDepartment() { } @Override - public List getAllDepartment(final long universityId, final String universityName) { + public List getAllDepartmentByUniversityName(final String universityName) { + return null; + } + + @Override + public List getAllDepartmentById(final long universityId) { return null; } } From 39c6050fe6840399aef6d50d0358e47aed36a5e6 Mon Sep 17 00:00:00 2001 From: Donghyun Kim Date: Wed, 1 May 2024 11:44:44 +0900 Subject: [PATCH 48/52] =?UTF-8?q?[BE]=20test=20:=20=EB=AC=B8=EC=84=9C?= =?UTF-8?q?=ED=99=94=EC=9A=A9=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../department/FakeDepartmentService.java | 19 +++++++- .../university/FakeUniversityService.java | 11 ++++- .../department/DepartmentAppenderTest.java | 2 +- .../department/DepartmentFinderTest.java | 48 ++++++++++++++++++- .../department/DepartmentControllerTest.java | 25 +++++----- .../university/UniversityControllerTest.java | 19 +++++--- .../java/moim_today/util/TestConstant.java | 2 +- 7 files changed, 100 insertions(+), 26 deletions(-) diff --git a/backend/src/test/java/moim_today/fake_class/department/FakeDepartmentService.java b/backend/src/test/java/moim_today/fake_class/department/FakeDepartmentService.java index c5aa308d..60f24655 100644 --- a/backend/src/test/java/moim_today/fake_class/department/FakeDepartmentService.java +++ b/backend/src/test/java/moim_today/fake_class/department/FakeDepartmentService.java @@ -14,11 +14,26 @@ public void patchAllDepartment() { @Override public List getAllDepartmentByUniversityName(final String universityName) { - return null; + + // given + List mockData = List.of( + new DepartmentInfoResponse(1L, "소프트웨어학과"), + new DepartmentInfoResponse(2L, "의예과"), + new DepartmentInfoResponse(3L, "철학과") + ); + + return mockData; } @Override public List getAllDepartmentById(final long universityId) { - return null; + // given + List mockData = List.of( + new DepartmentInfoResponse(1L, "소프트웨어학과"), + new DepartmentInfoResponse(2L, "의예과"), + new DepartmentInfoResponse(3L, "철학과") + ); + + return mockData; } } diff --git a/backend/src/test/java/moim_today/fake_class/university/FakeUniversityService.java b/backend/src/test/java/moim_today/fake_class/university/FakeUniversityService.java index 847b997a..78044d6b 100644 --- a/backend/src/test/java/moim_today/fake_class/university/FakeUniversityService.java +++ b/backend/src/test/java/moim_today/fake_class/university/FakeUniversityService.java @@ -3,6 +3,7 @@ import moim_today.application.university.UniversityService; import moim_today.dto.university.UniversityInfoResponse; +import java.util.Arrays; import java.util.List; public class FakeUniversityService implements UniversityService { @@ -14,6 +15,14 @@ public void patchAllUniversity() { @Override public List getUniversities() { - return null; + + // given + List mockUniversities = Arrays.asList( + new UniversityInfoResponse(1, "가야대학교", "kaya.ac.kr"), + new UniversityInfoResponse(2, "가천대학교", "gachon.ac.kr"), + new UniversityInfoResponse(3, "가톨릭관동대학교", "cku.ac.kr") + ); + + return mockUniversities; } } diff --git a/backend/src/test/java/moim_today/implement/department/DepartmentAppenderTest.java b/backend/src/test/java/moim_today/implement/department/DepartmentAppenderTest.java index 5b70bd36..9f85576b 100644 --- a/backend/src/test/java/moim_today/implement/department/DepartmentAppenderTest.java +++ b/backend/src/test/java/moim_today/implement/department/DepartmentAppenderTest.java @@ -38,7 +38,7 @@ void batchUpdate() { // when departmentAppender.batchUpdate(departmentJpaEntities); - List allDepartment = departmentFinder.getAllDepartment(0, null); + List allDepartment = departmentFinder.getAllDepartmentById(0); // then assertThat(allDepartment.size()).isEqualTo(10); diff --git a/backend/src/test/java/moim_today/implement/department/DepartmentFinderTest.java b/backend/src/test/java/moim_today/implement/department/DepartmentFinderTest.java index 065369a4..b11a3006 100644 --- a/backend/src/test/java/moim_today/implement/department/DepartmentFinderTest.java +++ b/backend/src/test/java/moim_today/implement/department/DepartmentFinderTest.java @@ -1,5 +1,6 @@ package moim_today.implement.department; +import moim_today.dto.department.DepartmentInfoResponse; import moim_today.persistence.entity.department.DepartmentJpaEntity; import moim_today.persistence.entity.university.UniversityJpaEntity; import moim_today.util.ImplementTest; @@ -7,7 +8,10 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import java.util.List; + import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; class DepartmentFinderTest extends ImplementTest { @@ -41,7 +45,49 @@ void isDepartmentAssociatedWithUniversity() { } + @DisplayName("한 대학교의 모든 학과 대학교 이름으로 조회") + @Test + void getAllDepartmentByUniversityName() { + // given + UniversityJpaEntity universityJpaEntity = UniversityJpaEntity.builder() + .universityName(UNIV_NAME) + .universityEmail(UNIV_MAIL) + .build(); + UniversityJpaEntity saveUniv = universityRepository.save(universityJpaEntity); + + DepartmentJpaEntity departmentJpaEntity = DepartmentJpaEntity.builder() + .universityId(saveUniv.getId()) + .departmentName(DEPARTMENT_NAME) + .build(); + DepartmentJpaEntity saveDepart = departmentRepository.save(departmentJpaEntity); + + // when + List allDepartmentByUniversityName = departmentFinder.getAllDepartmentByUniversityName(UNIV_NAME); + + // then + assertThat(allDepartmentByUniversityName.size()).isEqualTo(1); + } + + @DisplayName("한 대학교의 모든 학과 대학교 ID로 조회") @Test - void getAllDepartment() { + void getAllDepartmentByUniversityId() { + // given + UniversityJpaEntity universityJpaEntity = UniversityJpaEntity.builder() + .universityName(UNIV_NAME) + .universityEmail(UNIV_MAIL) + .build(); + UniversityJpaEntity saveUniv = universityRepository.save(universityJpaEntity); + + DepartmentJpaEntity departmentJpaEntity = DepartmentJpaEntity.builder() + .universityId(saveUniv.getId()) + .departmentName(DEPARTMENT_NAME) + .build(); + DepartmentJpaEntity saveDepart = departmentRepository.save(departmentJpaEntity); + + // when + List allDepartmentByUniversityId = departmentFinder.getAllDepartmentById(saveUniv.getId()); + + // then + assertThat(allDepartmentByUniversityId.size()).isEqualTo(1); } } \ No newline at end of file diff --git a/backend/src/test/java/moim_today/presentation/department/DepartmentControllerTest.java b/backend/src/test/java/moim_today/presentation/department/DepartmentControllerTest.java index 685e83e8..e5947a78 100644 --- a/backend/src/test/java/moim_today/presentation/department/DepartmentControllerTest.java +++ b/backend/src/test/java/moim_today/presentation/department/DepartmentControllerTest.java @@ -6,14 +6,15 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import static com.epages.restdocs.apispec.ResourceDocumentation.parameterWithName; import static com.epages.restdocs.apispec.ResourceDocumentation.resource; -import static javax.management.openmbean.SimpleType.STRING; import static moim_today.global.constant.StaticSymbolConstant.BLANK; import static moim_today.global.constant.StaticSymbolConstant.NO_UNIVERSITY_ID; import static moim_today.util.TestConstant.*; import static org.springframework.http.MediaType.APPLICATION_JSON; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.restdocs.payload.JsonFieldType.*; import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; import static org.springframework.restdocs.snippet.Attributes.key; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -38,15 +39,14 @@ void getDepartmentsById() throws Exception { resource(ResourceSnippetParameters.builder() .tag("학과") .summary("대학교 ID로 모든 학과 조회") - .requestFields( - fieldWithPath("universityId").type(STRING).description("대학교 ID") + .queryParameters( + parameterWithName("universityId").description("대학교 ID") .optional().attributes(key("defaultValue").value(NO_UNIVERSITY_ID)) ) .responseFields( - fieldWithPath("[]").description("대학교 내 모든 학과의 정보 리스트"), - fieldWithPath("[].departmentId").description("학과 ID"), - fieldWithPath("[].departmentName").description("학과 이름"), - fieldWithPath("[].universityId").description("대학교 ID").optional() + fieldWithPath("data").type(ARRAY).description("대학교 내 모든 학과의 정보 리스트"), + fieldWithPath("data[].departmentId").type(NUMBER).description("학과 ID"), + fieldWithPath("data[].departmentName").type(STRING).description("학과 이름") ) .build()) )); @@ -63,15 +63,14 @@ void getDepartmentsByUniversityName() throws Exception { resource(ResourceSnippetParameters.builder() .tag("학과") .summary("대학교 이름으로 모든 학과 조회") - .requestFields( - fieldWithPath("universityName").type(STRING).description("대학교 이름") + .queryParameters( + parameterWithName("universityName").description("대학교 이름") .optional().attributes(key("defaultValue").value(BLANK)) ) .responseFields( - fieldWithPath("[]").description("대학교 내 모든 학과의 정보 리스트"), - fieldWithPath("[].departmentId").description("학과 ID"), - fieldWithPath("[].departmentName").description("학과 이름"), - fieldWithPath("[].universityId").description("대학교 ID").optional() + fieldWithPath("data").type(ARRAY).description("대학교 내 모든 학과의 정보 리스트"), + fieldWithPath("data[].departmentId").type(NUMBER).description("학과 ID"), + fieldWithPath("data[].departmentName").type(STRING).description("학과 이름") ) .build()) )); diff --git a/backend/src/test/java/moim_today/presentation/university/UniversityControllerTest.java b/backend/src/test/java/moim_today/presentation/university/UniversityControllerTest.java index 5dd170e7..5d15f4bb 100644 --- a/backend/src/test/java/moim_today/presentation/university/UniversityControllerTest.java +++ b/backend/src/test/java/moim_today/presentation/university/UniversityControllerTest.java @@ -5,22 +5,23 @@ import moim_today.util.ControllerTest; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; import static com.epages.restdocs.apispec.ResourceDocumentation.resource; import static org.springframework.http.MediaType.APPLICATION_JSON; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.restdocs.payload.JsonFieldType.STRING; +import static org.springframework.restdocs.payload.JsonFieldType.*; import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; class UniversityControllerTest extends ControllerTest { - private final FakeUniversityService fakeScheduleService = new FakeUniversityService(); + private final FakeUniversityService fakeUniversityService = new FakeUniversityService(); @Override protected Object initController() { - return new UniversityController(fakeScheduleService); + return new UniversityController(fakeUniversityService); } @DisplayName("모든 대학교 정보를 가져오는 API") @@ -31,15 +32,19 @@ void getUniversity() throws Exception{ .contentType(APPLICATION_JSON) ) .andExpect(status().isOk()) + .andDo(MockMvcResultHandlers.print()) .andDo(document("모든 대학교 정보 조회 성공", resource(ResourceSnippetParameters.builder() .tag("대학교") .summary("모든 대학교 정보 조회") .responseFields( - fieldWithPath("[]").type(STRING).description("대학교 정보 리스트"), - fieldWithPath("[].universityId").type(STRING).description("대학교 ID"), - fieldWithPath("[].universityName").type(STRING).description("대학교 이름"), - fieldWithPath("[].universityEmail").type(STRING).description("대학교 이메일 도메인") + fieldWithPath("data").type(ARRAY).description("대학교 정보 리스트"), + fieldWithPath("data[].universityId").type(NUMBER) + .description("대학교 ID"), + fieldWithPath("data[].universityName").type(STRING) + .description("대학교 이름"), + fieldWithPath("data[].universityEmail").type(STRING) + .description("대학교 이메일 도메인") ) .build() ))); diff --git a/backend/src/test/java/moim_today/util/TestConstant.java b/backend/src/test/java/moim_today/util/TestConstant.java index 63577cc3..c8384f3b 100644 --- a/backend/src/test/java/moim_today/util/TestConstant.java +++ b/backend/src/test/java/moim_today/util/TestConstant.java @@ -31,7 +31,7 @@ public enum TestConstant { // 대학교 - UNIVERSITY_ID("universityID"), + UNIVERSITY_ID("universityId"), UNIV_ID("194"), UNIVERSITY_NAME("universityName"), AJOU_UNIVERSITY_NAME("아주대학교"), From 509b3b7fee00b7d87a42529f6ca9e09f1a64dc54 Mon Sep 17 00:00:00 2001 From: Jung-YouHwan Date: Wed, 1 May 2024 12:21:06 +0900 Subject: [PATCH 49/52] =?UTF-8?q?[BE]=20feat=20:=20CORS=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/moim_today/global/config/WebConfig.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/backend/src/main/java/moim_today/global/config/WebConfig.java b/backend/src/main/java/moim_today/global/config/WebConfig.java index beb8563f..a13f98ea 100644 --- a/backend/src/main/java/moim_today/global/config/WebConfig.java +++ b/backend/src/main/java/moim_today/global/config/WebConfig.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.context.annotation.Configuration; import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @@ -36,4 +37,12 @@ public void addInterceptors(final InterceptorRegistry registry) { public void addArgumentResolvers(final List resolvers) { resolvers.add(new MemberLoginArgumentResolver(objectMapper)); } + + @Override + public void addCorsMappings(final CorsRegistry registry) { + registry.addMapping("/**") + .allowedOrigins("https://moim.today") + .allowedMethods("*") + .allowCredentials(true); + } } From 8977d352a8ed33d1cba3b59feb95d29f2a449a51 Mon Sep 17 00:00:00 2001 From: Donghyun Kim Date: Wed, 1 May 2024 12:20:47 +0900 Subject: [PATCH 50/52] =?UTF-8?q?[BE]=20style=20:=20final=20=ED=82=A4?= =?UTF-8?q?=EC=9B=8C=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/moim_today/implement/university/UniversityUpdater.java | 2 +- .../persistence/entity/university/UniversityJpaEntity.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/moim_today/implement/university/UniversityUpdater.java b/backend/src/main/java/moim_today/implement/university/UniversityUpdater.java index f0599165..4fbd433b 100644 --- a/backend/src/main/java/moim_today/implement/university/UniversityUpdater.java +++ b/backend/src/main/java/moim_today/implement/university/UniversityUpdater.java @@ -28,7 +28,7 @@ public class UniversityUpdater { private String apiKey; public UniversityUpdater(final UniversityRepository universityRepository, - ObjectMapper objectMapper, RestTemplate restTemplate) { + final ObjectMapper objectMapper, final RestTemplate restTemplate) { this.universityRepository = universityRepository; this.objectMapper = objectMapper; this.restTemplate = restTemplate; diff --git a/backend/src/main/java/moim_today/persistence/entity/university/UniversityJpaEntity.java b/backend/src/main/java/moim_today/persistence/entity/university/UniversityJpaEntity.java index c1b1ce7b..52f04982 100644 --- a/backend/src/main/java/moim_today/persistence/entity/university/UniversityJpaEntity.java +++ b/backend/src/main/java/moim_today/persistence/entity/university/UniversityJpaEntity.java @@ -22,7 +22,7 @@ protected UniversityJpaEntity() { } @Builder - public UniversityJpaEntity(long id, final String universityName, final String universityEmail) { + public UniversityJpaEntity(final long id, final String universityName, final String universityEmail) { this.id = id; this.universityName = universityName; this.universityEmail = universityEmail; From c28759a7ff0243a032aeba6a8411956036587bb5 Mon Sep 17 00:00:00 2001 From: Donghyun Kim Date: Wed, 1 May 2024 13:52:29 +0900 Subject: [PATCH 51/52] =?UTF-8?q?[BE]=20refactor=20:=20=EB=AA=A8=ED=98=B8?= =?UTF-8?q?=ED=95=9C=20=ED=95=A8=EC=88=98=EB=AA=85=EA=B3=BC=20=EC=97=94?= =?UTF-8?q?=ED=8B=B0=ED=8B=B0=20=EC=97=AD=ED=95=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/university/UniversityService.java | 2 +- .../university/UniversityServiceImpl.java | 2 +- .../domain/university/ExtractUniversity.java | 9 +++++---- .../implement/university/UniversityUpdater.java | 15 ++++++--------- .../entity/university/UniversityJpaEntity.java | 2 +- .../university/UniversityController.java | 4 ++-- .../university/FakeUniversityService.java | 2 +- 7 files changed, 17 insertions(+), 19 deletions(-) diff --git a/backend/src/main/java/moim_today/application/university/UniversityService.java b/backend/src/main/java/moim_today/application/university/UniversityService.java index 44428a06..a646bc11 100644 --- a/backend/src/main/java/moim_today/application/university/UniversityService.java +++ b/backend/src/main/java/moim_today/application/university/UniversityService.java @@ -6,7 +6,7 @@ public interface UniversityService { - void patchAllUniversity(); + void fetchAllUniversity(); List getUniversities(); } diff --git a/backend/src/main/java/moim_today/application/university/UniversityServiceImpl.java b/backend/src/main/java/moim_today/application/university/UniversityServiceImpl.java index 598e9f5c..71e9cc1f 100644 --- a/backend/src/main/java/moim_today/application/university/UniversityServiceImpl.java +++ b/backend/src/main/java/moim_today/application/university/UniversityServiceImpl.java @@ -19,7 +19,7 @@ public UniversityServiceImpl(final UniversityUpdater universityUpdater, final Un } @Override - public void patchAllUniversity() { + public void fetchAllUniversity() { universityUpdater.fetchAllUniversity(); } diff --git a/backend/src/main/java/moim_today/domain/university/ExtractUniversity.java b/backend/src/main/java/moim_today/domain/university/ExtractUniversity.java index c9c4889a..897a9c77 100644 --- a/backend/src/main/java/moim_today/domain/university/ExtractUniversity.java +++ b/backend/src/main/java/moim_today/domain/university/ExtractUniversity.java @@ -64,10 +64,7 @@ private String extractSubstringBefore(final String startString) { public boolean checkUniversityType() { List universityType = List.of(ASSOCIATE_DEGREE.value(), GRADUATE_DEGREE.value()); - if (universityType.contains(this.schoolType)) { - return true; - } - return false; + return universityType.contains(this.schoolType); } public UniversityJpaEntity toEntity() { @@ -76,4 +73,8 @@ public UniversityJpaEntity toEntity() { .universityName(this.schoolName) .build(); } + + public boolean isEmailEmpty(){ + return link.isEmpty(); + } } diff --git a/backend/src/main/java/moim_today/implement/university/UniversityUpdater.java b/backend/src/main/java/moim_today/implement/university/UniversityUpdater.java index 4fbd433b..17c7770b 100644 --- a/backend/src/main/java/moim_today/implement/university/UniversityUpdater.java +++ b/backend/src/main/java/moim_today/implement/university/UniversityUpdater.java @@ -49,25 +49,22 @@ public void fetchAllUniversity() { continue; } extractUniversity.extractEmailExtension(); - putUniversity(extractUniversity.toEntity()); + putUniversity(extractUniversity); } } catch (JsonProcessingException e) { - e.printStackTrace(); throw new InternalServerException(CRAWLING_PARSE_ERROR.message()); } } @Transactional - public void putUniversity(final UniversityJpaEntity universityJpaEntity) { - Optional findUniversity = universityRepository.findByName(universityJpaEntity.getUniversityName()); + public void putUniversity(final ExtractUniversity extractUniversity) { + Optional findUniversity = universityRepository.findByName(extractUniversity.getSchoolName()); if (findUniversity.isEmpty()) { - universityRepository.save(universityJpaEntity); - return; - } - if (!universityJpaEntity.getUniversityEmail().isEmpty()) { + universityRepository.save(extractUniversity.toEntity()); + } else if (!extractUniversity.isEmailEmpty()) { UniversityJpaEntity getUniversity = findUniversity.get(); - getUniversity.updateEmail(universityJpaEntity.getUniversityEmail()); + getUniversity.updateEmail(extractUniversity.getLink()); universityRepository.save(getUniversity); } } diff --git a/backend/src/main/java/moim_today/persistence/entity/university/UniversityJpaEntity.java b/backend/src/main/java/moim_today/persistence/entity/university/UniversityJpaEntity.java index 52f04982..8cb0e271 100644 --- a/backend/src/main/java/moim_today/persistence/entity/university/UniversityJpaEntity.java +++ b/backend/src/main/java/moim_today/persistence/entity/university/UniversityJpaEntity.java @@ -28,7 +28,7 @@ public UniversityJpaEntity(final long id, final String universityName, final Str this.universityEmail = universityEmail; } - public void updateEmail(String universityEmail){ + public void updateEmail(final String universityEmail){ this.universityEmail = universityEmail; } } diff --git a/backend/src/main/java/moim_today/presentation/university/UniversityController.java b/backend/src/main/java/moim_today/presentation/university/UniversityController.java index d5150b86..c6ccf85f 100644 --- a/backend/src/main/java/moim_today/presentation/university/UniversityController.java +++ b/backend/src/main/java/moim_today/presentation/university/UniversityController.java @@ -21,8 +21,8 @@ public UniversityController(final UniversityService universityService) { } @PostMapping - public void updateUniversityInfo(){ - universityService.patchAllUniversity(); + public void fetchUniversityInfo(){ + universityService.fetchAllUniversity(); } @GetMapping diff --git a/backend/src/test/java/moim_today/fake_class/university/FakeUniversityService.java b/backend/src/test/java/moim_today/fake_class/university/FakeUniversityService.java index 78044d6b..9a5662b5 100644 --- a/backend/src/test/java/moim_today/fake_class/university/FakeUniversityService.java +++ b/backend/src/test/java/moim_today/fake_class/university/FakeUniversityService.java @@ -9,7 +9,7 @@ public class FakeUniversityService implements UniversityService { @Override - public void patchAllUniversity() { + public void fetchAllUniversity() { } From 2909b76fc39001feb20e7535f3d6d8e94c877a42 Mon Sep 17 00:00:00 2001 From: Donghyun Kim Date: Wed, 1 May 2024 14:05:00 +0900 Subject: [PATCH 52/52] =?UTF-8?q?[BE]=20fix=20:=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=98=A4=EB=A5=98=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../university/UniversityUpdaterTest.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/backend/src/test/java/moim_today/implement/university/UniversityUpdaterTest.java b/backend/src/test/java/moim_today/implement/university/UniversityUpdaterTest.java index 8f965ecb..3340435d 100644 --- a/backend/src/test/java/moim_today/implement/university/UniversityUpdaterTest.java +++ b/backend/src/test/java/moim_today/implement/university/UniversityUpdaterTest.java @@ -1,5 +1,6 @@ package moim_today.implement.university; +import moim_today.domain.university.ExtractUniversity; import moim_today.persistence.entity.university.UniversityJpaEntity; import moim_today.util.ImplementTest; import org.junit.jupiter.api.DisplayName; @@ -28,13 +29,13 @@ class UniversityUpdaterTest extends ImplementTest { universityRepository.save(universityJpaEntity); - UniversityJpaEntity updateUniversity = UniversityJpaEntity.builder() - .universityName(AJOU_UNIV_NAME) - .universityEmail(AJOU_EMAIL) + ExtractUniversity extractUniversity = ExtractUniversity.builder() + .schoolName(AJOU_UNIV_NAME) + .link(AJOU_EMAIL) .build(); // when - universityUpdater.putUniversity(updateUniversity); + universityUpdater.putUniversity(extractUniversity); UniversityJpaEntity findUniversity = universityRepository.findByName(AJOU_UNIV_NAME).get(); // then @@ -45,13 +46,13 @@ class UniversityUpdaterTest extends ImplementTest { @Test void 중복되는_대학이름이_없을_때_putUniversity(){ // given - UniversityJpaEntity universityJpaEntity = UniversityJpaEntity.builder() - .universityName(AJOU_UNIV_NAME) - .universityEmail(AJOU_EMAIL) + ExtractUniversity extractUniversity = ExtractUniversity.builder() + .schoolName(AJOU_UNIV_NAME) + .link(AJOU_EMAIL) .build(); // when - universityUpdater.putUniversity(universityJpaEntity); + universityUpdater.putUniversity(extractUniversity); UniversityJpaEntity findUniversity = universityRepository.findByName(AJOU_UNIV_NAME).get(); // then