From d323db9d5c6f0c08c71a053ccc15d3e60b3ecaa0 Mon Sep 17 00:00:00 2001 From: kevstevie Date: Wed, 1 Nov 2023 15:55:48 +0900 Subject: [PATCH 01/22] =?UTF-8?q?refactor:=20base=20root=20entity=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/domain/{ => base}/BaseEntity.java | 25 +--------------- .../backend/domain/base/BaseRootEntity.java | 30 +++++++++++++++++++ .../domain/certification/Certification.java | 2 +- .../backend/domain/feedpost/FeedPost.java | 2 +- .../MeetingDayOfTheWeek.java | 2 +- .../backend/domain/member/Member.java | 14 ++++----- .../backend/domain/report/Report.java | 2 +- .../yigongil/backend/domain/round/Round.java | 2 +- .../domain/roundofmember/RoundOfMember.java | 2 +- .../yigongil/backend/domain/study/Study.java | 2 +- .../domain/studymember/StudyMember.java | 2 +- 11 files changed, 45 insertions(+), 40 deletions(-) rename backend/src/main/java/com/yigongil/backend/domain/{ => base}/BaseEntity.java (52%) create mode 100644 backend/src/main/java/com/yigongil/backend/domain/base/BaseRootEntity.java diff --git a/backend/src/main/java/com/yigongil/backend/domain/BaseEntity.java b/backend/src/main/java/com/yigongil/backend/domain/base/BaseEntity.java similarity index 52% rename from backend/src/main/java/com/yigongil/backend/domain/BaseEntity.java rename to backend/src/main/java/com/yigongil/backend/domain/base/BaseEntity.java index 90980c463..9ac525b09 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/BaseEntity.java +++ b/backend/src/main/java/com/yigongil/backend/domain/base/BaseEntity.java @@ -1,17 +1,11 @@ -package com.yigongil.backend.domain; +package com.yigongil.backend.domain.base; -import com.yigongil.backend.domain.event.DomainEvent; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.Collection; import javax.persistence.Column; import javax.persistence.EntityListeners; import javax.persistence.MappedSuperclass; -import javax.persistence.Transient; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; -import org.springframework.data.domain.AfterDomainEventPublication; -import org.springframework.data.domain.DomainEvents; import org.springframework.data.jpa.domain.support.AuditingEntityListener; @EntityListeners(AuditingEntityListener.class) @@ -25,23 +19,6 @@ public abstract class BaseEntity { @LastModifiedDate protected LocalDateTime updatedAt; - @Transient - private Collection domainEvents = new ArrayList<>(); - - @DomainEvents - public Collection events() { - return domainEvents; - } - - @AfterDomainEventPublication - public void clear() { - domainEvents.clear(); - } - - protected void register(DomainEvent event) { - domainEvents.add(event); - } - public LocalDateTime getCreatedAt() { return createdAt; } diff --git a/backend/src/main/java/com/yigongil/backend/domain/base/BaseRootEntity.java b/backend/src/main/java/com/yigongil/backend/domain/base/BaseRootEntity.java new file mode 100644 index 000000000..05f86ab89 --- /dev/null +++ b/backend/src/main/java/com/yigongil/backend/domain/base/BaseRootEntity.java @@ -0,0 +1,30 @@ +package com.yigongil.backend.domain.base; + +import java.time.LocalDateTime; +import javax.persistence.Column; +import javax.persistence.EntityListeners; +import javax.persistence.MappedSuperclass; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.domain.AbstractAggregateRoot; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +@EntityListeners(AuditingEntityListener.class) +@MappedSuperclass +public class BaseRootEntity extends AbstractAggregateRoot { + + @CreatedDate + @Column(nullable = false) + protected LocalDateTime createdAt; + + @LastModifiedDate + protected LocalDateTime updatedAt; + + public LocalDateTime getCreatedAt() { + return createdAt; + } + + public LocalDateTime getUpdatedAt() { + return updatedAt; + } +} diff --git a/backend/src/main/java/com/yigongil/backend/domain/certification/Certification.java b/backend/src/main/java/com/yigongil/backend/domain/certification/Certification.java index 32824b93f..761259445 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/certification/Certification.java +++ b/backend/src/main/java/com/yigongil/backend/domain/certification/Certification.java @@ -1,6 +1,6 @@ package com.yigongil.backend.domain.certification; -import com.yigongil.backend.domain.BaseEntity; +import com.yigongil.backend.domain.base.BaseEntity; import com.yigongil.backend.domain.member.Member; import com.yigongil.backend.domain.round.Round; import com.yigongil.backend.domain.study.Study; diff --git a/backend/src/main/java/com/yigongil/backend/domain/feedpost/FeedPost.java b/backend/src/main/java/com/yigongil/backend/domain/feedpost/FeedPost.java index 1c2b96324..79eda8d10 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/feedpost/FeedPost.java +++ b/backend/src/main/java/com/yigongil/backend/domain/feedpost/FeedPost.java @@ -1,6 +1,6 @@ package com.yigongil.backend.domain.feedpost; -import com.yigongil.backend.domain.BaseEntity; +import com.yigongil.backend.domain.base.BaseEntity; import com.yigongil.backend.domain.member.Member; import com.yigongil.backend.domain.study.Study; import java.time.LocalDateTime; diff --git a/backend/src/main/java/com/yigongil/backend/domain/meetingdayoftheweek/MeetingDayOfTheWeek.java b/backend/src/main/java/com/yigongil/backend/domain/meetingdayoftheweek/MeetingDayOfTheWeek.java index 393de93b3..85554be33 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/meetingdayoftheweek/MeetingDayOfTheWeek.java +++ b/backend/src/main/java/com/yigongil/backend/domain/meetingdayoftheweek/MeetingDayOfTheWeek.java @@ -1,6 +1,6 @@ package com.yigongil.backend.domain.meetingdayoftheweek; -import com.yigongil.backend.domain.BaseEntity; +import com.yigongil.backend.domain.base.BaseEntity; import com.yigongil.backend.domain.study.Study; import java.time.DayOfWeek; import javax.persistence.Entity; diff --git a/backend/src/main/java/com/yigongil/backend/domain/member/Member.java b/backend/src/main/java/com/yigongil/backend/domain/member/Member.java index 054eb242d..b63c28d2b 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/member/Member.java +++ b/backend/src/main/java/com/yigongil/backend/domain/member/Member.java @@ -1,6 +1,6 @@ package com.yigongil.backend.domain.member; -import com.yigongil.backend.domain.BaseEntity; +import com.yigongil.backend.domain.base.BaseRootEntity; import com.yigongil.backend.domain.event.MemberDeleteEvent; import java.util.Objects; import javax.persistence.Column; @@ -17,11 +17,7 @@ @Getter @SQLDelete(sql = Member.DELETE_QUERY) @Entity -public class Member extends BaseEntity { - - private static final int MASTER_NUMBER = 0; - private static final int PARTICIPANT_NUMBER = 1; - private static final int MAXIMUM_TIER = 5; +public class Member extends BaseRootEntity { protected static final String DELETE_QUERY = """ update member @@ -32,7 +28,9 @@ public class Member extends BaseEntity { deleted = true where id = ? """; - + private static final int MASTER_NUMBER = 0; + private static final int PARTICIPANT_NUMBER = 1; + private static final int MAXIMUM_TIER = 5; @GeneratedValue(strategy = GenerationType.IDENTITY) @Id private Long id; @@ -103,7 +101,7 @@ public String getIntroduction() { @PreRemove public void registerDeleteEvent() { - register(new MemberDeleteEvent(id)); + registerEvent(new MemberDeleteEvent(id)); } public void addExperience(int exp) { diff --git a/backend/src/main/java/com/yigongil/backend/domain/report/Report.java b/backend/src/main/java/com/yigongil/backend/domain/report/Report.java index b58ffc469..48516db1d 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/report/Report.java +++ b/backend/src/main/java/com/yigongil/backend/domain/report/Report.java @@ -1,6 +1,6 @@ package com.yigongil.backend.domain.report; -import com.yigongil.backend.domain.BaseEntity; +import com.yigongil.backend.domain.base.BaseEntity; import com.yigongil.backend.domain.member.Member; import com.yigongil.backend.exception.InvalidReportContentLengthException; import com.yigongil.backend.exception.InvalidReportTitleLengthException; diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/Round.java b/backend/src/main/java/com/yigongil/backend/domain/round/Round.java index 79795fb48..6555a9197 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/round/Round.java +++ b/backend/src/main/java/com/yigongil/backend/domain/round/Round.java @@ -1,6 +1,6 @@ package com.yigongil.backend.domain.round; -import com.yigongil.backend.domain.BaseEntity; +import com.yigongil.backend.domain.base.BaseEntity; import com.yigongil.backend.domain.meetingdayoftheweek.MeetingDayOfTheWeek; import com.yigongil.backend.domain.member.Member; import com.yigongil.backend.domain.roundofmember.RoundOfMember; diff --git a/backend/src/main/java/com/yigongil/backend/domain/roundofmember/RoundOfMember.java b/backend/src/main/java/com/yigongil/backend/domain/roundofmember/RoundOfMember.java index 290cb1ef0..fe13aa35b 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/roundofmember/RoundOfMember.java +++ b/backend/src/main/java/com/yigongil/backend/domain/roundofmember/RoundOfMember.java @@ -1,6 +1,6 @@ package com.yigongil.backend.domain.roundofmember; -import com.yigongil.backend.domain.BaseEntity; +import com.yigongil.backend.domain.base.BaseEntity; import com.yigongil.backend.domain.member.Member; import com.yigongil.backend.domain.study.Study; import java.util.List; diff --git a/backend/src/main/java/com/yigongil/backend/domain/study/Study.java b/backend/src/main/java/com/yigongil/backend/domain/study/Study.java index 4082e0aa1..3a5015549 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/study/Study.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/Study.java @@ -1,6 +1,6 @@ package com.yigongil.backend.domain.study; -import com.yigongil.backend.domain.BaseEntity; +import com.yigongil.backend.domain.base.BaseEntity; import com.yigongil.backend.domain.meetingdayoftheweek.MeetingDayOfTheWeek; import com.yigongil.backend.domain.member.Member; import com.yigongil.backend.domain.round.Round; diff --git a/backend/src/main/java/com/yigongil/backend/domain/studymember/StudyMember.java b/backend/src/main/java/com/yigongil/backend/domain/studymember/StudyMember.java index c4168869e..9deb8ae3b 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/studymember/StudyMember.java +++ b/backend/src/main/java/com/yigongil/backend/domain/studymember/StudyMember.java @@ -1,6 +1,6 @@ package com.yigongil.backend.domain.studymember; -import com.yigongil.backend.domain.BaseEntity; +import com.yigongil.backend.domain.base.BaseEntity; import com.yigongil.backend.domain.member.Member; import com.yigongil.backend.domain.study.Study; import java.util.Objects; From b047845d4c8697e71eea125488cfe4aa7cb7b63b Mon Sep 17 00:00:00 2001 From: bjk1649 Date: Wed, 1 Nov 2023 23:42:54 +0900 Subject: [PATCH 02/22] =?UTF-8?q?refactor:=20round=EC=97=90=EC=84=9C=20mee?= =?UTF-8?q?tingDayOfTheWeek=20=EC=97=90=20=EB=8C=80=ED=95=9C=20=EC=9D=98?= =?UTF-8?q?=EC=A1=B4=EC=84=B1=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yigongil/backend/domain/round/Round.java | 28 ++++++++----------- .../yigongil/backend/domain/study/Study.java | 9 +++--- ...emove_meeting_day_of_the_week_In_round.sql | 10 +++++++ 3 files changed, 26 insertions(+), 21 deletions(-) create mode 100644 backend/src/main/resources/db/migration/V13_remove_meeting_day_of_the_week_In_round.sql diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/Round.java b/backend/src/main/java/com/yigongil/backend/domain/round/Round.java index 6555a9197..0b515c775 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/round/Round.java +++ b/backend/src/main/java/com/yigongil/backend/domain/round/Round.java @@ -1,7 +1,6 @@ package com.yigongil.backend.domain.round; import com.yigongil.backend.domain.base.BaseEntity; -import com.yigongil.backend.domain.meetingdayoftheweek.MeetingDayOfTheWeek; import com.yigongil.backend.domain.member.Member; import com.yigongil.backend.domain.roundofmember.RoundOfMember; import com.yigongil.backend.domain.study.Study; @@ -60,9 +59,8 @@ public class Round extends BaseEntity { @JoinColumn(name = "round_id", nullable = false) private List roundOfMembers = new ArrayList<>(); - @Cascade(CascadeType.PERSIST) - @ManyToOne(fetch = FetchType.LAZY) - private MeetingDayOfTheWeek meetingDayOfTheWeek; + @Enumerated(EnumType.ORDINAL) + private DayOfWeek dayOfWeek; @Column(nullable = false) private Integer weekNumber; @@ -80,7 +78,7 @@ public Round( String mustDo, Member master, List roundOfMembers, - MeetingDayOfTheWeek meetingDayOfTheWeek, + DayOfWeek dayOfWeek, Integer weekNumber ) { this.id = id; @@ -88,14 +86,14 @@ public Round( this.mustDo = mustDo; this.master = master; this.roundOfMembers = roundOfMembers == null ? new ArrayList<>() : roundOfMembers; - this.meetingDayOfTheWeek = meetingDayOfTheWeek; + this.dayOfWeek = dayOfWeek; this.weekNumber = weekNumber; } - public static Round of(MeetingDayOfTheWeek meetingDayOfTheWeek, Study study, Integer weekNumber) { + public static Round of(DayOfWeek dayOfWeek, Study study, Integer weekNumber) { return Round.builder() .study(study) - .meetingDayOfTheWeek(meetingDayOfTheWeek) + .dayOfWeek(dayOfWeek) .weekNumber(weekNumber) .master(study.getMaster()) .roundOfMembers(RoundOfMember.from(study)) @@ -140,7 +138,7 @@ public boolean isMustDoDone(Member member) { } public boolean isEndAt(LocalDate date) { - return meetingDayOfTheWeek.isSameDayOfWeek(date.getDayOfWeek()); + return dayOfWeek == date.getDayOfWeek(); } public RoundOfMember findRoundOfMemberBy(Member member) { @@ -180,12 +178,12 @@ public boolean isSameWeek(Integer weekNumber) { return this.weekNumber == weekNumber; } - public boolean isSameDayOfWeek(MeetingDayOfTheWeek meetingDayOfTheWeek) { - return this.meetingDayOfTheWeek.equals(meetingDayOfTheWeek); + public boolean isSameDayOfWeek(DayOfWeek dayOfWeek) { + return this.dayOfWeek.equals(dayOfWeek); } public boolean isNextDayOfWeek(DayOfWeek dayOfWeek) { - return this.meetingDayOfTheWeek.comesNext(dayOfWeek); + return this.dayOfWeek.getValue() > dayOfWeek.getValue(); } public boolean isInProgress() { @@ -193,17 +191,13 @@ public boolean isInProgress() { } public int calculateLeftDaysFrom(LocalDate date) { - int gap = meetingDayOfTheWeek.getDayOfWeek().getValue() - date.getDayOfWeek().getValue(); + int gap = dayOfWeek.getValue() - date.getDayOfWeek().getValue(); if (gap < 0) { return gap + DayOfWeek.values().length; } return gap; } - public DayOfWeek getDayOfWeek() { - return meetingDayOfTheWeek.getDayOfWeek(); - } - public boolean isBeforeOrSame(Integer minimumWeeks) { return weekNumber <= minimumWeeks; } diff --git a/backend/src/main/java/com/yigongil/backend/domain/study/Study.java b/backend/src/main/java/com/yigongil/backend/domain/study/Study.java index 3a5015549..9cd843a43 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/study/Study.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/Study.java @@ -252,7 +252,7 @@ private void initializeRounds(LocalDate startAt) { private List createRoundsOfFirstWeek(final LocalDate startAt) { List rounds = meetingDaysOfTheWeek.stream() .filter(meetingDayOfTheWeek -> meetingDayOfTheWeek.comesNext(startAt.getDayOfWeek())) - .map(meetingDayOfTheWeek -> Round.of(meetingDayOfTheWeek, this, FIRST_WEEK)) + .map(meetingDayOfTheWeek -> Round.of(meetingDayOfTheWeek.getDayOfWeek(), this, FIRST_WEEK)) .toList(); if (rounds.isEmpty()) { rounds = createRoundsOf(FIRST_WEEK); @@ -291,14 +291,15 @@ private Round findUpcomingRoundOf(int weekNumber) { private Round findFirstRoundOf(int nextWeekNumber) { return rounds.stream() - .filter(round -> round.isSameWeek(nextWeekNumber) && round.isSameDayOfWeek(findFirstMeetingDayOfTheWeek())) + .filter(round -> round.isSameWeek(nextWeekNumber) && round.isSameDayOfWeek(findFirstDayOfTheWeek())) .findAny() .orElseThrow(() -> new RoundNotFoundException("다음 주차의 라운드가 존재하지 않습니다.", getCurrentRound().getWeekNumber())); } - private MeetingDayOfTheWeek findFirstMeetingDayOfTheWeek() { + private DayOfWeek findFirstDayOfTheWeek() { return meetingDaysOfTheWeek.stream() .min(Comparator.comparing(MeetingDayOfTheWeek::getOrder)) + .map(MeetingDayOfTheWeek::getDayOfWeek) .orElseThrow(); } @@ -387,7 +388,7 @@ public void updateInformation( private List createRoundsOf(Integer weekNumber) { return meetingDaysOfTheWeek.stream() - .map(meetingDayOfTheWeek -> Round.of(meetingDayOfTheWeek, this, weekNumber)) + .map(meetingDayOfTheWeek -> Round.of(meetingDayOfTheWeek.getDayOfWeek(), this, weekNumber)) .toList(); } diff --git a/backend/src/main/resources/db/migration/V13_remove_meeting_day_of_the_week_In_round.sql b/backend/src/main/resources/db/migration/V13_remove_meeting_day_of_the_week_In_round.sql new file mode 100644 index 000000000..4c8aaf07c --- /dev/null +++ b/backend/src/main/resources/db/migration/V13_remove_meeting_day_of_the_week_In_round.sql @@ -0,0 +1,10 @@ +ALTER TABLE round ADD day_of_week INTEGER; + +UPDATE round + INNER JOIN meeting_day_of_the_week + ON round.meeting_day_of_the_week_id = meeting_day_of_the_week.id +SET round.day_of_week = meeting_day_of_the_week.day_of_week; + +alter table round drop foreign key FKp9ga9uq8uvomn6vytcr34vfl5; +ALTER TABLE round DROP COLUMN meeting_day_of_the_week_id; + From ae87fcda3d12c31d29776705a972f246192667e8 Mon Sep 17 00:00:00 2001 From: kevstevie Date: Wed, 1 Nov 2023 21:00:45 +0900 Subject: [PATCH 03/22] =?UTF-8?q?refactor:=20=EC=9D=98=EC=A1=B4=EC=84=B1?= =?UTF-8?q?=20=ED=99=95=EC=9D=B8=EC=9D=84=20=EC=9C=84=ED=95=9C=20=ED=8C=A8?= =?UTF-8?q?=ED=82=A4=EC=A7=80=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../certification}/CertificationService.java | 4 +--- .../{application => domain/feedpost}/FeedService.java | 4 +--- .../{ui => domain/image}/ImageResourceController.java | 3 +-- .../image}/ImageResourceService.java | 2 +- .../backend/{ui => domain/member}/HomeController.java | 5 ++--- .../backend/{ui => domain/member}/MemberController.java | 4 +--- .../{application => domain/member}/MemberService.java | 6 ++---- .../backend/{ui => domain/report}/ReportController.java | 3 +-- .../{application => domain/report}/ReportService.java | 7 +++---- .../backend/{ui => domain/round}/MustDoController.java | 3 +-- .../{application => domain/round}/MustDoService.java | 4 +--- .../{application => domain/round}/RoundService.java | 4 +--- .../{application => domain/study}/ScheduleService.java | 2 +- .../backend/{ui => domain/study}/StudyController.java | 4 +--- .../study}/StudyEventListener.java | 2 +- .../{application => domain/study}/StudyService.java | 8 +++----- .../yigongil/backend/application/MustDoServiceTest.java | 1 + .../yigongil/backend/application/StudyServiceTest.java | 3 +++ .../java/com/yigongil/backend/fake/FakeController.java | 2 +- .../com/yigongil/backend/ui/MemberControllerTest.java | 4 ++-- .../com/yigongil/backend/ui/MustDoControllerTest.java | 3 ++- .../com/yigongil/backend/ui/StudyControllerTest.java | 9 +++++---- 22 files changed, 36 insertions(+), 51 deletions(-) rename backend/src/main/java/com/yigongil/backend/{application => domain/certification}/CertificationService.java (90%) rename backend/src/main/java/com/yigongil/backend/{application => domain/feedpost}/FeedService.java (88%) rename backend/src/main/java/com/yigongil/backend/{ui => domain/image}/ImageResourceController.java (91%) rename backend/src/main/java/com/yigongil/backend/{application => domain/image}/ImageResourceService.java (98%) rename backend/src/main/java/com/yigongil/backend/{ui => domain/member}/HomeController.java (86%) rename backend/src/main/java/com/yigongil/backend/{ui => domain/member}/MemberController.java (95%) rename backend/src/main/java/com/yigongil/backend/{application => domain/member}/MemberService.java (95%) rename backend/src/main/java/com/yigongil/backend/{ui => domain/report}/ReportController.java (94%) rename backend/src/main/java/com/yigongil/backend/{application => domain/report}/ReportService.java (90%) rename backend/src/main/java/com/yigongil/backend/{ui => domain/round}/MustDoController.java (93%) rename backend/src/main/java/com/yigongil/backend/{application => domain/round}/MustDoService.java (86%) rename backend/src/main/java/com/yigongil/backend/{application => domain/round}/RoundService.java (92%) rename backend/src/main/java/com/yigongil/backend/{application => domain/study}/ScheduleService.java (92%) rename backend/src/main/java/com/yigongil/backend/{ui => domain/study}/StudyController.java (98%) rename backend/src/main/java/com/yigongil/backend/{application => domain/study}/StudyEventListener.java (93%) rename backend/src/main/java/com/yigongil/backend/{application => domain/study}/StudyService.java (97%) diff --git a/backend/src/main/java/com/yigongil/backend/application/CertificationService.java b/backend/src/main/java/com/yigongil/backend/domain/certification/CertificationService.java similarity index 90% rename from backend/src/main/java/com/yigongil/backend/application/CertificationService.java rename to backend/src/main/java/com/yigongil/backend/domain/certification/CertificationService.java index 6faad932a..37d6da5db 100644 --- a/backend/src/main/java/com/yigongil/backend/application/CertificationService.java +++ b/backend/src/main/java/com/yigongil/backend/domain/certification/CertificationService.java @@ -1,7 +1,5 @@ -package com.yigongil.backend.application; +package com.yigongil.backend.domain.certification; -import com.yigongil.backend.domain.certification.Certification; -import com.yigongil.backend.domain.certification.CertificationRepository; import com.yigongil.backend.domain.member.Member; import com.yigongil.backend.domain.study.Study; import com.yigongil.backend.exception.NoCertificationException; diff --git a/backend/src/main/java/com/yigongil/backend/application/FeedService.java b/backend/src/main/java/com/yigongil/backend/domain/feedpost/FeedService.java similarity index 88% rename from backend/src/main/java/com/yigongil/backend/application/FeedService.java rename to backend/src/main/java/com/yigongil/backend/domain/feedpost/FeedService.java index a27600cd7..0378a7260 100644 --- a/backend/src/main/java/com/yigongil/backend/application/FeedService.java +++ b/backend/src/main/java/com/yigongil/backend/domain/feedpost/FeedService.java @@ -1,7 +1,5 @@ -package com.yigongil.backend.application; +package com.yigongil.backend.domain.feedpost; -import com.yigongil.backend.domain.feedpost.FeedPost; -import com.yigongil.backend.domain.feedpost.FeedPostRepository; import com.yigongil.backend.domain.member.Member; import com.yigongil.backend.domain.study.Study; import com.yigongil.backend.request.FeedPostCreateRequest; diff --git a/backend/src/main/java/com/yigongil/backend/ui/ImageResourceController.java b/backend/src/main/java/com/yigongil/backend/domain/image/ImageResourceController.java similarity index 91% rename from backend/src/main/java/com/yigongil/backend/ui/ImageResourceController.java rename to backend/src/main/java/com/yigongil/backend/domain/image/ImageResourceController.java index 3ba15aa3c..fc5bb6722 100644 --- a/backend/src/main/java/com/yigongil/backend/ui/ImageResourceController.java +++ b/backend/src/main/java/com/yigongil/backend/domain/image/ImageResourceController.java @@ -1,6 +1,5 @@ -package com.yigongil.backend.ui; +package com.yigongil.backend.domain.image; -import com.yigongil.backend.application.ImageResourceService; import java.net.URI; import org.springframework.context.annotation.Profile; import org.springframework.http.ResponseEntity; diff --git a/backend/src/main/java/com/yigongil/backend/application/ImageResourceService.java b/backend/src/main/java/com/yigongil/backend/domain/image/ImageResourceService.java similarity index 98% rename from backend/src/main/java/com/yigongil/backend/application/ImageResourceService.java rename to backend/src/main/java/com/yigongil/backend/domain/image/ImageResourceService.java index e026bf1fc..9fcfe65e4 100644 --- a/backend/src/main/java/com/yigongil/backend/application/ImageResourceService.java +++ b/backend/src/main/java/com/yigongil/backend/domain/image/ImageResourceService.java @@ -1,4 +1,4 @@ -package com.yigongil.backend.application; +package com.yigongil.backend.domain.image; import com.yigongil.backend.exception.ImageToBytesException; import com.yigongil.backend.exception.InvalidImageExtensionException; diff --git a/backend/src/main/java/com/yigongil/backend/ui/HomeController.java b/backend/src/main/java/com/yigongil/backend/domain/member/HomeController.java similarity index 86% rename from backend/src/main/java/com/yigongil/backend/ui/HomeController.java rename to backend/src/main/java/com/yigongil/backend/domain/member/HomeController.java index 06bdc2722..f1f94454e 100644 --- a/backend/src/main/java/com/yigongil/backend/ui/HomeController.java +++ b/backend/src/main/java/com/yigongil/backend/domain/member/HomeController.java @@ -1,8 +1,7 @@ -package com.yigongil.backend.ui; +package com.yigongil.backend.domain.member; -import com.yigongil.backend.application.RoundService; import com.yigongil.backend.config.auth.Authorization; -import com.yigongil.backend.domain.member.Member; +import com.yigongil.backend.domain.round.RoundService; import com.yigongil.backend.response.UpcomingStudyResponse; import com.yigongil.backend.ui.doc.HomeApi; import java.util.List; diff --git a/backend/src/main/java/com/yigongil/backend/ui/MemberController.java b/backend/src/main/java/com/yigongil/backend/domain/member/MemberController.java similarity index 95% rename from backend/src/main/java/com/yigongil/backend/ui/MemberController.java rename to backend/src/main/java/com/yigongil/backend/domain/member/MemberController.java index ae9037602..c3e52f988 100644 --- a/backend/src/main/java/com/yigongil/backend/ui/MemberController.java +++ b/backend/src/main/java/com/yigongil/backend/domain/member/MemberController.java @@ -1,8 +1,6 @@ -package com.yigongil.backend.ui; +package com.yigongil.backend.domain.member; -import com.yigongil.backend.application.MemberService; import com.yigongil.backend.config.auth.Authorization; -import com.yigongil.backend.domain.member.Member; import com.yigongil.backend.request.ProfileUpdateRequest; import com.yigongil.backend.response.MyProfileResponse; import com.yigongil.backend.response.NicknameValidationResponse; diff --git a/backend/src/main/java/com/yigongil/backend/application/MemberService.java b/backend/src/main/java/com/yigongil/backend/domain/member/MemberService.java similarity index 95% rename from backend/src/main/java/com/yigongil/backend/application/MemberService.java rename to backend/src/main/java/com/yigongil/backend/domain/member/MemberService.java index fad500a24..52d02c4aa 100644 --- a/backend/src/main/java/com/yigongil/backend/application/MemberService.java +++ b/backend/src/main/java/com/yigongil/backend/domain/member/MemberService.java @@ -1,9 +1,7 @@ -package com.yigongil.backend.application; +package com.yigongil.backend.domain.member; -import com.yigongil.backend.domain.member.Member; -import com.yigongil.backend.domain.member.MemberRepository; -import com.yigongil.backend.domain.member.Nickname; import com.yigongil.backend.domain.study.Study; +import com.yigongil.backend.domain.study.StudyService; import com.yigongil.backend.domain.studymember.StudyMember; import com.yigongil.backend.domain.studymember.StudyMemberRepository; import com.yigongil.backend.exception.MemberNotFoundException; diff --git a/backend/src/main/java/com/yigongil/backend/ui/ReportController.java b/backend/src/main/java/com/yigongil/backend/domain/report/ReportController.java similarity index 94% rename from backend/src/main/java/com/yigongil/backend/ui/ReportController.java rename to backend/src/main/java/com/yigongil/backend/domain/report/ReportController.java index 24454b29a..d3063425f 100644 --- a/backend/src/main/java/com/yigongil/backend/ui/ReportController.java +++ b/backend/src/main/java/com/yigongil/backend/domain/report/ReportController.java @@ -1,6 +1,5 @@ -package com.yigongil.backend.ui; +package com.yigongil.backend.domain.report; -import com.yigongil.backend.application.ReportService; import com.yigongil.backend.config.auth.Authorization; import com.yigongil.backend.domain.member.Member; import com.yigongil.backend.request.MemberReportCreateRequest; diff --git a/backend/src/main/java/com/yigongil/backend/application/ReportService.java b/backend/src/main/java/com/yigongil/backend/domain/report/ReportService.java similarity index 90% rename from backend/src/main/java/com/yigongil/backend/application/ReportService.java rename to backend/src/main/java/com/yigongil/backend/domain/report/ReportService.java index 1656024bf..c6a2eb255 100644 --- a/backend/src/main/java/com/yigongil/backend/application/ReportService.java +++ b/backend/src/main/java/com/yigongil/backend/domain/report/ReportService.java @@ -1,10 +1,9 @@ -package com.yigongil.backend.application; +package com.yigongil.backend.domain.report; import com.yigongil.backend.domain.member.Member; -import com.yigongil.backend.domain.report.MemberReport; -import com.yigongil.backend.domain.report.ReportRepository; -import com.yigongil.backend.domain.report.StudyReport; +import com.yigongil.backend.domain.member.MemberService; import com.yigongil.backend.domain.study.Study; +import com.yigongil.backend.domain.study.StudyService; import com.yigongil.backend.request.MemberReportCreateRequest; import com.yigongil.backend.request.StudyReportCreateRequest; import org.springframework.stereotype.Service; diff --git a/backend/src/main/java/com/yigongil/backend/ui/MustDoController.java b/backend/src/main/java/com/yigongil/backend/domain/round/MustDoController.java similarity index 93% rename from backend/src/main/java/com/yigongil/backend/ui/MustDoController.java rename to backend/src/main/java/com/yigongil/backend/domain/round/MustDoController.java index 9f18013b1..3c4fc3bbb 100644 --- a/backend/src/main/java/com/yigongil/backend/ui/MustDoController.java +++ b/backend/src/main/java/com/yigongil/backend/domain/round/MustDoController.java @@ -1,6 +1,5 @@ -package com.yigongil.backend.ui; +package com.yigongil.backend.domain.round; -import com.yigongil.backend.application.MustDoService; import com.yigongil.backend.config.auth.Authorization; import com.yigongil.backend.domain.member.Member; import com.yigongil.backend.request.MustDoUpdateRequest; diff --git a/backend/src/main/java/com/yigongil/backend/application/MustDoService.java b/backend/src/main/java/com/yigongil/backend/domain/round/MustDoService.java similarity index 86% rename from backend/src/main/java/com/yigongil/backend/application/MustDoService.java rename to backend/src/main/java/com/yigongil/backend/domain/round/MustDoService.java index b1ed85e52..f22b16f69 100644 --- a/backend/src/main/java/com/yigongil/backend/application/MustDoService.java +++ b/backend/src/main/java/com/yigongil/backend/domain/round/MustDoService.java @@ -1,8 +1,6 @@ -package com.yigongil.backend.application; +package com.yigongil.backend.domain.round; import com.yigongil.backend.domain.member.Member; -import com.yigongil.backend.domain.round.Round; -import com.yigongil.backend.domain.round.RoundRepository; import com.yigongil.backend.exception.RoundNotFoundException; import com.yigongil.backend.request.MustDoUpdateRequest; import org.springframework.stereotype.Service; diff --git a/backend/src/main/java/com/yigongil/backend/application/RoundService.java b/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java similarity index 92% rename from backend/src/main/java/com/yigongil/backend/application/RoundService.java rename to backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java index 237d95633..33a0d12aa 100644 --- a/backend/src/main/java/com/yigongil/backend/application/RoundService.java +++ b/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java @@ -1,8 +1,6 @@ -package com.yigongil.backend.application; +package com.yigongil.backend.domain.round; import com.yigongil.backend.domain.member.Member; -import com.yigongil.backend.domain.round.Round; -import com.yigongil.backend.domain.round.RoundRepository; import com.yigongil.backend.domain.study.ProcessingStatus; import com.yigongil.backend.domain.study.Study; import com.yigongil.backend.domain.study.StudyRepository; diff --git a/backend/src/main/java/com/yigongil/backend/application/ScheduleService.java b/backend/src/main/java/com/yigongil/backend/domain/study/ScheduleService.java similarity index 92% rename from backend/src/main/java/com/yigongil/backend/application/ScheduleService.java rename to backend/src/main/java/com/yigongil/backend/domain/study/ScheduleService.java index cfcfe2496..fcd83ba27 100644 --- a/backend/src/main/java/com/yigongil/backend/application/ScheduleService.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/ScheduleService.java @@ -1,4 +1,4 @@ -package com.yigongil.backend.application; +package com.yigongil.backend.domain.study; import java.time.LocalDate; import org.springframework.scheduling.annotation.Scheduled; diff --git a/backend/src/main/java/com/yigongil/backend/ui/StudyController.java b/backend/src/main/java/com/yigongil/backend/domain/study/StudyController.java similarity index 98% rename from backend/src/main/java/com/yigongil/backend/ui/StudyController.java rename to backend/src/main/java/com/yigongil/backend/domain/study/StudyController.java index 6d8eec19a..667e6e941 100644 --- a/backend/src/main/java/com/yigongil/backend/ui/StudyController.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/StudyController.java @@ -1,9 +1,7 @@ -package com.yigongil.backend.ui; +package com.yigongil.backend.domain.study; -import com.yigongil.backend.application.StudyService; import com.yigongil.backend.config.auth.Authorization; import com.yigongil.backend.domain.member.Member; -import com.yigongil.backend.domain.study.ProcessingStatus; import com.yigongil.backend.domain.studymember.Role; import com.yigongil.backend.request.CertificationCreateRequest; import com.yigongil.backend.request.FeedPostCreateRequest; diff --git a/backend/src/main/java/com/yigongil/backend/application/StudyEventListener.java b/backend/src/main/java/com/yigongil/backend/domain/study/StudyEventListener.java similarity index 93% rename from backend/src/main/java/com/yigongil/backend/application/StudyEventListener.java rename to backend/src/main/java/com/yigongil/backend/domain/study/StudyEventListener.java index ae1b68d77..55e1bc774 100644 --- a/backend/src/main/java/com/yigongil/backend/application/StudyEventListener.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/StudyEventListener.java @@ -1,4 +1,4 @@ -package com.yigongil.backend.application; +package com.yigongil.backend.domain.study; import com.yigongil.backend.domain.event.MemberDeleteEvent; import org.springframework.stereotype.Component; diff --git a/backend/src/main/java/com/yigongil/backend/application/StudyService.java b/backend/src/main/java/com/yigongil/backend/domain/study/StudyService.java similarity index 97% rename from backend/src/main/java/com/yigongil/backend/application/StudyService.java rename to backend/src/main/java/com/yigongil/backend/domain/study/StudyService.java index 0abb26941..837a10982 100644 --- a/backend/src/main/java/com/yigongil/backend/application/StudyService.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/StudyService.java @@ -1,14 +1,12 @@ -package com.yigongil.backend.application; +package com.yigongil.backend.domain.study; import com.yigongil.backend.domain.certification.Certification; +import com.yigongil.backend.domain.certification.CertificationService; +import com.yigongil.backend.domain.feedpost.FeedService; import com.yigongil.backend.domain.member.Member; import com.yigongil.backend.domain.round.Round; import com.yigongil.backend.domain.round.RoundRepository; import com.yigongil.backend.domain.roundofmember.RoundOfMember; -import com.yigongil.backend.domain.study.PageStrategy; -import com.yigongil.backend.domain.study.ProcessingStatus; -import com.yigongil.backend.domain.study.Study; -import com.yigongil.backend.domain.study.StudyRepository; import com.yigongil.backend.domain.studymember.Role; import com.yigongil.backend.domain.studymember.StudyMember; import com.yigongil.backend.domain.studymember.StudyMemberRepository; diff --git a/backend/src/test/java/com/yigongil/backend/application/MustDoServiceTest.java b/backend/src/test/java/com/yigongil/backend/application/MustDoServiceTest.java index 1ae6eb943..7938af28e 100644 --- a/backend/src/test/java/com/yigongil/backend/application/MustDoServiceTest.java +++ b/backend/src/test/java/com/yigongil/backend/application/MustDoServiceTest.java @@ -5,6 +5,7 @@ import static org.mockito.BDDMockito.willReturn; import com.yigongil.backend.domain.member.Member; +import com.yigongil.backend.domain.round.MustDoService; import com.yigongil.backend.domain.round.Round; import com.yigongil.backend.domain.round.RoundRepository; import com.yigongil.backend.domain.roundofmember.RoundOfMember; diff --git a/backend/src/test/java/com/yigongil/backend/application/StudyServiceTest.java b/backend/src/test/java/com/yigongil/backend/application/StudyServiceTest.java index 3c6b4ce1a..7839980ac 100644 --- a/backend/src/test/java/com/yigongil/backend/application/StudyServiceTest.java +++ b/backend/src/test/java/com/yigongil/backend/application/StudyServiceTest.java @@ -4,9 +4,12 @@ import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; +import com.yigongil.backend.domain.certification.CertificationService; +import com.yigongil.backend.domain.feedpost.FeedService; import com.yigongil.backend.domain.member.Member; import com.yigongil.backend.domain.round.RoundRepository; import com.yigongil.backend.domain.study.StudyRepository; +import com.yigongil.backend.domain.study.StudyService; import com.yigongil.backend.domain.studymember.StudyMemberRepository; import com.yigongil.backend.exception.StudyNotFoundException; import com.yigongil.backend.fixture.MemberFixture; diff --git a/backend/src/test/java/com/yigongil/backend/fake/FakeController.java b/backend/src/test/java/com/yigongil/backend/fake/FakeController.java index bc7b5ed20..97cc3318b 100644 --- a/backend/src/test/java/com/yigongil/backend/fake/FakeController.java +++ b/backend/src/test/java/com/yigongil/backend/fake/FakeController.java @@ -1,9 +1,9 @@ package com.yigongil.backend.fake; -import com.yigongil.backend.application.StudyService; import com.yigongil.backend.config.auth.JwtTokenProvider; import com.yigongil.backend.domain.member.Member; import com.yigongil.backend.domain.member.MemberRepository; +import com.yigongil.backend.domain.study.StudyService; import com.yigongil.backend.response.TokenResponse; import java.time.LocalDate; import java.util.Optional; diff --git a/backend/src/test/java/com/yigongil/backend/ui/MemberControllerTest.java b/backend/src/test/java/com/yigongil/backend/ui/MemberControllerTest.java index 018552aec..7a78d0b90 100644 --- a/backend/src/test/java/com/yigongil/backend/ui/MemberControllerTest.java +++ b/backend/src/test/java/com/yigongil/backend/ui/MemberControllerTest.java @@ -13,12 +13,13 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import com.fasterxml.jackson.databind.ObjectMapper; -import com.yigongil.backend.application.MemberService; import com.yigongil.backend.config.AuthConfig; import com.yigongil.backend.config.auth.AuthContext; import com.yigongil.backend.config.auth.JwtTokenProvider; import com.yigongil.backend.domain.member.Member; +import com.yigongil.backend.domain.member.MemberController; import com.yigongil.backend.domain.member.MemberRepository; +import com.yigongil.backend.domain.member.MemberService; import com.yigongil.backend.fixture.MemberFixture; import com.yigongil.backend.request.ProfileUpdateRequest; import com.yigongil.backend.response.NicknameValidationResponse; @@ -65,7 +66,6 @@ class MemberControllerTest { private InternalServerErrorMessageConverter internalServerErrorMessageConverter; - @Test void 프로필_정보를_조회한다() throws Exception { Member member = MemberFixture.김진우.toMember(); diff --git a/backend/src/test/java/com/yigongil/backend/ui/MustDoControllerTest.java b/backend/src/test/java/com/yigongil/backend/ui/MustDoControllerTest.java index 5ef4b6692..f4c6bd94a 100644 --- a/backend/src/test/java/com/yigongil/backend/ui/MustDoControllerTest.java +++ b/backend/src/test/java/com/yigongil/backend/ui/MustDoControllerTest.java @@ -10,10 +10,11 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import com.fasterxml.jackson.databind.ObjectMapper; -import com.yigongil.backend.application.MustDoService; import com.yigongil.backend.config.auth.AuthContext; import com.yigongil.backend.config.auth.JwtTokenProvider; import com.yigongil.backend.domain.member.MemberRepository; +import com.yigongil.backend.domain.round.MustDoController; +import com.yigongil.backend.domain.round.MustDoService; import com.yigongil.backend.fixture.MemberFixture; import com.yigongil.backend.request.MustDoUpdateRequest; import com.yigongil.backend.ui.exceptionhandler.InternalServerErrorMessageConverter; diff --git a/backend/src/test/java/com/yigongil/backend/ui/StudyControllerTest.java b/backend/src/test/java/com/yigongil/backend/ui/StudyControllerTest.java index b3262f7d3..d8ec6acb2 100644 --- a/backend/src/test/java/com/yigongil/backend/ui/StudyControllerTest.java +++ b/backend/src/test/java/com/yigongil/backend/ui/StudyControllerTest.java @@ -9,13 +9,14 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import com.fasterxml.jackson.databind.ObjectMapper; -import com.yigongil.backend.application.CertificationService; -import com.yigongil.backend.application.FeedService; -import com.yigongil.backend.application.MustDoService; -import com.yigongil.backend.application.StudyService; import com.yigongil.backend.config.auth.AuthContext; import com.yigongil.backend.config.auth.JwtTokenProvider; +import com.yigongil.backend.domain.certification.CertificationService; +import com.yigongil.backend.domain.feedpost.FeedService; import com.yigongil.backend.domain.member.MemberRepository; +import com.yigongil.backend.domain.round.MustDoService; +import com.yigongil.backend.domain.study.StudyController; +import com.yigongil.backend.domain.study.StudyService; import com.yigongil.backend.fixture.MemberFixture; import com.yigongil.backend.request.StudyUpdateRequest; import com.yigongil.backend.ui.exceptionhandler.InternalServerErrorMessageConverter; From 2efd490073e9d9df6c18b314021e43ab61425356 Mon Sep 17 00:00:00 2001 From: kim dae hee Date: Fri, 17 Nov 2023 14:57:43 +0900 Subject: [PATCH 04/22] =?UTF-8?q?refactor:=20=EB=A9=A4=EB=B2=84=20?= =?UTF-8?q?=EC=9D=98=EC=A1=B4=EC=84=B1=20=EC=A0=95=EB=A6=AC=20=ED=94=84?= =?UTF-8?q?=EB=A1=9C=ED=95=84=20=EC=A1=B0=ED=9A=8C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/build.gradle | 1 + .../backend/application/AuthService.java | 4 +- .../config/auth/MemberArgumentResolver.java | 4 +- .../domain/certification/Certification.java | 2 +- .../certification/CertificationService.java | 2 +- .../backend/domain/feedpost/FeedPost.java | 2 +- .../backend/domain/feedpost/FeedService.java | 2 +- .../backend/domain/member/MemberService.java | 106 ------------------ .../member/application/MemberService.java | 35 ++++++ .../member/{ => domain}/Introduction.java | 2 +- .../domain/member/{ => domain}/Member.java | 2 +- .../member/{ => domain}/MemberRepository.java | 10 +- .../domain/member/{ => domain}/Nickname.java | 2 +- .../domain/member/{ => domain}/Tier.java | 2 +- .../member/{ => ui}/MemberController.java | 31 +---- .../backend/domain/report/MemberReport.java | 2 +- .../backend/domain/report/Report.java | 2 +- .../domain/report/ReportController.java | 2 +- .../backend/domain/report/ReportService.java | 12 +- .../backend/domain/report/StudyReport.java | 2 +- .../{member => round}/HomeController.java | 4 +- .../domain/round/MustDoController.java | 2 +- .../backend/domain/round/MustDoService.java | 2 +- .../yigongil/backend/domain/round/Round.java | 2 +- .../backend/domain/round/RoundService.java | 2 +- .../domain/roundofmember/RoundOfMember.java | 2 +- .../yigongil/backend/domain/study/Study.java | 2 +- .../backend/domain/study/StudyController.java | 2 +- .../backend/domain/study/StudyRepository.java | 2 +- .../backend/domain/study/StudyService.java | 2 +- .../domain/studymember/StudyMember.java | 2 +- .../backend/query/profile/ProfileService.java | 77 +++++++++++++ .../backend/query/profile/ui/ProfileApi.java | 39 +++++++ .../query/profile/ui/ProfileController.java | 47 ++++++++ .../response/MemberOfRoundResponse.java | 2 +- .../MembersCertificationResponse.java | 2 +- .../com/yigongil/backend/ui/doc/HomeApi.java | 2 +- .../yigongil/backend/ui/doc/MemberApi.java | 25 +---- .../yigongil/backend/ui/doc/MustDoApi.java | 2 +- .../yigongil/backend/ui/doc/ReportApi.java | 2 +- .../com/yigongil/backend/ui/doc/StudyApi.java | 2 +- .../application/MustDoServiceTest.java | 2 +- .../backend/application/StudyServiceTest.java | 2 +- .../backend/domain/member/MemberTest.java | 1 + .../backend/domain/member/TierTest.java | 1 + .../backend/domain/report/ReportTest.java | 2 +- .../backend/domain/round/RoundTest.java | 2 +- .../backend/domain/study/StudyTest.java | 2 +- .../StudyQueryRepositoryImplTest.java | 4 +- .../yigongil/backend/fake/FakeController.java | 4 +- .../backend/fixture/MemberFixture.java | 2 +- .../backend/fixture/RoundFixture.java | 2 +- .../backend/fixture/RoundOfMemberFixture.java | 2 +- .../backend/fixture/StudyFixture.java | 2 +- .../profile/ui/ProfileControllerTest.java | 79 +++++++++++++ .../backend/ui/MemberControllerTest.java | 35 +----- .../backend/ui/MustDoControllerTest.java | 2 +- .../backend/ui/StudyControllerTest.java | 2 +- 58 files changed, 352 insertions(+), 245 deletions(-) delete mode 100644 backend/src/main/java/com/yigongil/backend/domain/member/MemberService.java create mode 100644 backend/src/main/java/com/yigongil/backend/domain/member/application/MemberService.java rename backend/src/main/java/com/yigongil/backend/domain/member/{ => domain}/Introduction.java (96%) rename backend/src/main/java/com/yigongil/backend/domain/member/{ => domain}/Member.java (98%) rename backend/src/main/java/com/yigongil/backend/domain/member/{ => domain}/MemberRepository.java (51%) rename backend/src/main/java/com/yigongil/backend/domain/member/{ => domain}/Nickname.java (97%) rename backend/src/main/java/com/yigongil/backend/domain/member/{ => domain}/Tier.java (96%) rename backend/src/main/java/com/yigongil/backend/domain/member/{ => ui}/MemberController.java (65%) rename backend/src/main/java/com/yigongil/backend/domain/{member => round}/HomeController.java (90%) create mode 100644 backend/src/main/java/com/yigongil/backend/query/profile/ProfileService.java create mode 100644 backend/src/main/java/com/yigongil/backend/query/profile/ui/ProfileApi.java create mode 100644 backend/src/main/java/com/yigongil/backend/query/profile/ui/ProfileController.java create mode 100644 backend/src/test/java/com/yigongil/backend/query/profile/ui/ProfileControllerTest.java diff --git a/backend/build.gradle b/backend/build.gradle index 5a96d265a..d7cdbee0d 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -29,6 +29,7 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.boot:spring-boot-starter-web' + testImplementation 'org.testng:testng:7.1.0' compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.h2database:h2' runtimeOnly 'org.mariadb.jdbc:mariadb-java-client' diff --git a/backend/src/main/java/com/yigongil/backend/application/AuthService.java b/backend/src/main/java/com/yigongil/backend/application/AuthService.java index 6f0d559fc..d94d86bdd 100644 --- a/backend/src/main/java/com/yigongil/backend/application/AuthService.java +++ b/backend/src/main/java/com/yigongil/backend/application/AuthService.java @@ -3,8 +3,8 @@ import com.yigongil.backend.config.auth.JwtTokenProvider; import com.yigongil.backend.config.oauth.GithubOauth; import com.yigongil.backend.config.oauth.GithubProfileResponse; -import com.yigongil.backend.domain.member.Member; -import com.yigongil.backend.domain.member.MemberRepository; +import com.yigongil.backend.domain.member.domain.Member; +import com.yigongil.backend.domain.member.domain.MemberRepository; import com.yigongil.backend.request.TokenRequest; import com.yigongil.backend.response.TokenResponse; import java.util.Optional; diff --git a/backend/src/main/java/com/yigongil/backend/config/auth/MemberArgumentResolver.java b/backend/src/main/java/com/yigongil/backend/config/auth/MemberArgumentResolver.java index 05406b860..86f9af3f8 100644 --- a/backend/src/main/java/com/yigongil/backend/config/auth/MemberArgumentResolver.java +++ b/backend/src/main/java/com/yigongil/backend/config/auth/MemberArgumentResolver.java @@ -1,7 +1,7 @@ package com.yigongil.backend.config.auth; -import com.yigongil.backend.domain.member.Member; -import com.yigongil.backend.domain.member.MemberRepository; +import com.yigongil.backend.domain.member.domain.Member; +import com.yigongil.backend.domain.member.domain.MemberRepository; import com.yigongil.backend.exception.AuthorizationException; import org.springframework.core.MethodParameter; import org.springframework.stereotype.Component; diff --git a/backend/src/main/java/com/yigongil/backend/domain/certification/Certification.java b/backend/src/main/java/com/yigongil/backend/domain/certification/Certification.java index 761259445..d477434ef 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/certification/Certification.java +++ b/backend/src/main/java/com/yigongil/backend/domain/certification/Certification.java @@ -1,7 +1,7 @@ package com.yigongil.backend.domain.certification; import com.yigongil.backend.domain.base.BaseEntity; -import com.yigongil.backend.domain.member.Member; +import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.round.Round; import com.yigongil.backend.domain.study.Study; import java.time.LocalDateTime; diff --git a/backend/src/main/java/com/yigongil/backend/domain/certification/CertificationService.java b/backend/src/main/java/com/yigongil/backend/domain/certification/CertificationService.java index 37d6da5db..7dbbc551b 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/certification/CertificationService.java +++ b/backend/src/main/java/com/yigongil/backend/domain/certification/CertificationService.java @@ -1,6 +1,6 @@ package com.yigongil.backend.domain.certification; -import com.yigongil.backend.domain.member.Member; +import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.study.Study; import com.yigongil.backend.exception.NoCertificationException; import com.yigongil.backend.request.CertificationCreateRequest; diff --git a/backend/src/main/java/com/yigongil/backend/domain/feedpost/FeedPost.java b/backend/src/main/java/com/yigongil/backend/domain/feedpost/FeedPost.java index 79eda8d10..139c096bd 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/feedpost/FeedPost.java +++ b/backend/src/main/java/com/yigongil/backend/domain/feedpost/FeedPost.java @@ -1,7 +1,7 @@ package com.yigongil.backend.domain.feedpost; import com.yigongil.backend.domain.base.BaseEntity; -import com.yigongil.backend.domain.member.Member; +import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.study.Study; import java.time.LocalDateTime; import java.util.Objects; diff --git a/backend/src/main/java/com/yigongil/backend/domain/feedpost/FeedService.java b/backend/src/main/java/com/yigongil/backend/domain/feedpost/FeedService.java index 0378a7260..bdae36a6b 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/feedpost/FeedService.java +++ b/backend/src/main/java/com/yigongil/backend/domain/feedpost/FeedService.java @@ -1,6 +1,6 @@ package com.yigongil.backend.domain.feedpost; -import com.yigongil.backend.domain.member.Member; +import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.study.Study; import com.yigongil.backend.request.FeedPostCreateRequest; import java.util.List; diff --git a/backend/src/main/java/com/yigongil/backend/domain/member/MemberService.java b/backend/src/main/java/com/yigongil/backend/domain/member/MemberService.java deleted file mode 100644 index 52d02c4aa..000000000 --- a/backend/src/main/java/com/yigongil/backend/domain/member/MemberService.java +++ /dev/null @@ -1,106 +0,0 @@ -package com.yigongil.backend.domain.member; - -import com.yigongil.backend.domain.study.Study; -import com.yigongil.backend.domain.study.StudyService; -import com.yigongil.backend.domain.studymember.StudyMember; -import com.yigongil.backend.domain.studymember.StudyMemberRepository; -import com.yigongil.backend.exception.MemberNotFoundException; -import com.yigongil.backend.request.ProfileUpdateRequest; -import com.yigongil.backend.response.FinishedStudyResponse; -import com.yigongil.backend.response.NicknameValidationResponse; -import com.yigongil.backend.response.ProfileResponse; -import java.util.List; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -public class MemberService { - - private final MemberRepository memberRepository; - private final StudyMemberRepository studyMemberRepository; - private final StudyService studyService; - - public MemberService( - MemberRepository memberRepository, - StudyMemberRepository studyMemberRepository, - StudyService studyService - ) { - this.memberRepository = memberRepository; - this.studyMemberRepository = studyMemberRepository; - this.studyService = studyService; - } - - @Transactional(readOnly = true) - public ProfileResponse findById(Long id) { - Member member = findMemberById(id); - - List finishedStudyResponses = - studyMemberRepository.findAllByMemberId(member.getId()) - .stream() - .filter(StudyMember::isStudyEnd) - .map(this::createFinishedStudyResponse) - .toList(); - - return new ProfileResponse( - member.getId(), - member.getNickname(), - member.getGithubId(), - member.getProfileImageUrl(), - studyService.calculateSuccessRate(member), - calculateNumberOfSuccessRounds(member), - member.calculateProgress(), - member.getTier().getOrder(), - member.getIntroduction(), - finishedStudyResponses - ); - } - - public Member findMemberById(Long id) { - return memberRepository.findByIdAndDeletedFalse(id) - .orElseThrow(() -> new MemberNotFoundException( - "해당 멤버가 존재하지 않습니다.", String.valueOf(id) - ) - ); - } - - private FinishedStudyResponse createFinishedStudyResponse(StudyMember studyMember) { - Study study = studyMember.getStudy(); - return new FinishedStudyResponse( - study.getId(), - study.getName(), - study.calculateAverageTier(), - study.sizeOfCurrentMembers(), - study.getNumberOfMaximumMembers(), - studyMember.isSuccess() - ); - } - - private int calculateNumberOfSuccessRounds(Member member) { - List studies = studyMemberRepository.findAllByMemberId(member.getId()).stream() - .filter(StudyMember::isNotApplicant) - .map(StudyMember::getStudy) - .toList(); - - return (int) studies.stream() - .map(Study::getRounds) - .flatMap(List::stream) - .filter(round -> round.isMustDoDone(member)) - .count(); - } - - @Transactional - public void update(Member member, ProfileUpdateRequest request) { - member.updateProfile(request.nickname(), request.introduction()); - } - - @Transactional - public void delete(Member member) { - memberRepository.delete(member); - } - - @Transactional(readOnly = true) - public NicknameValidationResponse existsByNickname(String nickname) { - boolean exists = memberRepository.existsByNickname(new Nickname(nickname)); - return new NicknameValidationResponse(exists); - } -} diff --git a/backend/src/main/java/com/yigongil/backend/domain/member/application/MemberService.java b/backend/src/main/java/com/yigongil/backend/domain/member/application/MemberService.java new file mode 100644 index 000000000..7dc3ce494 --- /dev/null +++ b/backend/src/main/java/com/yigongil/backend/domain/member/application/MemberService.java @@ -0,0 +1,35 @@ +package com.yigongil.backend.domain.member.application; + +import com.yigongil.backend.domain.member.domain.Member; +import com.yigongil.backend.domain.member.domain.MemberRepository; +import com.yigongil.backend.domain.member.domain.Nickname; +import com.yigongil.backend.request.ProfileUpdateRequest; +import com.yigongil.backend.response.NicknameValidationResponse; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class MemberService { + + private final MemberRepository memberRepository; + + public MemberService(MemberRepository memberRepository) { + this.memberRepository = memberRepository; + } + + @Transactional + public void update(Member member, ProfileUpdateRequest request) { + member.updateProfile(request.nickname(), request.introduction()); + } + + @Transactional + public void delete(Member member) { + memberRepository.delete(member); + } + + @Transactional(readOnly = true) + public NicknameValidationResponse existsByNickname(String nickname) { + boolean exists = memberRepository.existsByNickname(new Nickname(nickname)); + return new NicknameValidationResponse(exists); + } +} diff --git a/backend/src/main/java/com/yigongil/backend/domain/member/Introduction.java b/backend/src/main/java/com/yigongil/backend/domain/member/domain/Introduction.java similarity index 96% rename from backend/src/main/java/com/yigongil/backend/domain/member/Introduction.java rename to backend/src/main/java/com/yigongil/backend/domain/member/domain/Introduction.java index 0a15bf772..8c98f0cd4 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/member/Introduction.java +++ b/backend/src/main/java/com/yigongil/backend/domain/member/domain/Introduction.java @@ -1,4 +1,4 @@ -package com.yigongil.backend.domain.member; +package com.yigongil.backend.domain.member.domain; import com.yigongil.backend.exception.InvalidIntroductionLengthException; import java.util.Objects; diff --git a/backend/src/main/java/com/yigongil/backend/domain/member/Member.java b/backend/src/main/java/com/yigongil/backend/domain/member/domain/Member.java similarity index 98% rename from backend/src/main/java/com/yigongil/backend/domain/member/Member.java rename to backend/src/main/java/com/yigongil/backend/domain/member/domain/Member.java index b63c28d2b..26b83bf44 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/member/Member.java +++ b/backend/src/main/java/com/yigongil/backend/domain/member/domain/Member.java @@ -1,4 +1,4 @@ -package com.yigongil.backend.domain.member; +package com.yigongil.backend.domain.member.domain; import com.yigongil.backend.domain.base.BaseRootEntity; import com.yigongil.backend.domain.event.MemberDeleteEvent; diff --git a/backend/src/main/java/com/yigongil/backend/domain/member/MemberRepository.java b/backend/src/main/java/com/yigongil/backend/domain/member/domain/MemberRepository.java similarity index 51% rename from backend/src/main/java/com/yigongil/backend/domain/member/MemberRepository.java rename to backend/src/main/java/com/yigongil/backend/domain/member/domain/MemberRepository.java index 16ce16733..a52375408 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/member/MemberRepository.java +++ b/backend/src/main/java/com/yigongil/backend/domain/member/domain/MemberRepository.java @@ -1,5 +1,6 @@ -package com.yigongil.backend.domain.member; +package com.yigongil.backend.domain.member.domain; +import com.yigongil.backend.exception.MemberNotFoundException; import java.util.Optional; import org.springframework.data.repository.Repository; @@ -7,6 +8,13 @@ public interface MemberRepository extends Repository { Optional findByIdAndDeletedFalse(Long id); + default Member getById(Long id) { + return findByIdAndDeletedFalse(id).orElseThrow(() -> new MemberNotFoundException( + "해당 멤버가 존재하지 않습니다.", String.valueOf(id) + ) + ); + } + Optional findByGithubId(String githubId); Member save(Member member); diff --git a/backend/src/main/java/com/yigongil/backend/domain/member/Nickname.java b/backend/src/main/java/com/yigongil/backend/domain/member/domain/Nickname.java similarity index 97% rename from backend/src/main/java/com/yigongil/backend/domain/member/Nickname.java rename to backend/src/main/java/com/yigongil/backend/domain/member/domain/Nickname.java index e21af0e32..4ccc214f0 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/member/Nickname.java +++ b/backend/src/main/java/com/yigongil/backend/domain/member/domain/Nickname.java @@ -1,4 +1,4 @@ -package com.yigongil.backend.domain.member; +package com.yigongil.backend.domain.member.domain; import com.yigongil.backend.exception.InvalidNicknameLengthException; import com.yigongil.backend.exception.InvalidNicknamePatternException; diff --git a/backend/src/main/java/com/yigongil/backend/domain/member/Tier.java b/backend/src/main/java/com/yigongil/backend/domain/member/domain/Tier.java similarity index 96% rename from backend/src/main/java/com/yigongil/backend/domain/member/Tier.java rename to backend/src/main/java/com/yigongil/backend/domain/member/domain/Tier.java index e128a14cf..56864708a 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/member/Tier.java +++ b/backend/src/main/java/com/yigongil/backend/domain/member/domain/Tier.java @@ -1,4 +1,4 @@ -package com.yigongil.backend.domain.member; +package com.yigongil.backend.domain.member.domain; import java.util.Arrays; import java.util.Comparator; diff --git a/backend/src/main/java/com/yigongil/backend/domain/member/MemberController.java b/backend/src/main/java/com/yigongil/backend/domain/member/ui/MemberController.java similarity index 65% rename from backend/src/main/java/com/yigongil/backend/domain/member/MemberController.java rename to backend/src/main/java/com/yigongil/backend/domain/member/ui/MemberController.java index c3e52f988..707e08a5e 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/member/MemberController.java +++ b/backend/src/main/java/com/yigongil/backend/domain/member/ui/MemberController.java @@ -1,18 +1,17 @@ -package com.yigongil.backend.domain.member; +package com.yigongil.backend.domain.member.ui; import com.yigongil.backend.config.auth.Authorization; +import com.yigongil.backend.domain.member.application.MemberService; +import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.request.ProfileUpdateRequest; -import com.yigongil.backend.response.MyProfileResponse; import com.yigongil.backend.response.NicknameValidationResponse; import com.yigongil.backend.response.OnboardingCheckResponse; -import com.yigongil.backend.response.ProfileResponse; import com.yigongil.backend.ui.doc.MemberApi; import javax.validation.Valid; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PatchMapping; -import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; @@ -28,30 +27,6 @@ public MemberController(MemberService memberService) { this.memberService = memberService; } - @GetMapping(path = "/{id}") - public ResponseEntity findProfile(@PathVariable Long id) { - ProfileResponse response = memberService.findById(id); - return ResponseEntity.ok(response); - } - - @GetMapping(path = "/my") - public ResponseEntity findMyProfile(@Authorization Member member) { - ProfileResponse profile = memberService.findById(member.getId()); - MyProfileResponse response = new MyProfileResponse( - profile.id(), - profile.nickname(), - profile.githubId(), - profile.profileImageUrl(), - profile.successRate(), - profile.successfulRoundCount(), - profile.tierProgress(), - profile.tier(), - profile.introduction() - ); - - return ResponseEntity.ok(response); - } - @PatchMapping public ResponseEntity updateProfile( @Authorization Member member, diff --git a/backend/src/main/java/com/yigongil/backend/domain/report/MemberReport.java b/backend/src/main/java/com/yigongil/backend/domain/report/MemberReport.java index 591b0b65e..f3081ceef 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/report/MemberReport.java +++ b/backend/src/main/java/com/yigongil/backend/domain/report/MemberReport.java @@ -1,6 +1,6 @@ package com.yigongil.backend.domain.report; -import com.yigongil.backend.domain.member.Member; +import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.exception.InvalidReportException; import java.time.LocalDate; import javax.persistence.Entity; diff --git a/backend/src/main/java/com/yigongil/backend/domain/report/Report.java b/backend/src/main/java/com/yigongil/backend/domain/report/Report.java index 48516db1d..b9976009e 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/report/Report.java +++ b/backend/src/main/java/com/yigongil/backend/domain/report/Report.java @@ -1,7 +1,7 @@ package com.yigongil.backend.domain.report; import com.yigongil.backend.domain.base.BaseEntity; -import com.yigongil.backend.domain.member.Member; +import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.exception.InvalidReportContentLengthException; import com.yigongil.backend.exception.InvalidReportTitleLengthException; import java.time.LocalDate; diff --git a/backend/src/main/java/com/yigongil/backend/domain/report/ReportController.java b/backend/src/main/java/com/yigongil/backend/domain/report/ReportController.java index d3063425f..4196988e8 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/report/ReportController.java +++ b/backend/src/main/java/com/yigongil/backend/domain/report/ReportController.java @@ -1,7 +1,7 @@ package com.yigongil.backend.domain.report; import com.yigongil.backend.config.auth.Authorization; -import com.yigongil.backend.domain.member.Member; +import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.request.MemberReportCreateRequest; import com.yigongil.backend.request.StudyReportCreateRequest; import com.yigongil.backend.ui.doc.ReportApi; diff --git a/backend/src/main/java/com/yigongil/backend/domain/report/ReportService.java b/backend/src/main/java/com/yigongil/backend/domain/report/ReportService.java index c6a2eb255..d0e79b6d5 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/report/ReportService.java +++ b/backend/src/main/java/com/yigongil/backend/domain/report/ReportService.java @@ -1,7 +1,7 @@ package com.yigongil.backend.domain.report; -import com.yigongil.backend.domain.member.Member; -import com.yigongil.backend.domain.member.MemberService; +import com.yigongil.backend.domain.member.domain.Member; +import com.yigongil.backend.domain.member.domain.MemberRepository; import com.yigongil.backend.domain.study.Study; import com.yigongil.backend.domain.study.StudyService; import com.yigongil.backend.request.MemberReportCreateRequest; @@ -13,22 +13,22 @@ public class ReportService { private final ReportRepository reportRepository; - private final MemberService memberService; + private final MemberRepository memberRepository; private final StudyService studyService; public ReportService( ReportRepository reportRepository, - MemberService memberService, + MemberRepository memberRepository, StudyService studyService ) { this.reportRepository = reportRepository; - this.memberService = memberService; + this.memberRepository = memberRepository; this.studyService = studyService; } @Transactional public void reportMember(Member reporter, MemberReportCreateRequest request) { - Member reportedMember = memberService.findMemberById(request.reportedMemberId()); + Member reportedMember = memberRepository.getById(request.reportedMemberId()); reportRepository.save( MemberReport.builder() .reporter(reporter) diff --git a/backend/src/main/java/com/yigongil/backend/domain/report/StudyReport.java b/backend/src/main/java/com/yigongil/backend/domain/report/StudyReport.java index 51c998301..642c4c178 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/report/StudyReport.java +++ b/backend/src/main/java/com/yigongil/backend/domain/report/StudyReport.java @@ -1,6 +1,6 @@ package com.yigongil.backend.domain.report; -import com.yigongil.backend.domain.member.Member; +import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.study.Study; import java.time.LocalDate; import javax.persistence.Entity; diff --git a/backend/src/main/java/com/yigongil/backend/domain/member/HomeController.java b/backend/src/main/java/com/yigongil/backend/domain/round/HomeController.java similarity index 90% rename from backend/src/main/java/com/yigongil/backend/domain/member/HomeController.java rename to backend/src/main/java/com/yigongil/backend/domain/round/HomeController.java index f1f94454e..ca2058f20 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/member/HomeController.java +++ b/backend/src/main/java/com/yigongil/backend/domain/round/HomeController.java @@ -1,7 +1,7 @@ -package com.yigongil.backend.domain.member; +package com.yigongil.backend.domain.round; import com.yigongil.backend.config.auth.Authorization; -import com.yigongil.backend.domain.round.RoundService; +import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.response.UpcomingStudyResponse; import com.yigongil.backend.ui.doc.HomeApi; import java.util.List; diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/MustDoController.java b/backend/src/main/java/com/yigongil/backend/domain/round/MustDoController.java index 3c4fc3bbb..c3e2cac4f 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/round/MustDoController.java +++ b/backend/src/main/java/com/yigongil/backend/domain/round/MustDoController.java @@ -1,7 +1,7 @@ package com.yigongil.backend.domain.round; import com.yigongil.backend.config.auth.Authorization; -import com.yigongil.backend.domain.member.Member; +import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.request.MustDoUpdateRequest; import com.yigongil.backend.ui.doc.MustDoApi; import javax.validation.Valid; diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/MustDoService.java b/backend/src/main/java/com/yigongil/backend/domain/round/MustDoService.java index f22b16f69..65241ab15 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/round/MustDoService.java +++ b/backend/src/main/java/com/yigongil/backend/domain/round/MustDoService.java @@ -1,6 +1,6 @@ package com.yigongil.backend.domain.round; -import com.yigongil.backend.domain.member.Member; +import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.exception.RoundNotFoundException; import com.yigongil.backend.request.MustDoUpdateRequest; import org.springframework.stereotype.Service; diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/Round.java b/backend/src/main/java/com/yigongil/backend/domain/round/Round.java index 0b515c775..89e906891 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/round/Round.java +++ b/backend/src/main/java/com/yigongil/backend/domain/round/Round.java @@ -1,7 +1,7 @@ package com.yigongil.backend.domain.round; import com.yigongil.backend.domain.base.BaseEntity; -import com.yigongil.backend.domain.member.Member; +import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.roundofmember.RoundOfMember; import com.yigongil.backend.domain.study.Study; import com.yigongil.backend.exception.InvalidTodoLengthException; diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java b/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java index 33a0d12aa..6957bf87b 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java +++ b/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java @@ -1,6 +1,6 @@ package com.yigongil.backend.domain.round; -import com.yigongil.backend.domain.member.Member; +import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.study.ProcessingStatus; import com.yigongil.backend.domain.study.Study; import com.yigongil.backend.domain.study.StudyRepository; diff --git a/backend/src/main/java/com/yigongil/backend/domain/roundofmember/RoundOfMember.java b/backend/src/main/java/com/yigongil/backend/domain/roundofmember/RoundOfMember.java index fe13aa35b..93e78da45 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/roundofmember/RoundOfMember.java +++ b/backend/src/main/java/com/yigongil/backend/domain/roundofmember/RoundOfMember.java @@ -1,7 +1,7 @@ package com.yigongil.backend.domain.roundofmember; import com.yigongil.backend.domain.base.BaseEntity; -import com.yigongil.backend.domain.member.Member; +import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.study.Study; import java.util.List; import javax.persistence.Column; diff --git a/backend/src/main/java/com/yigongil/backend/domain/study/Study.java b/backend/src/main/java/com/yigongil/backend/domain/study/Study.java index 9cd843a43..cc0cb0c04 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/study/Study.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/Study.java @@ -2,7 +2,7 @@ import com.yigongil.backend.domain.base.BaseEntity; import com.yigongil.backend.domain.meetingdayoftheweek.MeetingDayOfTheWeek; -import com.yigongil.backend.domain.member.Member; +import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.round.Round; import com.yigongil.backend.domain.roundofmember.RoundOfMember; import com.yigongil.backend.domain.studymember.Role; diff --git a/backend/src/main/java/com/yigongil/backend/domain/study/StudyController.java b/backend/src/main/java/com/yigongil/backend/domain/study/StudyController.java index 667e6e941..399792901 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/study/StudyController.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/StudyController.java @@ -1,7 +1,7 @@ package com.yigongil.backend.domain.study; import com.yigongil.backend.config.auth.Authorization; -import com.yigongil.backend.domain.member.Member; +import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.studymember.Role; import com.yigongil.backend.request.CertificationCreateRequest; import com.yigongil.backend.request.FeedPostCreateRequest; diff --git a/backend/src/main/java/com/yigongil/backend/domain/study/StudyRepository.java b/backend/src/main/java/com/yigongil/backend/domain/study/StudyRepository.java index ad202dd6f..2d9b799fd 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/study/StudyRepository.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/StudyRepository.java @@ -1,6 +1,6 @@ package com.yigongil.backend.domain.study; -import com.yigongil.backend.domain.member.Member; +import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.study.studyquery.StudyQueryRepository; import com.yigongil.backend.domain.studymember.Role; import java.util.List; diff --git a/backend/src/main/java/com/yigongil/backend/domain/study/StudyService.java b/backend/src/main/java/com/yigongil/backend/domain/study/StudyService.java index 837a10982..e92dbdb1f 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/study/StudyService.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/StudyService.java @@ -3,7 +3,7 @@ import com.yigongil.backend.domain.certification.Certification; import com.yigongil.backend.domain.certification.CertificationService; import com.yigongil.backend.domain.feedpost.FeedService; -import com.yigongil.backend.domain.member.Member; +import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.round.Round; import com.yigongil.backend.domain.round.RoundRepository; import com.yigongil.backend.domain.roundofmember.RoundOfMember; diff --git a/backend/src/main/java/com/yigongil/backend/domain/studymember/StudyMember.java b/backend/src/main/java/com/yigongil/backend/domain/studymember/StudyMember.java index 9deb8ae3b..ba6005e8d 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/studymember/StudyMember.java +++ b/backend/src/main/java/com/yigongil/backend/domain/studymember/StudyMember.java @@ -1,7 +1,7 @@ package com.yigongil.backend.domain.studymember; import com.yigongil.backend.domain.base.BaseEntity; -import com.yigongil.backend.domain.member.Member; +import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.study.Study; import java.util.Objects; import javax.persistence.Column; diff --git a/backend/src/main/java/com/yigongil/backend/query/profile/ProfileService.java b/backend/src/main/java/com/yigongil/backend/query/profile/ProfileService.java new file mode 100644 index 000000000..2c5a40c0c --- /dev/null +++ b/backend/src/main/java/com/yigongil/backend/query/profile/ProfileService.java @@ -0,0 +1,77 @@ +package com.yigongil.backend.query.profile; + +import com.yigongil.backend.domain.member.domain.Member; +import com.yigongil.backend.domain.member.domain.MemberRepository; +import com.yigongil.backend.domain.study.Study; +import com.yigongil.backend.domain.study.StudyService; +import com.yigongil.backend.domain.studymember.StudyMember; +import com.yigongil.backend.domain.studymember.StudyMemberRepository; +import com.yigongil.backend.response.FinishedStudyResponse; +import com.yigongil.backend.response.ProfileResponse; +import java.util.List; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Transactional(readOnly = true) +@Service +public class ProfileService { + + private final StudyMemberRepository studyMemberRepository; + private final StudyService studyService; + private final MemberRepository memberRepository; + + public ProfileService(StudyMemberRepository studyMemberRepository, StudyService studyService, + MemberRepository memberRepository) { + this.studyMemberRepository = studyMemberRepository; + this.studyService = studyService; + this.memberRepository = memberRepository; + } + + public ProfileResponse findById(Long id) { + Member member = memberRepository.getById(id); + + List finishedStudyResponses = studyMemberRepository.findAllByMemberId(id) + .stream() + .filter(StudyMember::isStudyEnd) + .map(this::createFinishedStudyResponse) + .toList(); + + return new ProfileResponse( + member.getId(), + member.getNickname(), + member.getGithubId(), + member.getProfileImageUrl(), + studyService.calculateSuccessRate(member), + calculateNumberOfSuccessRounds(member), + member.calculateProgress(), + member.getTier().getOrder(), + member.getIntroduction(), + finishedStudyResponses + ); + } + + private FinishedStudyResponse createFinishedStudyResponse(StudyMember studyMember) { + Study study = studyMember.getStudy(); + return new FinishedStudyResponse( + study.getId(), + study.getName(), + study.calculateAverageTier(), + study.sizeOfCurrentMembers(), + study.getNumberOfMaximumMembers(), + studyMember.isSuccess() + ); + } + + private int calculateNumberOfSuccessRounds(Member member) { + List studies = studyMemberRepository.findAllByMemberId(member.getId()).stream() + .filter(StudyMember::isNotApplicant) + .map(StudyMember::getStudy) + .toList(); + + return (int) studies.stream() + .map(Study::getRounds) + .flatMap(List::stream) + .filter(round -> round.isMustDoDone(member)) + .count(); + } +} diff --git a/backend/src/main/java/com/yigongil/backend/query/profile/ui/ProfileApi.java b/backend/src/main/java/com/yigongil/backend/query/profile/ui/ProfileApi.java new file mode 100644 index 000000000..7247c8b17 --- /dev/null +++ b/backend/src/main/java/com/yigongil/backend/query/profile/ui/ProfileApi.java @@ -0,0 +1,39 @@ +package com.yigongil.backend.query.profile.ui; + +import com.yigongil.backend.domain.member.domain.Member; +import com.yigongil.backend.response.MyProfileResponse; +import com.yigongil.backend.response.ProfileResponse; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.http.ResponseEntity; + +@Tag(name = "프로필 조회", description = "프로필 조회 api") +public interface ProfileApi { + + @ApiResponses( + value = { + @ApiResponse(responseCode = "200"), + @ApiResponse(responseCode = "404", content = @Content) + } + ) + @Operation(summary = "프로필을 조회") + ResponseEntity findProfile( + @Parameter(description = "조회할 회원의 식별자", required = true) Long id + ); + + @ApiResponses( + value = { + @ApiResponse(responseCode = "200"), + @ApiResponse(responseCode = "401", content = @Content) + } + ) + @SecurityRequirement(name = "token") + @Operation(summary = "내 프로필을 조회") + ResponseEntity findMyProfile(@Schema(hidden = true) Member member); +} diff --git a/backend/src/main/java/com/yigongil/backend/query/profile/ui/ProfileController.java b/backend/src/main/java/com/yigongil/backend/query/profile/ui/ProfileController.java new file mode 100644 index 000000000..22774874f --- /dev/null +++ b/backend/src/main/java/com/yigongil/backend/query/profile/ui/ProfileController.java @@ -0,0 +1,47 @@ +package com.yigongil.backend.query.profile.ui; + +import com.yigongil.backend.config.auth.Authorization; +import com.yigongil.backend.domain.member.domain.Member; +import com.yigongil.backend.query.profile.ProfileService; +import com.yigongil.backend.response.MyProfileResponse; +import com.yigongil.backend.response.ProfileResponse; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RequestMapping("/members") +@RestController +public class ProfileController implements ProfileApi { + + private final ProfileService profileService; + + public ProfileController(ProfileService profileService) { + this.profileService = profileService; + } + + @GetMapping(path = "/{id}") + public ResponseEntity findProfile(@PathVariable Long id) { + ProfileResponse response = profileService.findById(id); + return ResponseEntity.ok(response); + } + + @GetMapping(path = "/my") + public ResponseEntity findMyProfile(@Authorization Member member) { + ProfileResponse profile = profileService.findById(member.getId()); + MyProfileResponse response = new MyProfileResponse( + profile.id(), + profile.nickname(), + profile.githubId(), + profile.profileImageUrl(), + profile.successRate(), + profile.successfulRoundCount(), + profile.tierProgress(), + profile.tier(), + profile.introduction() + ); + + return ResponseEntity.ok(response); + } +} diff --git a/backend/src/main/java/com/yigongil/backend/response/MemberOfRoundResponse.java b/backend/src/main/java/com/yigongil/backend/response/MemberOfRoundResponse.java index 6d31358f8..98618baea 100644 --- a/backend/src/main/java/com/yigongil/backend/response/MemberOfRoundResponse.java +++ b/backend/src/main/java/com/yigongil/backend/response/MemberOfRoundResponse.java @@ -1,6 +1,6 @@ package com.yigongil.backend.response; -import com.yigongil.backend.domain.member.Member; +import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.roundofmember.RoundOfMember; import io.swagger.v3.oas.annotations.media.Schema; import java.util.List; diff --git a/backend/src/main/java/com/yigongil/backend/response/MembersCertificationResponse.java b/backend/src/main/java/com/yigongil/backend/response/MembersCertificationResponse.java index 0ce32a865..5f5d175a3 100644 --- a/backend/src/main/java/com/yigongil/backend/response/MembersCertificationResponse.java +++ b/backend/src/main/java/com/yigongil/backend/response/MembersCertificationResponse.java @@ -1,6 +1,6 @@ package com.yigongil.backend.response; -import com.yigongil.backend.domain.member.Member; +import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.round.Round; import com.yigongil.backend.domain.roundofmember.RoundOfMember; import com.yigongil.backend.exception.NotStudyMemberException; diff --git a/backend/src/main/java/com/yigongil/backend/ui/doc/HomeApi.java b/backend/src/main/java/com/yigongil/backend/ui/doc/HomeApi.java index c4ff6a5c4..25f235f03 100644 --- a/backend/src/main/java/com/yigongil/backend/ui/doc/HomeApi.java +++ b/backend/src/main/java/com/yigongil/backend/ui/doc/HomeApi.java @@ -1,6 +1,6 @@ package com.yigongil.backend.ui.doc; -import com.yigongil.backend.domain.member.Member; +import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.response.UpcomingStudyResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; diff --git a/backend/src/main/java/com/yigongil/backend/ui/doc/MemberApi.java b/backend/src/main/java/com/yigongil/backend/ui/doc/MemberApi.java index 762d3a51a..5addbf14d 100644 --- a/backend/src/main/java/com/yigongil/backend/ui/doc/MemberApi.java +++ b/backend/src/main/java/com/yigongil/backend/ui/doc/MemberApi.java @@ -1,11 +1,9 @@ package com.yigongil.backend.ui.doc; -import com.yigongil.backend.domain.member.Member; +import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.request.ProfileUpdateRequest; -import com.yigongil.backend.response.MyProfileResponse; import com.yigongil.backend.response.NicknameValidationResponse; import com.yigongil.backend.response.OnboardingCheckResponse; -import com.yigongil.backend.response.ProfileResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; @@ -19,27 +17,6 @@ @Tag(name = "회원", description = "회원 관련 api") public interface MemberApi { - @ApiResponses( - value = { - @ApiResponse(responseCode = "200"), - @ApiResponse(responseCode = "404", content = @Content) - } - ) - @Operation(summary = "프로필을 조회") - ResponseEntity findProfile( - @Parameter(description = "조회할 회원의 식별자", required = true) Long id - ); - - @ApiResponses( - value = { - @ApiResponse(responseCode = "200"), - @ApiResponse(responseCode = "401", content = @Content) - } - ) - @SecurityRequirement(name = "token") - @Operation(summary = "내 프로필을 조회") - ResponseEntity findMyProfile(@Schema(hidden = true) Member member); - @ApiResponses( value = { @ApiResponse(responseCode = "200"), diff --git a/backend/src/main/java/com/yigongil/backend/ui/doc/MustDoApi.java b/backend/src/main/java/com/yigongil/backend/ui/doc/MustDoApi.java index 7c824cea3..9c6ebd8ca 100644 --- a/backend/src/main/java/com/yigongil/backend/ui/doc/MustDoApi.java +++ b/backend/src/main/java/com/yigongil/backend/ui/doc/MustDoApi.java @@ -1,6 +1,6 @@ package com.yigongil.backend.ui.doc; -import com.yigongil.backend.domain.member.Member; +import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.request.MustDoUpdateRequest; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; diff --git a/backend/src/main/java/com/yigongil/backend/ui/doc/ReportApi.java b/backend/src/main/java/com/yigongil/backend/ui/doc/ReportApi.java index a64709007..ddbec5b28 100644 --- a/backend/src/main/java/com/yigongil/backend/ui/doc/ReportApi.java +++ b/backend/src/main/java/com/yigongil/backend/ui/doc/ReportApi.java @@ -1,7 +1,7 @@ package com.yigongil.backend.ui.doc; import com.yigongil.backend.config.auth.Authorization; -import com.yigongil.backend.domain.member.Member; +import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.request.MemberReportCreateRequest; import com.yigongil.backend.request.StudyReportCreateRequest; import io.swagger.v3.oas.annotations.Operation; diff --git a/backend/src/main/java/com/yigongil/backend/ui/doc/StudyApi.java b/backend/src/main/java/com/yigongil/backend/ui/doc/StudyApi.java index e7d7f14e2..946521422 100644 --- a/backend/src/main/java/com/yigongil/backend/ui/doc/StudyApi.java +++ b/backend/src/main/java/com/yigongil/backend/ui/doc/StudyApi.java @@ -1,6 +1,6 @@ package com.yigongil.backend.ui.doc; -import com.yigongil.backend.domain.member.Member; +import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.study.ProcessingStatus; import com.yigongil.backend.request.CertificationCreateRequest; import com.yigongil.backend.request.FeedPostCreateRequest; diff --git a/backend/src/test/java/com/yigongil/backend/application/MustDoServiceTest.java b/backend/src/test/java/com/yigongil/backend/application/MustDoServiceTest.java index 7938af28e..cfc28cdce 100644 --- a/backend/src/test/java/com/yigongil/backend/application/MustDoServiceTest.java +++ b/backend/src/test/java/com/yigongil/backend/application/MustDoServiceTest.java @@ -4,7 +4,7 @@ import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.mockito.BDDMockito.willReturn; -import com.yigongil.backend.domain.member.Member; +import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.round.MustDoService; import com.yigongil.backend.domain.round.Round; import com.yigongil.backend.domain.round.RoundRepository; diff --git a/backend/src/test/java/com/yigongil/backend/application/StudyServiceTest.java b/backend/src/test/java/com/yigongil/backend/application/StudyServiceTest.java index 7839980ac..a05687902 100644 --- a/backend/src/test/java/com/yigongil/backend/application/StudyServiceTest.java +++ b/backend/src/test/java/com/yigongil/backend/application/StudyServiceTest.java @@ -6,7 +6,7 @@ import com.yigongil.backend.domain.certification.CertificationService; import com.yigongil.backend.domain.feedpost.FeedService; -import com.yigongil.backend.domain.member.Member; +import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.round.RoundRepository; import com.yigongil.backend.domain.study.StudyRepository; import com.yigongil.backend.domain.study.StudyService; diff --git a/backend/src/test/java/com/yigongil/backend/domain/member/MemberTest.java b/backend/src/test/java/com/yigongil/backend/domain/member/MemberTest.java index 747b1481f..c8bec545e 100644 --- a/backend/src/test/java/com/yigongil/backend/domain/member/MemberTest.java +++ b/backend/src/test/java/com/yigongil/backend/domain/member/MemberTest.java @@ -3,6 +3,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.exception.InvalidIntroductionLengthException; import com.yigongil.backend.exception.InvalidNicknameLengthException; import com.yigongil.backend.exception.InvalidNicknamePatternException; diff --git a/backend/src/test/java/com/yigongil/backend/domain/member/TierTest.java b/backend/src/test/java/com/yigongil/backend/domain/member/TierTest.java index 5fde9d30e..34c86ea0f 100644 --- a/backend/src/test/java/com/yigongil/backend/domain/member/TierTest.java +++ b/backend/src/test/java/com/yigongil/backend/domain/member/TierTest.java @@ -3,6 +3,7 @@ import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; +import com.yigongil.backend.domain.member.domain.Tier; import org.junit.jupiter.api.Test; class TierTest { diff --git a/backend/src/test/java/com/yigongil/backend/domain/report/ReportTest.java b/backend/src/test/java/com/yigongil/backend/domain/report/ReportTest.java index c3acd7cf8..1f234bdb8 100644 --- a/backend/src/test/java/com/yigongil/backend/domain/report/ReportTest.java +++ b/backend/src/test/java/com/yigongil/backend/domain/report/ReportTest.java @@ -2,7 +2,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; -import com.yigongil.backend.domain.member.Member; +import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.exception.InvalidReportContentLengthException; import com.yigongil.backend.exception.InvalidReportException; import com.yigongil.backend.exception.InvalidReportTitleLengthException; diff --git a/backend/src/test/java/com/yigongil/backend/domain/round/RoundTest.java b/backend/src/test/java/com/yigongil/backend/domain/round/RoundTest.java index 9001a9230..62126523b 100644 --- a/backend/src/test/java/com/yigongil/backend/domain/round/RoundTest.java +++ b/backend/src/test/java/com/yigongil/backend/domain/round/RoundTest.java @@ -3,7 +3,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import com.yigongil.backend.domain.member.Member; +import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.exception.InvalidTodoLengthException; import com.yigongil.backend.exception.NotStudyMasterException; import com.yigongil.backend.fixture.RoundFixture; diff --git a/backend/src/test/java/com/yigongil/backend/domain/study/StudyTest.java b/backend/src/test/java/com/yigongil/backend/domain/study/StudyTest.java index c41b72e1d..bfea88e43 100644 --- a/backend/src/test/java/com/yigongil/backend/domain/study/StudyTest.java +++ b/backend/src/test/java/com/yigongil/backend/domain/study/StudyTest.java @@ -3,7 +3,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import com.yigongil.backend.domain.member.Member; +import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.round.Round; import com.yigongil.backend.exception.InvalidMemberSizeException; import com.yigongil.backend.exception.InvalidProcessingStatusException; diff --git a/backend/src/test/java/com/yigongil/backend/domain/study/studyquery/StudyQueryRepositoryImplTest.java b/backend/src/test/java/com/yigongil/backend/domain/study/studyquery/StudyQueryRepositoryImplTest.java index a8e562b93..ee7ac6a1b 100644 --- a/backend/src/test/java/com/yigongil/backend/domain/study/studyquery/StudyQueryRepositoryImplTest.java +++ b/backend/src/test/java/com/yigongil/backend/domain/study/studyquery/StudyQueryRepositoryImplTest.java @@ -4,8 +4,8 @@ import com.yigongil.backend.config.JpaConfig; import com.yigongil.backend.config.QueryFactoryConfig; -import com.yigongil.backend.domain.member.Member; -import com.yigongil.backend.domain.member.MemberRepository; +import com.yigongil.backend.domain.member.domain.Member; +import com.yigongil.backend.domain.member.domain.MemberRepository; import com.yigongil.backend.domain.study.PageStrategy; import com.yigongil.backend.domain.study.ProcessingStatus; import com.yigongil.backend.domain.study.Study; diff --git a/backend/src/test/java/com/yigongil/backend/fake/FakeController.java b/backend/src/test/java/com/yigongil/backend/fake/FakeController.java index 97cc3318b..58d28dc84 100644 --- a/backend/src/test/java/com/yigongil/backend/fake/FakeController.java +++ b/backend/src/test/java/com/yigongil/backend/fake/FakeController.java @@ -1,8 +1,8 @@ package com.yigongil.backend.fake; import com.yigongil.backend.config.auth.JwtTokenProvider; -import com.yigongil.backend.domain.member.Member; -import com.yigongil.backend.domain.member.MemberRepository; +import com.yigongil.backend.domain.member.domain.Member; +import com.yigongil.backend.domain.member.domain.MemberRepository; import com.yigongil.backend.domain.study.StudyService; import com.yigongil.backend.response.TokenResponse; import java.time.LocalDate; diff --git a/backend/src/test/java/com/yigongil/backend/fixture/MemberFixture.java b/backend/src/test/java/com/yigongil/backend/fixture/MemberFixture.java index 3fe1501e5..17d1e0c9e 100644 --- a/backend/src/test/java/com/yigongil/backend/fixture/MemberFixture.java +++ b/backend/src/test/java/com/yigongil/backend/fixture/MemberFixture.java @@ -1,6 +1,6 @@ package com.yigongil.backend.fixture; -import com.yigongil.backend.domain.member.Member; +import com.yigongil.backend.domain.member.domain.Member; public enum MemberFixture { diff --git a/backend/src/test/java/com/yigongil/backend/fixture/RoundFixture.java b/backend/src/test/java/com/yigongil/backend/fixture/RoundFixture.java index c892b6249..fd0f87a1f 100644 --- a/backend/src/test/java/com/yigongil/backend/fixture/RoundFixture.java +++ b/backend/src/test/java/com/yigongil/backend/fixture/RoundFixture.java @@ -1,6 +1,6 @@ package com.yigongil.backend.fixture; -import com.yigongil.backend.domain.member.Member; +import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.round.Round; import com.yigongil.backend.domain.roundofmember.RoundOfMember; import java.util.ArrayList; diff --git a/backend/src/test/java/com/yigongil/backend/fixture/RoundOfMemberFixture.java b/backend/src/test/java/com/yigongil/backend/fixture/RoundOfMemberFixture.java index c44b5bda4..c6dc50ad4 100644 --- a/backend/src/test/java/com/yigongil/backend/fixture/RoundOfMemberFixture.java +++ b/backend/src/test/java/com/yigongil/backend/fixture/RoundOfMemberFixture.java @@ -1,6 +1,6 @@ package com.yigongil.backend.fixture; -import com.yigongil.backend.domain.member.Member; +import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.roundofmember.RoundOfMember; public enum RoundOfMemberFixture { diff --git a/backend/src/test/java/com/yigongil/backend/fixture/StudyFixture.java b/backend/src/test/java/com/yigongil/backend/fixture/StudyFixture.java index 8a6745942..97a7015c4 100644 --- a/backend/src/test/java/com/yigongil/backend/fixture/StudyFixture.java +++ b/backend/src/test/java/com/yigongil/backend/fixture/StudyFixture.java @@ -1,6 +1,6 @@ package com.yigongil.backend.fixture; -import com.yigongil.backend.domain.member.Member; +import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.round.Round; import com.yigongil.backend.domain.study.ProcessingStatus; import com.yigongil.backend.domain.study.Study; diff --git a/backend/src/test/java/com/yigongil/backend/query/profile/ui/ProfileControllerTest.java b/backend/src/test/java/com/yigongil/backend/query/profile/ui/ProfileControllerTest.java new file mode 100644 index 000000000..eb6f913f8 --- /dev/null +++ b/backend/src/test/java/com/yigongil/backend/query/profile/ui/ProfileControllerTest.java @@ -0,0 +1,79 @@ +package com.yigongil.backend.query.profile.ui; + +import static org.mockito.BDDMockito.given; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.yigongil.backend.config.AuthConfig; +import com.yigongil.backend.config.auth.AuthContext; +import com.yigongil.backend.config.auth.JwtTokenProvider; +import com.yigongil.backend.domain.member.domain.Member; +import com.yigongil.backend.domain.member.domain.MemberRepository; +import com.yigongil.backend.domain.member.ui.MemberController; +import com.yigongil.backend.fixture.MemberFixture; +import com.yigongil.backend.query.profile.ProfileService; +import com.yigongil.backend.response.ProfileResponse; +import com.yigongil.backend.ui.exceptionhandler.InternalServerErrorMessageConverter; +import com.yigongil.backend.utils.querycounter.ApiQueryCounter; +import java.util.Collections; +import java.util.Optional; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; +import org.springframework.test.web.servlet.MockMvc; + +@Import(AuthConfig.class) +@WebMvcTest(ProfileController.class) +class ProfileControllerTest { + + @Autowired + private MockMvc mockMvc; + + @MockBean + private ProfileService profileService; + + @MockBean + private MemberRepository memberRepository; + + @MockBean + private AuthContext authContext; + + @MockBean + private JwtTokenProvider tokenProvider; + + @MockBean + private ApiQueryCounter apiQueryCounter; + + @MockBean + private InternalServerErrorMessageConverter internalServerErrorMessageConverter; + + @Test + void 프로필_정보를_조회한다() throws Exception { + Member member = MemberFixture.김진우.toMember(); + given(memberRepository.findByIdAndDeletedFalse(1L)).willReturn(Optional.of(member)); + given(profileService.findById(1L)).willReturn( + new ProfileResponse( + member.getId(), + member.getNickname(), + member.getGithubId(), + member.getProfileImageUrl(), + 0.0, + 0, + 0, + member.getExperience(), + member.getIntroduction(), + Collections.emptyList() + ) + ); + + mockMvc.perform(get("/members/1")) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.nickname").value(member.getNickname())) + .andExpect(jsonPath("$.githubId").value(member.getGithubId())); + } +} diff --git a/backend/src/test/java/com/yigongil/backend/ui/MemberControllerTest.java b/backend/src/test/java/com/yigongil/backend/ui/MemberControllerTest.java index 7a78d0b90..416691f9b 100644 --- a/backend/src/test/java/com/yigongil/backend/ui/MemberControllerTest.java +++ b/backend/src/test/java/com/yigongil/backend/ui/MemberControllerTest.java @@ -16,10 +16,10 @@ import com.yigongil.backend.config.AuthConfig; import com.yigongil.backend.config.auth.AuthContext; import com.yigongil.backend.config.auth.JwtTokenProvider; -import com.yigongil.backend.domain.member.Member; -import com.yigongil.backend.domain.member.MemberController; -import com.yigongil.backend.domain.member.MemberRepository; -import com.yigongil.backend.domain.member.MemberService; +import com.yigongil.backend.domain.member.domain.Member; +import com.yigongil.backend.domain.member.ui.MemberController; +import com.yigongil.backend.domain.member.domain.MemberRepository; +import com.yigongil.backend.domain.member.application.MemberService; import com.yigongil.backend.fixture.MemberFixture; import com.yigongil.backend.request.ProfileUpdateRequest; import com.yigongil.backend.response.NicknameValidationResponse; @@ -65,33 +65,6 @@ class MemberControllerTest { @MockBean private InternalServerErrorMessageConverter internalServerErrorMessageConverter; - - @Test - void 프로필_정보를_조회한다() throws Exception { - Member member = MemberFixture.김진우.toMember(); - given(memberRepository.findByIdAndDeletedFalse(1L)).willReturn(Optional.of(member)); - given(memberService.findById(1L)).willReturn( - new ProfileResponse( - member.getId(), - member.getNickname(), - member.getGithubId(), - member.getProfileImageUrl(), - 0.0, - 0, - 0, - member.getExperience(), - member.getIntroduction(), - Collections.emptyList() - ) - ); - - mockMvc.perform(get("/members/1")) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.nickname").value(member.getNickname())) - .andExpect(jsonPath("$.githubId").value(member.getGithubId())); - } - @Test void 프로필_정보를_업데이트_한다() throws Exception { ProfileUpdateRequest request = new ProfileUpdateRequest("수정된김진우", "수정된자기소개"); diff --git a/backend/src/test/java/com/yigongil/backend/ui/MustDoControllerTest.java b/backend/src/test/java/com/yigongil/backend/ui/MustDoControllerTest.java index f4c6bd94a..8b4b0abd1 100644 --- a/backend/src/test/java/com/yigongil/backend/ui/MustDoControllerTest.java +++ b/backend/src/test/java/com/yigongil/backend/ui/MustDoControllerTest.java @@ -12,7 +12,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.yigongil.backend.config.auth.AuthContext; import com.yigongil.backend.config.auth.JwtTokenProvider; -import com.yigongil.backend.domain.member.MemberRepository; +import com.yigongil.backend.domain.member.domain.MemberRepository; import com.yigongil.backend.domain.round.MustDoController; import com.yigongil.backend.domain.round.MustDoService; import com.yigongil.backend.fixture.MemberFixture; diff --git a/backend/src/test/java/com/yigongil/backend/ui/StudyControllerTest.java b/backend/src/test/java/com/yigongil/backend/ui/StudyControllerTest.java index d8ec6acb2..e7ee0dc1e 100644 --- a/backend/src/test/java/com/yigongil/backend/ui/StudyControllerTest.java +++ b/backend/src/test/java/com/yigongil/backend/ui/StudyControllerTest.java @@ -13,7 +13,7 @@ import com.yigongil.backend.config.auth.JwtTokenProvider; import com.yigongil.backend.domain.certification.CertificationService; import com.yigongil.backend.domain.feedpost.FeedService; -import com.yigongil.backend.domain.member.MemberRepository; +import com.yigongil.backend.domain.member.domain.MemberRepository; import com.yigongil.backend.domain.round.MustDoService; import com.yigongil.backend.domain.study.StudyController; import com.yigongil.backend.domain.study.StudyService; From ea3df4faa2eb95ebc1419dfff0485728ae36f120 Mon Sep 17 00:00:00 2001 From: kim dae hee Date: Mon, 20 Nov 2023 14:11:10 +0900 Subject: [PATCH 05/22] =?UTF-8?q?refactor:=20=EC=9D=B8=EC=A6=9D=20?= =?UTF-8?q?=EC=9D=98=EC=A1=B4=EC=84=B1=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../certification/CertificationApi.java | 33 +++++++++++++ .../CertificationController.java | 31 +++++++++++++ .../CertificationRepository.java | 5 ++ .../certification/CertificationService.java | 19 ++++---- .../domain/member/ui/MemberController.java | 4 +- .../backend/domain/study/StudyController.java | 32 ------------- .../backend/domain/study/StudyRepository.java | 5 ++ .../backend/domain/study/StudyService.java | 31 +------------ .../certification/CertificationQueryApi.java | 44 ++++++++++++++++++ .../CertificationQueryController.java | 38 +++++++++++++++ .../CertificationQueryService.java | 40 ++++++++++++++++ .../query/profile/{ui => }/ProfileApi.java | 2 +- .../profile/{ui => }/ProfileController.java | 3 +- .../com/yigongil/backend/ui/doc/StudyApi.java | 46 ------------------- .../backend/application/StudyServiceTest.java | 1 - .../profile/ui/ProfileControllerTest.java | 2 +- 16 files changed, 213 insertions(+), 123 deletions(-) create mode 100644 backend/src/main/java/com/yigongil/backend/domain/certification/CertificationApi.java create mode 100644 backend/src/main/java/com/yigongil/backend/domain/certification/CertificationController.java create mode 100644 backend/src/main/java/com/yigongil/backend/query/certification/CertificationQueryApi.java create mode 100644 backend/src/main/java/com/yigongil/backend/query/certification/CertificationQueryController.java create mode 100644 backend/src/main/java/com/yigongil/backend/query/certification/CertificationQueryService.java rename backend/src/main/java/com/yigongil/backend/query/profile/{ui => }/ProfileApi.java (96%) rename backend/src/main/java/com/yigongil/backend/query/profile/{ui => }/ProfileController.java (93%) diff --git a/backend/src/main/java/com/yigongil/backend/domain/certification/CertificationApi.java b/backend/src/main/java/com/yigongil/backend/domain/certification/CertificationApi.java new file mode 100644 index 000000000..48f040b41 --- /dev/null +++ b/backend/src/main/java/com/yigongil/backend/domain/certification/CertificationApi.java @@ -0,0 +1,33 @@ +package com.yigongil.backend.domain.certification; + +import com.yigongil.backend.domain.member.domain.Member; +import com.yigongil.backend.request.CertificationCreateRequest; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.http.ResponseEntity; + +@Tag(name = "인증", description = "인증 관련 api") +public interface CertificationApi { + + @ApiResponses( + value = { + @ApiResponse(responseCode = "200"), + @ApiResponse(responseCode = "400", content = @Content), + @ApiResponse(responseCode = "401", content = @Content), + @ApiResponse(responseCode = "404", content = @Content) + } + ) + @SecurityRequirement(name = "token") + @Operation(summary = "인증 피드 등록") + ResponseEntity createCertification( + @Schema(hidden = true) Member member, + @Parameter(description = "피드가 등록되는 스터디 id", required = true) Long id, + CertificationCreateRequest request + ); +} diff --git a/backend/src/main/java/com/yigongil/backend/domain/certification/CertificationController.java b/backend/src/main/java/com/yigongil/backend/domain/certification/CertificationController.java new file mode 100644 index 000000000..e29a5e725 --- /dev/null +++ b/backend/src/main/java/com/yigongil/backend/domain/certification/CertificationController.java @@ -0,0 +1,31 @@ +package com.yigongil.backend.domain.certification; + +import com.yigongil.backend.config.auth.Authorization; +import com.yigongil.backend.domain.member.domain.Member; +import com.yigongil.backend.request.CertificationCreateRequest; +import java.net.URI; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class CertificationController implements CertificationApi { + + private final CertificationService certificationService; + + public CertificationController(CertificationService certificationService) { + this.certificationService = certificationService; + } + + @PostMapping("/studies/{id}/certifications") + public ResponseEntity createCertification( + @Authorization Member member, + @PathVariable Long id, + @RequestBody CertificationCreateRequest request + ) { + Long certificationId = certificationService.createCertification(member, id, request); + return ResponseEntity.created(URI.create("/studies/" + id + "/certifications/" + certificationId)).build(); + } +} diff --git a/backend/src/main/java/com/yigongil/backend/domain/certification/CertificationRepository.java b/backend/src/main/java/com/yigongil/backend/domain/certification/CertificationRepository.java index 179c0ddc4..4a9dc8290 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/certification/CertificationRepository.java +++ b/backend/src/main/java/com/yigongil/backend/domain/certification/CertificationRepository.java @@ -1,5 +1,6 @@ package com.yigongil.backend.domain.certification; +import com.yigongil.backend.exception.NoCertificationException; import java.util.Optional; import org.springframework.data.repository.Repository; @@ -8,4 +9,8 @@ public interface CertificationRepository extends Repository Certification save(Certification feedPost); Optional findByRoundIdAndAuthorId(Long roundId, Long memberId); + + default Certification getByRoundIdAndAuthorId(Long roundId, Long memberId) { + return findByRoundIdAndAuthorId(roundId, memberId).orElseThrow(() -> new NoCertificationException("인증을 찾을 수 없습니다", String.valueOf(memberId))); + } } diff --git a/backend/src/main/java/com/yigongil/backend/domain/certification/CertificationService.java b/backend/src/main/java/com/yigongil/backend/domain/certification/CertificationService.java index 7dbbc551b..9a49dc07c 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/certification/CertificationService.java +++ b/backend/src/main/java/com/yigongil/backend/domain/certification/CertificationService.java @@ -2,7 +2,7 @@ import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.study.Study; -import com.yigongil.backend.exception.NoCertificationException; +import com.yigongil.backend.domain.study.StudyRepository; import com.yigongil.backend.request.CertificationCreateRequest; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -11,13 +11,20 @@ public class CertificationService { private final CertificationRepository certificationRepository; + private final StudyRepository studyRepository; - public CertificationService(CertificationRepository certificationRepository) { + public CertificationService(CertificationRepository certificationRepository, StudyRepository studyRepository) { this.certificationRepository = certificationRepository; + this.studyRepository = studyRepository; } @Transactional - public Certification createCertification(Study study, Member member, CertificationCreateRequest request) { + public Long createCertification(Member member, Long studyId, CertificationCreateRequest request) { + Study study = studyRepository.getById(studyId); + return createCertification(study, member, request).getId(); + } + + private Certification createCertification(Study study, Member member, CertificationCreateRequest request) { Certification feedPost = Certification.builder() .author(member) .study(study) @@ -28,10 +35,4 @@ public Certification createCertification(Study study, Member member, Certificati study.completeRound(member); return certificationRepository.save(feedPost); } - - @Transactional(readOnly = true) - public Certification findByRoundIdAndMemberId(Long roundId, Long memberId) { - return certificationRepository.findByRoundIdAndAuthorId(roundId, memberId) - .orElseThrow(() -> new NoCertificationException("인증을 찾을 수 없습니다", String.valueOf(memberId))); - } } diff --git a/backend/src/main/java/com/yigongil/backend/domain/member/ui/MemberController.java b/backend/src/main/java/com/yigongil/backend/domain/member/ui/MemberController.java index 707e08a5e..8c902f224 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/member/ui/MemberController.java +++ b/backend/src/main/java/com/yigongil/backend/domain/member/ui/MemberController.java @@ -29,8 +29,8 @@ public MemberController(MemberService memberService) { @PatchMapping public ResponseEntity updateProfile( - @Authorization Member member, - @RequestBody @Valid ProfileUpdateRequest request + @Authorization Member member, + @RequestBody @Valid ProfileUpdateRequest request ) { memberService.update(member, request); return ResponseEntity.ok().build(); diff --git a/backend/src/main/java/com/yigongil/backend/domain/study/StudyController.java b/backend/src/main/java/com/yigongil/backend/domain/study/StudyController.java index 399792901..671677a53 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/study/StudyController.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/StudyController.java @@ -3,13 +3,10 @@ import com.yigongil.backend.config.auth.Authorization; import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.studymember.Role; -import com.yigongil.backend.request.CertificationCreateRequest; import com.yigongil.backend.request.FeedPostCreateRequest; import com.yigongil.backend.request.StudyStartRequest; import com.yigongil.backend.request.StudyUpdateRequest; -import com.yigongil.backend.response.CertificationResponse; import com.yigongil.backend.response.FeedPostResponse; -import com.yigongil.backend.response.MembersCertificationResponse; import com.yigongil.backend.response.MyStudyResponse; import com.yigongil.backend.response.RoundResponse; import com.yigongil.backend.response.StudyDetailResponse; @@ -154,34 +151,6 @@ public ResponseEntity createFeedPost( return ResponseEntity.ok().build(); } - @PostMapping("/{id}/certifications") - public ResponseEntity createCertification( - @Authorization Member member, - @PathVariable Long id, - @RequestBody CertificationCreateRequest request - ) { - Long certificationId = studyService.createCertification(member, id, request); - return ResponseEntity.created(URI.create("/studies/" + id + "/certifications/" + certificationId)).build(); - } - - @GetMapping("/{id}/certifications") - public ResponseEntity findAllMembersCertification( - @Authorization Member member, - @PathVariable Long id - ) { - MembersCertificationResponse response = studyService.findAllMembersCertification(member, id); - return ResponseEntity.ok(response); - } - - @GetMapping("/{id}/rounds/{roundId}/members/{memberId}") - public ResponseEntity findMemberCertification( - @PathVariable Long roundId, - @PathVariable Long memberId - ) { - CertificationResponse response = studyService.findCertification(roundId, memberId); - return ResponseEntity.ok(response); - } - @GetMapping("/{studyId}/members/role") public ResponseEntity getStudyMemberRole( @Authorization Member member, @@ -229,4 +198,3 @@ public ResponseEntity exitStudy( return ResponseEntity.ok().build(); } } - diff --git a/backend/src/main/java/com/yigongil/backend/domain/study/StudyRepository.java b/backend/src/main/java/com/yigongil/backend/domain/study/StudyRepository.java index 2d9b799fd..79bb9c7f8 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/study/StudyRepository.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/StudyRepository.java @@ -3,6 +3,7 @@ import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.study.studyquery.StudyQueryRepository; import com.yigongil.backend.domain.studymember.Role; +import com.yigongil.backend.exception.StudyNotFoundException; import java.util.List; import java.util.Optional; import org.springframework.data.jpa.repository.EntityGraph; @@ -49,4 +50,8 @@ List findAllByMasterIdAndProcessingStatus( where s in :studies """) void deleteAll(@Param("studies") Iterable studies); + + default Study getById(Long studyId) { + return findById(studyId).orElseThrow(() -> new StudyNotFoundException("해당 스터디를 찾을 수 없습니다", studyId)); + } } diff --git a/backend/src/main/java/com/yigongil/backend/domain/study/StudyService.java b/backend/src/main/java/com/yigongil/backend/domain/study/StudyService.java index e92dbdb1f..0dcfd9491 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/study/StudyService.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/StudyService.java @@ -1,25 +1,19 @@ package com.yigongil.backend.domain.study; -import com.yigongil.backend.domain.certification.Certification; -import com.yigongil.backend.domain.certification.CertificationService; import com.yigongil.backend.domain.feedpost.FeedService; import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.round.Round; import com.yigongil.backend.domain.round.RoundRepository; -import com.yigongil.backend.domain.roundofmember.RoundOfMember; import com.yigongil.backend.domain.studymember.Role; import com.yigongil.backend.domain.studymember.StudyMember; import com.yigongil.backend.domain.studymember.StudyMemberRepository; import com.yigongil.backend.domain.studymember.StudyResult; import com.yigongil.backend.exception.ApplicantNotFoundException; import com.yigongil.backend.exception.StudyNotFoundException; -import com.yigongil.backend.request.CertificationCreateRequest; import com.yigongil.backend.request.FeedPostCreateRequest; import com.yigongil.backend.request.StudyStartRequest; import com.yigongil.backend.request.StudyUpdateRequest; -import com.yigongil.backend.response.CertificationResponse; import com.yigongil.backend.response.FeedPostResponse; -import com.yigongil.backend.response.MembersCertificationResponse; import com.yigongil.backend.response.MyStudyResponse; import com.yigongil.backend.response.RoundResponse; import com.yigongil.backend.response.StudyDetailResponse; @@ -41,19 +35,17 @@ public class StudyService { private final StudyRepository studyRepository; private final StudyMemberRepository studyMemberRepository; - private final CertificationService certificationService; private final FeedService feedService; private final RoundRepository roundRepository; public StudyService( StudyRepository studyRepository, StudyMemberRepository studyMemberRepository, - CertificationService certificationService, FeedService feedService, - final RoundRepository roundRepository) { + RoundRepository roundRepository + ) { this.studyRepository = studyRepository; this.studyMemberRepository = studyMemberRepository; - this.certificationService = certificationService; this.feedService = feedService; this.roundRepository = roundRepository; } @@ -134,12 +126,6 @@ public void createFeedPost(Member member, Long studyId, FeedPostCreateRequest re feedService.createFeedPost(member, study, request); } - @Transactional - public Long createCertification(Member member, Long id, CertificationCreateRequest request) { - Study study = findStudyById(id); - return certificationService.createCertification(study, member, request).getId(); - } - public Study findStudyById(Long studyId) { return studyRepository.findById(studyId) .orElseThrow(() -> new StudyNotFoundException("해당 스터디를 찾을 수 없습니다", studyId)); @@ -267,19 +253,6 @@ public StudyMemberRoleResponse getMemberRoleOfStudy(Member member, Long studyId) return StudyMemberRoleResponse.from(role); } - @Transactional(readOnly = true) - public MembersCertificationResponse findAllMembersCertification(Member member, Long studyId) { - Study study = findStudyById(studyId); - final List roundOfMembers = study.getCurrentRoundOfMembers(); - return MembersCertificationResponse.of(study.getName(), study.getCurrentRound(), member, roundOfMembers); - } - - @Transactional(readOnly = true) - public CertificationResponse findCertification(Long roundId, Long memberId) { - Certification certification = certificationService.findByRoundIdAndMemberId(roundId, memberId); - return CertificationResponse.from(certification); - } - @Transactional(readOnly = true) public List findFeedPosts(Long id, Long oldestFeedPostId) { return feedService.findFeedPosts(id, oldestFeedPostId) diff --git a/backend/src/main/java/com/yigongil/backend/query/certification/CertificationQueryApi.java b/backend/src/main/java/com/yigongil/backend/query/certification/CertificationQueryApi.java new file mode 100644 index 000000000..8e2c30005 --- /dev/null +++ b/backend/src/main/java/com/yigongil/backend/query/certification/CertificationQueryApi.java @@ -0,0 +1,44 @@ +package com.yigongil.backend.query.certification; + +import com.yigongil.backend.domain.member.domain.Member; +import com.yigongil.backend.response.CertificationResponse; +import com.yigongil.backend.response.MembersCertificationResponse; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.http.ResponseEntity; + +@Tag(name = "인증 조회", description = "인증 조회 관련 api") +public interface CertificationQueryApi { + + @ApiResponses( + value = { + @ApiResponse(responseCode = "200"), + @ApiResponse(responseCode = "401", content = @Content) + } + ) + @SecurityRequirement(name = "token") + @Operation(summary = "스터디 멤버 전체 인증 정보 조회") + ResponseEntity findAllMembersCertification( + @Schema(hidden = true) Member member, + @Parameter(description = "조회하려는 스터디 id", required = true) Long id + ); + + @ApiResponses( + value = { + @ApiResponse(responseCode = "200"), + @ApiResponse(responseCode = "401", content = @Content) + } + ) + @SecurityRequirement(name = "token") + @Operation(summary = "스터디 멤버 단일 인증 게시글 조회") + ResponseEntity findMemberCertification( + @Parameter(description = "인증 게시 회차 id") Long roundId, + @Parameter(description = "작성자 id") Long memberId + ); +} diff --git a/backend/src/main/java/com/yigongil/backend/query/certification/CertificationQueryController.java b/backend/src/main/java/com/yigongil/backend/query/certification/CertificationQueryController.java new file mode 100644 index 000000000..4e1be6e44 --- /dev/null +++ b/backend/src/main/java/com/yigongil/backend/query/certification/CertificationQueryController.java @@ -0,0 +1,38 @@ +package com.yigongil.backend.query.certification; + +import com.yigongil.backend.config.auth.Authorization; +import com.yigongil.backend.domain.member.domain.Member; +import com.yigongil.backend.response.CertificationResponse; +import com.yigongil.backend.response.MembersCertificationResponse; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class CertificationQueryController implements CertificationQueryApi { + + private final CertificationQueryService certificationQueryService; + + public CertificationQueryController(CertificationQueryService certificationQueryService) { + this.certificationQueryService = certificationQueryService; + } + + @GetMapping("/studies/{id}/rounds/{roundId}/members/{memberId}") + public ResponseEntity findMemberCertification( + @PathVariable Long roundId, + @PathVariable Long memberId + ) { + CertificationResponse response = certificationQueryService.findCertification(roundId, memberId); + return ResponseEntity.ok(response); + } + + @GetMapping("/studies/{id}/certifications") + public ResponseEntity findAllMembersCertification( + @Authorization Member member, + @PathVariable Long id + ) { + MembersCertificationResponse response = certificationQueryService.findAllMembersCertification(member, id); + return ResponseEntity.ok(response); + } +} diff --git a/backend/src/main/java/com/yigongil/backend/query/certification/CertificationQueryService.java b/backend/src/main/java/com/yigongil/backend/query/certification/CertificationQueryService.java new file mode 100644 index 000000000..d1c9e0ca3 --- /dev/null +++ b/backend/src/main/java/com/yigongil/backend/query/certification/CertificationQueryService.java @@ -0,0 +1,40 @@ +package com.yigongil.backend.query.certification; + +import com.yigongil.backend.domain.certification.Certification; +import com.yigongil.backend.domain.certification.CertificationRepository; +import com.yigongil.backend.domain.member.domain.Member; +import com.yigongil.backend.domain.roundofmember.RoundOfMember; +import com.yigongil.backend.domain.study.Study; +import com.yigongil.backend.domain.study.StudyRepository; +import com.yigongil.backend.response.CertificationResponse; +import com.yigongil.backend.response.MembersCertificationResponse; +import java.util.List; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Transactional(readOnly = true) +@Service +public class CertificationQueryService { + + private final CertificationRepository certificationRepository; + private final StudyRepository studyRepository; + + public CertificationQueryService( + CertificationRepository certificationRepository, + StudyRepository studyRepository + ) { + this.certificationRepository = certificationRepository; + this.studyRepository = studyRepository; + } + + public CertificationResponse findCertification(Long roundId, Long memberId) { + Certification certification = certificationRepository.getByRoundIdAndAuthorId(roundId, memberId); + return CertificationResponse.from(certification); + } + + public MembersCertificationResponse findAllMembersCertification(Member member, Long studyId) { + Study study = studyRepository.getById(studyId); + final List roundOfMembers = study.getCurrentRoundOfMembers(); + return MembersCertificationResponse.of(study.getName(), study.getCurrentRound(), member, roundOfMembers); + } +} diff --git a/backend/src/main/java/com/yigongil/backend/query/profile/ui/ProfileApi.java b/backend/src/main/java/com/yigongil/backend/query/profile/ProfileApi.java similarity index 96% rename from backend/src/main/java/com/yigongil/backend/query/profile/ui/ProfileApi.java rename to backend/src/main/java/com/yigongil/backend/query/profile/ProfileApi.java index 7247c8b17..c86ce1ad1 100644 --- a/backend/src/main/java/com/yigongil/backend/query/profile/ui/ProfileApi.java +++ b/backend/src/main/java/com/yigongil/backend/query/profile/ProfileApi.java @@ -1,4 +1,4 @@ -package com.yigongil.backend.query.profile.ui; +package com.yigongil.backend.query.profile; import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.response.MyProfileResponse; diff --git a/backend/src/main/java/com/yigongil/backend/query/profile/ui/ProfileController.java b/backend/src/main/java/com/yigongil/backend/query/profile/ProfileController.java similarity index 93% rename from backend/src/main/java/com/yigongil/backend/query/profile/ui/ProfileController.java rename to backend/src/main/java/com/yigongil/backend/query/profile/ProfileController.java index 22774874f..680c928ec 100644 --- a/backend/src/main/java/com/yigongil/backend/query/profile/ui/ProfileController.java +++ b/backend/src/main/java/com/yigongil/backend/query/profile/ProfileController.java @@ -1,8 +1,7 @@ -package com.yigongil.backend.query.profile.ui; +package com.yigongil.backend.query.profile; import com.yigongil.backend.config.auth.Authorization; import com.yigongil.backend.domain.member.domain.Member; -import com.yigongil.backend.query.profile.ProfileService; import com.yigongil.backend.response.MyProfileResponse; import com.yigongil.backend.response.ProfileResponse; import org.springframework.http.ResponseEntity; diff --git a/backend/src/main/java/com/yigongil/backend/ui/doc/StudyApi.java b/backend/src/main/java/com/yigongil/backend/ui/doc/StudyApi.java index 946521422..485fb25d1 100644 --- a/backend/src/main/java/com/yigongil/backend/ui/doc/StudyApi.java +++ b/backend/src/main/java/com/yigongil/backend/ui/doc/StudyApi.java @@ -2,13 +2,10 @@ import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.study.ProcessingStatus; -import com.yigongil.backend.request.CertificationCreateRequest; import com.yigongil.backend.request.FeedPostCreateRequest; import com.yigongil.backend.request.StudyStartRequest; import com.yigongil.backend.request.StudyUpdateRequest; -import com.yigongil.backend.response.CertificationResponse; import com.yigongil.backend.response.FeedPostResponse; -import com.yigongil.backend.response.MembersCertificationResponse; import com.yigongil.backend.response.MyStudyResponse; import com.yigongil.backend.response.RoundResponse; import com.yigongil.backend.response.StudyDetailResponse; @@ -204,49 +201,6 @@ ResponseEntity createFeedPost( FeedPostCreateRequest request ); - @ApiResponses( - value = { - @ApiResponse(responseCode = "200"), - @ApiResponse(responseCode = "400", content = @Content), - @ApiResponse(responseCode = "401", content = @Content), - @ApiResponse(responseCode = "404", content = @Content) - } - ) - @SecurityRequirement(name = "token") - @Operation(summary = "인증 피드 등록") - ResponseEntity createCertification( - @Schema(hidden = true) Member member, - @Parameter(description = "피드가 등록되는 스터디 id", required = true) Long id, - CertificationCreateRequest request - ); - - @ApiResponses( - value = { - @ApiResponse(responseCode = "200"), - @ApiResponse(responseCode = "401", content = @Content) - } - ) - @SecurityRequirement(name = "token") - @Operation(summary = "스터디 멤버 전체 인증 정보 조회") - ResponseEntity findAllMembersCertification( - @Schema(hidden = true) Member member, - @Parameter(description = "조회하려는 스터디 id", required = true) Long id - ); - - - @ApiResponses( - value = { - @ApiResponse(responseCode = "200"), - @ApiResponse(responseCode = "401", content = @Content) - } - ) - @SecurityRequirement(name = "token") - @Operation(summary = "스터디 멤버 단일 인증 게시글 조회") - ResponseEntity findMemberCertification( - @Parameter(description = "인증 게시 회차 id") Long roundId, - @Parameter(description = "작성자 id") Long memberId - ); - @ApiResponses( value = { @ApiResponse(responseCode = "200"), diff --git a/backend/src/test/java/com/yigongil/backend/application/StudyServiceTest.java b/backend/src/test/java/com/yigongil/backend/application/StudyServiceTest.java index a05687902..45a93a5c2 100644 --- a/backend/src/test/java/com/yigongil/backend/application/StudyServiceTest.java +++ b/backend/src/test/java/com/yigongil/backend/application/StudyServiceTest.java @@ -30,7 +30,6 @@ class StudyServiceTest { private final StudyService studyService = new StudyService( studyRepository, studyMemberRepository, - mock(CertificationService.class), mock(FeedService.class), mock(RoundRepository.class) ); diff --git a/backend/src/test/java/com/yigongil/backend/query/profile/ui/ProfileControllerTest.java b/backend/src/test/java/com/yigongil/backend/query/profile/ui/ProfileControllerTest.java index eb6f913f8..2091d9217 100644 --- a/backend/src/test/java/com/yigongil/backend/query/profile/ui/ProfileControllerTest.java +++ b/backend/src/test/java/com/yigongil/backend/query/profile/ui/ProfileControllerTest.java @@ -11,8 +11,8 @@ import com.yigongil.backend.config.auth.JwtTokenProvider; import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.member.domain.MemberRepository; -import com.yigongil.backend.domain.member.ui.MemberController; import com.yigongil.backend.fixture.MemberFixture; +import com.yigongil.backend.query.profile.ProfileController; import com.yigongil.backend.query.profile.ProfileService; import com.yigongil.backend.response.ProfileResponse; import com.yigongil.backend.ui.exceptionhandler.InternalServerErrorMessageConverter; From 6b82e5928583e5a42984e7719c87345f70eec355 Mon Sep 17 00:00:00 2001 From: kim dae hee Date: Mon, 20 Nov 2023 14:27:57 +0900 Subject: [PATCH 06/22] =?UTF-8?q?refactor:=20=ED=94=BC=EB=93=9C=20?= =?UTF-8?q?=EC=9D=98=EC=A1=B4=EC=84=B1=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/domain/feedpost/FeedApi.java | 33 ++++++++++++++++++ .../domain/feedpost/FeedController.java | 30 ++++++++++++++++ .../backend/domain/feedpost/FeedService.java | 16 ++++----- .../backend/domain/study/StudyController.java | 25 -------------- .../backend/domain/study/StudyService.java | 20 ----------- .../backend/query/feed/FeedQueryApi.java | 32 +++++++++++++++++ .../query/feed/FeedQueryController.java | 32 +++++++++++++++++ .../backend/query/feed/FeedQueryService.java | 26 ++++++++++++++ .../com/yigongil/backend/ui/doc/StudyApi.java | 34 ------------------- .../backend/application/StudyServiceTest.java | 1 - 10 files changed, 161 insertions(+), 88 deletions(-) create mode 100644 backend/src/main/java/com/yigongil/backend/domain/feedpost/FeedApi.java create mode 100644 backend/src/main/java/com/yigongil/backend/domain/feedpost/FeedController.java create mode 100644 backend/src/main/java/com/yigongil/backend/query/feed/FeedQueryApi.java create mode 100644 backend/src/main/java/com/yigongil/backend/query/feed/FeedQueryController.java create mode 100644 backend/src/main/java/com/yigongil/backend/query/feed/FeedQueryService.java diff --git a/backend/src/main/java/com/yigongil/backend/domain/feedpost/FeedApi.java b/backend/src/main/java/com/yigongil/backend/domain/feedpost/FeedApi.java new file mode 100644 index 000000000..d9ea9897d --- /dev/null +++ b/backend/src/main/java/com/yigongil/backend/domain/feedpost/FeedApi.java @@ -0,0 +1,33 @@ +package com.yigongil.backend.domain.feedpost; + +import com.yigongil.backend.domain.member.domain.Member; +import com.yigongil.backend.request.FeedPostCreateRequest; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.http.ResponseEntity; + +@Tag(name = "피드", description = "피드 관련 api") +public interface FeedApi { + + @ApiResponses( + value = { + @ApiResponse(responseCode = "200"), + @ApiResponse(responseCode = "400", content = @Content), + @ApiResponse(responseCode = "401", content = @Content), + @ApiResponse(responseCode = "404", content = @Content) + } + ) + @SecurityRequirement(name = "token") + @Operation(summary = "일반 피드 등록") + ResponseEntity createFeedPost( + @Schema(hidden = true) Member member, + @Parameter(description = "피드가 등록되는 스터디 id", required = true) Long id, + FeedPostCreateRequest request + ); +} diff --git a/backend/src/main/java/com/yigongil/backend/domain/feedpost/FeedController.java b/backend/src/main/java/com/yigongil/backend/domain/feedpost/FeedController.java new file mode 100644 index 000000000..ebb29b9e5 --- /dev/null +++ b/backend/src/main/java/com/yigongil/backend/domain/feedpost/FeedController.java @@ -0,0 +1,30 @@ +package com.yigongil.backend.domain.feedpost; + +import com.yigongil.backend.config.auth.Authorization; +import com.yigongil.backend.domain.member.domain.Member; +import com.yigongil.backend.request.FeedPostCreateRequest; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class FeedController implements FeedApi { + + private final FeedService feedService; + + public FeedController(FeedService feedService) { + this.feedService = feedService; + } + + @PostMapping("/studies/{id}/feeds") + public ResponseEntity createFeedPost( + @Authorization Member member, + @PathVariable Long id, + @RequestBody FeedPostCreateRequest request + ) { + feedService.createFeedPost(member, id, request); + return ResponseEntity.ok().build(); + } +} diff --git a/backend/src/main/java/com/yigongil/backend/domain/feedpost/FeedService.java b/backend/src/main/java/com/yigongil/backend/domain/feedpost/FeedService.java index bdae36a6b..452ee2609 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/feedpost/FeedService.java +++ b/backend/src/main/java/com/yigongil/backend/domain/feedpost/FeedService.java @@ -2,8 +2,8 @@ import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.study.Study; +import com.yigongil.backend.domain.study.StudyRepository; import com.yigongil.backend.request.FeedPostCreateRequest; -import java.util.List; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -11,24 +11,24 @@ public class FeedService { private final FeedPostRepository feedPostRepository; + private final StudyRepository studyRepository; - public FeedService(FeedPostRepository feedPostRepository) { + public FeedService(FeedPostRepository feedPostRepository, StudyRepository studyRepository) { this.feedPostRepository = feedPostRepository; + this.studyRepository = studyRepository; } @Transactional - public void createFeedPost(Member member, Study study, FeedPostCreateRequest request) { + public void createFeedPost(Member member, Long studyId, FeedPostCreateRequest request) { + Study study = studyRepository.getById(studyId); + FeedPost regularFeedPost = FeedPost.builder() .author(member) .study(study) .imageUrl(request.imageUrl()) .content(request.content()) .build(); - feedPostRepository.save(regularFeedPost); - } - @Transactional(readOnly = true) - public List findFeedPosts(Long studyId, Long oldestFeedPostId) { - return feedPostRepository.findAllByStudyIdStartWithOldestFeedPostId(studyId, oldestFeedPostId); + feedPostRepository.save(regularFeedPost); } } diff --git a/backend/src/main/java/com/yigongil/backend/domain/study/StudyController.java b/backend/src/main/java/com/yigongil/backend/domain/study/StudyController.java index 671677a53..a2d1f4b6b 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/study/StudyController.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/StudyController.java @@ -3,10 +3,8 @@ import com.yigongil.backend.config.auth.Authorization; import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.studymember.Role; -import com.yigongil.backend.request.FeedPostCreateRequest; import com.yigongil.backend.request.StudyStartRequest; import com.yigongil.backend.request.StudyUpdateRequest; -import com.yigongil.backend.response.FeedPostResponse; import com.yigongil.backend.response.MyStudyResponse; import com.yigongil.backend.response.RoundResponse; import com.yigongil.backend.response.StudyDetailResponse; @@ -16,7 +14,6 @@ import com.yigongil.backend.ui.doc.StudyApi; import java.net.URI; import java.util.List; -import java.util.Optional; import javax.validation.Valid; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; @@ -129,28 +126,6 @@ public ResponseEntity startStudy( return ResponseEntity.ok().build(); } - @GetMapping("/{id}/feeds") - public ResponseEntity> findFeedPosts( - @PathVariable Long id, - @RequestParam Optional oldestFeedPostId - ) { - List response = studyService.findFeedPosts( - id, - oldestFeedPostId.orElse(Long.MAX_VALUE) - ); - return ResponseEntity.ok(response); - } - - @PostMapping("/{id}/feeds") - public ResponseEntity createFeedPost( - @Authorization Member member, - @PathVariable Long id, - @RequestBody FeedPostCreateRequest request - ) { - studyService.createFeedPost(member, id, request); - return ResponseEntity.ok().build(); - } - @GetMapping("/{studyId}/members/role") public ResponseEntity getStudyMemberRole( @Authorization Member member, diff --git a/backend/src/main/java/com/yigongil/backend/domain/study/StudyService.java b/backend/src/main/java/com/yigongil/backend/domain/study/StudyService.java index 0dcfd9491..2e273fad4 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/study/StudyService.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/StudyService.java @@ -1,6 +1,5 @@ package com.yigongil.backend.domain.study; -import com.yigongil.backend.domain.feedpost.FeedService; import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.round.Round; import com.yigongil.backend.domain.round.RoundRepository; @@ -10,10 +9,8 @@ import com.yigongil.backend.domain.studymember.StudyResult; import com.yigongil.backend.exception.ApplicantNotFoundException; import com.yigongil.backend.exception.StudyNotFoundException; -import com.yigongil.backend.request.FeedPostCreateRequest; import com.yigongil.backend.request.StudyStartRequest; import com.yigongil.backend.request.StudyUpdateRequest; -import com.yigongil.backend.response.FeedPostResponse; import com.yigongil.backend.response.MyStudyResponse; import com.yigongil.backend.response.RoundResponse; import com.yigongil.backend.response.StudyDetailResponse; @@ -35,18 +32,15 @@ public class StudyService { private final StudyRepository studyRepository; private final StudyMemberRepository studyMemberRepository; - private final FeedService feedService; private final RoundRepository roundRepository; public StudyService( StudyRepository studyRepository, StudyMemberRepository studyMemberRepository, - FeedService feedService, RoundRepository roundRepository ) { this.studyRepository = studyRepository; this.studyMemberRepository = studyMemberRepository; - this.feedService = feedService; this.roundRepository = roundRepository; } @@ -120,12 +114,6 @@ public void apply(Member member, Long studyId) { study.apply(member); } - @Transactional - public void createFeedPost(Member member, Long studyId, FeedPostCreateRequest request) { - final Study study = findStudyById(studyId); - feedService.createFeedPost(member, study, request); - } - public Study findStudyById(Long studyId) { return studyRepository.findById(studyId) .orElseThrow(() -> new StudyNotFoundException("해당 스터디를 찾을 수 없습니다", studyId)); @@ -253,14 +241,6 @@ public StudyMemberRoleResponse getMemberRoleOfStudy(Member member, Long studyId) return StudyMemberRoleResponse.from(role); } - @Transactional(readOnly = true) - public List findFeedPosts(Long id, Long oldestFeedPostId) { - return feedService.findFeedPosts(id, oldestFeedPostId) - .stream() - .map(FeedPostResponse::from) - .toList(); - } - private List toRecruitingStudyResponse(Slice studies) { return studies.get() .map(StudyListItemResponse::from) diff --git a/backend/src/main/java/com/yigongil/backend/query/feed/FeedQueryApi.java b/backend/src/main/java/com/yigongil/backend/query/feed/FeedQueryApi.java new file mode 100644 index 000000000..db4b48743 --- /dev/null +++ b/backend/src/main/java/com/yigongil/backend/query/feed/FeedQueryApi.java @@ -0,0 +1,32 @@ +package com.yigongil.backend.query.feed; + +import com.yigongil.backend.response.FeedPostResponse; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +import java.util.List; +import java.util.Optional; +import org.springframework.http.ResponseEntity; + +@Tag(name = "피드", description = "피드 관련 api") +public interface FeedQueryApi { + + @ApiResponses( + value = { + @ApiResponse(responseCode = "200"), + @ApiResponse(responseCode = "400", content = @Content), + @ApiResponse(responseCode = "401", content = @Content), + @ApiResponse(responseCode = "404", content = @Content) + } + ) + @SecurityRequirement(name = "token") + @Operation(summary = "피드 조회") + ResponseEntity> findFeedPosts( + @Parameter(description = "조회할 스터디 id", required = true) Long id, + @Parameter(description = "마지막으로 본 피드의 아이디, 첫 요청에서는 필요 없음", allowEmptyValue = true) Optional oldestFeedPostId + ); +} diff --git a/backend/src/main/java/com/yigongil/backend/query/feed/FeedQueryController.java b/backend/src/main/java/com/yigongil/backend/query/feed/FeedQueryController.java new file mode 100644 index 000000000..fdea3fc98 --- /dev/null +++ b/backend/src/main/java/com/yigongil/backend/query/feed/FeedQueryController.java @@ -0,0 +1,32 @@ +package com.yigongil.backend.query.feed; + +import com.yigongil.backend.response.FeedPostResponse; +import java.util.List; +import java.util.Optional; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class FeedQueryController implements FeedQueryApi { + + private final FeedQueryService feedQueryService; + + public FeedQueryController(FeedQueryService feedQueryService) { + this.feedQueryService = feedQueryService; + } + + @GetMapping("/studies/{id}/feeds") + public ResponseEntity> findFeedPosts( + @PathVariable Long id, + @RequestParam Optional oldestFeedPostId + ) { + List response = feedQueryService.findFeedPosts( + id, + oldestFeedPostId.orElse(Long.MAX_VALUE) + ); + return ResponseEntity.ok(response); + } +} diff --git a/backend/src/main/java/com/yigongil/backend/query/feed/FeedQueryService.java b/backend/src/main/java/com/yigongil/backend/query/feed/FeedQueryService.java new file mode 100644 index 000000000..88bedaa6d --- /dev/null +++ b/backend/src/main/java/com/yigongil/backend/query/feed/FeedQueryService.java @@ -0,0 +1,26 @@ +package com.yigongil.backend.query.feed; + +import com.yigongil.backend.domain.feedpost.FeedPostRepository; +import com.yigongil.backend.response.FeedPostResponse; +import java.util.List; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Transactional(readOnly = true) +@Service +public class FeedQueryService { + + private final FeedPostRepository feedPostRepository; + + public FeedQueryService(FeedPostRepository feedPostRepository) { + this.feedPostRepository = feedPostRepository; + } + + @Transactional(readOnly = true) + public List findFeedPosts(Long studyId, Long oldestFeedPostId) { + return feedPostRepository.findAllByStudyIdStartWithOldestFeedPostId(studyId, oldestFeedPostId) + .stream() + .map(FeedPostResponse::from) + .toList(); + } +} diff --git a/backend/src/main/java/com/yigongil/backend/ui/doc/StudyApi.java b/backend/src/main/java/com/yigongil/backend/ui/doc/StudyApi.java index 485fb25d1..0fe77d047 100644 --- a/backend/src/main/java/com/yigongil/backend/ui/doc/StudyApi.java +++ b/backend/src/main/java/com/yigongil/backend/ui/doc/StudyApi.java @@ -2,10 +2,8 @@ import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.study.ProcessingStatus; -import com.yigongil.backend.request.FeedPostCreateRequest; import com.yigongil.backend.request.StudyStartRequest; import com.yigongil.backend.request.StudyUpdateRequest; -import com.yigongil.backend.response.FeedPostResponse; import com.yigongil.backend.response.MyStudyResponse; import com.yigongil.backend.response.RoundResponse; import com.yigongil.backend.response.StudyDetailResponse; @@ -22,7 +20,6 @@ import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; import java.util.List; -import java.util.Optional; import org.springframework.http.ResponseEntity; @Tag(name = "스터디", description = "스터디 관련 api") @@ -170,37 +167,6 @@ ResponseEntity startStudy( StudyStartRequest studyStartRequest ); - @ApiResponses( - value = { - @ApiResponse(responseCode = "200"), - @ApiResponse(responseCode = "400", content = @Content), - @ApiResponse(responseCode = "401", content = @Content), - @ApiResponse(responseCode = "404", content = @Content) - } - ) - @SecurityRequirement(name = "token") - @Operation(summary = "피드 조회") - ResponseEntity> findFeedPosts( - @Parameter(description = "조회할 스터디 id", required = true) Long id, - @Parameter(description = "마지막으로 본 피드의 아이디, 첫 요청에서는 필요 없음", allowEmptyValue = true) Optional oldestFeedPostId - ); - - @ApiResponses( - value = { - @ApiResponse(responseCode = "200"), - @ApiResponse(responseCode = "400", content = @Content), - @ApiResponse(responseCode = "401", content = @Content), - @ApiResponse(responseCode = "404", content = @Content) - } - ) - @SecurityRequirement(name = "token") - @Operation(summary = "일반 피드 등록") - ResponseEntity createFeedPost( - @Schema(hidden = true) Member member, - @Parameter(description = "피드가 등록되는 스터디 id", required = true) Long id, - FeedPostCreateRequest request - ); - @ApiResponses( value = { @ApiResponse(responseCode = "200"), diff --git a/backend/src/test/java/com/yigongil/backend/application/StudyServiceTest.java b/backend/src/test/java/com/yigongil/backend/application/StudyServiceTest.java index 45a93a5c2..dec4f4c55 100644 --- a/backend/src/test/java/com/yigongil/backend/application/StudyServiceTest.java +++ b/backend/src/test/java/com/yigongil/backend/application/StudyServiceTest.java @@ -30,7 +30,6 @@ class StudyServiceTest { private final StudyService studyService = new StudyService( studyRepository, studyMemberRepository, - mock(FeedService.class), mock(RoundRepository.class) ); From d4d0e21fb3b102123061e237e7845a5e04d49c6c Mon Sep 17 00:00:00 2001 From: kim dae hee Date: Mon, 20 Nov 2023 15:05:08 +0900 Subject: [PATCH 07/22] =?UTF-8?q?refactor:=20=EC=8A=A4=ED=84=B0=EB=94=94,?= =?UTF-8?q?=20=EB=9D=BC=EC=9A=B4=EB=93=9C=20=EC=84=9C=EB=B9=84=EC=8A=A4=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/domain/round/HomeController.java | 28 ---------- .../domain/round/MustDoController.java | 34 ------------ .../backend/domain/round/MustDoService.java | 30 ----------- .../yigongil/backend/domain/round/Round.java | 1 - .../backend/domain/round/RoundApi.java | 41 +++++++++++++++ .../backend/domain/round/RoundController.java | 52 +++++++++++++++++++ .../RoundOfMember.java | 2 +- .../backend/domain/round/RoundService.java | 31 +++++++++++ .../RoundOfMemberRepository.java | 11 ---- .../backend/domain/study/ScheduleService.java | 9 ++-- .../yigongil/backend/domain/study/Study.java | 2 +- .../backend/domain/study/StudyController.java | 10 ---- .../backend/domain/study/StudyService.java | 26 +--------- .../CertificationQueryService.java | 2 +- .../response/MemberCertificationResponse.java | 2 +- .../response/MemberOfRoundResponse.java | 2 +- .../MembersCertificationResponse.java | 2 +- .../yigongil/backend/ui/doc/MustDoApi.java | 32 ------------ .../com/yigongil/backend/ui/doc/StudyApi.java | 8 --- .../application/MustDoServiceTest.java | 10 ++-- .../backend/application/StudyServiceTest.java | 6 +-- .../yigongil/backend/fake/FakeController.java | 14 +++-- .../backend/fixture/RoundFixture.java | 2 +- .../backend/fixture/RoundOfMemberFixture.java | 2 +- ...llerTest.java => RoundControllerTest.java} | 16 +++--- .../backend/ui/StudyControllerTest.java | 4 +- 26 files changed, 163 insertions(+), 216 deletions(-) delete mode 100644 backend/src/main/java/com/yigongil/backend/domain/round/HomeController.java delete mode 100644 backend/src/main/java/com/yigongil/backend/domain/round/MustDoController.java delete mode 100644 backend/src/main/java/com/yigongil/backend/domain/round/MustDoService.java create mode 100644 backend/src/main/java/com/yigongil/backend/domain/round/RoundApi.java create mode 100644 backend/src/main/java/com/yigongil/backend/domain/round/RoundController.java rename backend/src/main/java/com/yigongil/backend/domain/{roundofmember => round}/RoundOfMember.java (97%) delete mode 100644 backend/src/main/java/com/yigongil/backend/domain/roundofmember/RoundOfMemberRepository.java delete mode 100644 backend/src/main/java/com/yigongil/backend/ui/doc/MustDoApi.java rename backend/src/test/java/com/yigongil/backend/ui/{MustDoControllerTest.java => RoundControllerTest.java} (84%) diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/HomeController.java b/backend/src/main/java/com/yigongil/backend/domain/round/HomeController.java deleted file mode 100644 index ca2058f20..000000000 --- a/backend/src/main/java/com/yigongil/backend/domain/round/HomeController.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.yigongil.backend.domain.round; - -import com.yigongil.backend.config.auth.Authorization; -import com.yigongil.backend.domain.member.domain.Member; -import com.yigongil.backend.response.UpcomingStudyResponse; -import com.yigongil.backend.ui.doc.HomeApi; -import java.util.List; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@RequestMapping("/home") -@RestController -public class HomeController implements HomeApi { - - private final RoundService roundService; - - public HomeController(RoundService roundService) { - this.roundService = roundService; - } - - @GetMapping - public ResponseEntity> home(@Authorization Member member) { - List response = roundService.findCurrentRoundOfStudies(member); - return ResponseEntity.ok(response); - } -} diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/MustDoController.java b/backend/src/main/java/com/yigongil/backend/domain/round/MustDoController.java deleted file mode 100644 index c3e2cac4f..000000000 --- a/backend/src/main/java/com/yigongil/backend/domain/round/MustDoController.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.yigongil.backend.domain.round; - -import com.yigongil.backend.config.auth.Authorization; -import com.yigongil.backend.domain.member.domain.Member; -import com.yigongil.backend.request.MustDoUpdateRequest; -import com.yigongil.backend.ui.doc.MustDoApi; -import javax.validation.Valid; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@RequestMapping("/rounds/{roundId}") -@RestController -public class MustDoController implements MustDoApi { - - private final MustDoService mustDoService; - - public MustDoController(MustDoService mustDoService) { - this.mustDoService = mustDoService; - } - - @PutMapping("/todos") - public ResponseEntity updateMustDo( - @Authorization Member member, - @PathVariable Long roundId, - @RequestBody @Valid MustDoUpdateRequest request - ) { - mustDoService.updateMustDo(member, roundId, request); - return ResponseEntity.ok().build(); - } -} diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/MustDoService.java b/backend/src/main/java/com/yigongil/backend/domain/round/MustDoService.java deleted file mode 100644 index 65241ab15..000000000 --- a/backend/src/main/java/com/yigongil/backend/domain/round/MustDoService.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.yigongil.backend.domain.round; - -import com.yigongil.backend.domain.member.domain.Member; -import com.yigongil.backend.exception.RoundNotFoundException; -import com.yigongil.backend.request.MustDoUpdateRequest; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -public class MustDoService { - - private final RoundRepository roundRepository; - - public MustDoService( - RoundRepository roundRepository - ) { - this.roundRepository = roundRepository; - } - - @Transactional - public void updateMustDo(Member member, Long roundId, MustDoUpdateRequest request) { - Round round = findRoundById(roundId); - round.updateMustDo(member, request.content()); - } - - private Round findRoundById(Long roundId) { - return roundRepository.findById(roundId) - .orElseThrow(() -> new RoundNotFoundException("존재하지 않는 회차입니다.", roundId)); - } -} diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/Round.java b/backend/src/main/java/com/yigongil/backend/domain/round/Round.java index 89e906891..4c715d4dc 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/round/Round.java +++ b/backend/src/main/java/com/yigongil/backend/domain/round/Round.java @@ -2,7 +2,6 @@ import com.yigongil.backend.domain.base.BaseEntity; import com.yigongil.backend.domain.member.domain.Member; -import com.yigongil.backend.domain.roundofmember.RoundOfMember; import com.yigongil.backend.domain.study.Study; import com.yigongil.backend.exception.InvalidTodoLengthException; import com.yigongil.backend.exception.NecessaryTodoNotExistException; diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/RoundApi.java b/backend/src/main/java/com/yigongil/backend/domain/round/RoundApi.java new file mode 100644 index 000000000..6c80bd140 --- /dev/null +++ b/backend/src/main/java/com/yigongil/backend/domain/round/RoundApi.java @@ -0,0 +1,41 @@ +package com.yigongil.backend.domain.round; + +import com.yigongil.backend.domain.member.domain.Member; +import com.yigongil.backend.request.MustDoUpdateRequest; +import com.yigongil.backend.response.RoundResponse; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +import java.util.List; +import org.springframework.http.ResponseEntity; + +@Tag(name = "라운드", description = "라운드 관련 api") +public interface RoundApi { + + @SecurityRequirement(name = "token") + @Operation(summary = "주별 회차 정보 조회") + ResponseEntity> findRoundDetailsOfWeek( + @Parameter(description = "조회할 스터디 id", required = true) Long studyId, + @Parameter(description = "조회할 주차", required = true) Integer weekNumber + ); + + @ApiResponses( + value = { + @ApiResponse(responseCode = "200"), + @ApiResponse(responseCode = "400"), + @ApiResponse(responseCode = "401"), + @ApiResponse(responseCode = "404") + } + ) + @SecurityRequirement(name = "token") + @Operation(summary = " 머스트두 생성") + ResponseEntity updateMustDo( + @Schema(hidden = true) Member member, + @Parameter(description = " 머스트두를 생성할 라운드 id", required = true) Long roundId, + MustDoUpdateRequest request + ); +} diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/RoundController.java b/backend/src/main/java/com/yigongil/backend/domain/round/RoundController.java new file mode 100644 index 000000000..0d9c8d38a --- /dev/null +++ b/backend/src/main/java/com/yigongil/backend/domain/round/RoundController.java @@ -0,0 +1,52 @@ +package com.yigongil.backend.domain.round; + +import com.yigongil.backend.config.auth.Authorization; +import com.yigongil.backend.domain.member.domain.Member; +import com.yigongil.backend.request.MustDoUpdateRequest; +import com.yigongil.backend.response.RoundResponse; +import com.yigongil.backend.response.UpcomingStudyResponse; +import com.yigongil.backend.ui.doc.HomeApi; +import java.util.List; +import javax.validation.Valid; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class RoundController implements HomeApi, RoundApi { + + private final RoundService roundService; + + public RoundController(RoundService roundService) { + this.roundService = roundService; + } + + @GetMapping("/home") + public ResponseEntity> home(@Authorization Member member) { + List response = roundService.findCurrentRoundOfStudies(member); + return ResponseEntity.ok(response); + } + + @PutMapping("/rounds/{roundId}/todos") + public ResponseEntity updateMustDo( + @Authorization Member member, + @PathVariable Long roundId, + @RequestBody @Valid MustDoUpdateRequest request + ) { + roundService.updateMustDo(member, roundId, request); + return ResponseEntity.ok().build(); + } + + @GetMapping("/studies/{studyId}/rounds") + public ResponseEntity> findRoundDetailsOfWeek( + @PathVariable Long studyId, + @RequestParam Integer weekNumber + ) { + List roundResponses = roundService.findRoundDetailsOfWeek(studyId, weekNumber); + return ResponseEntity.ok(roundResponses); + } +} diff --git a/backend/src/main/java/com/yigongil/backend/domain/roundofmember/RoundOfMember.java b/backend/src/main/java/com/yigongil/backend/domain/round/RoundOfMember.java similarity index 97% rename from backend/src/main/java/com/yigongil/backend/domain/roundofmember/RoundOfMember.java rename to backend/src/main/java/com/yigongil/backend/domain/round/RoundOfMember.java index 93e78da45..05aa4c4fa 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/roundofmember/RoundOfMember.java +++ b/backend/src/main/java/com/yigongil/backend/domain/round/RoundOfMember.java @@ -1,4 +1,4 @@ -package com.yigongil.backend.domain.roundofmember; +package com.yigongil.backend.domain.round; import com.yigongil.backend.domain.base.BaseEntity; import com.yigongil.backend.domain.member.domain.Member; diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java b/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java index 6957bf87b..9441d265e 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java +++ b/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java @@ -5,6 +5,9 @@ import com.yigongil.backend.domain.study.Study; import com.yigongil.backend.domain.study.StudyRepository; import com.yigongil.backend.domain.studymember.StudyMember; +import com.yigongil.backend.exception.RoundNotFoundException; +import com.yigongil.backend.request.MustDoUpdateRequest; +import com.yigongil.backend.response.RoundResponse; import com.yigongil.backend.response.UpcomingStudyResponse; import java.time.LocalDate; import java.util.ArrayList; @@ -51,4 +54,32 @@ public List findCurrentRoundOfStudies(Member member) { return upcomingStudyResponses; } + + @Transactional + public void updateMustDo(Member member, Long roundId, MustDoUpdateRequest request) { + Round round = findRoundById(roundId); + round.updateMustDo(member, request.content()); + } + + private Round findRoundById(Long roundId) { + return roundRepository.findById(roundId) + .orElseThrow(() -> new RoundNotFoundException("존재하지 않는 회차입니다.", roundId)); + } + + @Transactional(readOnly = true) + public List findRoundDetailsOfWeek(Long id, Integer weekNumber) { + List roundsOfWeek = roundRepository.findAllByStudyIdAndWeekNumber(id, weekNumber); + return roundsOfWeek.stream() + .map(RoundResponse::from) + .toList(); + } + + @Transactional + public void proceedRound(LocalDate today) { + List studies = studyRepository.findAllByProcessingStatus(ProcessingStatus.PROCESSING); + + studies.stream() + .filter(study -> study.isCurrentRoundEndAt(today.minusDays(1))) + .forEach(Study::updateToNextRound); + } } diff --git a/backend/src/main/java/com/yigongil/backend/domain/roundofmember/RoundOfMemberRepository.java b/backend/src/main/java/com/yigongil/backend/domain/roundofmember/RoundOfMemberRepository.java deleted file mode 100644 index c694cecc0..000000000 --- a/backend/src/main/java/com/yigongil/backend/domain/roundofmember/RoundOfMemberRepository.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.yigongil.backend.domain.roundofmember; - -import java.util.List; -import org.springframework.data.jpa.repository.EntityGraph; -import org.springframework.data.repository.Repository; - -public interface RoundOfMemberRepository extends Repository { - - @EntityGraph(attributePaths = "member") - List findAllByIdIn(List ids); -} diff --git a/backend/src/main/java/com/yigongil/backend/domain/study/ScheduleService.java b/backend/src/main/java/com/yigongil/backend/domain/study/ScheduleService.java index fcd83ba27..45ac8db06 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/study/ScheduleService.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/ScheduleService.java @@ -1,5 +1,6 @@ package com.yigongil.backend.domain.study; +import com.yigongil.backend.domain.round.RoundService; import java.time.LocalDate; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; @@ -8,15 +9,15 @@ @Service public class ScheduleService { - private final StudyService studyService; + private final RoundService roundService; - public ScheduleService(StudyService studyService) { - this.studyService = studyService; + public ScheduleService(RoundService roundService) { + this.roundService = roundService; } @Scheduled(cron = "0 0 0 * * *") @Transactional public void proceedRoundPerDay() { - studyService.proceedRound(LocalDate.now()); + roundService.proceedRound(LocalDate.now()); } } diff --git a/backend/src/main/java/com/yigongil/backend/domain/study/Study.java b/backend/src/main/java/com/yigongil/backend/domain/study/Study.java index cc0cb0c04..34813baa5 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/study/Study.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/Study.java @@ -4,7 +4,7 @@ import com.yigongil.backend.domain.meetingdayoftheweek.MeetingDayOfTheWeek; import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.round.Round; -import com.yigongil.backend.domain.roundofmember.RoundOfMember; +import com.yigongil.backend.domain.round.RoundOfMember; import com.yigongil.backend.domain.studymember.Role; import com.yigongil.backend.domain.studymember.StudyMember; import com.yigongil.backend.domain.studymember.StudyResult; diff --git a/backend/src/main/java/com/yigongil/backend/domain/study/StudyController.java b/backend/src/main/java/com/yigongil/backend/domain/study/StudyController.java index a2d1f4b6b..7fe22c04b 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/study/StudyController.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/StudyController.java @@ -6,7 +6,6 @@ import com.yigongil.backend.request.StudyStartRequest; import com.yigongil.backend.request.StudyUpdateRequest; import com.yigongil.backend.response.MyStudyResponse; -import com.yigongil.backend.response.RoundResponse; import com.yigongil.backend.response.StudyDetailResponse; import com.yigongil.backend.response.StudyListItemResponse; import com.yigongil.backend.response.StudyMemberResponse; @@ -155,15 +154,6 @@ public ResponseEntity endStudy( return ResponseEntity.ok().build(); } - @GetMapping("/{studyId}/rounds") - public ResponseEntity> findRoundDetailsOfWeek( - @PathVariable Long studyId, - @RequestParam Integer weekNumber - ) { - List roundResponses = studyService.findRoundDetailsOfWeek(studyId, weekNumber); - return ResponseEntity.ok(roundResponses); - } - @DeleteMapping("/{studyId}/exit") public ResponseEntity exitStudy( @Authorization Member member, diff --git a/backend/src/main/java/com/yigongil/backend/domain/study/StudyService.java b/backend/src/main/java/com/yigongil/backend/domain/study/StudyService.java index 2e273fad4..1a40a4e4b 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/study/StudyService.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/StudyService.java @@ -1,8 +1,6 @@ package com.yigongil.backend.domain.study; import com.yigongil.backend.domain.member.domain.Member; -import com.yigongil.backend.domain.round.Round; -import com.yigongil.backend.domain.round.RoundRepository; import com.yigongil.backend.domain.studymember.Role; import com.yigongil.backend.domain.studymember.StudyMember; import com.yigongil.backend.domain.studymember.StudyMemberRepository; @@ -12,13 +10,11 @@ import com.yigongil.backend.request.StudyStartRequest; import com.yigongil.backend.request.StudyUpdateRequest; import com.yigongil.backend.response.MyStudyResponse; -import com.yigongil.backend.response.RoundResponse; import com.yigongil.backend.response.StudyDetailResponse; import com.yigongil.backend.response.StudyListItemResponse; import com.yigongil.backend.response.StudyMemberResponse; import com.yigongil.backend.response.StudyMemberRoleResponse; import java.time.DayOfWeek; -import java.time.LocalDate; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -32,16 +28,13 @@ public class StudyService { private final StudyRepository studyRepository; private final StudyMemberRepository studyMemberRepository; - private final RoundRepository roundRepository; public StudyService( StudyRepository studyRepository, - StudyMemberRepository studyMemberRepository, - RoundRepository roundRepository + StudyMemberRepository studyMemberRepository ) { this.studyRepository = studyRepository; this.studyMemberRepository = studyMemberRepository; - this.roundRepository = roundRepository; } @Transactional @@ -190,15 +183,6 @@ private StudyMember findApplicantByMemberIdAndStudyId(Long memberId, Long studyI return studyMember; } - @Transactional - public void proceedRound(LocalDate today) { - List studies = studyRepository.findAllByProcessingStatus(ProcessingStatus.PROCESSING); - - studies.stream() - .filter(study -> study.isCurrentRoundEndAt(today.minusDays(1))) - .forEach(Study::updateToNextRound); - } - @Transactional public void start(Member member, Long studyId, StudyStartRequest request) { List meetingDaysOfTheWeek = createDayOfWeek(request.meetingDaysOfTheWeek()); @@ -253,14 +237,6 @@ public void finish(Member member, Long studyId) { study.finishStudy(member); } - @Transactional(readOnly = true) - public List findRoundDetailsOfWeek(Long id, Integer weekNumber) { - List roundsOfWeek = roundRepository.findAllByStudyIdAndWeekNumber(id, weekNumber); - return roundsOfWeek.stream() - .map(RoundResponse::from) - .toList(); - } - @Transactional public void exit(Member member, Long studyId) { Study study = findStudyById(studyId); diff --git a/backend/src/main/java/com/yigongil/backend/query/certification/CertificationQueryService.java b/backend/src/main/java/com/yigongil/backend/query/certification/CertificationQueryService.java index d1c9e0ca3..1a22f6776 100644 --- a/backend/src/main/java/com/yigongil/backend/query/certification/CertificationQueryService.java +++ b/backend/src/main/java/com/yigongil/backend/query/certification/CertificationQueryService.java @@ -3,7 +3,7 @@ import com.yigongil.backend.domain.certification.Certification; import com.yigongil.backend.domain.certification.CertificationRepository; import com.yigongil.backend.domain.member.domain.Member; -import com.yigongil.backend.domain.roundofmember.RoundOfMember; +import com.yigongil.backend.domain.round.RoundOfMember; import com.yigongil.backend.domain.study.Study; import com.yigongil.backend.domain.study.StudyRepository; import com.yigongil.backend.response.CertificationResponse; diff --git a/backend/src/main/java/com/yigongil/backend/response/MemberCertificationResponse.java b/backend/src/main/java/com/yigongil/backend/response/MemberCertificationResponse.java index 4deb3edb2..d2b205503 100644 --- a/backend/src/main/java/com/yigongil/backend/response/MemberCertificationResponse.java +++ b/backend/src/main/java/com/yigongil/backend/response/MemberCertificationResponse.java @@ -1,6 +1,6 @@ package com.yigongil.backend.response; -import com.yigongil.backend.domain.roundofmember.RoundOfMember; +import com.yigongil.backend.domain.round.RoundOfMember; import java.util.List; public record MemberCertificationResponse( diff --git a/backend/src/main/java/com/yigongil/backend/response/MemberOfRoundResponse.java b/backend/src/main/java/com/yigongil/backend/response/MemberOfRoundResponse.java index 98618baea..5dcd9712a 100644 --- a/backend/src/main/java/com/yigongil/backend/response/MemberOfRoundResponse.java +++ b/backend/src/main/java/com/yigongil/backend/response/MemberOfRoundResponse.java @@ -1,7 +1,7 @@ package com.yigongil.backend.response; import com.yigongil.backend.domain.member.domain.Member; -import com.yigongil.backend.domain.roundofmember.RoundOfMember; +import com.yigongil.backend.domain.round.RoundOfMember; import io.swagger.v3.oas.annotations.media.Schema; import java.util.List; diff --git a/backend/src/main/java/com/yigongil/backend/response/MembersCertificationResponse.java b/backend/src/main/java/com/yigongil/backend/response/MembersCertificationResponse.java index 5f5d175a3..c923ef70a 100644 --- a/backend/src/main/java/com/yigongil/backend/response/MembersCertificationResponse.java +++ b/backend/src/main/java/com/yigongil/backend/response/MembersCertificationResponse.java @@ -2,7 +2,7 @@ import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.round.Round; -import com.yigongil.backend.domain.roundofmember.RoundOfMember; +import com.yigongil.backend.domain.round.RoundOfMember; import com.yigongil.backend.exception.NotStudyMemberException; import java.util.List; diff --git a/backend/src/main/java/com/yigongil/backend/ui/doc/MustDoApi.java b/backend/src/main/java/com/yigongil/backend/ui/doc/MustDoApi.java deleted file mode 100644 index 9c6ebd8ca..000000000 --- a/backend/src/main/java/com/yigongil/backend/ui/doc/MustDoApi.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.yigongil.backend.ui.doc; - -import com.yigongil.backend.domain.member.domain.Member; -import com.yigongil.backend.request.MustDoUpdateRequest; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; -import io.swagger.v3.oas.annotations.security.SecurityRequirement; -import io.swagger.v3.oas.annotations.tags.Tag; -import org.springframework.http.ResponseEntity; - -@Tag(name = "머스트두", description = "머스트두 관련 api") -public interface MustDoApi { - - @ApiResponses( - value = { - @ApiResponse(responseCode = "200"), - @ApiResponse(responseCode = "400"), - @ApiResponse(responseCode = "401"), - @ApiResponse(responseCode = "404") - } - ) - @SecurityRequirement(name = "token") - @Operation(summary = " 머스트두 생성") - ResponseEntity updateMustDo( - @Schema(hidden = true) Member member, - @Parameter(description = " 머스트두를 생성할 라운드 id", required = true) Long roundId, - MustDoUpdateRequest request - ); -} diff --git a/backend/src/main/java/com/yigongil/backend/ui/doc/StudyApi.java b/backend/src/main/java/com/yigongil/backend/ui/doc/StudyApi.java index 0fe77d047..ff23e0c2a 100644 --- a/backend/src/main/java/com/yigongil/backend/ui/doc/StudyApi.java +++ b/backend/src/main/java/com/yigongil/backend/ui/doc/StudyApi.java @@ -5,7 +5,6 @@ import com.yigongil.backend.request.StudyStartRequest; import com.yigongil.backend.request.StudyUpdateRequest; import com.yigongil.backend.response.MyStudyResponse; -import com.yigongil.backend.response.RoundResponse; import com.yigongil.backend.response.StudyDetailResponse; import com.yigongil.backend.response.StudyListItemResponse; import com.yigongil.backend.response.StudyMemberResponse; @@ -179,11 +178,4 @@ ResponseEntity getStudyMemberRole( @Schema(hidden = true) Member member, @Parameter(description = "멤버가 속해 있는 스터디 id", required = true) Long studyId ); - - @SecurityRequirement(name = "token") - @Operation(summary = "주별 회차 정보 조회") - ResponseEntity> findRoundDetailsOfWeek( - @Parameter(description = "조회할 스터디 id", required = true) Long studyId, - @Parameter(description = "조회할 주차", required = true) Integer weekNumber - ); } diff --git a/backend/src/test/java/com/yigongil/backend/application/MustDoServiceTest.java b/backend/src/test/java/com/yigongil/backend/application/MustDoServiceTest.java index cfc28cdce..38bb2be9e 100644 --- a/backend/src/test/java/com/yigongil/backend/application/MustDoServiceTest.java +++ b/backend/src/test/java/com/yigongil/backend/application/MustDoServiceTest.java @@ -5,10 +5,10 @@ import static org.mockito.BDDMockito.willReturn; import com.yigongil.backend.domain.member.domain.Member; -import com.yigongil.backend.domain.round.MustDoService; import com.yigongil.backend.domain.round.Round; import com.yigongil.backend.domain.round.RoundRepository; -import com.yigongil.backend.domain.roundofmember.RoundOfMember; +import com.yigongil.backend.domain.round.RoundOfMember; +import com.yigongil.backend.domain.round.RoundService; import com.yigongil.backend.exception.InvalidTodoLengthException; import com.yigongil.backend.fixture.MemberFixture; import com.yigongil.backend.request.MustDoUpdateRequest; @@ -26,7 +26,7 @@ class MustDoServiceTest { @InjectMocks - private MustDoService mustDoService; + private RoundService roundService; @Mock private RoundRepository roundRepository; @@ -61,7 +61,7 @@ class _머스트두 { //when //then - assertDoesNotThrow(() -> mustDoService.updateMustDo(member, round.getId(), request)); + assertDoesNotThrow(() -> roundService.updateMustDo(member, round.getId(), request)); } @Test @@ -73,7 +73,7 @@ class _머스트두 { //when //then - assertThatThrownBy(() -> mustDoService.updateMustDo(member, round.getId(), request)) + assertThatThrownBy(() -> roundService.updateMustDo(member, round.getId(), request)) .isInstanceOf(InvalidTodoLengthException.class); } } diff --git a/backend/src/test/java/com/yigongil/backend/application/StudyServiceTest.java b/backend/src/test/java/com/yigongil/backend/application/StudyServiceTest.java index dec4f4c55..8f09100b1 100644 --- a/backend/src/test/java/com/yigongil/backend/application/StudyServiceTest.java +++ b/backend/src/test/java/com/yigongil/backend/application/StudyServiceTest.java @@ -4,10 +4,7 @@ import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; -import com.yigongil.backend.domain.certification.CertificationService; -import com.yigongil.backend.domain.feedpost.FeedService; import com.yigongil.backend.domain.member.domain.Member; -import com.yigongil.backend.domain.round.RoundRepository; import com.yigongil.backend.domain.study.StudyRepository; import com.yigongil.backend.domain.study.StudyService; import com.yigongil.backend.domain.studymember.StudyMemberRepository; @@ -29,8 +26,7 @@ class StudyServiceTest { private final StudyService studyService = new StudyService( studyRepository, - studyMemberRepository, - mock(RoundRepository.class) + studyMemberRepository ); @Nested diff --git a/backend/src/test/java/com/yigongil/backend/fake/FakeController.java b/backend/src/test/java/com/yigongil/backend/fake/FakeController.java index 58d28dc84..2e95ec9d3 100644 --- a/backend/src/test/java/com/yigongil/backend/fake/FakeController.java +++ b/backend/src/test/java/com/yigongil/backend/fake/FakeController.java @@ -3,7 +3,7 @@ import com.yigongil.backend.config.auth.JwtTokenProvider; import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.member.domain.MemberRepository; -import com.yigongil.backend.domain.study.StudyService; +import com.yigongil.backend.domain.round.RoundService; import com.yigongil.backend.response.TokenResponse; import java.time.LocalDate; import java.util.Optional; @@ -22,12 +22,16 @@ public class FakeController { private final MemberRepository memberRepository; private final JwtTokenProvider jwtTokenProvider; - private final StudyService studyService; + private final RoundService roundService; - public FakeController(MemberRepository memberRepository, JwtTokenProvider jwtTokenProvider, StudyService studyService) { + public FakeController( + MemberRepository memberRepository, + JwtTokenProvider jwtTokenProvider, + RoundService roundService + ) { this.memberRepository = memberRepository; this.jwtTokenProvider = jwtTokenProvider; - this.studyService = studyService; + this.roundService = roundService; } @GetMapping("/login/fake/tokens") @@ -48,7 +52,7 @@ public ResponseEntity createFakeToken(@RequestParam String github @PutMapping("/fake/proceed") public ResponseEntity proceed(@RequestParam Integer days) { for (int i = 1; i <= days; i++) { - studyService.proceedRound(LocalDate.now().plusDays(i)); + roundService.proceedRound(LocalDate.now().plusDays(i)); } return ResponseEntity.ok().build(); } diff --git a/backend/src/test/java/com/yigongil/backend/fixture/RoundFixture.java b/backend/src/test/java/com/yigongil/backend/fixture/RoundFixture.java index fd0f87a1f..38facac89 100644 --- a/backend/src/test/java/com/yigongil/backend/fixture/RoundFixture.java +++ b/backend/src/test/java/com/yigongil/backend/fixture/RoundFixture.java @@ -2,7 +2,7 @@ import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.round.Round; -import com.yigongil.backend.domain.roundofmember.RoundOfMember; +import com.yigongil.backend.domain.round.RoundOfMember; import java.util.ArrayList; import java.util.Arrays; import java.util.List; diff --git a/backend/src/test/java/com/yigongil/backend/fixture/RoundOfMemberFixture.java b/backend/src/test/java/com/yigongil/backend/fixture/RoundOfMemberFixture.java index c6dc50ad4..055e63b0e 100644 --- a/backend/src/test/java/com/yigongil/backend/fixture/RoundOfMemberFixture.java +++ b/backend/src/test/java/com/yigongil/backend/fixture/RoundOfMemberFixture.java @@ -1,7 +1,7 @@ package com.yigongil.backend.fixture; import com.yigongil.backend.domain.member.domain.Member; -import com.yigongil.backend.domain.roundofmember.RoundOfMember; +import com.yigongil.backend.domain.round.RoundOfMember; public enum RoundOfMemberFixture { diff --git a/backend/src/test/java/com/yigongil/backend/ui/MustDoControllerTest.java b/backend/src/test/java/com/yigongil/backend/ui/RoundControllerTest.java similarity index 84% rename from backend/src/test/java/com/yigongil/backend/ui/MustDoControllerTest.java rename to backend/src/test/java/com/yigongil/backend/ui/RoundControllerTest.java index 8b4b0abd1..363592b6c 100644 --- a/backend/src/test/java/com/yigongil/backend/ui/MustDoControllerTest.java +++ b/backend/src/test/java/com/yigongil/backend/ui/RoundControllerTest.java @@ -13,8 +13,8 @@ import com.yigongil.backend.config.auth.AuthContext; import com.yigongil.backend.config.auth.JwtTokenProvider; import com.yigongil.backend.domain.member.domain.MemberRepository; -import com.yigongil.backend.domain.round.MustDoController; -import com.yigongil.backend.domain.round.MustDoService; +import com.yigongil.backend.domain.round.RoundController; +import com.yigongil.backend.domain.round.RoundService; import com.yigongil.backend.fixture.MemberFixture; import com.yigongil.backend.request.MustDoUpdateRequest; import com.yigongil.backend.ui.exceptionhandler.InternalServerErrorMessageConverter; @@ -29,8 +29,8 @@ import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; -@WebMvcTest(MustDoController.class) -class MustDoControllerTest { +@WebMvcTest(RoundController.class) +class RoundControllerTest { @Autowired private MockMvc mockMvc; @@ -39,7 +39,7 @@ class MustDoControllerTest { private ObjectMapper objectMapper; @MockBean - private MustDoService mustDoService; + private RoundService roundService; @MockBean private MemberRepository memberRepository; @@ -65,7 +65,7 @@ void setUp() { void 머스트두를_생성한다() throws Exception { MustDoUpdateRequest request = new MustDoUpdateRequest("첫 머스트두"); - willDoNothing().given(mustDoService).updateMustDo(MemberFixture.김진우.toMember(), 1L, request); + willDoNothing().given(roundService).updateMustDo(MemberFixture.김진우.toMember(), 1L, request); mockMvc.perform(put("/rounds/1/todos") .header(HttpHeaders.AUTHORIZATION, "1") @@ -79,7 +79,7 @@ void setUp() { void 머스트두를_업데이트한다() throws Exception { MustDoUpdateRequest request = new MustDoUpdateRequest("수정"); - willDoNothing().given(mustDoService).updateMustDo(MemberFixture.김진우.toMember(), 1L, request); + willDoNothing().given(roundService).updateMustDo(MemberFixture.김진우.toMember(), 1L, request); mockMvc.perform(put("/rounds/1/todos") .header(HttpHeaders.AUTHORIZATION, "1") @@ -88,6 +88,6 @@ void setUp() { .andDo(print()) .andExpect(status().isOk()); - verify(mustDoService, only()).updateMustDo(MemberFixture.김진우.toMember(), 1L, request); + verify(roundService, only()).updateMustDo(MemberFixture.김진우.toMember(), 1L, request); } } diff --git a/backend/src/test/java/com/yigongil/backend/ui/StudyControllerTest.java b/backend/src/test/java/com/yigongil/backend/ui/StudyControllerTest.java index e7ee0dc1e..16d981d1e 100644 --- a/backend/src/test/java/com/yigongil/backend/ui/StudyControllerTest.java +++ b/backend/src/test/java/com/yigongil/backend/ui/StudyControllerTest.java @@ -14,7 +14,7 @@ import com.yigongil.backend.domain.certification.CertificationService; import com.yigongil.backend.domain.feedpost.FeedService; import com.yigongil.backend.domain.member.domain.MemberRepository; -import com.yigongil.backend.domain.round.MustDoService; +import com.yigongil.backend.domain.round.RoundService; import com.yigongil.backend.domain.study.StudyController; import com.yigongil.backend.domain.study.StudyService; import com.yigongil.backend.fixture.MemberFixture; @@ -44,7 +44,7 @@ class StudyControllerTest { private StudyService studyService; @MockBean - private MustDoService mustDoService; + private RoundService roundService; @MockBean private MemberRepository memberRepository; From 600da1e2cfa9003b14a6bfc1bff60a12e8afb5f7 Mon Sep 17 00:00:00 2001 From: kim dae hee Date: Mon, 20 Nov 2023 16:07:51 +0900 Subject: [PATCH 08/22] =?UTF-8?q?refactor:=20MeetingDayOfTheWeek=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 --- .../MeetingDayOfTheWeek.java | 55 ------------------- .../yigongil/backend/domain/study/Study.java | 45 +++++++-------- .../acceptance/steps/DatabaseCleaner.java | 6 +- 3 files changed, 26 insertions(+), 80 deletions(-) delete mode 100644 backend/src/main/java/com/yigongil/backend/domain/meetingdayoftheweek/MeetingDayOfTheWeek.java diff --git a/backend/src/main/java/com/yigongil/backend/domain/meetingdayoftheweek/MeetingDayOfTheWeek.java b/backend/src/main/java/com/yigongil/backend/domain/meetingdayoftheweek/MeetingDayOfTheWeek.java deleted file mode 100644 index 85554be33..000000000 --- a/backend/src/main/java/com/yigongil/backend/domain/meetingdayoftheweek/MeetingDayOfTheWeek.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.yigongil.backend.domain.meetingdayoftheweek; - -import com.yigongil.backend.domain.base.BaseEntity; -import com.yigongil.backend.domain.study.Study; -import java.time.DayOfWeek; -import javax.persistence.Entity; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import lombok.Builder; -import lombok.Getter; - -@Getter -@Entity -public class MeetingDayOfTheWeek extends BaseEntity { - - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Id - private Long id; - - @ManyToOne - @JoinColumn(name = "study_id") - private Study study; - - @Enumerated(EnumType.ORDINAL) - private DayOfWeek dayOfWeek; - - protected MeetingDayOfTheWeek() { - } - - @Builder - public MeetingDayOfTheWeek(Long id, Study study, DayOfWeek dayOfWeek) { - this.id = id; - this.study = study; - this.dayOfWeek = dayOfWeek; - } - - public boolean isSameDayOfWeek(DayOfWeek dayOfWeek) { - return this.dayOfWeek.equals(dayOfWeek); - } - - public boolean comesNext(DayOfWeek dayOfWeek) { - return this.dayOfWeek.compareTo(dayOfWeek) > 0; - } - - public int getOrder() { - return this.dayOfWeek.getValue(); - } -} - - diff --git a/backend/src/main/java/com/yigongil/backend/domain/study/Study.java b/backend/src/main/java/com/yigongil/backend/domain/study/Study.java index 34813baa5..41e3a53bc 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/study/Study.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/Study.java @@ -1,7 +1,6 @@ package com.yigongil.backend.domain.study; -import com.yigongil.backend.domain.base.BaseEntity; -import com.yigongil.backend.domain.meetingdayoftheweek.MeetingDayOfTheWeek; +import com.yigongil.backend.domain.base.BaseRootEntity; import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.round.Round; import com.yigongil.backend.domain.round.RoundOfMember; @@ -24,7 +23,9 @@ import java.util.ArrayList; import java.util.Comparator; import java.util.List; +import javax.persistence.CollectionTable; import javax.persistence.Column; +import javax.persistence.ElementCollection; import javax.persistence.Entity; import javax.persistence.EnumType; import javax.persistence.Enumerated; @@ -42,7 +43,7 @@ @Getter @Entity -public class Study extends BaseEntity { +public class Study extends BaseRootEntity { private static final int ONE_MEMBER = 1; private static final int MIN_NAME_LENGTH = 1; @@ -71,9 +72,10 @@ public class Study extends BaseEntity { private LocalDateTime endAt; - @Cascade(CascadeType.PERSIST) - @OneToMany(mappedBy = "study", orphanRemoval = true, fetch = FetchType.LAZY) - private List meetingDaysOfTheWeek = new ArrayList<>(); + @ElementCollection(targetClass = DayOfWeek.class) + @CollectionTable(name = "day_of_week") + @Enumerated(EnumType.ORDINAL) + private List dayOfWeeks = new ArrayList<>(); @Column(nullable = false) private Integer minimumWeeks; @@ -225,6 +227,7 @@ public void start(Member member, List daysOfTheWeek, LocalDateTime st this.meetingDaysCountPerWeek = daysOfTheWeek.size(); initializeMeetingDaysOfTheWeek(daysOfTheWeek); initializeRounds(startAt.toLocalDate()); +// registerEvent() } private void deleteLeftApplicant() { @@ -234,13 +237,8 @@ private void deleteLeftApplicant() { studyMembers.removeAll(currentApplicant); } - private void initializeMeetingDaysOfTheWeek(List daysOfTheWeek) { - this.meetingDaysOfTheWeek.addAll(daysOfTheWeek.stream() - .map(dayOfTheWeek -> MeetingDayOfTheWeek.builder() - .dayOfWeek(dayOfTheWeek) - .study(this) - .build()) - .toList()); + private void initializeMeetingDaysOfTheWeek(List dayOfWeeks) { + this.dayOfWeeks.addAll(dayOfWeeks); } private void initializeRounds(LocalDate startAt) { @@ -250,10 +248,10 @@ private void initializeRounds(LocalDate startAt) { } private List createRoundsOfFirstWeek(final LocalDate startAt) { - List rounds = meetingDaysOfTheWeek.stream() - .filter(meetingDayOfTheWeek -> meetingDayOfTheWeek.comesNext(startAt.getDayOfWeek())) - .map(meetingDayOfTheWeek -> Round.of(meetingDayOfTheWeek.getDayOfWeek(), this, FIRST_WEEK)) - .toList(); + List rounds = dayOfWeeks.stream() + .filter(dayOfWeek -> dayOfWeek.compareTo(startAt.getDayOfWeek()) > 0) + .map(dayOfWeek -> Round.of(dayOfWeek, this, FIRST_WEEK)) + .toList(); if (rounds.isEmpty()) { rounds = createRoundsOf(FIRST_WEEK); } @@ -297,10 +295,9 @@ private Round findFirstRoundOf(int nextWeekNumber) { } private DayOfWeek findFirstDayOfTheWeek() { - return meetingDaysOfTheWeek.stream() - .min(Comparator.comparing(MeetingDayOfTheWeek::getOrder)) - .map(MeetingDayOfTheWeek::getDayOfWeek) - .orElseThrow(); + return dayOfWeeks.stream() + .min(Comparator.comparing(DayOfWeek::getValue)) + .orElseThrow(); } public void finishStudy(Member master) { @@ -387,9 +384,9 @@ public void updateInformation( } private List createRoundsOf(Integer weekNumber) { - return meetingDaysOfTheWeek.stream() - .map(meetingDayOfTheWeek -> Round.of(meetingDayOfTheWeek.getDayOfWeek(), this, weekNumber)) - .toList(); + return dayOfWeeks.stream() + .map(dayOfWeek -> Round.of(dayOfWeek, this, weekNumber)) + .toList(); } public void apply(Member member) { diff --git a/backend/src/test/java/com/yigongil/backend/acceptance/steps/DatabaseCleaner.java b/backend/src/test/java/com/yigongil/backend/acceptance/steps/DatabaseCleaner.java index 32183f585..784afdaca 100644 --- a/backend/src/test/java/com/yigongil/backend/acceptance/steps/DatabaseCleaner.java +++ b/backend/src/test/java/com/yigongil/backend/acceptance/steps/DatabaseCleaner.java @@ -23,7 +23,10 @@ public void init() { this.tables = entityManager.getMetamodel().getEntities().stream() .filter(entityType -> entityType.getJavaType().getSuperclass() .getSimpleName() - .equals("BaseEntity")) + .equals("BaseEntity") + || entityType.getJavaType().getSuperclass() + .getSimpleName() + .equals("BaseRootEntity")) .map(EntityType::getName) .map(this::toSnake) .toList(); @@ -48,6 +51,7 @@ public void clean() { for (String table : tables) { entityManager.createNativeQuery("truncate table " + table).executeUpdate(); } + entityManager.createNativeQuery("truncate table day_of_week").executeUpdate(); entityManager.createNativeQuery("set foreign_key_checks = 1").executeUpdate(); } From c311d70fe4bd90f3eb84acf5b91f2e43632bbc75 Mon Sep 17 00:00:00 2001 From: kim dae hee Date: Mon, 20 Nov 2023 16:30:52 +0900 Subject: [PATCH 09/22] =?UTF-8?q?refactor:=20Round=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/domain/round/RoundRepository.java | 2 + .../backend/domain/round/RoundService.java | 62 +++++++++++++++---- .../yigongil/backend/domain/study/Study.java | 32 +++------- .../backend/domain/study/StudyService.java | 1 + .../domain/study/StudyStartedEvent.java | 13 ++++ .../backend/domain/study/StudyTest.java | 49 --------------- 6 files changed, 72 insertions(+), 87 deletions(-) create mode 100644 backend/src/main/java/com/yigongil/backend/domain/study/StudyStartedEvent.java diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/RoundRepository.java b/backend/src/main/java/com/yigongil/backend/domain/round/RoundRepository.java index 0138ff6dc..ad71dff0a 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/round/RoundRepository.java +++ b/backend/src/main/java/com/yigongil/backend/domain/round/RoundRepository.java @@ -11,4 +11,6 @@ public interface RoundRepository extends Repository { Optional findById(Long id); List findAllByStudyIdAndWeekNumber(Long studyId, Integer weekNumber); + + Round save(Round round); } diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java b/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java index 9441d265e..44cb361e2 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java +++ b/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java @@ -4,16 +4,20 @@ import com.yigongil.backend.domain.study.ProcessingStatus; import com.yigongil.backend.domain.study.Study; import com.yigongil.backend.domain.study.StudyRepository; +import com.yigongil.backend.domain.study.StudyStartedEvent; import com.yigongil.backend.domain.studymember.StudyMember; import com.yigongil.backend.exception.RoundNotFoundException; import com.yigongil.backend.request.MustDoUpdateRequest; import com.yigongil.backend.response.RoundResponse; import com.yigongil.backend.response.UpcomingStudyResponse; +import java.time.DayOfWeek; import java.time.LocalDate; import java.util.ArrayList; import java.util.List; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.transaction.event.TransactionPhase; +import org.springframework.transaction.event.TransactionalEventListener; @Service public class RoundService { @@ -22,8 +26,8 @@ public class RoundService { private final StudyRepository studyRepository; public RoundService( - RoundRepository roundRepository, - StudyRepository studyRepository + RoundRepository roundRepository, + StudyRepository studyRepository ) { this.roundRepository = roundRepository; this.studyRepository = studyRepository; @@ -31,7 +35,8 @@ public RoundService( @Transactional(readOnly = true) public List findCurrentRoundOfStudies(Member member) { - List studies = studyRepository.findByMemberAndProcessingStatus(member, ProcessingStatus.PROCESSING); + List studies = studyRepository.findByMemberAndProcessingStatus(member, + ProcessingStatus.PROCESSING); List upcomingStudyResponses = new ArrayList<>(); for (Study study : studies) { @@ -41,14 +46,14 @@ public List findCurrentRoundOfStudies(Member member) { int leftDays = currentRound.calculateLeftDaysFrom(LocalDate.now()); upcomingStudyResponses.add( - new UpcomingStudyResponse( - study.getId(), - study.getName(), - currentRound.getMustDo(), - leftDays, - studyMember.calculateAccumulatedExperience(), - study.isMaster(member) - ) + new UpcomingStudyResponse( + study.getId(), + study.getName(), + currentRound.getMustDo(), + leftDays, + studyMember.calculateAccumulatedExperience(), + study.isMaster(member) + ) ); } @@ -63,7 +68,8 @@ public void updateMustDo(Member member, Long roundId, MustDoUpdateRequest reques private Round findRoundById(Long roundId) { return roundRepository.findById(roundId) - .orElseThrow(() -> new RoundNotFoundException("존재하지 않는 회차입니다.", roundId)); + .orElseThrow( + () -> new RoundNotFoundException("존재하지 않는 회차입니다.", roundId)); } @Transactional(readOnly = true) @@ -76,10 +82,40 @@ public List findRoundDetailsOfWeek(Long id, Integer weekNumber) { @Transactional public void proceedRound(LocalDate today) { - List studies = studyRepository.findAllByProcessingStatus(ProcessingStatus.PROCESSING); + List studies = studyRepository.findAllByProcessingStatus( + ProcessingStatus.PROCESSING); studies.stream() .filter(study -> study.isCurrentRoundEndAt(today.minusDays(1))) .forEach(Study::updateToNextRound); } + + @TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT) + public void initializeRounds(StudyStartedEvent event) { + Study study = studyRepository.getById(event.studyId()); + List rounds = new ArrayList<>(); + rounds.addAll(createRoundsOfFirstWeek(study, event.dayOfWeeks(), event.startAt())); + rounds.addAll(createRoundsOf(2, study, event.dayOfWeeks())); + rounds.get(0).proceed(); + for (Round round : rounds) { + roundRepository.save(round); + } + } + + private List createRoundsOfFirstWeek(Study study, List dayOfWeeks, LocalDate startAt) { + List rounds = dayOfWeeks.stream() + .filter(dayOfWeek -> dayOfWeek.compareTo(startAt.getDayOfWeek()) > 0) + .map(dayOfWeek -> Round.of(dayOfWeek, study, 1)) + .toList(); + if (rounds.isEmpty()) { + rounds = createRoundsOf(1, study, dayOfWeeks); + } + return rounds; + } + + private List createRoundsOf(Integer weekNumber, Study study, List dayOfWeeks) { + return dayOfWeeks.stream() + .map(dayOfWeek -> Round.of(dayOfWeek, study, weekNumber)) + .toList(); + } } diff --git a/backend/src/main/java/com/yigongil/backend/domain/study/Study.java b/backend/src/main/java/com/yigongil/backend/domain/study/Study.java index 41e3a53bc..66036562d 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/study/Study.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/Study.java @@ -226,8 +226,7 @@ public void start(Member member, List daysOfTheWeek, LocalDateTime st this.processingStatus = ProcessingStatus.PROCESSING; this.meetingDaysCountPerWeek = daysOfTheWeek.size(); initializeMeetingDaysOfTheWeek(daysOfTheWeek); - initializeRounds(startAt.toLocalDate()); -// registerEvent() + registerEvent(new StudyStartedEvent(id, dayOfWeeks, startAt.toLocalDate())); } private void deleteLeftApplicant() { @@ -241,23 +240,6 @@ private void initializeMeetingDaysOfTheWeek(List dayOfWeeks) { this.dayOfWeeks.addAll(dayOfWeeks); } - private void initializeRounds(LocalDate startAt) { - this.rounds.addAll(createRoundsOfFirstWeek(startAt)); - this.rounds.addAll(createRoundsOf(FIRST_WEEK + 1)); - rounds.get(0).proceed(); - } - - private List createRoundsOfFirstWeek(final LocalDate startAt) { - List rounds = dayOfWeeks.stream() - .filter(dayOfWeek -> dayOfWeek.compareTo(startAt.getDayOfWeek()) > 0) - .map(dayOfWeek -> Round.of(dayOfWeek, this, FIRST_WEEK)) - .toList(); - if (rounds.isEmpty()) { - rounds = createRoundsOf(FIRST_WEEK); - } - return rounds; - } - public void validateMaster(Member candidate) { Member master = getMaster(); if (master.getId().equals(candidate.getId())) { @@ -275,6 +257,12 @@ public void updateToNextRound() { updateCurrentRound(nextRound); } + private List createRoundsOf(Integer weekNumber) { + return dayOfWeeks.stream() + .map(dayOfWeek -> Round.of(dayOfWeek, this, weekNumber)) + .toList(); + } + private void updateCurrentRound(Round upcomingRound) { upcomingRound.proceed(); getCurrentRound().finish(); @@ -383,12 +371,6 @@ public void updateInformation( this.meetingDaysCountPerWeek = meetingDaysCountPerWeek; } - private List createRoundsOf(Integer weekNumber) { - return dayOfWeeks.stream() - .map(dayOfWeek -> Round.of(dayOfWeek, this, weekNumber)) - .toList(); - } - public void apply(Member member) { validateMemberSize(); validateApplicant(member); diff --git a/backend/src/main/java/com/yigongil/backend/domain/study/StudyService.java b/backend/src/main/java/com/yigongil/backend/domain/study/StudyService.java index 1a40a4e4b..e8ab3de44 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/study/StudyService.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/StudyService.java @@ -189,6 +189,7 @@ public void start(Member member, Long studyId, StudyStartRequest request) { Study study = findStudyById(studyId); study.start(member, meetingDaysOfTheWeek, LocalDateTime.now()); + studyRepository.save(study); } private List createDayOfWeek(List daysOfTheWeek) { diff --git a/backend/src/main/java/com/yigongil/backend/domain/study/StudyStartedEvent.java b/backend/src/main/java/com/yigongil/backend/domain/study/StudyStartedEvent.java new file mode 100644 index 000000000..d4c4272a7 --- /dev/null +++ b/backend/src/main/java/com/yigongil/backend/domain/study/StudyStartedEvent.java @@ -0,0 +1,13 @@ +package com.yigongil.backend.domain.study; + +import java.time.DayOfWeek; +import java.time.LocalDate; +import java.util.List; + +public record StudyStartedEvent( + Long studyId, + List dayOfWeeks, + LocalDate startAt +) { + +} diff --git a/backend/src/test/java/com/yigongil/backend/domain/study/StudyTest.java b/backend/src/test/java/com/yigongil/backend/domain/study/StudyTest.java index bfea88e43..705a1b965 100644 --- a/backend/src/test/java/com/yigongil/backend/domain/study/StudyTest.java +++ b/backend/src/test/java/com/yigongil/backend/domain/study/StudyTest.java @@ -4,7 +4,6 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.yigongil.backend.domain.member.domain.Member; -import com.yigongil.backend.domain.round.Round; import com.yigongil.backend.exception.InvalidMemberSizeException; import com.yigongil.backend.exception.InvalidProcessingStatusException; import com.yigongil.backend.fixture.MemberFixture; @@ -60,39 +59,6 @@ void setUp() { LOCAL_DATE_OF_MONDAY.atStartOfDay()); } - @Test - void 현재_주차의_라운드가_끝이나면_다음_주차의_첫_번째_라운드가_현재_주차가_된다() { - // given - Round previousRound = study.getCurrentRound(); - - // when - study.updateToNextRound(); - Round currentRound = study.getCurrentRound(); - - // then - assertThat(currentRound.isSameWeek(previousRound.getWeekNumber() + 1)).isTrue(); - } - - @Test - void 스터디의_현재_라운드가_종료되는_날이면_true를_반환한다() { - // given - // when - boolean actual1 = study.isCurrentRoundEndAt(LOCAL_DATE_OF_MONDAY); - - // then - assertThat(actual1).isTrue(); - } - - @Test - void 스터디의_현재_라운드가_종료되는_날이_아니면_false를_반환한다() { - // given - // when - boolean actual = study.isCurrentRoundEndAt(LOCAL_DATE_OF_MONDAY.plusDays(1)); - - // then - assertThat(actual).isFalse(); - } - @Test void 모집중이지_않은_스터디에_Member를_추가하면_예외가_발생한다() { // given @@ -122,21 +88,6 @@ void setUp() { .isInstanceOf(InvalidProcessingStatusException.class); } } - - @Test - void 스터디를_다음_라운드로_넘기면_현재_라운드가_다음_라운드로_변한다() { - // given - study.start(study.getMaster(), List.of(DayOfWeek.TUESDAY, DayOfWeek.THURSDAY), - LOCAL_DATE_OF_MONDAY.atStartOfDay()); - Round currentRound = study.getCurrentRound(); - - // when - study.updateToNextRound(); - Round nextRound = study.getCurrentRound(); - - // then - assertThat(nextRound.isNextDayOfWeek(currentRound.getDayOfWeek())).isTrue(); - } } @Test From 5ab2af2883f5077c63a249ce923ec1f90b7280b9 Mon Sep 17 00:00:00 2001 From: kim dae hee Date: Tue, 21 Nov 2023 16:08:17 +0900 Subject: [PATCH 10/22] =?UTF-8?q?refactor:=20Round=20=EC=A7=84=ED=96=89=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20Round=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yigongil/backend/domain/round/Round.java | 8 ++++ .../backend/domain/round/RoundRepository.java | 10 +++++ .../backend/domain/round/RoundService.java | 37 +++++++++++++--- .../yigongil/backend/domain/study/Study.java | 44 ------------------- 4 files changed, 50 insertions(+), 49 deletions(-) diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/Round.java b/backend/src/main/java/com/yigongil/backend/domain/round/Round.java index 4c715d4dc..4afdf6298 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/round/Round.java +++ b/backend/src/main/java/com/yigongil/backend/domain/round/Round.java @@ -189,6 +189,10 @@ public boolean isInProgress() { return roundStatus == RoundStatus.IN_PROGRESS; } + public boolean isNotStarted() { + return roundStatus == RoundStatus.NOT_STARTED; + } + public int calculateLeftDaysFrom(LocalDate date) { int gap = dayOfWeek.getValue() - date.getDayOfWeek().getValue(); if (gap < 0) { @@ -208,6 +212,10 @@ public void exit(Member member) { roundOfMembers.remove(findRoundOfMemberBy(member)); } + public Round createNextWeekRound() { + return of(dayOfWeek, study, weekNumber + 1); + } + @Override public boolean equals(Object o) { if (this == o) { diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/RoundRepository.java b/backend/src/main/java/com/yigongil/backend/domain/round/RoundRepository.java index ad71dff0a..aaa318398 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/round/RoundRepository.java +++ b/backend/src/main/java/com/yigongil/backend/domain/round/RoundRepository.java @@ -1,5 +1,6 @@ package com.yigongil.backend.domain.round; +import java.time.DayOfWeek; import java.util.List; import java.util.Optional; import org.springframework.data.jpa.repository.EntityGraph; @@ -13,4 +14,13 @@ public interface RoundRepository extends Repository { List findAllByStudyIdAndWeekNumber(Long studyId, Integer weekNumber); Round save(Round round); + + List findByRoundStatusAndDayOfWeek( + RoundStatus roundStatus, + DayOfWeek dayOfWeek + ); + + List findAllByStudyIdAndWeekNumberIn(Long studyId, List weekNumbers); + + void saveAll(Iterable rounds); } diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java b/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java index 44cb361e2..2da909e4d 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java +++ b/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java @@ -13,6 +13,7 @@ import java.time.DayOfWeek; import java.time.LocalDate; import java.util.ArrayList; +import java.util.Comparator; import java.util.List; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -82,12 +83,38 @@ public List findRoundDetailsOfWeek(Long id, Integer weekNumber) { @Transactional public void proceedRound(LocalDate today) { - List studies = studyRepository.findAllByProcessingStatus( - ProcessingStatus.PROCESSING); + List rounds = roundRepository.findByRoundStatusAndDayOfWeek( + RoundStatus.IN_PROGRESS, + today.minusDays(1).getDayOfWeek() + ); - studies.stream() - .filter(study -> study.isCurrentRoundEndAt(today.minusDays(1))) - .forEach(Study::updateToNextRound); + for (Round round : rounds) { + Integer currentWeek = round.getWeekNumber(); + List upcomingCandidates = roundRepository.findAllByStudyIdAndWeekNumberIn( + round.getStudy().getId(), + List.of(currentWeek, currentWeek + 1) + ); + + Round upcomingRound = upcomingCandidates.stream() + .filter(candidate -> candidate.isSameWeek(currentWeek) && candidate.isNotStarted()) + .min(Comparator.comparing(Round::getDayOfWeek)) + .orElseGet(() -> upcomingCandidates.stream() + .filter(candidate -> candidate.isSameWeek(currentWeek + 1)) + .min(Comparator.comparing(Round::getDayOfWeek)) + .orElseThrow(() -> new IllegalStateException("다음 주 라운드를 안 만들어놓음"))); + + round.finish(); + upcomingRound.proceed(); + + if (!upcomingRound.isSameWeek(currentWeek)) { + List nextWeekRounds = upcomingCandidates.stream() + .filter(candidate -> candidate.isSameWeek(currentWeek + 1)) + .map(Round::createNextWeekRound) + .toList(); + + roundRepository.saveAll(nextWeekRounds); + } + } } @TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT) diff --git a/backend/src/main/java/com/yigongil/backend/domain/study/Study.java b/backend/src/main/java/com/yigongil/backend/domain/study/Study.java index 66036562d..14e71c0b2 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/study/Study.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/Study.java @@ -209,10 +209,6 @@ public int sizeOfCurrentMembers() { .count(); } - public boolean isCurrentRoundEndAt(LocalDate date) { - return getCurrentRound().isEndAt(date); - } - public void start(Member member, List daysOfTheWeek, LocalDateTime startAt) { validateMaster(member); if (processingStatus != ProcessingStatus.RECRUITING) { @@ -248,46 +244,6 @@ public void validateMaster(Member candidate) { throw new NotStudyMasterException(" 머스트두를 수정할 권한이 없습니다.", candidate.getNickname()); } - public void updateToNextRound() { - Round nextRound = findUpcomingRoundOf(getCurrentRound().getWeekNumber()); - - if (nextRound.isSameWeek(getCurrentRound().getWeekNumber() + 1)) { - rounds.addAll(createRoundsOf(nextRound.getWeekNumber() + 1)); - } - updateCurrentRound(nextRound); - } - - private List createRoundsOf(Integer weekNumber) { - return dayOfWeeks.stream() - .map(dayOfWeek -> Round.of(dayOfWeek, this, weekNumber)) - .toList(); - } - - private void updateCurrentRound(Round upcomingRound) { - upcomingRound.proceed(); - getCurrentRound().finish(); - } - - private Round findUpcomingRoundOf(int weekNumber) { - return rounds.stream() - .filter(round -> round.isSameWeek(weekNumber) && round.isNextDayOfWeek(getCurrentRound().getDayOfWeek())) - .findFirst() - .orElseGet(() -> findFirstRoundOf(weekNumber + 1)); - } - - private Round findFirstRoundOf(int nextWeekNumber) { - return rounds.stream() - .filter(round -> round.isSameWeek(nextWeekNumber) && round.isSameDayOfWeek(findFirstDayOfTheWeek())) - .findAny() - .orElseThrow(() -> new RoundNotFoundException("다음 주차의 라운드가 존재하지 않습니다.", getCurrentRound().getWeekNumber())); - } - - private DayOfWeek findFirstDayOfTheWeek() { - return dayOfWeeks.stream() - .min(Comparator.comparing(DayOfWeek::getValue)) - .orElseThrow(); - } - public void finishStudy(Member master) { validateMaster(master); validateStudyCanFinish(); From f077b61034aeddb5215873cf4d8966f9f36970e3 Mon Sep 17 00:00:00 2001 From: kim dae hee Date: Tue, 21 Nov 2023 17:27:50 +0900 Subject: [PATCH 11/22] =?UTF-8?q?refactor:=20=EC=9E=84=EC=8B=9C=20?= =?UTF-8?q?=EC=BB=A4=EB=B0=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yigongil/backend/config/AuthConfig.java | 4 +- .../certification/CertificationApi.java | 2 +- .../certification/CertificationService.java | 14 ++++- .../backend/domain/feedpost/FeedApi.java | 2 +- .../yigongil/backend/domain/round/Round.java | 32 ++++++---- .../backend/domain/round/RoundApi.java | 4 +- .../backend/domain/round/RoundOfMember.java | 4 +- .../backend/domain/round/RoundRepository.java | 9 +++ .../backend/domain/round/RoundService.java | 42 +++++++++++-- .../yigongil/backend/domain/study/Study.java | 63 ++++++++----------- .../domain/study/StudyExitedEvent.java | 5 ++ .../domain/study/StudyFinishedEvent.java | 5 ++ .../backend/domain/study/StudyService.java | 2 + .../domain/studymember/StudyMember.java | 11 ---- .../certification/CertificationQueryApi.java | 6 +- .../CertificationQueryService.java | 14 ++++- .../backend/query/feed/FeedQueryApi.java | 2 +- .../backend/query/profile/ProfileService.java | 8 ++- .../request/MemberReportCreateRequest.java | 2 +- .../request/StudyReportCreateRequest.java | 2 +- .../MembersCertificationResponse.java | 4 +- .../com/yigongil/backend/ui/doc/StudyApi.java | 18 +++--- backend/src/main/resources/application.yml | 2 +- backend/src/test/resources/application.yml | 2 +- 24 files changed, 157 insertions(+), 102 deletions(-) create mode 100644 backend/src/main/java/com/yigongil/backend/domain/study/StudyExitedEvent.java create mode 100644 backend/src/main/java/com/yigongil/backend/domain/study/StudyFinishedEvent.java diff --git a/backend/src/main/java/com/yigongil/backend/config/AuthConfig.java b/backend/src/main/java/com/yigongil/backend/config/AuthConfig.java index c75fefac1..829d74674 100644 --- a/backend/src/main/java/com/yigongil/backend/config/AuthConfig.java +++ b/backend/src/main/java/com/yigongil/backend/config/AuthConfig.java @@ -26,14 +26,14 @@ public void addInterceptors(InterceptorRegistry registry) { .excludePathPatterns("/login/github/tokens") .excludePathPatterns("/login/tokens/refresh") .excludePathPatterns("/login/fake/tokens") - .excludePathPatterns("/members/{id:[0-9]\\d*}") + .excludePathPatterns("/members/{studyId:[0-9]\\d*}") .excludePathPatterns("/members/exists") .excludePathPatterns("/api/**") .excludePathPatterns("/api-docs/**") .excludePathPatterns("/swagger-ui/**") .excludePathPatterns("/actuator/**") .excludePathPatterns("/fake/proceed") - .excludePathPatterns("/studies/{id:[0-9]\\d*}/rounds/{id:[0-9]\\d*}/progress-rate"); + .excludePathPatterns("/studies/{studyId:[0-9]\\d*}/rounds/{studyId:[0-9]\\d*}/progress-rate"); } diff --git a/backend/src/main/java/com/yigongil/backend/domain/certification/CertificationApi.java b/backend/src/main/java/com/yigongil/backend/domain/certification/CertificationApi.java index 48f040b41..0d3dbf2ad 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/certification/CertificationApi.java +++ b/backend/src/main/java/com/yigongil/backend/domain/certification/CertificationApi.java @@ -27,7 +27,7 @@ public interface CertificationApi { @Operation(summary = "인증 피드 등록") ResponseEntity createCertification( @Schema(hidden = true) Member member, - @Parameter(description = "피드가 등록되는 스터디 id", required = true) Long id, + @Parameter(description = "피드가 등록되는 스터디 studyId", required = true) Long id, CertificationCreateRequest request ); } diff --git a/backend/src/main/java/com/yigongil/backend/domain/certification/CertificationService.java b/backend/src/main/java/com/yigongil/backend/domain/certification/CertificationService.java index 9a49dc07c..e9bc78ed0 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/certification/CertificationService.java +++ b/backend/src/main/java/com/yigongil/backend/domain/certification/CertificationService.java @@ -1,8 +1,12 @@ package com.yigongil.backend.domain.certification; import com.yigongil.backend.domain.member.domain.Member; +import com.yigongil.backend.domain.round.Round; +import com.yigongil.backend.domain.round.RoundRepository; +import com.yigongil.backend.domain.round.RoundStatus; import com.yigongil.backend.domain.study.Study; import com.yigongil.backend.domain.study.StudyRepository; +import com.yigongil.backend.exception.RoundNotFoundException; import com.yigongil.backend.request.CertificationCreateRequest; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -12,10 +16,12 @@ public class CertificationService { private final CertificationRepository certificationRepository; private final StudyRepository studyRepository; + private final RoundRepository roundRepository; - public CertificationService(CertificationRepository certificationRepository, StudyRepository studyRepository) { + public CertificationService(CertificationRepository certificationRepository, StudyRepository studyRepository, RoundRepository roundRepository) { this.certificationRepository = certificationRepository; this.studyRepository = studyRepository; + this.roundRepository = roundRepository; } @Transactional @@ -25,14 +31,16 @@ public Long createCertification(Member member, Long studyId, CertificationCreate } private Certification createCertification(Study study, Member member, CertificationCreateRequest request) { + Round round = roundRepository.findByStudyIdAndRoundStatus(study.getId(), RoundStatus.IN_PROGRESS) + .orElseThrow(() -> new RoundNotFoundException("", -1L)); Certification feedPost = Certification.builder() .author(member) .study(study) - .round(study.getCurrentRound()) + .round(round) .content(request.content()) .imageUrl(request.imageUrl()) .build(); - study.completeRound(member); + round.completeRound(member); return certificationRepository.save(feedPost); } } diff --git a/backend/src/main/java/com/yigongil/backend/domain/feedpost/FeedApi.java b/backend/src/main/java/com/yigongil/backend/domain/feedpost/FeedApi.java index d9ea9897d..025da99f9 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/feedpost/FeedApi.java +++ b/backend/src/main/java/com/yigongil/backend/domain/feedpost/FeedApi.java @@ -27,7 +27,7 @@ public interface FeedApi { @Operation(summary = "일반 피드 등록") ResponseEntity createFeedPost( @Schema(hidden = true) Member member, - @Parameter(description = "피드가 등록되는 스터디 id", required = true) Long id, + @Parameter(description = "피드가 등록되는 스터디 studyId", required = true) Long id, FeedPostCreateRequest request ); } diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/Round.java b/backend/src/main/java/com/yigongil/backend/domain/round/Round.java index 4afdf6298..09ddb46df 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/round/Round.java +++ b/backend/src/main/java/com/yigongil/backend/domain/round/Round.java @@ -1,5 +1,7 @@ package com.yigongil.backend.domain.round; +import static java.util.stream.Collectors.toMap; + import com.yigongil.backend.domain.base.BaseEntity; import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.study.Study; @@ -11,6 +13,7 @@ import java.time.LocalDate; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Objects; import javax.persistence.Column; import javax.persistence.Entity; @@ -129,23 +132,23 @@ public void completeRound(Member member) { if (mustDo == null) { throw new NecessaryTodoNotExistException(" 머스트두가 생성되지 않았습니다.", String.valueOf(id)); } - findRoundOfMemberBy(member).completeRound(); + findRoundOfMemberBy(member.getId()).completeRound(); } public boolean isMustDoDone(Member member) { - return findRoundOfMemberBy(member).isDone(); + return findRoundOfMemberBy(member.getId()).isDone(); } public boolean isEndAt(LocalDate date) { return dayOfWeek == date.getDayOfWeek(); } - public RoundOfMember findRoundOfMemberBy(Member member) { + public RoundOfMember findRoundOfMemberBy(Long memberId) { return roundOfMembers.stream() - .filter(roundOfMember -> roundOfMember.isMemberEquals(member)) + .filter(roundOfMember -> roundOfMember.isMemberEquals(memberId)) .findAny() .orElseThrow( - () -> new NotStudyMemberException("해당 스터디의 멤버가 아닙니다.", member.getGithubId()) + () -> new NotStudyMemberException("해당 스터디의 멤버가 아닙니다.", memberId.toString()) ); } @@ -166,11 +169,11 @@ public void finish() { } public boolean isSuccess(Member member) { - return findRoundOfMemberBy(member).isDone(); + return findRoundOfMemberBy(member.getId()).isDone(); } - public boolean isMaster(Member member) { - return master.equals(member); + public boolean isMaster(Long memberId) { + return master.equals(memberId); } public boolean isSameWeek(Integer weekNumber) { @@ -205,11 +208,16 @@ public boolean isBeforeOrSame(Integer minimumWeeks) { return weekNumber <= minimumWeeks; } - public void exit(Member member) { - if (isMaster(member)) { - throw new NotStudyMemberException("스터디장은 스터디를 나갈 수 없습니다.", member.getGithubId()); + public Map calculateExperience(Integer roundScore) { + return roundOfMembers.stream() + .collect(toMap(RoundOfMember::getMember, roundOfMember -> roundOfMember.isDone() ? roundScore : 0)); + } + + public void exit(Long memberId) { + if (isMaster(memberId)) { + throw new NotStudyMemberException("스터디장은 스터디를 나갈 수 없습니다.", memberId.toString()); } - roundOfMembers.remove(findRoundOfMemberBy(member)); + roundOfMembers.remove(findRoundOfMemberBy(memberId)); } public Round createNextWeekRound() { diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/RoundApi.java b/backend/src/main/java/com/yigongil/backend/domain/round/RoundApi.java index 6c80bd140..0b80d19c3 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/round/RoundApi.java +++ b/backend/src/main/java/com/yigongil/backend/domain/round/RoundApi.java @@ -19,7 +19,7 @@ public interface RoundApi { @SecurityRequirement(name = "token") @Operation(summary = "주별 회차 정보 조회") ResponseEntity> findRoundDetailsOfWeek( - @Parameter(description = "조회할 스터디 id", required = true) Long studyId, + @Parameter(description = "조회할 스터디 studyId", required = true) Long studyId, @Parameter(description = "조회할 주차", required = true) Integer weekNumber ); @@ -35,7 +35,7 @@ ResponseEntity> findRoundDetailsOfWeek( @Operation(summary = " 머스트두 생성") ResponseEntity updateMustDo( @Schema(hidden = true) Member member, - @Parameter(description = " 머스트두를 생성할 라운드 id", required = true) Long roundId, + @Parameter(description = " 머스트두를 생성할 라운드 studyId", required = true) Long roundId, MustDoUpdateRequest request ); } diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/RoundOfMember.java b/backend/src/main/java/com/yigongil/backend/domain/round/RoundOfMember.java index 05aa4c4fa..eb06c8692 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/round/RoundOfMember.java +++ b/backend/src/main/java/com/yigongil/backend/domain/round/RoundOfMember.java @@ -56,7 +56,7 @@ public void completeRound() { this.isDone = true; } - public boolean isMemberEquals(Member member) { - return this.member.equals(member); + public boolean isMemberEquals(Long memberId) { + return this.member.getId().equals(memberId); } } diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/RoundRepository.java b/backend/src/main/java/com/yigongil/backend/domain/round/RoundRepository.java index aaa318398..767b2a9eb 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/round/RoundRepository.java +++ b/backend/src/main/java/com/yigongil/backend/domain/round/RoundRepository.java @@ -1,5 +1,6 @@ package com.yigongil.backend.domain.round; +import com.yigongil.backend.exception.RoundNotFoundException; import java.time.DayOfWeek; import java.util.List; import java.util.Optional; @@ -23,4 +24,12 @@ List findByRoundStatusAndDayOfWeek( List findAllByStudyIdAndWeekNumberIn(Long studyId, List weekNumbers); void saveAll(Iterable rounds); + + List findAllByStudyId(Long studyId); + + Optional findByStudyIdAndRoundStatus(Long studyId, RoundStatus roundStatus); + + default Round getByStudyIdAndRoundStatus(Long studyId, RoundStatus roundStatus) { + return findByStudyIdAndRoundStatus(studyId, roundStatus).orElseThrow(() -> new RoundNotFoundException("", -1)); + } } diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java b/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java index 2da909e4d..b40349e16 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java +++ b/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java @@ -3,9 +3,10 @@ import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.study.ProcessingStatus; import com.yigongil.backend.domain.study.Study; +import com.yigongil.backend.domain.study.StudyExitedEvent; +import com.yigongil.backend.domain.study.StudyFinishedEvent; import com.yigongil.backend.domain.study.StudyRepository; import com.yigongil.backend.domain.study.StudyStartedEvent; -import com.yigongil.backend.domain.studymember.StudyMember; import com.yigongil.backend.exception.RoundNotFoundException; import com.yigongil.backend.request.MustDoUpdateRequest; import com.yigongil.backend.response.RoundResponse; @@ -14,7 +15,9 @@ import java.time.LocalDate; import java.util.ArrayList; import java.util.Comparator; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.event.TransactionPhase; @@ -26,6 +29,7 @@ public class RoundService { private final RoundRepository roundRepository; private final StudyRepository studyRepository; + public RoundService( RoundRepository roundRepository, StudyRepository studyRepository @@ -36,13 +40,11 @@ public RoundService( @Transactional(readOnly = true) public List findCurrentRoundOfStudies(Member member) { - List studies = studyRepository.findByMemberAndProcessingStatus(member, - ProcessingStatus.PROCESSING); + List studies = studyRepository.findByMemberAndProcessingStatus(member, ProcessingStatus.PROCESSING); List upcomingStudyResponses = new ArrayList<>(); for (Study study : studies) { - Round currentRound = study.getCurrentRound(); - StudyMember studyMember = study.getStudyMemberByMember(member); + Round currentRound = roundRepository.getByStudyIdAndRoundStatus(study.getId(), RoundStatus.IN_PROGRESS); int leftDays = currentRound.calculateLeftDaysFrom(LocalDate.now()); @@ -52,7 +54,7 @@ public List findCurrentRoundOfStudies(Member member) { study.getName(), currentRound.getMustDo(), leftDays, - studyMember.calculateAccumulatedExperience(), + calculateExperience(study.getId(), study.getRoundExperience()).get(member), study.isMaster(member) ) ); @@ -61,6 +63,34 @@ public List findCurrentRoundOfStudies(Member member) { return upcomingStudyResponses; } + @TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT) + public void addExperience(StudyFinishedEvent event) { + Map memberToExperience = calculateExperience(event.studyId(), event.roundExperience()); + + for (Member member : memberToExperience.keySet()) { + member.addExperience(memberToExperience.get(member)); + } + } + + @TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT) + public void exit(StudyExitedEvent event) { + List rounds = roundRepository.findAllByStudyId(event.studyId()); + for (Round round : rounds) { + round.exit(event.memberId()); + } + } + + private Map calculateExperience(Long studyId, Integer roundExperience) { + List rounds = roundRepository.findAllByStudyId(studyId); + + Map memberToExperience = new HashMap<>(); + for (Round round : rounds) { + round.calculateExperience(roundExperience) + .forEach(((member, experience) -> memberToExperience.merge(member, experience, Integer::sum))); + } + return memberToExperience; + } + @Transactional public void updateMustDo(Member member, Long roundId, MustDoUpdateRequest request) { Round round = findRoundById(roundId); diff --git a/backend/src/main/java/com/yigongil/backend/domain/study/Study.java b/backend/src/main/java/com/yigongil/backend/domain/study/Study.java index 14e71c0b2..7f77b7717 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/study/Study.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/Study.java @@ -52,6 +52,7 @@ public class Study extends BaseRootEntity { private static final int MAX_MEMBER_SIZE = 8; private static final int INITIAL_ROUND_COUNT = 2; private static final int FIRST_WEEK = 1; + private static final int EXPERIENCE_BASE_UNIT = 1; @GeneratedValue(strategy = GenerationType.IDENTITY) @Id @@ -90,11 +91,11 @@ public class Study extends BaseRootEntity { @OneToMany(mappedBy = "study", orphanRemoval = true, fetch = FetchType.LAZY) private List studyMembers = new ArrayList<>(); - - @Cascade(CascadeType.PERSIST) - @OnDelete(action = OnDeleteAction.CASCADE) - @OneToMany(mappedBy = "study", orphanRemoval = true, fetch = FetchType.LAZY) - private List rounds = new ArrayList<>(); +// +// @Cascade(CascadeType.PERSIST) +// @OnDelete(action = OnDeleteAction.CASCADE) +// @OneToMany(mappedBy = "study", orphanRemoval = true, fetch = FetchType.LAZY) +// private List rounds = new ArrayList<>(); protected Study() { } @@ -129,7 +130,7 @@ public Study( .member(master) .studyResult(StudyResult.NONE) .build()); - this.rounds = rounds == null ? new ArrayList<>() : rounds; +// this.rounds = rounds == null ? new ArrayList<>() : rounds; this.minimumWeeks = minimumWeeks; this.meetingDaysCountPerWeek = meetingDaysCountPerWeek; } @@ -247,17 +248,24 @@ public void validateMaster(Member candidate) { public void finishStudy(Member master) { validateMaster(master); validateStudyCanFinish(); + registerEvent(new StudyFinishedEvent(id, getRoundExperience())); studyMembers.forEach(StudyMember::completeSuccessfully); this.processingStatus = ProcessingStatus.END; } + public Integer getRoundExperience() { + int defaultRoundExperience = EXPERIENCE_BASE_UNIT * 2; + int additionalExperienceOfPeriodLength = EXPERIENCE_BASE_UNIT * 3 / meetingDaysCountPerWeek + 1; + return defaultRoundExperience + additionalExperienceOfPeriodLength; + } + private void validateStudyCanFinish() { if (isEnd()) { throw new CannotEndException("이미 종료된 스터디입니다.", String.valueOf(id)); } - if (getCurrentRound().isBeforeOrSame(minimumWeeks)) { - throw new CannotEndException("최소 진행 주차를 채우지 못했습니다.", String.valueOf(id)); - } +// if (getCurrentRound().isBeforeOrSame(minimumWeeks)) { +// throw new CannotEndException("최소 진행 주차를 채우지 못했습니다.", String.valueOf(id)); +// } } public Member getMaster() { @@ -283,29 +291,15 @@ public boolean isEnd() { return this.processingStatus == ProcessingStatus.END; } - public void completeRound(Member member) { - getCurrentRound().completeRound(member); - } - - public List getCurrentRoundOfMembers() { - return getCurrentRound().getRoundOfMembers(); - } - - public int calculateSuccessfulRoundCount(Member member) { - return (int) rounds.stream() - .filter(round -> round.isSuccess(member)) - .count(); - } - - public Round getCurrentRound() { - return rounds.stream() - .filter(Round::isInProgress) - .findAny() - .orElseThrow(() -> new RoundNotFoundException("현재 진행중인 라운드가 없습니다.", -1)); - } +// public Round getCurrentRound() { +// return rounds.stream() +// .filter(Round::isInProgress) +// .findAny() +// .orElseThrow(() -> new RoundNotFoundException("현재 진행중인 라운드가 없습니다.", -1)); +// } public boolean isMaster(Member member) { - return getCurrentRound().isMaster(member); + return getMaster().getId().equals(member.getId()); } public void updateInformation( @@ -350,8 +344,8 @@ private boolean isAlreadyExist(Member member) { } public void exit(Member member) { - rounds.forEach(round -> round.exit(member)); findStudyMemberBy(member).failStudy(); + registerEvent(new StudyExitedEvent(id, member.getId())); } private StudyMember findStudyMemberBy(Member member) { @@ -360,11 +354,4 @@ private StudyMember findStudyMemberBy(Member member) { .findAny() .orElseThrow(() -> new NotStudyMemberException("해당 스터디의 멤버가 아닙니다.", member.getGithubId())); } - - public StudyMember getStudyMemberByMember(Member member) { - return studyMembers.stream() - .filter(studyMember -> studyMember.getMember().equals(member)) - .findAny() - .orElseThrow(() -> new NotStudyMemberException("해당 스터디의 멤버가 아닙니다.", member.getGithubId())); - } } diff --git a/backend/src/main/java/com/yigongil/backend/domain/study/StudyExitedEvent.java b/backend/src/main/java/com/yigongil/backend/domain/study/StudyExitedEvent.java new file mode 100644 index 000000000..1e4f2d8c2 --- /dev/null +++ b/backend/src/main/java/com/yigongil/backend/domain/study/StudyExitedEvent.java @@ -0,0 +1,5 @@ +package com.yigongil.backend.domain.study; + +public record StudyExitedEvent(Long studyId, Long memberId) { + +} diff --git a/backend/src/main/java/com/yigongil/backend/domain/study/StudyFinishedEvent.java b/backend/src/main/java/com/yigongil/backend/domain/study/StudyFinishedEvent.java new file mode 100644 index 000000000..5c768337c --- /dev/null +++ b/backend/src/main/java/com/yigongil/backend/domain/study/StudyFinishedEvent.java @@ -0,0 +1,5 @@ +package com.yigongil.backend.domain.study; + +public record StudyFinishedEvent(Long studyId, Integer roundExperience) { + +} diff --git a/backend/src/main/java/com/yigongil/backend/domain/study/StudyService.java b/backend/src/main/java/com/yigongil/backend/domain/study/StudyService.java index e8ab3de44..d2c6dddf3 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/study/StudyService.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/StudyService.java @@ -236,11 +236,13 @@ private List toRecruitingStudyResponse(Slice studi public void finish(Member member, Long studyId) { Study study = findStudyById(studyId); study.finishStudy(member); + studyRepository.save(study); } @Transactional public void exit(Member member, Long studyId) { Study study = findStudyById(studyId); study.exit(member); + studyRepository.save(study); } } diff --git a/backend/src/main/java/com/yigongil/backend/domain/studymember/StudyMember.java b/backend/src/main/java/com/yigongil/backend/domain/studymember/StudyMember.java index ba6005e8d..2e7f89d58 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/studymember/StudyMember.java +++ b/backend/src/main/java/com/yigongil/backend/domain/studymember/StudyMember.java @@ -22,8 +22,6 @@ @Entity public class StudyMember extends BaseEntity { - private static final int EXPERIENCE_BASE_UNIT = 1; - @GeneratedValue(strategy = GenerationType.IDENTITY) @Id private Long id; @@ -86,18 +84,9 @@ public boolean isMaster() { } public void completeSuccessfully() { - int totalExperience = calculateAccumulatedExperience(); - member.addExperience(totalExperience); this.studyResult = StudyResult.SUCCESS; } - public int calculateAccumulatedExperience() { - int successfulRoundCount = study.calculateSuccessfulRoundCount(member); - int defaultRoundExperience = EXPERIENCE_BASE_UNIT * 2; - int additionalExperienceOfPeriodLength = EXPERIENCE_BASE_UNIT * 3 / study.getMeetingDaysCountPerWeek() + 1; - return successfulRoundCount * (defaultRoundExperience + additionalExperienceOfPeriodLength); - } - public void failStudy() { this.studyResult = StudyResult.FAIL; } diff --git a/backend/src/main/java/com/yigongil/backend/query/certification/CertificationQueryApi.java b/backend/src/main/java/com/yigongil/backend/query/certification/CertificationQueryApi.java index 8e2c30005..a6e85d42d 100644 --- a/backend/src/main/java/com/yigongil/backend/query/certification/CertificationQueryApi.java +++ b/backend/src/main/java/com/yigongil/backend/query/certification/CertificationQueryApi.java @@ -26,7 +26,7 @@ public interface CertificationQueryApi { @Operation(summary = "스터디 멤버 전체 인증 정보 조회") ResponseEntity findAllMembersCertification( @Schema(hidden = true) Member member, - @Parameter(description = "조회하려는 스터디 id", required = true) Long id + @Parameter(description = "조회하려는 스터디 studyId", required = true) Long id ); @ApiResponses( @@ -38,7 +38,7 @@ ResponseEntity findAllMembersCertification( @SecurityRequirement(name = "token") @Operation(summary = "스터디 멤버 단일 인증 게시글 조회") ResponseEntity findMemberCertification( - @Parameter(description = "인증 게시 회차 id") Long roundId, - @Parameter(description = "작성자 id") Long memberId + @Parameter(description = "인증 게시 회차 studyId") Long roundId, + @Parameter(description = "작성자 studyId") Long memberId ); } diff --git a/backend/src/main/java/com/yigongil/backend/query/certification/CertificationQueryService.java b/backend/src/main/java/com/yigongil/backend/query/certification/CertificationQueryService.java index 1a22f6776..b06f6c4e1 100644 --- a/backend/src/main/java/com/yigongil/backend/query/certification/CertificationQueryService.java +++ b/backend/src/main/java/com/yigongil/backend/query/certification/CertificationQueryService.java @@ -3,7 +3,10 @@ import com.yigongil.backend.domain.certification.Certification; import com.yigongil.backend.domain.certification.CertificationRepository; import com.yigongil.backend.domain.member.domain.Member; +import com.yigongil.backend.domain.round.Round; import com.yigongil.backend.domain.round.RoundOfMember; +import com.yigongil.backend.domain.round.RoundRepository; +import com.yigongil.backend.domain.round.RoundStatus; import com.yigongil.backend.domain.study.Study; import com.yigongil.backend.domain.study.StudyRepository; import com.yigongil.backend.response.CertificationResponse; @@ -18,13 +21,17 @@ public class CertificationQueryService { private final CertificationRepository certificationRepository; private final StudyRepository studyRepository; + private final RoundRepository roundRepository; + public CertificationQueryService( CertificationRepository certificationRepository, - StudyRepository studyRepository + StudyRepository studyRepository, + RoundRepository roundRepository ) { this.certificationRepository = certificationRepository; this.studyRepository = studyRepository; + this.roundRepository = roundRepository; } public CertificationResponse findCertification(Long roundId, Long memberId) { @@ -34,7 +41,8 @@ public CertificationResponse findCertification(Long roundId, Long memberId) { public MembersCertificationResponse findAllMembersCertification(Member member, Long studyId) { Study study = studyRepository.getById(studyId); - final List roundOfMembers = study.getCurrentRoundOfMembers(); - return MembersCertificationResponse.of(study.getName(), study.getCurrentRound(), member, roundOfMembers); + Round round = roundRepository.getByStudyIdAndRoundStatus(studyId, RoundStatus.IN_PROGRESS); + final List roundOfMembers = round.getRoundOfMembers(); + return MembersCertificationResponse.of(study.getName(), round, member, roundOfMembers); } } diff --git a/backend/src/main/java/com/yigongil/backend/query/feed/FeedQueryApi.java b/backend/src/main/java/com/yigongil/backend/query/feed/FeedQueryApi.java index db4b48743..2c7c48b73 100644 --- a/backend/src/main/java/com/yigongil/backend/query/feed/FeedQueryApi.java +++ b/backend/src/main/java/com/yigongil/backend/query/feed/FeedQueryApi.java @@ -26,7 +26,7 @@ public interface FeedQueryApi { @SecurityRequirement(name = "token") @Operation(summary = "피드 조회") ResponseEntity> findFeedPosts( - @Parameter(description = "조회할 스터디 id", required = true) Long id, + @Parameter(description = "조회할 스터디 studyId", required = true) Long id, @Parameter(description = "마지막으로 본 피드의 아이디, 첫 요청에서는 필요 없음", allowEmptyValue = true) Optional oldestFeedPostId ); } diff --git a/backend/src/main/java/com/yigongil/backend/query/profile/ProfileService.java b/backend/src/main/java/com/yigongil/backend/query/profile/ProfileService.java index 2c5a40c0c..c3c532053 100644 --- a/backend/src/main/java/com/yigongil/backend/query/profile/ProfileService.java +++ b/backend/src/main/java/com/yigongil/backend/query/profile/ProfileService.java @@ -2,6 +2,7 @@ import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.member.domain.MemberRepository; +import com.yigongil.backend.domain.round.RoundRepository; import com.yigongil.backend.domain.study.Study; import com.yigongil.backend.domain.study.StudyService; import com.yigongil.backend.domain.studymember.StudyMember; @@ -19,12 +20,15 @@ public class ProfileService { private final StudyMemberRepository studyMemberRepository; private final StudyService studyService; private final MemberRepository memberRepository; + private final RoundRepository roundRepository; + public ProfileService(StudyMemberRepository studyMemberRepository, StudyService studyService, - MemberRepository memberRepository) { + MemberRepository memberRepository, RoundRepository roundRepository) { this.studyMemberRepository = studyMemberRepository; this.studyService = studyService; this.memberRepository = memberRepository; + this.roundRepository = roundRepository; } public ProfileResponse findById(Long id) { @@ -69,7 +73,7 @@ private int calculateNumberOfSuccessRounds(Member member) { .toList(); return (int) studies.stream() - .map(Study::getRounds) + .map(study -> roundRepository.findAllByStudyId(study.getId())) .flatMap(List::stream) .filter(round -> round.isMustDoDone(member)) .count(); diff --git a/backend/src/main/java/com/yigongil/backend/request/MemberReportCreateRequest.java b/backend/src/main/java/com/yigongil/backend/request/MemberReportCreateRequest.java index 50c183cf7..8cfede9af 100644 --- a/backend/src/main/java/com/yigongil/backend/request/MemberReportCreateRequest.java +++ b/backend/src/main/java/com/yigongil/backend/request/MemberReportCreateRequest.java @@ -7,7 +7,7 @@ import javax.validation.constraints.Positive; public record MemberReportCreateRequest( - @Schema(description = "신고할 회원 id", example = "1") + @Schema(description = "신고할 회원 studyId", example = "1") @Positive(message = "피신고자 식별자는 양수만 입력 가능합니다.") Long reportedMemberId, diff --git a/backend/src/main/java/com/yigongil/backend/request/StudyReportCreateRequest.java b/backend/src/main/java/com/yigongil/backend/request/StudyReportCreateRequest.java index aa7485879..95fcea387 100644 --- a/backend/src/main/java/com/yigongil/backend/request/StudyReportCreateRequest.java +++ b/backend/src/main/java/com/yigongil/backend/request/StudyReportCreateRequest.java @@ -7,7 +7,7 @@ import javax.validation.constraints.Positive; public record StudyReportCreateRequest( - @Schema(description = "신고할 스터디 id", example = "1") + @Schema(description = "신고할 스터디 studyId", example = "1") @Positive(message = "신고할 스터디의 식별자는 양수만 입력 가능합니다.") Long reportedStudyId, diff --git a/backend/src/main/java/com/yigongil/backend/response/MembersCertificationResponse.java b/backend/src/main/java/com/yigongil/backend/response/MembersCertificationResponse.java index c923ef70a..8ed9212f6 100644 --- a/backend/src/main/java/com/yigongil/backend/response/MembersCertificationResponse.java +++ b/backend/src/main/java/com/yigongil/backend/response/MembersCertificationResponse.java @@ -15,7 +15,7 @@ public record MembersCertificationResponse( public static MembersCertificationResponse of(String studyName, Round upcomingRound, Member requestingMember, List roundOfMembers) { List others = roundOfMembers.stream() - .filter(roundOfMember -> !roundOfMember.isMemberEquals(requestingMember)) + .filter(roundOfMember -> !roundOfMember.isMemberEquals(requestingMember.getId())) .map(roundOfMember -> new MemberCertificationResponse( roundOfMember.getMember().getId(), roundOfMember.getMember().getNickname(), @@ -23,7 +23,7 @@ public static MembersCertificationResponse of(String studyName, Round upcomingRo roundOfMember.isDone())) .toList(); MemberCertificationResponse me = roundOfMembers.stream() - .filter(roundOfMember -> roundOfMember.isMemberEquals(requestingMember)) + .filter(roundOfMember -> roundOfMember.isMemberEquals(requestingMember.getId())) .findAny() .map(roundOfMember -> new MemberCertificationResponse( roundOfMember.getMember().getId(), diff --git a/backend/src/main/java/com/yigongil/backend/ui/doc/StudyApi.java b/backend/src/main/java/com/yigongil/backend/ui/doc/StudyApi.java index ff23e0c2a..53c61ff1d 100644 --- a/backend/src/main/java/com/yigongil/backend/ui/doc/StudyApi.java +++ b/backend/src/main/java/com/yigongil/backend/ui/doc/StudyApi.java @@ -49,7 +49,7 @@ ResponseEntity createStudy( @Operation(summary = "스터디 정보 수정") ResponseEntity updateStudy( @Schema(hidden = true) Member member, - @Parameter(description = "수정할 스터디 id", required = true) Long studyId, + @Parameter(description = "수정할 스터디 studyId", required = true) Long studyId, StudyUpdateRequest request ); @@ -65,7 +65,7 @@ ResponseEntity updateStudy( @Operation(summary = "스터디 지원") ResponseEntity applyStudy( @Schema(hidden = true) Member member, - @Parameter(description = "지원할 스터디 id", required = true) Long studyId + @Parameter(description = "지원할 스터디 studyId", required = true) Long studyId ); @ApiResponses( @@ -80,8 +80,8 @@ ResponseEntity applyStudy( @Operation(summary = "스터디 지원 수락") ResponseEntity permitApplicant( @Schema(hidden = true) Member master, - @Parameter(description = "수락할 스터디 id", required = true) Long studyId, - @Parameter(description = "지원한 회원 id", required = true) Long memberId + @Parameter(description = "수락할 스터디 studyId", required = true) Long studyId, + @Parameter(description = "지원한 회원 studyId", required = true) Long memberId ); @ApiResponses( @@ -96,7 +96,7 @@ ResponseEntity permitApplicant( @Operation(summary = "스터디 지원 취소") ResponseEntity deleteApplicant( @Schema(hidden = true) Member member, - @Parameter(description = "지원 취소할 스터디 id", required = true) Long studyId + @Parameter(description = "지원 취소할 스터디 studyId", required = true) Long studyId ); @ApiResponses( @@ -109,7 +109,7 @@ ResponseEntity deleteApplicant( @SecurityRequirement(name = "token") @Operation(summary = "스터디 상세 조회") ResponseEntity viewStudyDetail( - @Parameter(description = "조회할 스터디 id", required = true) Long id + @Parameter(description = "조회할 스터디 studyId", required = true) Long id ); @ApiResponses( @@ -135,7 +135,7 @@ ResponseEntity> findStudies( @SecurityRequirement(name = "token") @Operation(summary = "스터디 지원자 조회") ResponseEntity> findApplicantOfStudy( - @Parameter(description = "조회할 스터디 id", required = true) Long id, + @Parameter(description = "조회할 스터디 studyId", required = true) Long id, @Schema(hidden = true) Member master ); @@ -162,7 +162,7 @@ ResponseEntity> findApplicantOfStudy( @Operation(summary = "스터디 시작") ResponseEntity startStudy( @Schema(hidden = true) Member member, - @Parameter(description = "시작할 스터디 id", required = true) Long id, + @Parameter(description = "시작할 스터디 studyId", required = true) Long id, StudyStartRequest studyStartRequest ); @@ -176,6 +176,6 @@ ResponseEntity startStudy( @Operation(summary = "스터디 멤버 역할 조회") ResponseEntity getStudyMemberRole( @Schema(hidden = true) Member member, - @Parameter(description = "멤버가 속해 있는 스터디 id", required = true) Long studyId + @Parameter(description = "멤버가 속해 있는 스터디 studyId", required = true) Long studyId ); } diff --git a/backend/src/main/resources/application.yml b/backend/src/main/resources/application.yml index 322223ef3..f9a5511f9 100644 --- a/backend/src/main/resources/application.yml +++ b/backend/src/main/resources/application.yml @@ -47,7 +47,7 @@ logging: oauth2: github: client: - id: github-client-id + id: github-client-studyId secret: github-secret github-login-uri: https://github.com/login/oauth/authorize provider: diff --git a/backend/src/test/resources/application.yml b/backend/src/test/resources/application.yml index 7fdfd8537..40fae4f4b 100644 --- a/backend/src/test/resources/application.yml +++ b/backend/src/test/resources/application.yml @@ -31,7 +31,7 @@ logging: oauth2: github: client: - id: github-client-id + id: github-client-studyId secret: github-secret github-login-uri: https://github.com/login/oauth/authorize provider: From c00c4916e0cb09a6570ba68b85026cef6d4e935b Mon Sep 17 00:00:00 2001 From: bjk1649 Date: Wed, 1 Nov 2023 15:49:13 +0900 Subject: [PATCH 12/22] =?UTF-8?q?chore:=20datadog=20=EC=9D=98=EC=A1=B4?= =?UTF-8?q?=EC=84=B1=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/build.gradle | 3 --- 1 file changed, 3 deletions(-) diff --git a/backend/build.gradle b/backend/build.gradle index d7cdbee0d..a31db64b2 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -77,9 +77,6 @@ dependencies { annotationProcessor "javax.persistence:javax.persistence-api" annotationProcessor "javax.annotation:javax.annotation-api" annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jpa" - - // datadog - runtimeOnly 'io.micrometer:micrometer-registry-datadog' } tasks.named('test') { From 293251248d9ea24bfa771a12fe26dfc4a1f04fa9 Mon Sep 17 00:00:00 2001 From: bjk1649 Date: Tue, 21 Nov 2023 17:47:53 +0900 Subject: [PATCH 13/22] =?UTF-8?q?refactor:=20study=EC=97=90=EC=84=9C=20rou?= =?UTF-8?q?nd=EC=97=90=20=EB=8C=80=ED=95=9C=20=EC=9D=98=EC=A1=B4=EC=84=B1?= =?UTF-8?q?=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/domain/round/RoundService.java | 13 ++++++- .../{study => round}/ScheduleService.java | 3 +- .../yigongil/backend/domain/study/Study.java | 37 +++---------------- .../backend/domain/study/StudyController.java | 2 +- .../domain/study/StudyFinishedEvent.java | 2 +- .../backend/domain/study/StudyRepository.java | 7 +--- .../backend/domain/study/StudyService.java | 8 ++-- .../domain/{ => study}/studymember/Role.java | 2 +- .../studymember/RoleConverter.java | 2 +- .../{ => study}/studymember/StudyMember.java | 2 +- .../studymember/StudyMemberRepository.java | 12 +----- .../{ => study}/studymember/StudyResult.java | 2 +- .../studyquery/StudyQueryRepository.java | 2 +- .../studyquery/StudyQueryRepositoryImpl.java | 5 ++- .../backend/query/profile/ProfileService.java | 4 +- .../response/StudyMemberRoleResponse.java | 2 +- .../acceptance/steps/MyStudyFindSteps.java | 2 +- .../backend/application/StudyServiceTest.java | 2 +- .../backend/fixture/StudyFixture.java | 22 +---------- 19 files changed, 40 insertions(+), 91 deletions(-) rename backend/src/main/java/com/yigongil/backend/domain/{study => round}/ScheduleService.java (84%) rename backend/src/main/java/com/yigongil/backend/domain/{ => study}/studymember/Role.java (90%) rename backend/src/main/java/com/yigongil/backend/domain/{ => study}/studymember/RoleConverter.java (80%) rename backend/src/main/java/com/yigongil/backend/domain/{ => study}/studymember/StudyMember.java (98%) rename backend/src/main/java/com/yigongil/backend/domain/{ => study}/studymember/StudyMemberRepository.java (73%) rename backend/src/main/java/com/yigongil/backend/domain/{ => study}/studymember/StudyResult.java (53%) diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java b/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java index b40349e16..2171ef4b8 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java +++ b/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java @@ -7,6 +7,7 @@ import com.yigongil.backend.domain.study.StudyFinishedEvent; import com.yigongil.backend.domain.study.StudyRepository; import com.yigongil.backend.domain.study.StudyStartedEvent; +import com.yigongil.backend.exception.CannotEndException; import com.yigongil.backend.exception.RoundNotFoundException; import com.yigongil.backend.request.MustDoUpdateRequest; import com.yigongil.backend.response.RoundResponse; @@ -54,7 +55,7 @@ public List findCurrentRoundOfStudies(Member member) { study.getName(), currentRound.getMustDo(), leftDays, - calculateExperience(study.getId(), study.getRoundExperience()).get(member), + calculateExperience(study.getId(), study.calculateRoundExperience()).get(member), study.isMaster(member) ) ); @@ -64,7 +65,8 @@ public List findCurrentRoundOfStudies(Member member) { } @TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT) - public void addExperience(StudyFinishedEvent event) { + public void finishRounds(StudyFinishedEvent event) { + validateCanFinish(event); Map memberToExperience = calculateExperience(event.studyId(), event.roundExperience()); for (Member member : memberToExperience.keySet()) { @@ -72,6 +74,13 @@ public void addExperience(StudyFinishedEvent event) { } } + private void validateCanFinish(StudyFinishedEvent event) { + Round currentRound = roundRepository.getByStudyIdAndRoundStatus(event.studyId(), RoundStatus.IN_PROGRESS); + if (currentRound.isBeforeOrSame(event.minimumWeeks())) { + throw new CannotEndException("최소 진행 주차를 채우지 못했습니다.", String.valueOf(event.studyId())); + } + } + @TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT) public void exit(StudyExitedEvent event) { List rounds = roundRepository.findAllByStudyId(event.studyId()); diff --git a/backend/src/main/java/com/yigongil/backend/domain/study/ScheduleService.java b/backend/src/main/java/com/yigongil/backend/domain/round/ScheduleService.java similarity index 84% rename from backend/src/main/java/com/yigongil/backend/domain/study/ScheduleService.java rename to backend/src/main/java/com/yigongil/backend/domain/round/ScheduleService.java index 45ac8db06..280a8628e 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/study/ScheduleService.java +++ b/backend/src/main/java/com/yigongil/backend/domain/round/ScheduleService.java @@ -1,6 +1,5 @@ -package com.yigongil.backend.domain.study; +package com.yigongil.backend.domain.round; -import com.yigongil.backend.domain.round.RoundService; import java.time.LocalDate; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; diff --git a/backend/src/main/java/com/yigongil/backend/domain/study/Study.java b/backend/src/main/java/com/yigongil/backend/domain/study/Study.java index 7f77b7717..61d2a303a 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/study/Study.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/Study.java @@ -2,11 +2,9 @@ import com.yigongil.backend.domain.base.BaseRootEntity; import com.yigongil.backend.domain.member.domain.Member; -import com.yigongil.backend.domain.round.Round; -import com.yigongil.backend.domain.round.RoundOfMember; -import com.yigongil.backend.domain.studymember.Role; -import com.yigongil.backend.domain.studymember.StudyMember; -import com.yigongil.backend.domain.studymember.StudyResult; +import com.yigongil.backend.domain.study.studymember.Role; +import com.yigongil.backend.domain.study.studymember.StudyMember; +import com.yigongil.backend.domain.study.studymember.StudyResult; import com.yigongil.backend.exception.ApplicantAlreadyExistException; import com.yigongil.backend.exception.CannotEndException; import com.yigongil.backend.exception.CannotStartException; @@ -16,12 +14,9 @@ import com.yigongil.backend.exception.InvalidStudyNameLengthException; import com.yigongil.backend.exception.NotStudyMasterException; import com.yigongil.backend.exception.NotStudyMemberException; -import com.yigongil.backend.exception.RoundNotFoundException; import java.time.DayOfWeek; -import java.time.LocalDate; import java.time.LocalDateTime; import java.util.ArrayList; -import java.util.Comparator; import java.util.List; import javax.persistence.CollectionTable; import javax.persistence.Column; @@ -38,8 +33,6 @@ import lombok.Getter; import org.hibernate.annotations.Cascade; import org.hibernate.annotations.CascadeType; -import org.hibernate.annotations.OnDelete; -import org.hibernate.annotations.OnDeleteAction; @Getter @Entity @@ -91,12 +84,6 @@ public class Study extends BaseRootEntity { @OneToMany(mappedBy = "study", orphanRemoval = true, fetch = FetchType.LAZY) private List studyMembers = new ArrayList<>(); -// -// @Cascade(CascadeType.PERSIST) -// @OnDelete(action = OnDeleteAction.CASCADE) -// @OneToMany(mappedBy = "study", orphanRemoval = true, fetch = FetchType.LAZY) -// private List rounds = new ArrayList<>(); - protected Study() { } @@ -111,8 +98,7 @@ public Study( Member master, Integer minimumWeeks, Integer meetingDaysCountPerWeek, - Long currentRoundNumber, - List rounds + Long currentRoundNumber ) { name = name.strip(); validateNumberOfMaximumMembers(numberOfMaximumMembers); @@ -130,7 +116,6 @@ public Study( .member(master) .studyResult(StudyResult.NONE) .build()); -// this.rounds = rounds == null ? new ArrayList<>() : rounds; this.minimumWeeks = minimumWeeks; this.meetingDaysCountPerWeek = meetingDaysCountPerWeek; } @@ -248,12 +233,12 @@ public void validateMaster(Member candidate) { public void finishStudy(Member master) { validateMaster(master); validateStudyCanFinish(); - registerEvent(new StudyFinishedEvent(id, getRoundExperience())); + registerEvent(new StudyFinishedEvent(id, calculateRoundExperience(), minimumWeeks)); studyMembers.forEach(StudyMember::completeSuccessfully); this.processingStatus = ProcessingStatus.END; } - public Integer getRoundExperience() { + public Integer calculateRoundExperience() { int defaultRoundExperience = EXPERIENCE_BASE_UNIT * 2; int additionalExperienceOfPeriodLength = EXPERIENCE_BASE_UNIT * 3 / meetingDaysCountPerWeek + 1; return defaultRoundExperience + additionalExperienceOfPeriodLength; @@ -263,9 +248,6 @@ private void validateStudyCanFinish() { if (isEnd()) { throw new CannotEndException("이미 종료된 스터디입니다.", String.valueOf(id)); } -// if (getCurrentRound().isBeforeOrSame(minimumWeeks)) { -// throw new CannotEndException("최소 진행 주차를 채우지 못했습니다.", String.valueOf(id)); -// } } public Member getMaster() { @@ -291,13 +273,6 @@ public boolean isEnd() { return this.processingStatus == ProcessingStatus.END; } -// public Round getCurrentRound() { -// return rounds.stream() -// .filter(Round::isInProgress) -// .findAny() -// .orElseThrow(() -> new RoundNotFoundException("현재 진행중인 라운드가 없습니다.", -1)); -// } - public boolean isMaster(Member member) { return getMaster().getId().equals(member.getId()); } diff --git a/backend/src/main/java/com/yigongil/backend/domain/study/StudyController.java b/backend/src/main/java/com/yigongil/backend/domain/study/StudyController.java index 7fe22c04b..604ce2db1 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/study/StudyController.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/StudyController.java @@ -2,7 +2,7 @@ import com.yigongil.backend.config.auth.Authorization; import com.yigongil.backend.domain.member.domain.Member; -import com.yigongil.backend.domain.studymember.Role; +import com.yigongil.backend.domain.study.studymember.Role; import com.yigongil.backend.request.StudyStartRequest; import com.yigongil.backend.request.StudyUpdateRequest; import com.yigongil.backend.response.MyStudyResponse; diff --git a/backend/src/main/java/com/yigongil/backend/domain/study/StudyFinishedEvent.java b/backend/src/main/java/com/yigongil/backend/domain/study/StudyFinishedEvent.java index 5c768337c..383795b73 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/study/StudyFinishedEvent.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/StudyFinishedEvent.java @@ -1,5 +1,5 @@ package com.yigongil.backend.domain.study; -public record StudyFinishedEvent(Long studyId, Integer roundExperience) { +public record StudyFinishedEvent(Long studyId, Integer roundExperience, Integer minimumWeeks) { } diff --git a/backend/src/main/java/com/yigongil/backend/domain/study/StudyRepository.java b/backend/src/main/java/com/yigongil/backend/domain/study/StudyRepository.java index 79bb9c7f8..bbcb1a99a 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/study/StudyRepository.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/StudyRepository.java @@ -1,12 +1,11 @@ package com.yigongil.backend.domain.study; import com.yigongil.backend.domain.member.domain.Member; +import com.yigongil.backend.domain.study.studymember.Role; import com.yigongil.backend.domain.study.studyquery.StudyQueryRepository; -import com.yigongil.backend.domain.studymember.Role; import com.yigongil.backend.exception.StudyNotFoundException; import java.util.List; import java.util.Optional; -import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.Repository; @@ -16,16 +15,12 @@ public interface StudyRepository extends Repository, StudyQueryRepo Study save(Study study); - @EntityGraph(attributePaths = {"rounds"}) Optional findById(Long studyId); - List findAllByProcessingStatus(ProcessingStatus processingStatus); - @Query(""" select distinct s from Study s join StudyMember sm on s = sm.study - join fetch s.rounds where sm.member = :member and s.processingStatus = :processingStatus """) diff --git a/backend/src/main/java/com/yigongil/backend/domain/study/StudyService.java b/backend/src/main/java/com/yigongil/backend/domain/study/StudyService.java index d2c6dddf3..1bba147d2 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/study/StudyService.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/StudyService.java @@ -1,10 +1,10 @@ package com.yigongil.backend.domain.study; import com.yigongil.backend.domain.member.domain.Member; -import com.yigongil.backend.domain.studymember.Role; -import com.yigongil.backend.domain.studymember.StudyMember; -import com.yigongil.backend.domain.studymember.StudyMemberRepository; -import com.yigongil.backend.domain.studymember.StudyResult; +import com.yigongil.backend.domain.study.studymember.Role; +import com.yigongil.backend.domain.study.studymember.StudyMember; +import com.yigongil.backend.domain.study.studymember.StudyMemberRepository; +import com.yigongil.backend.domain.study.studymember.StudyResult; import com.yigongil.backend.exception.ApplicantNotFoundException; import com.yigongil.backend.exception.StudyNotFoundException; import com.yigongil.backend.request.StudyStartRequest; diff --git a/backend/src/main/java/com/yigongil/backend/domain/studymember/Role.java b/backend/src/main/java/com/yigongil/backend/domain/study/studymember/Role.java similarity index 90% rename from backend/src/main/java/com/yigongil/backend/domain/studymember/Role.java rename to backend/src/main/java/com/yigongil/backend/domain/study/studymember/Role.java index 33051f4df..b57cc2e1c 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/studymember/Role.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/studymember/Role.java @@ -1,4 +1,4 @@ -package com.yigongil.backend.domain.studymember; +package com.yigongil.backend.domain.study.studymember; import java.util.Arrays; import lombok.Getter; diff --git a/backend/src/main/java/com/yigongil/backend/domain/studymember/RoleConverter.java b/backend/src/main/java/com/yigongil/backend/domain/study/studymember/RoleConverter.java similarity index 80% rename from backend/src/main/java/com/yigongil/backend/domain/studymember/RoleConverter.java rename to backend/src/main/java/com/yigongil/backend/domain/study/studymember/RoleConverter.java index 19f9901ab..d27a1ee40 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/studymember/RoleConverter.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/studymember/RoleConverter.java @@ -1,4 +1,4 @@ -package com.yigongil.backend.domain.studymember; +package com.yigongil.backend.domain.study.studymember; import org.springframework.core.convert.converter.Converter; diff --git a/backend/src/main/java/com/yigongil/backend/domain/studymember/StudyMember.java b/backend/src/main/java/com/yigongil/backend/domain/study/studymember/StudyMember.java similarity index 98% rename from backend/src/main/java/com/yigongil/backend/domain/studymember/StudyMember.java rename to backend/src/main/java/com/yigongil/backend/domain/study/studymember/StudyMember.java index 2e7f89d58..1e3faae93 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/studymember/StudyMember.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/studymember/StudyMember.java @@ -1,4 +1,4 @@ -package com.yigongil.backend.domain.studymember; +package com.yigongil.backend.domain.study.studymember; import com.yigongil.backend.domain.base.BaseEntity; import com.yigongil.backend.domain.member.domain.Member; diff --git a/backend/src/main/java/com/yigongil/backend/domain/studymember/StudyMemberRepository.java b/backend/src/main/java/com/yigongil/backend/domain/study/studymember/StudyMemberRepository.java similarity index 73% rename from backend/src/main/java/com/yigongil/backend/domain/studymember/StudyMemberRepository.java rename to backend/src/main/java/com/yigongil/backend/domain/study/studymember/StudyMemberRepository.java index 89a6bc83c..8a7e9d847 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/studymember/StudyMemberRepository.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/studymember/StudyMemberRepository.java @@ -1,4 +1,4 @@ -package com.yigongil.backend.domain.studymember; +package com.yigongil.backend.domain.study.studymember; import java.util.List; import java.util.Optional; @@ -15,26 +15,16 @@ public interface StudyMemberRepository extends Repository { @EntityGraph(attributePaths = "member") List findAllByStudyIdAndRole(Long studyId, Role role); - @EntityGraph(attributePaths = "member") - List findAllByStudyId(Long studyId); - @EntityGraph(attributePaths = "study") List findAllByMemberId(Long memberId); - @EntityGraph(attributePaths = "member") - List findAllByStudyIdAndRoleNot(Long studyId, Role role); - @EntityGraph(attributePaths = "member") List findAllByStudyIdAndRoleNotAndStudyResult(Long studyId, Role role, StudyResult studyResult); @EntityGraph(attributePaths = "study") List findAllByMemberIdAndRoleNotAndStudyResult(Long memberId, Role role, StudyResult studyResult); - boolean existsByStudyIdAndMemberId(Long studyId, Long memberId); - void delete(StudyMember studyMember); Long countByMemberIdAndStudyResult(Long memberId, StudyResult studyResult); - - void deleteAllByStudyIdAndRole(Long studyId, Role role); } diff --git a/backend/src/main/java/com/yigongil/backend/domain/studymember/StudyResult.java b/backend/src/main/java/com/yigongil/backend/domain/study/studymember/StudyResult.java similarity index 53% rename from backend/src/main/java/com/yigongil/backend/domain/studymember/StudyResult.java rename to backend/src/main/java/com/yigongil/backend/domain/study/studymember/StudyResult.java index db6ae8f3d..13991b243 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/studymember/StudyResult.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/studymember/StudyResult.java @@ -1,4 +1,4 @@ -package com.yigongil.backend.domain.studymember; +package com.yigongil.backend.domain.study.studymember; public enum StudyResult { diff --git a/backend/src/main/java/com/yigongil/backend/domain/study/studyquery/StudyQueryRepository.java b/backend/src/main/java/com/yigongil/backend/domain/study/studyquery/StudyQueryRepository.java index 990c7bcf6..763df1843 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/study/studyquery/StudyQueryRepository.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/studyquery/StudyQueryRepository.java @@ -2,7 +2,7 @@ import com.yigongil.backend.domain.study.ProcessingStatus; import com.yigongil.backend.domain.study.Study; -import com.yigongil.backend.domain.studymember.Role; +import com.yigongil.backend.domain.study.studymember.Role; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; diff --git a/backend/src/main/java/com/yigongil/backend/domain/study/studyquery/StudyQueryRepositoryImpl.java b/backend/src/main/java/com/yigongil/backend/domain/study/studyquery/StudyQueryRepositoryImpl.java index 57e0ffa50..977eef0fb 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/study/studyquery/StudyQueryRepositoryImpl.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/studyquery/StudyQueryRepositoryImpl.java @@ -1,7 +1,8 @@ package com.yigongil.backend.domain.study.studyquery; + import static com.yigongil.backend.domain.study.QStudy.study; -import static com.yigongil.backend.domain.studymember.QStudyMember.studyMember; +import static com.yigongil.backend.domain.study.studymember.QStudyMember.studyMember; import com.querydsl.core.types.OrderSpecifier; import com.querydsl.core.types.Predicate; @@ -10,7 +11,7 @@ import com.querydsl.jpa.impl.JPAQueryFactory; import com.yigongil.backend.domain.study.ProcessingStatus; import com.yigongil.backend.domain.study.Study; -import com.yigongil.backend.domain.studymember.Role; +import com.yigongil.backend.domain.study.studymember.Role; import java.util.ArrayList; import java.util.List; import org.springframework.data.domain.Pageable; diff --git a/backend/src/main/java/com/yigongil/backend/query/profile/ProfileService.java b/backend/src/main/java/com/yigongil/backend/query/profile/ProfileService.java index c3c532053..8e941e023 100644 --- a/backend/src/main/java/com/yigongil/backend/query/profile/ProfileService.java +++ b/backend/src/main/java/com/yigongil/backend/query/profile/ProfileService.java @@ -5,8 +5,8 @@ import com.yigongil.backend.domain.round.RoundRepository; import com.yigongil.backend.domain.study.Study; import com.yigongil.backend.domain.study.StudyService; -import com.yigongil.backend.domain.studymember.StudyMember; -import com.yigongil.backend.domain.studymember.StudyMemberRepository; +import com.yigongil.backend.domain.study.studymember.StudyMember; +import com.yigongil.backend.domain.study.studymember.StudyMemberRepository; import com.yigongil.backend.response.FinishedStudyResponse; import com.yigongil.backend.response.ProfileResponse; import java.util.List; diff --git a/backend/src/main/java/com/yigongil/backend/response/StudyMemberRoleResponse.java b/backend/src/main/java/com/yigongil/backend/response/StudyMemberRoleResponse.java index fa2458dbc..28c63053b 100644 --- a/backend/src/main/java/com/yigongil/backend/response/StudyMemberRoleResponse.java +++ b/backend/src/main/java/com/yigongil/backend/response/StudyMemberRoleResponse.java @@ -1,6 +1,6 @@ package com.yigongil.backend.response; -import com.yigongil.backend.domain.studymember.Role; +import com.yigongil.backend.domain.study.studymember.Role; import io.swagger.v3.oas.annotations.media.Schema; public record StudyMemberRoleResponse( diff --git a/backend/src/test/java/com/yigongil/backend/acceptance/steps/MyStudyFindSteps.java b/backend/src/test/java/com/yigongil/backend/acceptance/steps/MyStudyFindSteps.java index c828d3de0..6455d09e4 100644 --- a/backend/src/test/java/com/yigongil/backend/acceptance/steps/MyStudyFindSteps.java +++ b/backend/src/test/java/com/yigongil/backend/acceptance/steps/MyStudyFindSteps.java @@ -4,7 +4,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; -import com.yigongil.backend.domain.studymember.Role; +import com.yigongil.backend.domain.study.studymember.Role; import com.yigongil.backend.response.MyStudyResponse; import io.cucumber.java.en.Then; import io.cucumber.java.en.When; diff --git a/backend/src/test/java/com/yigongil/backend/application/StudyServiceTest.java b/backend/src/test/java/com/yigongil/backend/application/StudyServiceTest.java index 8f09100b1..4d4c34b89 100644 --- a/backend/src/test/java/com/yigongil/backend/application/StudyServiceTest.java +++ b/backend/src/test/java/com/yigongil/backend/application/StudyServiceTest.java @@ -7,7 +7,7 @@ import com.yigongil.backend.domain.member.domain.Member; import com.yigongil.backend.domain.study.StudyRepository; import com.yigongil.backend.domain.study.StudyService; -import com.yigongil.backend.domain.studymember.StudyMemberRepository; +import com.yigongil.backend.domain.study.studymember.StudyMemberRepository; import com.yigongil.backend.exception.StudyNotFoundException; import com.yigongil.backend.fixture.MemberFixture; import java.util.Optional; diff --git a/backend/src/test/java/com/yigongil/backend/fixture/StudyFixture.java b/backend/src/test/java/com/yigongil/backend/fixture/StudyFixture.java index 97a7015c4..3f70cfd73 100644 --- a/backend/src/test/java/com/yigongil/backend/fixture/StudyFixture.java +++ b/backend/src/test/java/com/yigongil/backend/fixture/StudyFixture.java @@ -1,19 +1,14 @@ package com.yigongil.backend.fixture; import com.yigongil.backend.domain.member.domain.Member; -import com.yigongil.backend.domain.round.Round; import com.yigongil.backend.domain.study.ProcessingStatus; import com.yigongil.backend.domain.study.Study; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; public enum StudyFixture { 자바_스터디_모집중(null, LocalDateTime.now(), "자바", "스터디소개", ProcessingStatus.RECRUITING, 4, 2, 4), - 자바_스터디_모집중_정원_2(null, LocalDateTime.now(), "자바", "스터디소개", ProcessingStatus.RECRUITING, 2, 2, 4) - ; + 자바_스터디_모집중_정원_2(null, LocalDateTime.now(), "자바", "스터디소개", ProcessingStatus.RECRUITING, 2, 2, 4); private final Long id; private final String name; @@ -59,19 +54,4 @@ public Study toStudyWithMaster(Member master) { .minimumWeeks(minimumWeeks) .build(); } - - public Study toStudyWithRounds(RoundFixture... roundFixtures) { - List rounds = new ArrayList<>(Arrays.stream(roundFixtures) - .map(RoundFixture::toRound) - .toList()); - - return Study.builder() - .id(id) - .name(name) - .introduction(introduction) - .processingStatus(processingStatus) - .numberOfMaximumMembers(numberOfMaximumMember) - .rounds(rounds) - .build(); - } } From 8e9491ad52535ead96fe48214f57a4b7f487cee6 Mon Sep 17 00:00:00 2001 From: kim dae hee Date: Tue, 21 Nov 2023 19:33:50 +0900 Subject: [PATCH 14/22] =?UTF-8?q?refactor:=20AuthService=20=ED=8C=A8?= =?UTF-8?q?=ED=82=A4=EC=A7=80=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/{application => config/auth}/AuthService.java | 3 +-- .../src/main/java/com/yigongil/backend/ui/LoginController.java | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) rename backend/src/main/java/com/yigongil/backend/{application => config/auth}/AuthService.java (95%) diff --git a/backend/src/main/java/com/yigongil/backend/application/AuthService.java b/backend/src/main/java/com/yigongil/backend/config/auth/AuthService.java similarity index 95% rename from backend/src/main/java/com/yigongil/backend/application/AuthService.java rename to backend/src/main/java/com/yigongil/backend/config/auth/AuthService.java index d94d86bdd..c05678682 100644 --- a/backend/src/main/java/com/yigongil/backend/application/AuthService.java +++ b/backend/src/main/java/com/yigongil/backend/config/auth/AuthService.java @@ -1,6 +1,5 @@ -package com.yigongil.backend.application; +package com.yigongil.backend.config.auth; -import com.yigongil.backend.config.auth.JwtTokenProvider; import com.yigongil.backend.config.oauth.GithubOauth; import com.yigongil.backend.config.oauth.GithubProfileResponse; import com.yigongil.backend.domain.member.domain.Member; diff --git a/backend/src/main/java/com/yigongil/backend/ui/LoginController.java b/backend/src/main/java/com/yigongil/backend/ui/LoginController.java index 9124a077c..b569b311c 100644 --- a/backend/src/main/java/com/yigongil/backend/ui/LoginController.java +++ b/backend/src/main/java/com/yigongil/backend/ui/LoginController.java @@ -1,6 +1,6 @@ package com.yigongil.backend.ui; -import com.yigongil.backend.application.AuthService; +import com.yigongil.backend.config.auth.AuthService; import com.yigongil.backend.request.TokenRequest; import com.yigongil.backend.response.TokenResponse; import com.yigongil.backend.ui.doc.LoginApi; From 7429261c22205407577c98cbe634f504f3751de6 Mon Sep 17 00:00:00 2001 From: kim dae hee Date: Mon, 13 Nov 2023 19:10:53 +0900 Subject: [PATCH 15/22] =?UTF-8?q?test:=20=EC=84=B1=EB=8A=A5=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/main/resources/yigongil-private | 2 +- .../backend/acceptance/steps/ApplySteps.java | 39 +++++++++++++ .../acceptance/steps/StudyProgressStep.java | 4 +- .../backend/acceptance/steps/StudySteps.java | 55 +++++++++++++++++++ .../resources/features/proceed_test.feature | 13 +++++ 5 files changed, 110 insertions(+), 3 deletions(-) create mode 100644 backend/src/test/resources/features/proceed_test.feature diff --git a/backend/src/main/resources/yigongil-private b/backend/src/main/resources/yigongil-private index 18f1ca643..d04a1280d 160000 --- a/backend/src/main/resources/yigongil-private +++ b/backend/src/main/resources/yigongil-private @@ -1 +1 @@ -Subproject commit 18f1ca643188ea10e5a6532c47ca9306c25be390 +Subproject commit d04a1280d4b2222beea8989c1694191e371ffce4 diff --git a/backend/src/test/java/com/yigongil/backend/acceptance/steps/ApplySteps.java b/backend/src/test/java/com/yigongil/backend/acceptance/steps/ApplySteps.java index 494afa606..5cccfed51 100644 --- a/backend/src/test/java/com/yigongil/backend/acceptance/steps/ApplySteps.java +++ b/backend/src/test/java/com/yigongil/backend/acceptance/steps/ApplySteps.java @@ -37,6 +37,25 @@ public ApplySteps(SharedContext sharedContext) { sharedContext.setResponse(response); } + @Given("깃허브 아이디가 {string}인 멤버가 이름이 {string}스터디 {int}개에 신청한다.") + public void 스터디_신청(String githubId, String studyName, Integer count) { + String token = sharedContext.getToken(githubId); + for (int i = 0; i < count; i++) { + String realName = studyName + i; + ExtractableResponse response = given().log() + .all() + .header(HttpHeaders.AUTHORIZATION, token) + .when() + .post("/studies/" + sharedContext.getParameter(realName) + "/applicants") + .then() + .log() + .all() + .extract(); + + sharedContext.setResponse(response); + } + } + @When("{string}가 이름이 {string}인 스터디의 신청자를 조회한다.") public void 스터디_신청자_조회(String masterGithubId, String studyName) { ExtractableResponse response = @@ -80,6 +99,26 @@ public ApplySteps(SharedContext sharedContext) { sharedContext.setResponse(response); } + @When("{string}가 {string}의 {string} 스터디 {int}개 신청을 수락한다.") + public void 스터디_신청_수락(String masterName, String memberName, String studyName, Integer count) { + for (int i = 0; i < count; i++) { + String realName = studyName + i; + Object studyId = sharedContext.getParameter(realName); + Object memberId = sharedContext.getParameter(memberName); + + ExtractableResponse response = + given().log().all() + .header(HttpHeaders.AUTHORIZATION, sharedContext.getToken(masterName)) + .when() + .patch("/studies/{studyId}/applicants/{memberId}", studyId, memberId) + .then() + .log().all() + .extract(); + + sharedContext.setResponse(response); + } + } + @Then("{string}는 {string} 스터디의 스터디원으로 추가되어 있다.") public void 스터디원_추가_완료(String memberName, String studyName) { Long memberId = sharedContext.getId(memberName); diff --git a/backend/src/test/java/com/yigongil/backend/acceptance/steps/StudyProgressStep.java b/backend/src/test/java/com/yigongil/backend/acceptance/steps/StudyProgressStep.java index ebee4956d..ed5f3ab62 100644 --- a/backend/src/test/java/com/yigongil/backend/acceptance/steps/StudyProgressStep.java +++ b/backend/src/test/java/com/yigongil/backend/acceptance/steps/StudyProgressStep.java @@ -29,7 +29,7 @@ public StudyProgressStep(SharedContext sharedContext) { @Given("{int}일이 지난다.") public void 시간_소요(int days) { - given().when() + given().log().all().when() .put("/fake/proceed?days=" + days) .then() .log() @@ -43,7 +43,7 @@ public StudyProgressStep(SharedContext sharedContext) { LocalDate sunday = today.with(DayOfWeek.SUNDAY); long daysUntilSunday = ChronoUnit.DAYS.between(today, sunday); - given().when() + given().log().all().when() .put("/fake/proceed?days=" + daysUntilSunday) .then() .log() diff --git a/backend/src/test/java/com/yigongil/backend/acceptance/steps/StudySteps.java b/backend/src/test/java/com/yigongil/backend/acceptance/steps/StudySteps.java index 7a234ffcf..a1f3e7a5e 100644 --- a/backend/src/test/java/com/yigongil/backend/acceptance/steps/StudySteps.java +++ b/backend/src/test/java/com/yigongil/backend/acceptance/steps/StudySteps.java @@ -75,6 +75,43 @@ public StudySteps(ObjectMapper objectMapper, SharedContext sharedContext) { sharedContext.setParameter(name, studyId); } + @Given("{string}가 제목-{string}, 정원-{string}명, 최소 주차-{string}주, 주당 진행 횟수-{string}회, 소개-{string}로 스터디를 {int}개 개설한다.") + public void 스터디를_개설한다( + String masterGithubId, + String name, + String numberOfMaximumMembers, + String minimumWeeks, + String meetingDaysCountPerWeek, + String introduction, + Integer count + ) throws JsonProcessingException { + for (int i = 0; i < count; i++) { + String realName = name + i; + StudyUpdateRequest request = new StudyUpdateRequest( + realName, + Integer.parseInt(numberOfMaximumMembers), + Integer.parseInt(minimumWeeks), + Integer.parseInt(meetingDaysCountPerWeek), + introduction + ); + String token = sharedContext.getToken(masterGithubId); + + String location = given().log().all() + .header(HttpHeaders.AUTHORIZATION, token) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .body(objectMapper.writeValueAsString(request)) + .when() + .post("/studies") + .then().log().all() + .extract() + .header(HttpHeaders.LOCATION); + + String studyId = location.substring(location.lastIndexOf("/") + 1); + + sharedContext.setParameter(realName, studyId); + } + } + @When("모집 중인 스터디 탭을 클릭한다.") public void 모집_중인_스터디를_요청한다() { ExtractableResponse response = given().log().all() @@ -225,6 +262,24 @@ public StudySteps(ObjectMapper objectMapper, SharedContext sharedContext) { .then().log().all(); } + @Given("{string}가 이름이 {string}인 스터디 {int}개를 {string}에 진행되도록 하여 시작한다.") + public void 스터디_시작(String memberGithubId, String studyName, Integer count, String days) { + String token = sharedContext.getToken(memberGithubId); + for (int i = 0; i < count; i++) { + String realName = studyName + i; + String studyId = (String) sharedContext.getParameter(realName); + StudyStartRequest request = new StudyStartRequest(Arrays.stream(days.split(",")).map(String::strip).toList()); + + given().log().all() + .header(HttpHeaders.AUTHORIZATION, token) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .body(request) + .when() + .patch("/studies/" + studyId + "/start") + .then().log().all(); + } + } + @Given("{string}가 이름이 {string}인 스터디를 내일에 해당하는 요일에 진행되도록 하여 시작한다.") public void 스터디_시작_내일에_해당하는_요일(String memberGithubId, String studyName) { String token = sharedContext.getToken(memberGithubId); diff --git a/backend/src/test/resources/features/proceed_test.feature b/backend/src/test/resources/features/proceed_test.feature new file mode 100644 index 000000000..572639841 --- /dev/null +++ b/backend/src/test/resources/features/proceed_test.feature @@ -0,0 +1,13 @@ +Feature: 스터디를 진행 성능 테스트 + Scenario Outline: 스터디 진행 성능 테스트 + Given "jinwoo"의 깃허브 아이디로 회원가입을 한다. + Given "jinwoo"가 제목-"자바숫자", 정원-"6"명, 최소 주차-"7"주, 주당 진행 횟수-"3"회, 소개-"스터디소개1"로 스터디를 개 개설한다. + Given "noiman"의 깃허브 아이디로 회원가입을 한다. + Given 깃허브 아이디가 "noiman"인 멤버가 이름이 "자바숫자"스터디 개에 신청한다. + Given "jinwoo"가 "noiman"의 "자바숫자" 스터디 개 신청을 수락한다. + Given "jinwoo"가 이름이 "자바숫자"인 스터디 개를 "MONDAY"에 진행되도록 하여 시작한다. + Given 1일이 지난다. + + Examples: + | count | + | 1000 | From 3846e149eca13d30c180b8717a01e1e3271cf10b Mon Sep 17 00:00:00 2001 From: kim dae hee Date: Thu, 16 Nov 2023 15:57:58 +0900 Subject: [PATCH 16/22] =?UTF-8?q?=EC=84=B1=EB=8A=A5=20=EC=B8=A1=EC=A0=95?= =?UTF-8?q?=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/test/resources/features/proceed_test.feature | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/test/resources/features/proceed_test.feature b/backend/src/test/resources/features/proceed_test.feature index 572639841..4c2690835 100644 --- a/backend/src/test/resources/features/proceed_test.feature +++ b/backend/src/test/resources/features/proceed_test.feature @@ -10,4 +10,4 @@ Feature: 스터디를 진행 성능 테스트 Examples: | count | - | 1000 | + | 10 | From d5a245a68409f97e0d5b77207385216965233900 Mon Sep 17 00:00:00 2001 From: kim dae hee Date: Tue, 21 Nov 2023 22:48:05 +0900 Subject: [PATCH 17/22] =?UTF-8?q?refactor:=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 --- .../yigongil/backend/domain/round/Round.java | 29 +++++++--- .../backend/domain/round/RoundService.java | 55 +++++++++++++++---- .../yigongil/backend/fake/FakeController.java | 2 +- .../resources/features/proceed_test.feature | 6 +- 4 files changed, 69 insertions(+), 23 deletions(-) diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/Round.java b/backend/src/main/java/com/yigongil/backend/domain/round/Round.java index 09ddb46df..07d8c8422 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/round/Round.java +++ b/backend/src/main/java/com/yigongil/backend/domain/round/Round.java @@ -44,9 +44,8 @@ public class Round extends BaseEntity { @Id private Long id; - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "study_id", nullable = false) - private Study study; + @Column(name = "study_id") + private Long studyId; @Column(length = MAX_TODO_CONTENT_LENGTH) private String mustDo; @@ -58,7 +57,7 @@ public class Round extends BaseEntity { @Cascade(CascadeType.PERSIST) @OnDelete(action = OnDeleteAction.CASCADE) @OneToMany - @JoinColumn(name = "round_id", nullable = false) + @JoinColumn(name = "round_id", nullable = false, updatable = false) private List roundOfMembers = new ArrayList<>(); @Enumerated(EnumType.ORDINAL) @@ -76,7 +75,7 @@ protected Round() { @Builder public Round( Long id, - Study study, + Long studyId, String mustDo, Member master, List roundOfMembers, @@ -84,7 +83,7 @@ public Round( Integer weekNumber ) { this.id = id; - this.study = study; + this.studyId = studyId; this.mustDo = mustDo; this.master = master; this.roundOfMembers = roundOfMembers == null ? new ArrayList<>() : roundOfMembers; @@ -94,7 +93,7 @@ public Round( public static Round of(DayOfWeek dayOfWeek, Study study, Integer weekNumber) { return Round.builder() - .study(study) + .studyId(study.getId()) .dayOfWeek(dayOfWeek) .weekNumber(weekNumber) .master(study.getMaster()) @@ -221,7 +220,21 @@ public void exit(Long memberId) { } public Round createNextWeekRound() { - return of(dayOfWeek, study, weekNumber + 1); + List list = roundOfMembers.stream() + .map( + roundOfMember -> RoundOfMember.builder() + .member( + roundOfMember.getMember()) + .isDone(false) + .build()) + .toList(); + return Round.builder() + .studyId(studyId) + .dayOfWeek(dayOfWeek) + .weekNumber(weekNumber + 1) + .master(master) + .roundOfMembers(list) + .build(); } @Override diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java b/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java index 2171ef4b8..99c8d683b 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java +++ b/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java @@ -12,6 +12,11 @@ import com.yigongil.backend.request.MustDoUpdateRequest; import com.yigongil.backend.response.RoundResponse; import com.yigongil.backend.response.UpcomingStudyResponse; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; import java.time.DayOfWeek; import java.time.LocalDate; import java.util.ArrayList; @@ -19,6 +24,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import javax.persistence.EntityManager; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.event.TransactionPhase; @@ -29,14 +35,17 @@ public class RoundService { private final RoundRepository roundRepository; private final StudyRepository studyRepository; + private final EntityManager entityManager; public RoundService( RoundRepository roundRepository, - StudyRepository studyRepository + StudyRepository studyRepository, + EntityManager entityManager ) { this.roundRepository = roundRepository; this.studyRepository = studyRepository; + this.entityManager = entityManager; } @Transactional(readOnly = true) @@ -122,6 +131,11 @@ public List findRoundDetailsOfWeek(Long id, Integer weekNumber) { @Transactional public void proceedRound(LocalDate today) { + entityManager.flush(); + entityManager.clear(); + System.out.println("StudyService.proceedRound"); + long from = System.currentTimeMillis(); + // List rounds = roundRepository.findByRoundStatusAndDayOfWeek( RoundStatus.IN_PROGRESS, today.minusDays(1).getDayOfWeek() @@ -130,30 +144,49 @@ public void proceedRound(LocalDate today) { for (Round round : rounds) { Integer currentWeek = round.getWeekNumber(); List upcomingCandidates = roundRepository.findAllByStudyIdAndWeekNumberIn( - round.getStudy().getId(), + round.getStudyId(), List.of(currentWeek, currentWeek + 1) ); Round upcomingRound = upcomingCandidates.stream() - .filter(candidate -> candidate.isSameWeek(currentWeek) && candidate.isNotStarted()) - .min(Comparator.comparing(Round::getDayOfWeek)) - .orElseGet(() -> upcomingCandidates.stream() - .filter(candidate -> candidate.isSameWeek(currentWeek + 1)) - .min(Comparator.comparing(Round::getDayOfWeek)) - .orElseThrow(() -> new IllegalStateException("다음 주 라운드를 안 만들어놓음"))); + .filter(candidate -> candidate.isSameWeek(currentWeek) && candidate.isNotStarted()) + .min(Comparator.comparing(Round::getDayOfWeek)) + .orElseGet(() -> upcomingCandidates.stream() + .filter(candidate -> candidate.isSameWeek(currentWeek + 1)) + .min(Comparator.comparing(Round::getDayOfWeek)) + .orElseThrow(() -> new IllegalStateException("다음 주 라운드를 안 만들어놓음"))); round.finish(); upcomingRound.proceed(); if (!upcomingRound.isSameWeek(currentWeek)) { List nextWeekRounds = upcomingCandidates.stream() - .filter(candidate -> candidate.isSameWeek(currentWeek + 1)) - .map(Round::createNextWeekRound) - .toList(); + .filter(candidate -> candidate.isSameWeek(currentWeek + 1)) + .map(Round::createNextWeekRound) + .toList(); roundRepository.saveAll(nextWeekRounds); } } + // + Runtime runtime = Runtime.getRuntime(); + long totalMemory = runtime.totalMemory(); + long freeMemory = runtime.freeMemory(); + long usedMemory = (totalMemory - freeMemory) / 1000000; + + long to = System.currentTimeMillis(); + Path path = Paths.get("time_test.txt"); + try { + if (Files.exists(path)) { + Files.write(path, ("time spent to proceed Round \nstudy size: " + rounds.size() + "\ntotal time spent: " + (to - from) + "\nThe JVM is using " + usedMemory + " MB of memory." + "\n\n").getBytes(), StandardOpenOption.APPEND); + } else { + Files.createFile(path); + Files.write(path, ("time spent to proceed Round \nstudy size: " + rounds.size() + "\ntotal time spent: " + (to - from) + "\n\n").getBytes()); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } @TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT) diff --git a/backend/src/test/java/com/yigongil/backend/fake/FakeController.java b/backend/src/test/java/com/yigongil/backend/fake/FakeController.java index 2e95ec9d3..315952191 100644 --- a/backend/src/test/java/com/yigongil/backend/fake/FakeController.java +++ b/backend/src/test/java/com/yigongil/backend/fake/FakeController.java @@ -51,7 +51,7 @@ public ResponseEntity createFakeToken(@RequestParam String github @PutMapping("/fake/proceed") public ResponseEntity proceed(@RequestParam Integer days) { - for (int i = 1; i <= days; i++) { + for (int i = 2; i <= days; i++) { roundService.proceedRound(LocalDate.now().plusDays(i)); } return ResponseEntity.ok().build(); diff --git a/backend/src/test/resources/features/proceed_test.feature b/backend/src/test/resources/features/proceed_test.feature index 4c2690835..e0391e517 100644 --- a/backend/src/test/resources/features/proceed_test.feature +++ b/backend/src/test/resources/features/proceed_test.feature @@ -5,9 +5,9 @@ Feature: 스터디를 진행 성능 테스트 Given "noiman"의 깃허브 아이디로 회원가입을 한다. Given 깃허브 아이디가 "noiman"인 멤버가 이름이 "자바숫자"스터디 개에 신청한다. Given "jinwoo"가 "noiman"의 "자바숫자" 스터디 개 신청을 수락한다. - Given "jinwoo"가 이름이 "자바숫자"인 스터디 개를 "MONDAY"에 진행되도록 하여 시작한다. - Given 1일이 지난다. + Given "jinwoo"가 이름이 "자바숫자"인 스터디 개를 "WEDNESDAY"에 진행되도록 하여 시작한다. + Given 2일이 지난다. Examples: | count | - | 10 | + | 100 | From ccb5fdbdb9337df2c22416bab61b7b94a667f901 Mon Sep 17 00:00:00 2001 From: kim dae hee Date: Wed, 22 Nov 2023 00:41:31 +0900 Subject: [PATCH 18/22] =?UTF-8?q?refactor:=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 --- .../backend/domain/round/RoundService.java | 1 + .../acceptance/steps/StudyProgressStep.java | 14 +++++---- .../yigongil/backend/fake/FakeController.java | 4 +-- .../resources/features/proceed_test.feature | 30 +++++++++++++++---- 4 files changed, 34 insertions(+), 15 deletions(-) diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java b/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java index 99c8d683b..df3b77744 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java +++ b/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java @@ -169,6 +169,7 @@ public void proceedRound(LocalDate today) { } } // + entityManager.flush(); Runtime runtime = Runtime.getRuntime(); long totalMemory = runtime.totalMemory(); long freeMemory = runtime.freeMemory(); diff --git a/backend/src/test/java/com/yigongil/backend/acceptance/steps/StudyProgressStep.java b/backend/src/test/java/com/yigongil/backend/acceptance/steps/StudyProgressStep.java index ed5f3ab62..6a693c84b 100644 --- a/backend/src/test/java/com/yigongil/backend/acceptance/steps/StudyProgressStep.java +++ b/backend/src/test/java/com/yigongil/backend/acceptance/steps/StudyProgressStep.java @@ -29,12 +29,14 @@ public StudyProgressStep(SharedContext sharedContext) { @Given("{int}일이 지난다.") public void 시간_소요(int days) { - given().log().all().when() - .put("/fake/proceed?days=" + days) - .then() - .log() - .all() - .extract(); + for (int i = 1; i <= days; i++) { + given().log().all().when() + .put("/fake/proceed?days=" + i) + .then() + .log() + .all() + .extract(); + } } @Given("이번주 일요일이 됐다.") diff --git a/backend/src/test/java/com/yigongil/backend/fake/FakeController.java b/backend/src/test/java/com/yigongil/backend/fake/FakeController.java index 315952191..5a7af691b 100644 --- a/backend/src/test/java/com/yigongil/backend/fake/FakeController.java +++ b/backend/src/test/java/com/yigongil/backend/fake/FakeController.java @@ -51,9 +51,7 @@ public ResponseEntity createFakeToken(@RequestParam String github @PutMapping("/fake/proceed") public ResponseEntity proceed(@RequestParam Integer days) { - for (int i = 2; i <= days; i++) { - roundService.proceedRound(LocalDate.now().plusDays(i)); - } + roundService.proceedRound(LocalDate.now().plusDays(days)); return ResponseEntity.ok().build(); } } diff --git a/backend/src/test/resources/features/proceed_test.feature b/backend/src/test/resources/features/proceed_test.feature index e0391e517..6249365f0 100644 --- a/backend/src/test/resources/features/proceed_test.feature +++ b/backend/src/test/resources/features/proceed_test.feature @@ -1,12 +1,30 @@ Feature: 스터디를 진행 성능 테스트 Scenario Outline: 스터디 진행 성능 테스트 Given "jinwoo"의 깃허브 아이디로 회원가입을 한다. - Given "jinwoo"가 제목-"자바숫자", 정원-"6"명, 최소 주차-"7"주, 주당 진행 횟수-"3"회, 소개-"스터디소개1"로 스터디를 개 개설한다. - Given "noiman"의 깃허브 아이디로 회원가입을 한다. - Given 깃허브 아이디가 "noiman"인 멤버가 이름이 "자바숫자"스터디 개에 신청한다. - Given "jinwoo"가 "noiman"의 "자바숫자" 스터디 개 신청을 수락한다. - Given "jinwoo"가 이름이 "자바숫자"인 스터디 개를 "WEDNESDAY"에 진행되도록 하여 시작한다. - Given 2일이 지난다. + Given "jinwoo"가 제목-"자바숫자", 정원-"8"명, 최소 주차-"7"주, 주당 진행 횟수-"3"회, 소개-"스터디소개1"로 스터디를 개 개설한다. + Given "noiman1"의 깃허브 아이디로 회원가입을 한다. + Given 깃허브 아이디가 "noiman1"인 멤버가 이름이 "자바숫자"스터디 개에 신청한다. + Given "jinwoo"가 "noiman1"의 "자바숫자" 스터디 개 신청을 수락한다. + Given "noiman2"의 깃허브 아이디로 회원가입을 한다. + Given 깃허브 아이디가 "noiman2"인 멤버가 이름이 "자바숫자"스터디 개에 신청한다. + Given "jinwoo"가 "noiman2"의 "자바숫자" 스터디 개 신청을 수락한다. + Given "noiman3"의 깃허브 아이디로 회원가입을 한다. + Given 깃허브 아이디가 "noiman3"인 멤버가 이름이 "자바숫자"스터디 개에 신청한다. + Given "jinwoo"가 "noiman3"의 "자바숫자" 스터디 개 신청을 수락한다. + Given "noiman4"의 깃허브 아이디로 회원가입을 한다. + Given 깃허브 아이디가 "noiman4"인 멤버가 이름이 "자바숫자"스터디 개에 신청한다. + Given "jinwoo"가 "noiman4"의 "자바숫자" 스터디 개 신청을 수락한다. + Given "noiman5"의 깃허브 아이디로 회원가입을 한다. + Given 깃허브 아이디가 "noiman5"인 멤버가 이름이 "자바숫자"스터디 개에 신청한다. + Given "jinwoo"가 "noiman5"의 "자바숫자" 스터디 개 신청을 수락한다. + Given "noiman6"의 깃허브 아이디로 회원가입을 한다. + Given 깃허브 아이디가 "noiman6"인 멤버가 이름이 "자바숫자"스터디 개에 신청한다. + Given "jinwoo"가 "noiman6"의 "자바숫자" 스터디 개 신청을 수락한다. + Given "noiman7"의 깃허브 아이디로 회원가입을 한다. + Given 깃허브 아이디가 "noiman7"인 멤버가 이름이 "자바숫자"스터디 개에 신청한다. + Given "jinwoo"가 "noiman7"의 "자바숫자" 스터디 개 신청을 수락한다. + Given "jinwoo"가 이름이 "자바숫자"인 스터디 개를 "MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY,SUNDAY"에 진행되도록 하여 시작한다. + Given 5일이 지난다. Examples: | count | From 2f3c07b4ffa8d6ac71fee3f1ec7ef63beb198558 Mon Sep 17 00:00:00 2001 From: kim dae hee Date: Wed, 22 Nov 2023 13:30:39 +0900 Subject: [PATCH 19/22] =?UTF-8?q?refactor:=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 --- .../com/yigongil/backend/domain/round/RoundService.java | 5 +++++ backend/src/test/resources/application.yml | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java b/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java index df3b77744..305248da5 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java +++ b/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java @@ -140,6 +140,11 @@ public void proceedRound(LocalDate today) { RoundStatus.IN_PROGRESS, today.minusDays(1).getDayOfWeek() ); +// roundRepository.findCurrentRoundAndUpcomingRound(); +// List rounds = roundRepository.findByRoundStatusAndDayOfWeek( +// RoundStatus.IN_PROGRESS, +// today.minusDays(1).getDayOfWeek() +// ); for (Round round : rounds) { Integer currentWeek = round.getWeekNumber(); diff --git a/backend/src/test/resources/application.yml b/backend/src/test/resources/application.yml index 40fae4f4b..89e0f7b19 100644 --- a/backend/src/test/resources/application.yml +++ b/backend/src/test/resources/application.yml @@ -17,8 +17,14 @@ spring: hibernate: format_sql: true show_sql: true + jdbc: + batch_size: 500 + order_inserts: true + order_updates: true + batch_versioned_data: true hibernate: ddl-auto: update + database-platform: org.hibernate.dialect.MySQL5InnoDBDialect flyway: enabled: false From e64a09c85b27c27ed0e5a66abd7b0d380fdfe600 Mon Sep 17 00:00:00 2001 From: kim dae hee Date: Wed, 22 Nov 2023 16:38:41 +0900 Subject: [PATCH 20/22] =?UTF-8?q?refactor:=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 --- .../yigongil/backend/domain/round/Round.java | 1 - .../round/RoundOfMemberBatchRepository.java | 8 +++ .../RoundOfMemberJdbcBatchRepository.java | 49 +++++++++++++++++++ .../backend/domain/round/RoundRepository.java | 1 + .../backend/domain/round/RoundService.java | 37 +++++++++----- .../PreparedStatementProxyHandler.java | 2 +- 6 files changed, 84 insertions(+), 14 deletions(-) create mode 100644 backend/src/main/java/com/yigongil/backend/domain/round/RoundOfMemberBatchRepository.java create mode 100644 backend/src/main/java/com/yigongil/backend/domain/round/RoundOfMemberJdbcBatchRepository.java diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/Round.java b/backend/src/main/java/com/yigongil/backend/domain/round/Round.java index 07d8c8422..715be156a 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/round/Round.java +++ b/backend/src/main/java/com/yigongil/backend/domain/round/Round.java @@ -54,7 +54,6 @@ public class Round extends BaseEntity { @JoinColumn(name = "master_id", nullable = false) private Member master; - @Cascade(CascadeType.PERSIST) @OnDelete(action = OnDeleteAction.CASCADE) @OneToMany @JoinColumn(name = "round_id", nullable = false, updatable = false) diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/RoundOfMemberBatchRepository.java b/backend/src/main/java/com/yigongil/backend/domain/round/RoundOfMemberBatchRepository.java new file mode 100644 index 000000000..c0f6b5d5c --- /dev/null +++ b/backend/src/main/java/com/yigongil/backend/domain/round/RoundOfMemberBatchRepository.java @@ -0,0 +1,8 @@ +package com.yigongil.backend.domain.round; + +import java.util.List; +import java.util.Map; + +public interface RoundOfMemberBatchRepository { + void batchSaveAll(Map> roundOfMembers); +} diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/RoundOfMemberJdbcBatchRepository.java b/backend/src/main/java/com/yigongil/backend/domain/round/RoundOfMemberJdbcBatchRepository.java new file mode 100644 index 000000000..2fefbd11b --- /dev/null +++ b/backend/src/main/java/com/yigongil/backend/domain/round/RoundOfMemberJdbcBatchRepository.java @@ -0,0 +1,49 @@ +package com.yigongil.backend.domain.round; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.jdbc.core.namedparam.SqlParameterSource; +import org.springframework.stereotype.Repository; + +@Repository +public class RoundOfMemberJdbcBatchRepository implements RoundOfMemberBatchRepository { + + private final NamedParameterJdbcTemplate namedParameterJdbcTemplate; + + public RoundOfMemberJdbcBatchRepository(NamedParameterJdbcTemplate namedParameterJdbcTemplate) { + this.namedParameterJdbcTemplate = namedParameterJdbcTemplate; + } + + @Override + public void batchSaveAll(Map> roundOfMembersMap) { + String sql = """ + INSERT INTO round_of_member (round_id, member_id, is_done, created_at /* other columns */) + VALUES (:roundId, :memberId, :isDone, :createdAt /* other values */) + """; + + List parameters = new ArrayList<>(); + for (Map.Entry> entry : roundOfMembersMap.entrySet()) { + Long roundId = entry.getKey(); + for (RoundOfMember roundOfMember : entry.getValue()) { + SqlParameterSource param = new MapSqlParameterSource() + .addValue("roundId", roundId) + .addValue("memberId", roundOfMember.getMember().getId()) + .addValue("isDone", roundOfMember.isDone()) + .addValue("createdAt", LocalDateTime.now()); + + // Add other parameters as needed + parameters.add(param); + } + } + + SqlParameterSource[] batch = new SqlParameterSource[parameters.size()]; + batch = parameters.toArray(batch); + + namedParameterJdbcTemplate.batchUpdate(sql, batch); + } + +} diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/RoundRepository.java b/backend/src/main/java/com/yigongil/backend/domain/round/RoundRepository.java index 767b2a9eb..cfd304a76 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/round/RoundRepository.java +++ b/backend/src/main/java/com/yigongil/backend/domain/round/RoundRepository.java @@ -21,6 +21,7 @@ List findByRoundStatusAndDayOfWeek( DayOfWeek dayOfWeek ); + @EntityGraph(attributePaths = "roundOfMembers") List findAllByStudyIdAndWeekNumberIn(Long studyId, List weekNumbers); void saveAll(Iterable rounds); diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java b/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java index 305248da5..5d961dccf 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java +++ b/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java @@ -24,6 +24,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import javax.persistence.EntityManager; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -36,16 +37,17 @@ public class RoundService { private final RoundRepository roundRepository; private final StudyRepository studyRepository; private final EntityManager entityManager; - + private final RoundOfMemberBatchRepository roundOfMemberBatchRepository; public RoundService( RoundRepository roundRepository, StudyRepository studyRepository, - EntityManager entityManager - ) { + EntityManager entityManager, + RoundOfMemberBatchRepository roundOfMemberBatchRepository) { this.roundRepository = roundRepository; this.studyRepository = studyRepository; this.entityManager = entityManager; + this.roundOfMemberBatchRepository = roundOfMemberBatchRepository; } @Transactional(readOnly = true) @@ -140,12 +142,10 @@ public void proceedRound(LocalDate today) { RoundStatus.IN_PROGRESS, today.minusDays(1).getDayOfWeek() ); -// roundRepository.findCurrentRoundAndUpcomingRound(); -// List rounds = roundRepository.findByRoundStatusAndDayOfWeek( -// RoundStatus.IN_PROGRESS, -// today.minusDays(1).getDayOfWeek() -// ); + List nextWeekRoundsAll = new ArrayList<>(); + List willBeFinished = new ArrayList<>(); + List willProgress = new ArrayList<>(); for (Round round : rounds) { Integer currentWeek = round.getWeekNumber(); List upcomingCandidates = roundRepository.findAllByStudyIdAndWeekNumberIn( @@ -161,20 +161,29 @@ public void proceedRound(LocalDate today) { .min(Comparator.comparing(Round::getDayOfWeek)) .orElseThrow(() -> new IllegalStateException("다음 주 라운드를 안 만들어놓음"))); - round.finish(); - upcomingRound.proceed(); + willBeFinished.add(round); + willProgress.add(upcomingRound); if (!upcomingRound.isSameWeek(currentWeek)) { List nextWeekRounds = upcomingCandidates.stream() .filter(candidate -> candidate.isSameWeek(currentWeek + 1)) .map(Round::createNextWeekRound) .toList(); + nextWeekRoundsAll.addAll(nextWeekRounds); - roundRepository.saveAll(nextWeekRounds); } + + } - // + willBeFinished.forEach(Round::finish); + willProgress.forEach(Round::proceed); + roundRepository.saveAll(nextWeekRoundsAll); entityManager.flush(); + + Map> map = nextWeekRoundsAll.stream().collect( + Collectors.toMap(Round::getId, Round::getRoundOfMembers)); + roundOfMemberBatchRepository.batchSaveAll(map); + // Runtime runtime = Runtime.getRuntime(); long totalMemory = runtime.totalMemory(); long freeMemory = runtime.freeMemory(); @@ -205,6 +214,10 @@ public void initializeRounds(StudyStartedEvent event) { for (Round round : rounds) { roundRepository.save(round); } + entityManager.flush(); + Map> map = rounds.stream().collect( + Collectors.toMap(Round::getId, Round::getRoundOfMembers)); + roundOfMemberBatchRepository.batchSaveAll(map); } private List createRoundsOfFirstWeek(Study study, List dayOfWeeks, LocalDate startAt) { diff --git a/backend/src/main/java/com/yigongil/backend/utils/querycounter/PreparedStatementProxyHandler.java b/backend/src/main/java/com/yigongil/backend/utils/querycounter/PreparedStatementProxyHandler.java index bf0c1fda1..c2b8b6c59 100644 --- a/backend/src/main/java/com/yigongil/backend/utils/querycounter/PreparedStatementProxyHandler.java +++ b/backend/src/main/java/com/yigongil/backend/utils/querycounter/PreparedStatementProxyHandler.java @@ -25,7 +25,7 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Invocati private boolean isExecuteQuery(Method method) { String methodName = method.getName(); - return methodName.equals("executeQuery") || methodName.equals("execute") || methodName.equals("executeUpdate"); + return methodName.startsWith("execute"); } private boolean isInRequestScope() { From e796b9d8a5120108721fbc5d178faf017c0bf5cd Mon Sep 17 00:00:00 2001 From: kim dae hee Date: Wed, 22 Nov 2023 17:54:10 +0900 Subject: [PATCH 21/22] =?UTF-8?q?refactor:=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 --- .../java/com/yigongil/backend/domain/round/Round.java | 8 +++++--- .../yigongil/backend/domain/round/RoundRepository.java | 7 ++++--- .../yigongil/backend/domain/round/RoundService.java | 10 +++++----- backend/src/test/resources/application.yml | 6 ++---- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/Round.java b/backend/src/main/java/com/yigongil/backend/domain/round/Round.java index 715be156a..1cce4b803 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/round/Round.java +++ b/backend/src/main/java/com/yigongil/backend/domain/round/Round.java @@ -26,10 +26,9 @@ import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; +import javax.persistence.TableGenerator; import lombok.Builder; import lombok.Getter; -import org.hibernate.annotations.Cascade; -import org.hibernate.annotations.CascadeType; import org.hibernate.annotations.OnDelete; import org.hibernate.annotations.OnDeleteAction; @@ -40,7 +39,10 @@ public class Round extends BaseEntity { private static final int MAX_TODO_CONTENT_LENGTH = 20; private static final int MIN_TODO_CONTENT_LENGTH = 1; - @GeneratedValue(strategy = GenerationType.IDENTITY) + @GeneratedValue(strategy = GenerationType.TABLE, generator = "sequence_generator") + @TableGenerator(name = "sequence_generator", table = "round_sequence", + pkColumnName = "sequence_name", pkColumnValue = "id", + initialValue = 1, allocationSize=500) @Id private Long id; diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/RoundRepository.java b/backend/src/main/java/com/yigongil/backend/domain/round/RoundRepository.java index cfd304a76..31c36254a 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/round/RoundRepository.java +++ b/backend/src/main/java/com/yigongil/backend/domain/round/RoundRepository.java @@ -21,9 +21,6 @@ List findByRoundStatusAndDayOfWeek( DayOfWeek dayOfWeek ); - @EntityGraph(attributePaths = "roundOfMembers") - List findAllByStudyIdAndWeekNumberIn(Long studyId, List weekNumbers); - void saveAll(Iterable rounds); List findAllByStudyId(Long studyId); @@ -33,4 +30,8 @@ List findByRoundStatusAndDayOfWeek( default Round getByStudyIdAndRoundStatus(Long studyId, RoundStatus roundStatus) { return findByStudyIdAndRoundStatus(studyId, roundStatus).orElseThrow(() -> new RoundNotFoundException("", -1)); } + + @EntityGraph(attributePaths = "roundOfMembers") + + List findByStudyIdInAndRoundStatus(Iterable todayDoneStudyIds, RoundStatus roundStatus); } diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java b/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java index 5d961dccf..546061da0 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java +++ b/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java @@ -135,23 +135,23 @@ public List findRoundDetailsOfWeek(Long id, Integer weekNumber) { public void proceedRound(LocalDate today) { entityManager.flush(); entityManager.clear(); - System.out.println("StudyService.proceedRound"); long from = System.currentTimeMillis(); // List rounds = roundRepository.findByRoundStatusAndDayOfWeek( RoundStatus.IN_PROGRESS, today.minusDays(1).getDayOfWeek() ); + List todayDoneStudyIds = rounds.stream().map(Round::getStudyId).toList(); + Map> collect = roundRepository.findByStudyIdInAndRoundStatus( + todayDoneStudyIds, RoundStatus.NOT_STARTED) + .stream().collect(Collectors.groupingBy(Round::getStudyId)); List nextWeekRoundsAll = new ArrayList<>(); List willBeFinished = new ArrayList<>(); List willProgress = new ArrayList<>(); for (Round round : rounds) { Integer currentWeek = round.getWeekNumber(); - List upcomingCandidates = roundRepository.findAllByStudyIdAndWeekNumberIn( - round.getStudyId(), - List.of(currentWeek, currentWeek + 1) - ); + List upcomingCandidates = collect.get(round.getStudyId()); Round upcomingRound = upcomingCandidates.stream() .filter(candidate -> candidate.isSameWeek(currentWeek) && candidate.isNotStarted()) diff --git a/backend/src/test/resources/application.yml b/backend/src/test/resources/application.yml index 89e0f7b19..3e3374ecc 100644 --- a/backend/src/test/resources/application.yml +++ b/backend/src/test/resources/application.yml @@ -15,8 +15,6 @@ spring: jpa: properties: hibernate: - format_sql: true - show_sql: true jdbc: batch_size: 500 order_inserts: true @@ -31,8 +29,8 @@ spring: logging: level: - org.hibernate.type: trace - org.hibernate.sql: debug + org.hibernate.type: error + org.hibernate.sql: error oauth2: github: From d0584ab37de797885457756214a7fa369b8f858e Mon Sep 17 00:00:00 2001 From: yujamint Date: Wed, 10 Jan 2024 16:33:48 +0900 Subject: [PATCH 22/22] =?UTF-8?q?refactor:=20proceedRound=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EC=8B=9C=EA=B0=84=20=EC=B8=A1=EC=A0=95=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/domain/round/RoundService.java | 30 ------------------- 1 file changed, 30 deletions(-) diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java b/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java index 546061da0..c148ee3bb 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java +++ b/backend/src/main/java/com/yigongil/backend/domain/round/RoundService.java @@ -12,11 +12,6 @@ import com.yigongil.backend.request.MustDoUpdateRequest; import com.yigongil.backend.response.RoundResponse; import com.yigongil.backend.response.UpcomingStudyResponse; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.StandardOpenOption; import java.time.DayOfWeek; import java.time.LocalDate; import java.util.ArrayList; @@ -133,10 +128,6 @@ public List findRoundDetailsOfWeek(Long id, Integer weekNumber) { @Transactional public void proceedRound(LocalDate today) { - entityManager.flush(); - entityManager.clear(); - long from = System.currentTimeMillis(); - // List rounds = roundRepository.findByRoundStatusAndDayOfWeek( RoundStatus.IN_PROGRESS, today.minusDays(1).getDayOfWeek() @@ -172,8 +163,6 @@ public void proceedRound(LocalDate today) { nextWeekRoundsAll.addAll(nextWeekRounds); } - - } willBeFinished.forEach(Round::finish); willProgress.forEach(Round::proceed); @@ -183,25 +172,6 @@ public void proceedRound(LocalDate today) { Map> map = nextWeekRoundsAll.stream().collect( Collectors.toMap(Round::getId, Round::getRoundOfMembers)); roundOfMemberBatchRepository.batchSaveAll(map); - // - Runtime runtime = Runtime.getRuntime(); - long totalMemory = runtime.totalMemory(); - long freeMemory = runtime.freeMemory(); - long usedMemory = (totalMemory - freeMemory) / 1000000; - - long to = System.currentTimeMillis(); - Path path = Paths.get("time_test.txt"); - try { - if (Files.exists(path)) { - Files.write(path, ("time spent to proceed Round \nstudy size: " + rounds.size() + "\ntotal time spent: " + (to - from) + "\nThe JVM is using " + usedMemory + " MB of memory." + "\n\n").getBytes(), StandardOpenOption.APPEND); - } else { - Files.createFile(path); - Files.write(path, ("time spent to proceed Round \nstudy size: " + rounds.size() + "\ntotal time spent: " + (to - from) + "\n\n").getBytes()); - } - } catch (IOException e) { - throw new RuntimeException(e); - } - } @TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT)