diff --git a/backend/.gitignore b/backend/.gitignore index 9f039158..c66f5806 100644 --- a/backend/.gitignore +++ b/backend/.gitignore @@ -9,7 +9,7 @@ build/ **/src/main/generated/ ### initDB ### -**/src/main/java/moim_today/global/init/** +**/src/main/java/moim_today/**/init/** ### Properties ### application.yml diff --git a/backend/build.gradle b/backend/build.gradle index 8f6a1460..2042f2e4 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -12,6 +12,7 @@ plugins { id 'io.spring.dependency-management' version '1.1.4' id 'com.epages.restdocs-api-spec' version "${restdocsApiSpecVersion}" id 'org.hidetake.swagger.generator' version '2.18.2' + id 'jacoco' } group = 'u2dj2' @@ -118,6 +119,7 @@ dependencies { tasks.named('test') { outputs.dir snippetsDir useJUnitPlatform() + finalizedBy jacocoTestReport } tasks.withType(GenerateSwaggerUI) { @@ -144,4 +146,26 @@ bootJar { } } -jar.enabled = false \ No newline at end of file +jar.enabled = false + +jacoco { + toolVersion = "0.8.10" +} + +jacocoTestReport { + dependsOn test + reports { + xml.required = true + html.required = true + } + afterEvaluate { + classDirectories.setFrom(files(classDirectories.files.collect { + fileTree(dir: it, exclude: [ + 'moim_today/dto/**', + 'moim_today/global/**', + 'moim_today/application/**', + '**/Q*.*' + ]) + })) + } +} diff --git a/backend/src/main/java/moim_today/application/auth/AuthService.java b/backend/src/main/java/moim_today/application/auth/AuthService.java index da8edfba..68538dda 100644 --- a/backend/src/main/java/moim_today/application/auth/AuthService.java +++ b/backend/src/main/java/moim_today/application/auth/AuthService.java @@ -3,6 +3,7 @@ import jakarta.servlet.http.HttpServletRequest; import moim_today.dto.auth.MemberLoginRequest; import moim_today.dto.auth.MemberSignUpRequest; +import moim_today.dto.auth.MemberSessionValidateResponse; public interface AuthService { @@ -11,4 +12,6 @@ public interface AuthService { void signUp(final MemberSignUpRequest memberSignUpRequest, final HttpServletRequest request); void logout(final HttpServletRequest request); + + MemberSessionValidateResponse validateMemberSession(final HttpServletRequest request); } diff --git a/backend/src/main/java/moim_today/application/auth/AuthServiceImpl.java b/backend/src/main/java/moim_today/application/auth/AuthServiceImpl.java index 14afef71..7af244c8 100644 --- a/backend/src/main/java/moim_today/application/auth/AuthServiceImpl.java +++ b/backend/src/main/java/moim_today/application/auth/AuthServiceImpl.java @@ -1,10 +1,12 @@ package moim_today.application.auth; +import jakarta.servlet.http.HttpServletRequest; +import moim_today.domain.member.MemberSession; import moim_today.dto.auth.MemberLoginRequest; import moim_today.dto.auth.MemberSignUpRequest; +import moim_today.dto.auth.MemberSessionValidateResponse; import moim_today.implement.department.DepartmentFinder; import moim_today.implement.member.AuthManager; -import jakarta.servlet.http.HttpServletRequest; import moim_today.implement.member.MemberFinder; import moim_today.implement.university.UniversityFinder; import org.springframework.stereotype.Service; @@ -46,4 +48,9 @@ public void signUp(final MemberSignUpRequest memberSignUpRequest, memberFinder.validateEmailNotExists(memberSignUpRequest.email()); authManager.signUp(memberSignUpRequest, request); } + + @Override + public MemberSessionValidateResponse validateMemberSession(final HttpServletRequest request) { + return MemberSession.validateMemberSession(request); + } } diff --git a/backend/src/main/java/moim_today/application/email_subscribe/EmailSubscribeService.java b/backend/src/main/java/moim_today/application/email_subscribe/EmailSubscribeService.java new file mode 100644 index 00000000..dd8eb02b --- /dev/null +++ b/backend/src/main/java/moim_today/application/email_subscribe/EmailSubscribeService.java @@ -0,0 +1,10 @@ +package moim_today.application.email_subscribe; + +import moim_today.dto.mail.EmailSubscriptionResponse; + +public interface EmailSubscribeService { + + EmailSubscriptionResponse getSubscriptionStatus(final long memberId); + + void updateSubscribeStatus(final long memberId, final boolean subscribedStatus); +} diff --git a/backend/src/main/java/moim_today/application/email_subscribe/EmailSubscribeServiceImpl.java b/backend/src/main/java/moim_today/application/email_subscribe/EmailSubscribeServiceImpl.java new file mode 100644 index 00000000..1a5dea63 --- /dev/null +++ b/backend/src/main/java/moim_today/application/email_subscribe/EmailSubscribeServiceImpl.java @@ -0,0 +1,30 @@ +package moim_today.application.email_subscribe; + +import moim_today.dto.mail.EmailSubscriptionResponse; +import moim_today.implement.email_subscribe.EmailSubscribeUpdater; +import moim_today.implement.email_subscribe.EmailSubscriptionFinder; +import org.springframework.stereotype.Service; + +@Service +public class EmailSubscribeServiceImpl implements EmailSubscribeService { + + private final EmailSubscribeUpdater emailSubscribeUpdater; + private final EmailSubscriptionFinder emailSubscriptionFinder; + + public EmailSubscribeServiceImpl(final EmailSubscribeUpdater emailSubscribeUpdater, + final EmailSubscriptionFinder emailSubscriptionFinder) { + this.emailSubscribeUpdater = emailSubscribeUpdater; + this.emailSubscriptionFinder = emailSubscriptionFinder; + } + + @Override + public EmailSubscriptionResponse getSubscriptionStatus(final long memberId) { + boolean subscriptionStatus = emailSubscriptionFinder.getSubscriptionStatus(memberId); + return EmailSubscriptionResponse.of(subscriptionStatus); + } + + @Override + public void updateSubscribeStatus(final long memberId, final boolean subscribedStatus) { + emailSubscribeUpdater.updateSubscribeStatus(memberId, subscribedStatus); + } +} diff --git a/backend/src/main/java/moim_today/application/meeting/joined_meeting/JoinedMeetingService.java b/backend/src/main/java/moim_today/application/meeting/joined_meeting/JoinedMeetingService.java index 65585d18..241c0c82 100644 --- a/backend/src/main/java/moim_today/application/meeting/joined_meeting/JoinedMeetingService.java +++ b/backend/src/main/java/moim_today/application/meeting/joined_meeting/JoinedMeetingService.java @@ -1,8 +1,11 @@ package moim_today.application.meeting.joined_meeting; + public interface JoinedMeetingService { void acceptanceJoinMeeting(final long memberId, final long meetingId); void refuseJoinMeeting(final long memberId, final long meetingId); + + void deleteAllByMeetingId(final long meetingId); } diff --git a/backend/src/main/java/moim_today/application/meeting/joined_meeting/JoinedMeetingServiceImpl.java b/backend/src/main/java/moim_today/application/meeting/joined_meeting/JoinedMeetingServiceImpl.java index 965cc423..df4c163f 100644 --- a/backend/src/main/java/moim_today/application/meeting/joined_meeting/JoinedMeetingServiceImpl.java +++ b/backend/src/main/java/moim_today/application/meeting/joined_meeting/JoinedMeetingServiceImpl.java @@ -1,26 +1,40 @@ package moim_today.application.meeting.joined_meeting; +import moim_today.implement.meeting.joined_meeting.JoinedMeetingRemover; import moim_today.implement.meeting.joined_meeting.JoinedMeetingUpdater; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + @Service public class JoinedMeetingServiceImpl implements JoinedMeetingService { private final JoinedMeetingUpdater joinedMeetingUpdater; + private final JoinedMeetingRemover joinedMeetingRemover; - public JoinedMeetingServiceImpl(final JoinedMeetingUpdater joinedMeetingUpdater) { + public JoinedMeetingServiceImpl(final JoinedMeetingUpdater joinedMeetingUpdater, + final JoinedMeetingRemover joinedMeetingRemover) { this.joinedMeetingUpdater = joinedMeetingUpdater; + this.joinedMeetingRemover = joinedMeetingRemover; } + @Transactional @Override public void acceptanceJoinMeeting(final long memberId, final long meetingId) { boolean attendance = true; joinedMeetingUpdater.updateAttendance(memberId, meetingId, attendance); } + @Transactional @Override public void refuseJoinMeeting(final long memberId, final long meetingId) { boolean attendance = false; joinedMeetingUpdater.updateAttendance(memberId, meetingId, attendance); } + + @Transactional + @Override + public void deleteAllByMeetingId(final long meetingId) { + joinedMeetingRemover.deleteAllByMeetingId(meetingId); + } } diff --git a/backend/src/main/java/moim_today/application/meeting/meeting/MeetingService.java b/backend/src/main/java/moim_today/application/meeting/meeting/MeetingService.java index 7120c3b6..07c90eab 100644 --- a/backend/src/main/java/moim_today/application/meeting/meeting/MeetingService.java +++ b/backend/src/main/java/moim_today/application/meeting/meeting/MeetingService.java @@ -1,19 +1,19 @@ package moim_today.application.meeting.meeting; import moim_today.domain.meeting.enums.MeetingStatus; -import moim_today.dto.meeting.MeetingCreateRequest; -import moim_today.dto.meeting.MeetingDetailResponse; -import moim_today.dto.meeting.MeetingSimpleResponse; +import moim_today.dto.meeting.meeting.*; import java.util.List; public interface MeetingService { - void createMeeting(final MeetingCreateRequest meetingCreateRequest); + MeetingCreateResponse createMeeting(final long memberId, final MeetingCreateRequest meetingCreateRequest); List findAllByMoimId(final long moimId, final long memberId, final MeetingStatus meetingStatus); MeetingDetailResponse findDetailsById(final long meetingId); + void updateMeeting(final long memberId, final MeetingUpdateRequest meetingUpdateRequest); + void deleteMeeting(final long memberId, final long meetingId); } diff --git a/backend/src/main/java/moim_today/application/meeting/meeting/MeetingServiceImpl.java b/backend/src/main/java/moim_today/application/meeting/meeting/MeetingServiceImpl.java index 2490933b..705a4d47 100644 --- a/backend/src/main/java/moim_today/application/meeting/meeting/MeetingServiceImpl.java +++ b/backend/src/main/java/moim_today/application/meeting/meeting/MeetingServiceImpl.java @@ -1,15 +1,18 @@ package moim_today.application.meeting.meeting; +import moim_today.application.meeting.joined_meeting.JoinedMeetingService; +import moim_today.application.schedule.ScheduleService; import moim_today.domain.meeting.enums.MeetingStatus; -import moim_today.dto.meeting.MeetingCreateRequest; -import moim_today.dto.meeting.MeetingDetailResponse; -import moim_today.dto.meeting.MeetingSimpleDao; -import moim_today.dto.meeting.MeetingSimpleResponse; +import moim_today.dto.meeting.meeting.*; import moim_today.implement.meeting.meeting.MeetingFinder; import moim_today.implement.meeting.meeting.MeetingManager; import moim_today.implement.meeting.meeting.MeetingRemover; +import moim_today.implement.meeting.meeting.MeetingUpdater; +import moim_today.persistence.entity.meeting.meeting.MeetingJpaEntity; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import java.time.LocalDate; import java.time.LocalDateTime; import java.util.List; @@ -18,18 +21,25 @@ public class MeetingServiceImpl implements MeetingService { private final MeetingManager meetingManager; private final MeetingFinder meetingFinder; + private final MeetingUpdater meetingUpdater; private final MeetingRemover meetingRemover; + private final ScheduleService scheduleService; + private final JoinedMeetingService joinedMeetingService; public MeetingServiceImpl(final MeetingManager meetingManager, final MeetingFinder meetingFinder, - final MeetingRemover meetingRemover) { + final MeetingUpdater meetingUpdater, final MeetingRemover meetingRemover, + final ScheduleService scheduleService, final JoinedMeetingService joinedMeetingService) { this.meetingManager = meetingManager; this.meetingFinder = meetingFinder; + this.meetingUpdater = meetingUpdater; this.meetingRemover = meetingRemover; + this.scheduleService = scheduleService; + this.joinedMeetingService = joinedMeetingService; } @Override - public void createMeeting(final MeetingCreateRequest meetingCreateRequest) { - meetingManager.createMeeting(meetingCreateRequest); + public MeetingCreateResponse createMeeting(final long memberId, final MeetingCreateRequest meetingCreateRequest) { + return meetingManager.createMeeting(memberId, meetingCreateRequest, LocalDate.now()); } @Override @@ -45,8 +55,16 @@ public MeetingDetailResponse findDetailsById(final long meetingId) { return meetingFinder.findDetailsById(meetingId); } + @Override + public void updateMeeting(final long memberId, final MeetingUpdateRequest meetingUpdateRequest) { + meetingUpdater.updateMeeting(memberId, meetingUpdateRequest); + } + + @Transactional @Override public void deleteMeeting(final long memberId, final long meetingId) { meetingRemover.deleteMeeting(meetingId, meetingId); + scheduleService.deleteAllByMeetingId(meetingId); + joinedMeetingService.deleteAllByMeetingId(meetingId); } } diff --git a/backend/src/main/java/moim_today/application/meeting/meeting_comment/MeetingCommentService.java b/backend/src/main/java/moim_today/application/meeting/meeting_comment/MeetingCommentService.java new file mode 100644 index 00000000..4bed00e1 --- /dev/null +++ b/backend/src/main/java/moim_today/application/meeting/meeting_comment/MeetingCommentService.java @@ -0,0 +1,18 @@ +package moim_today.application.meeting.meeting_comment; + +import moim_today.dto.meeting.meeting_comment.MeetingCommentCreateRequest; +import moim_today.dto.meeting.meeting_comment.MeetingCommentResponse; +import moim_today.dto.meeting.meeting_comment.MeetingCommentUpdateRequest; + +import java.util.List; + +public interface MeetingCommentService { + + void createMeetingComment(final long memberId, final MeetingCommentCreateRequest meetingCommentCreateRequest); + + List findAllByMeetingId(final long memberId, final long meetingId); + + void updateMeetingComment(final long memberId, final MeetingCommentUpdateRequest meetingCommentUpdateRequest); + + void deleteMeetingComment(final long memberId, final long meetingCommentId); +} diff --git a/backend/src/main/java/moim_today/application/meeting/meeting_comment/MeetingCommentServiceImpl.java b/backend/src/main/java/moim_today/application/meeting/meeting_comment/MeetingCommentServiceImpl.java new file mode 100644 index 00000000..f3b9189b --- /dev/null +++ b/backend/src/main/java/moim_today/application/meeting/meeting_comment/MeetingCommentServiceImpl.java @@ -0,0 +1,71 @@ +package moim_today.application.meeting.meeting_comment; + +import moim_today.dto.meeting.meeting_comment.MeetingCommentCreateRequest; +import moim_today.dto.meeting.meeting_comment.MeetingCommentResponse; +import moim_today.dto.meeting.meeting_comment.MeetingCommentUpdateRequest; +import moim_today.implement.meeting.meeting.MeetingFinder; +import moim_today.implement.meeting.meeting_comment.MeetingCommentAppender; +import moim_today.implement.meeting.meeting_comment.MeetingCommentFinder; +import moim_today.implement.meeting.meeting_comment.MeetingCommentRemover; +import moim_today.implement.meeting.meeting_comment.MeetingCommentUpdater; +import moim_today.implement.moim.joined_moim.JoinedMoimFinder; +import moim_today.persistence.entity.meeting.meeting_comment.MeetingCommentJpaEntity; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +public class MeetingCommentServiceImpl implements MeetingCommentService { + + private final MeetingCommentAppender meetingCommentAppender; + private final MeetingCommentFinder meetingCommentFinder; + private final MeetingCommentUpdater meetingCommentUpdater; + private final MeetingCommentRemover meetingCommentRemover; + private final MeetingFinder meetingFinder; + private final JoinedMoimFinder joinedMoimFinder; + + public MeetingCommentServiceImpl(final MeetingCommentAppender meetingCommentAppender, + final MeetingCommentFinder meetingCommentFinder, + final MeetingCommentUpdater meetingCommentUpdater, + final MeetingCommentRemover meetingCommentRemover, + final MeetingFinder meetingFinder, + final JoinedMoimFinder joinedMoimFinder) { + this.meetingCommentAppender = meetingCommentAppender; + this.meetingCommentFinder = meetingCommentFinder; + this.meetingCommentUpdater = meetingCommentUpdater; + this.meetingCommentRemover = meetingCommentRemover; + this.meetingFinder = meetingFinder; + this.joinedMoimFinder = joinedMoimFinder; + } + + @Override + public void createMeetingComment(final long memberId, final MeetingCommentCreateRequest meetingCommentCreateRequest) { + long moimId = meetingFinder.getMoimIdByMeetingId(meetingCommentCreateRequest.meetingId()); + joinedMoimFinder.validateMemberInMoim(memberId, moimId); + meetingCommentAppender.createMeetingComment(memberId, meetingCommentCreateRequest); + } + + @Override + public List findAllByMeetingId(final long memberId, final long meetingId) { + long moimId = meetingFinder.getMoimIdByMeetingId(meetingId); + joinedMoimFinder.validateMemberInMoim(memberId, moimId); + return meetingCommentFinder.findAllByMeetingId(meetingId); + } + + @Transactional + @Override + public void updateMeetingComment(final long memberId, final MeetingCommentUpdateRequest meetingCommentUpdateRequest) { + long meetingCommentId = meetingCommentUpdateRequest.meetingCommentId(); + MeetingCommentJpaEntity meetingCommentJpaEntity = meetingCommentFinder.getById(meetingCommentId); + meetingCommentJpaEntity.validateMember(memberId); + meetingCommentUpdater.updateMeetingComment(meetingCommentId, meetingCommentUpdateRequest); + } + + @Override + public void deleteMeetingComment(final long memberId, final long meetingCommentId) { + MeetingCommentJpaEntity meetingCommentJpaEntity = meetingCommentFinder.getById(meetingCommentId); + meetingCommentJpaEntity.validateMember(memberId); + meetingCommentRemover.deleteById(meetingCommentId); + } +} diff --git a/backend/src/main/java/moim_today/application/member/MemberService.java b/backend/src/main/java/moim_today/application/member/MemberService.java index 4d96adee..149f1ed8 100644 --- a/backend/src/main/java/moim_today/application/member/MemberService.java +++ b/backend/src/main/java/moim_today/application/member/MemberService.java @@ -18,5 +18,7 @@ public interface MemberService { MemberHostResponse isHost(final long memberId, final long moimId); + MemberJoinedMoimResponse isJoinedMoim(final long moimId, final long memberId); + MemberSimpleResponse getHostProfileByMoimId(final long moimId); } diff --git a/backend/src/main/java/moim_today/application/member/MemberServiceImpl.java b/backend/src/main/java/moim_today/application/member/MemberServiceImpl.java index 1845ec3a..f4aa8027 100644 --- a/backend/src/main/java/moim_today/application/member/MemberServiceImpl.java +++ b/backend/src/main/java/moim_today/application/member/MemberServiceImpl.java @@ -66,9 +66,13 @@ public ProfileImageResponse uploadProfileImage(final long memberId, final Multip @Override public MemberHostResponse isHost(final long memberId, final long moimId) { boolean isHost = moimManager.isHost(memberId, moimId); - return MemberHostResponse.builder() - .isHost(isHost) - .build(); + return MemberHostResponse.from(isHost); + } + + @Override + public MemberJoinedMoimResponse isJoinedMoim(final long moimId, final long memberId) { + boolean isJoinedMoim = moimManager.isJoinedMoim(moimId, memberId); + return MemberJoinedMoimResponse.from(isJoinedMoim); } @Override diff --git a/backend/src/main/java/moim_today/application/moim/moim/MoimService.java b/backend/src/main/java/moim_today/application/moim/moim/MoimService.java index fd1f8041..75e4c4e7 100644 --- a/backend/src/main/java/moim_today/application/moim/moim/MoimService.java +++ b/backend/src/main/java/moim_today/application/moim/moim/MoimService.java @@ -10,8 +10,10 @@ public interface MoimService { + List findAllMyJoinedMoimResponse(final long memberId); + MoimIdResponse createMoim(final long memberId, final long universityId, - final MoimCreateRequest moimCreateRequest); + final MoimCreateRequest moimCreateRequest); MoimImageResponse uploadMoimImage(final MultipartFile file); @@ -29,7 +31,9 @@ MoimIdResponse createMoim(final long memberId, final long universityId, void appendMemberToMoim(final long requestMemberId, final MoimJoinRequest moimJoinRequest); - List findAllMoimResponse(final MoimCategoryDto moimCategoryDto, final MoimSortedFilter moimSortedFilter); + List findAllMoimResponses(final long universityId, final MoimCategoryDto moimCategoryDto, final MoimSortedFilter moimSortedFilter); + + List searchMoim(final long universityId, final String searchParam); - List searchMoim(final String searchParam); + List findAllMyJoinedMoimSimpleResponse(final long memberId, final boolean ended, final boolean onlyHost); } diff --git a/backend/src/main/java/moim_today/application/moim/moim/MoimServiceImpl.java b/backend/src/main/java/moim_today/application/moim/moim/MoimServiceImpl.java index f4c8a239..a316270d 100644 --- a/backend/src/main/java/moim_today/application/moim/moim/MoimServiceImpl.java +++ b/backend/src/main/java/moim_today/application/moim/moim/MoimServiceImpl.java @@ -19,6 +19,7 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; +import java.time.LocalDate; import java.util.List; import static moim_today.global.constant.FileTypeConstant.MOIM_IMAGE; @@ -68,6 +69,11 @@ public MoimServiceImpl(final MoimAppender moimAppender, this.moimManager = moimManager; } + @Override + public List findAllMyJoinedMoimResponse(final long memberId) { + return moimFinder.findAllMyMoimResponse(memberId); + } + @Override public MoimIdResponse createMoim(final long memberId, final long universityId, final MoimCreateRequest moimCreateRequest) { @@ -151,17 +157,30 @@ public void deleteMember(final long deleteMemberId, final MoimMemberDeleteReques @Override public void appendMemberToMoim(final long requestMemberId, final MoimJoinRequest moimJoinRequest) { long enterMoimId = moimJoinRequest.moimId(); - moimManager.appendMemberToMoim(requestMemberId, enterMoimId); } @Override - public List findAllMoimResponse(final MoimCategoryDto moimCategoryDto, final MoimSortedFilter moimSortedFilter) { - return moimFinder.findAllMoimResponse(moimCategoryDto, moimSortedFilter); + public List findAllMoimResponses( + final long universityId, + final MoimCategoryDto moimCategoryDto, + final MoimSortedFilter moimSortedFilter) { + + return moimFinder.findAllMoimResponses(universityId, moimCategoryDto, moimSortedFilter); + } + + @Override + public List searchMoim(final long universityId, final String searchParam) { + return moimFinder.searchMoim(universityId, searchParam); } @Override - public List searchMoim(final String searchParam) { - return moimFinder.searchMoim(searchParam); + public List findAllMyJoinedMoimSimpleResponse(final long memberId, + final boolean ended, + final boolean onlyHost) { + if(onlyHost){ + return moimManager.findAllHostMoimSimpleResponsesByEndStatus(memberId, LocalDate.now(), ended); + } + return moimManager.findAllJoinedMoimSimpleResponseByEndStatus(memberId, LocalDate.now(), ended); } } diff --git a/backend/src/main/java/moim_today/application/schedule/ScheduleService.java b/backend/src/main/java/moim_today/application/schedule/ScheduleService.java index a6431f84..005ced8f 100644 --- a/backend/src/main/java/moim_today/application/schedule/ScheduleService.java +++ b/backend/src/main/java/moim_today/application/schedule/ScheduleService.java @@ -24,4 +24,6 @@ public interface ScheduleService { void updateSchedule(final long memberId, final ScheduleUpdateRequest scheduleUpdateRequest); void deleteSchedule(final long memberId, final long scheduleId); + + void deleteAllByMeetingId(final long meetingId); } diff --git a/backend/src/main/java/moim_today/application/schedule/ScheduleServiceImpl.java b/backend/src/main/java/moim_today/application/schedule/ScheduleServiceImpl.java index 444e36a2..48c5ef2b 100644 --- a/backend/src/main/java/moim_today/application/schedule/ScheduleServiceImpl.java +++ b/backend/src/main/java/moim_today/application/schedule/ScheduleServiceImpl.java @@ -96,4 +96,9 @@ public void updateSchedule(final long memberId, final ScheduleUpdateRequest sche public void deleteSchedule(final long memberId, final long scheduleId) { scheduleRemover.deleteSchedule(memberId, scheduleId); } + + @Override + public void deleteAllByMeetingId(final long meetingId) { + scheduleRemover.deleteAllByMeetingId(meetingId); + } } \ No newline at end of file diff --git a/backend/src/main/java/moim_today/domain/member/MemberSession.java b/backend/src/main/java/moim_today/domain/member/MemberSession.java index 936236ad..977d12bf 100644 --- a/backend/src/main/java/moim_today/domain/member/MemberSession.java +++ b/backend/src/main/java/moim_today/domain/member/MemberSession.java @@ -5,6 +5,7 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpSession; import lombok.Builder; +import moim_today.dto.auth.MemberSessionValidateResponse; import moim_today.global.error.InternalServerException; import moim_today.persistence.entity.member.MemberJpaEntity; @@ -50,4 +51,13 @@ public void setSession(final HttpServletRequest request, final String memberSess session.setMaxInactiveInterval(ONE_DAYS_IN_SECONDS.value()); } } + + public static MemberSessionValidateResponse validateMemberSession(final HttpServletRequest request) { + HttpSession session = request.getSession(false); + + if (session == null || session.getAttribute(MEMBER_SESSION.value()) == null) { + return new MemberSessionValidateResponse(false); + } + return new MemberSessionValidateResponse(true); + } } diff --git a/backend/src/main/java/moim_today/domain/schedule/enums/ColorHex.java b/backend/src/main/java/moim_today/domain/schedule/enums/ColorHex.java index 7393a2da..ca7a620b 100644 --- a/backend/src/main/java/moim_today/domain/schedule/enums/ColorHex.java +++ b/backend/src/main/java/moim_today/domain/schedule/enums/ColorHex.java @@ -24,7 +24,6 @@ public enum ColorHex { GRAY("#999999"), CORAL("#CC6666"); - private final String value; ColorHex(final String value) { diff --git a/backend/src/main/java/moim_today/dto/auth/MemberSessionValidateResponse.java b/backend/src/main/java/moim_today/dto/auth/MemberSessionValidateResponse.java new file mode 100644 index 00000000..67048bca --- /dev/null +++ b/backend/src/main/java/moim_today/dto/auth/MemberSessionValidateResponse.java @@ -0,0 +1,6 @@ +package moim_today.dto.auth; + +public record MemberSessionValidateResponse( + boolean isValidateMemberSession +) { +} diff --git a/backend/src/main/java/moim_today/dto/mail/EmailSubscribeRequest.java b/backend/src/main/java/moim_today/dto/mail/EmailSubscribeRequest.java new file mode 100644 index 00000000..f930fd6a --- /dev/null +++ b/backend/src/main/java/moim_today/dto/mail/EmailSubscribeRequest.java @@ -0,0 +1,15 @@ +package moim_today.dto.mail; + +import lombok.Builder; + +@Builder +public record EmailSubscribeRequest( + boolean subscribeStatus +) { + + public static EmailSubscribeRequest of(final boolean subscribeStatus) { + return EmailSubscribeRequest.builder() + .subscribeStatus(subscribeStatus) + .build(); + } +} diff --git a/backend/src/main/java/moim_today/dto/mail/EmailSubscriptionResponse.java b/backend/src/main/java/moim_today/dto/mail/EmailSubscriptionResponse.java new file mode 100644 index 00000000..5d12d851 --- /dev/null +++ b/backend/src/main/java/moim_today/dto/mail/EmailSubscriptionResponse.java @@ -0,0 +1,15 @@ +package moim_today.dto.mail; + +import lombok.Builder; + +@Builder +public record EmailSubscriptionResponse( + boolean subscribeStatus +) { + + public static EmailSubscriptionResponse of(final boolean subscribeStatus) { + return EmailSubscriptionResponse.builder() + .subscribeStatus(subscribeStatus) + .build(); + } +} diff --git a/backend/src/main/java/moim_today/dto/meeting/MeetingCreateRequest.java b/backend/src/main/java/moim_today/dto/meeting/meeting/MeetingCreateRequest.java similarity index 97% rename from backend/src/main/java/moim_today/dto/meeting/MeetingCreateRequest.java rename to backend/src/main/java/moim_today/dto/meeting/meeting/MeetingCreateRequest.java index 43e39576..637da04d 100644 --- a/backend/src/main/java/moim_today/dto/meeting/MeetingCreateRequest.java +++ b/backend/src/main/java/moim_today/dto/meeting/meeting/MeetingCreateRequest.java @@ -1,4 +1,4 @@ -package moim_today.dto.meeting; +package moim_today.dto.meeting.meeting; import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Builder; diff --git a/backend/src/main/java/moim_today/dto/meeting/meeting/MeetingCreateResponse.java b/backend/src/main/java/moim_today/dto/meeting/meeting/MeetingCreateResponse.java new file mode 100644 index 00000000..43eb1c35 --- /dev/null +++ b/backend/src/main/java/moim_today/dto/meeting/meeting/MeetingCreateResponse.java @@ -0,0 +1,33 @@ +package moim_today.dto.meeting.meeting; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Builder; +import moim_today.domain.meeting.enums.MeetingCategory; + +import java.time.LocalDateTime; + +@Builder +public record MeetingCreateResponse( + long meetingId, + String agenda, + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul") + LocalDateTime startDateTime, + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul") + LocalDateTime endDateTime, + + String place, + MeetingCategory meetingCategory +) { + + public static MeetingCreateResponse of(final long meetingId, final MeetingCreateRequest meetingCreateRequest) { + return MeetingCreateResponse.builder() + .meetingId(meetingId) + .agenda(meetingCreateRequest.agenda()) + .startDateTime(meetingCreateRequest.startDateTime()) + .endDateTime(meetingCreateRequest.endDateTime()) + .place(meetingCreateRequest.place()) + .meetingCategory(meetingCreateRequest.meetingCategory()) + .build(); + } +} diff --git a/backend/src/main/java/moim_today/dto/meeting/MeetingDetailResponse.java b/backend/src/main/java/moim_today/dto/meeting/meeting/MeetingDetailResponse.java similarity index 97% rename from backend/src/main/java/moim_today/dto/meeting/MeetingDetailResponse.java rename to backend/src/main/java/moim_today/dto/meeting/meeting/MeetingDetailResponse.java index 19a6238e..6fc9920d 100644 --- a/backend/src/main/java/moim_today/dto/meeting/MeetingDetailResponse.java +++ b/backend/src/main/java/moim_today/dto/meeting/meeting/MeetingDetailResponse.java @@ -1,4 +1,4 @@ -package moim_today.dto.meeting; +package moim_today.dto.meeting.meeting; import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Builder; diff --git a/backend/src/main/java/moim_today/dto/meeting/MeetingSimpleDao.java b/backend/src/main/java/moim_today/dto/meeting/meeting/MeetingSimpleDao.java similarity index 92% rename from backend/src/main/java/moim_today/dto/meeting/MeetingSimpleDao.java rename to backend/src/main/java/moim_today/dto/meeting/meeting/MeetingSimpleDao.java index bb324381..77d69a44 100644 --- a/backend/src/main/java/moim_today/dto/meeting/MeetingSimpleDao.java +++ b/backend/src/main/java/moim_today/dto/meeting/meeting/MeetingSimpleDao.java @@ -1,4 +1,4 @@ -package moim_today.dto.meeting; +package moim_today.dto.meeting.meeting; import com.fasterxml.jackson.annotation.JsonFormat; import com.querydsl.core.annotations.QueryProjection; diff --git a/backend/src/main/java/moim_today/dto/meeting/MeetingSimpleResponse.java b/backend/src/main/java/moim_today/dto/meeting/meeting/MeetingSimpleResponse.java similarity index 97% rename from backend/src/main/java/moim_today/dto/meeting/MeetingSimpleResponse.java rename to backend/src/main/java/moim_today/dto/meeting/meeting/MeetingSimpleResponse.java index acc09c3a..de3568c3 100644 --- a/backend/src/main/java/moim_today/dto/meeting/MeetingSimpleResponse.java +++ b/backend/src/main/java/moim_today/dto/meeting/meeting/MeetingSimpleResponse.java @@ -1,4 +1,4 @@ -package moim_today.dto.meeting; +package moim_today.dto.meeting.meeting; import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Builder; diff --git a/backend/src/main/java/moim_today/dto/meeting/meeting/MeetingUpdateRequest.java b/backend/src/main/java/moim_today/dto/meeting/meeting/MeetingUpdateRequest.java new file mode 100644 index 00000000..daccc4f5 --- /dev/null +++ b/backend/src/main/java/moim_today/dto/meeting/meeting/MeetingUpdateRequest.java @@ -0,0 +1,19 @@ +package moim_today.dto.meeting.meeting; + +import lombok.Builder; + +@Builder +public record MeetingUpdateRequest( + long meetingId, + String agenda, + String place +) { + + public static MeetingUpdateRequest of(final long meetingId, final String agenda, final String place) { + return MeetingUpdateRequest.builder() + .meetingId(meetingId) + .agenda(agenda) + .place(place) + .build(); + } +} diff --git a/backend/src/main/java/moim_today/dto/meeting/meeting_comment/MeetingCommentCreateRequest.java b/backend/src/main/java/moim_today/dto/meeting/meeting_comment/MeetingCommentCreateRequest.java new file mode 100644 index 00000000..627484a8 --- /dev/null +++ b/backend/src/main/java/moim_today/dto/meeting/meeting_comment/MeetingCommentCreateRequest.java @@ -0,0 +1,22 @@ +package moim_today.dto.meeting.meeting_comment; + +import lombok.Builder; +import moim_today.persistence.entity.meeting.meeting_comment.MeetingCommentJpaEntity; + +import static moim_today.global.constant.NumberConstant.DEFAULT_PARENT_COMMENT_ID; + +@Builder +public record MeetingCommentCreateRequest ( + long meetingId, + String contents +){ + + public MeetingCommentJpaEntity toEntity(final long memberId) { + return MeetingCommentJpaEntity.builder() + .meetingId(meetingId) + .parentId(DEFAULT_PARENT_COMMENT_ID.value()) + .memberId(memberId) + .contents(contents) + .build(); + } +} diff --git a/backend/src/main/java/moim_today/dto/meeting/meeting_comment/MeetingCommentDeleteRequest.java b/backend/src/main/java/moim_today/dto/meeting/meeting_comment/MeetingCommentDeleteRequest.java new file mode 100644 index 00000000..8146c25c --- /dev/null +++ b/backend/src/main/java/moim_today/dto/meeting/meeting_comment/MeetingCommentDeleteRequest.java @@ -0,0 +1,6 @@ +package moim_today.dto.meeting.meeting_comment; + +public record MeetingCommentDeleteRequest( + long meetingCommentId +) { +} diff --git a/backend/src/main/java/moim_today/dto/meeting/meeting_comment/MeetingCommentResponse.java b/backend/src/main/java/moim_today/dto/meeting/meeting_comment/MeetingCommentResponse.java new file mode 100644 index 00000000..8b268e12 --- /dev/null +++ b/backend/src/main/java/moim_today/dto/meeting/meeting_comment/MeetingCommentResponse.java @@ -0,0 +1,22 @@ +package moim_today.dto.meeting.meeting_comment; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.querydsl.core.annotations.QueryProjection; +import lombok.Builder; + +import java.time.LocalDateTime; + +@Builder +public record MeetingCommentResponse( + long meetingCommentId, + String username, + String imageUrl, + String contents, + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "Asia/Seoul") + LocalDateTime createdAt +) { + + @QueryProjection + public MeetingCommentResponse { + } +} diff --git a/backend/src/main/java/moim_today/dto/meeting/meeting_comment/MeetingCommentUpdateRequest.java b/backend/src/main/java/moim_today/dto/meeting/meeting_comment/MeetingCommentUpdateRequest.java new file mode 100644 index 00000000..3bef0420 --- /dev/null +++ b/backend/src/main/java/moim_today/dto/meeting/meeting_comment/MeetingCommentUpdateRequest.java @@ -0,0 +1,10 @@ +package moim_today.dto.meeting.meeting_comment; + +import lombok.Builder; + +@Builder +public record MeetingCommentUpdateRequest( + long meetingCommentId, + String contents +) { +} diff --git a/backend/src/main/java/moim_today/dto/member/MemberHostResponse.java b/backend/src/main/java/moim_today/dto/member/MemberHostResponse.java index 2c28abff..29c9a126 100644 --- a/backend/src/main/java/moim_today/dto/member/MemberHostResponse.java +++ b/backend/src/main/java/moim_today/dto/member/MemberHostResponse.java @@ -6,4 +6,10 @@ public record MemberHostResponse( boolean isHost ) { + + public static MemberHostResponse from(final boolean isHost) { + return MemberHostResponse.builder() + .isHost(isHost) + .build(); + } } diff --git a/backend/src/main/java/moim_today/dto/member/MemberJoinedMoimResponse.java b/backend/src/main/java/moim_today/dto/member/MemberJoinedMoimResponse.java new file mode 100644 index 00000000..33a4d065 --- /dev/null +++ b/backend/src/main/java/moim_today/dto/member/MemberJoinedMoimResponse.java @@ -0,0 +1,15 @@ +package moim_today.dto.member; + +import lombok.Builder; + +@Builder +public record MemberJoinedMoimResponse( + boolean isJoined +) { + + public static MemberJoinedMoimResponse from(final boolean isJoined) { + return MemberJoinedMoimResponse.builder() + .isJoined(isJoined) + .build(); + } +} diff --git a/backend/src/main/java/moim_today/dto/moim/moim/MyMoimResponse.java b/backend/src/main/java/moim_today/dto/moim/moim/MyMoimResponse.java new file mode 100644 index 00000000..e42080c9 --- /dev/null +++ b/backend/src/main/java/moim_today/dto/moim/moim/MyMoimResponse.java @@ -0,0 +1,22 @@ +package moim_today.dto.moim.moim; + +import com.querydsl.core.annotations.QueryProjection; +import lombok.Builder; + +@Builder +public record MyMoimResponse( + long moimId, + String title +) { + + @QueryProjection + public MyMoimResponse { + } + + public static MyMoimResponse of(final long moimId, final String title) { + return MyMoimResponse.builder() + .moimId(moimId) + .title(title) + .build(); + } +} diff --git a/backend/src/main/java/moim_today/dto/moim/moim_notice/MoimNoticeCreateRequest.java b/backend/src/main/java/moim_today/dto/moim/moim_notice/MoimNoticeCreateRequest.java index 4be6e318..4bf6439e 100644 --- a/backend/src/main/java/moim_today/dto/moim/moim_notice/MoimNoticeCreateRequest.java +++ b/backend/src/main/java/moim_today/dto/moim/moim_notice/MoimNoticeCreateRequest.java @@ -1,7 +1,9 @@ package moim_today.dto.moim.moim_notice; +import lombok.Builder; import moim_today.persistence.entity.moim.moim_notice.MoimNoticeJpaEntity; +@Builder public record MoimNoticeCreateRequest( long moimId, String title, diff --git a/backend/src/main/java/moim_today/global/config/WebConfig.java b/backend/src/main/java/moim_today/global/config/WebConfig.java index 6171d8a9..915c2aa4 100644 --- a/backend/src/main/java/moim_today/global/config/WebConfig.java +++ b/backend/src/main/java/moim_today/global/config/WebConfig.java @@ -29,6 +29,8 @@ public void addInterceptors(final InterceptorRegistry registry) { "/api/login", "/api/certification/**", "/api/sign-up", + "/api/session-validation", + "/api", "/api/universities", "/api/universities/departments/**", "/api/departments/university-name", diff --git a/backend/src/main/java/moim_today/global/constant/NumberConstant.java b/backend/src/main/java/moim_today/global/constant/NumberConstant.java index f2ac7a90..ce0dc72f 100644 --- a/backend/src/main/java/moim_today/global/constant/NumberConstant.java +++ b/backend/src/main/java/moim_today/global/constant/NumberConstant.java @@ -19,6 +19,7 @@ public enum NumberConstant { SCHEDULE_TIME_START_IDX(0), MOIM_SCHEDULE_FIRST_IDX(0), TIME_TABLE_SCHEDULING_COUNT(10), + DEFAULT_PARENT_COMMENT_ID(0), EVERYTIME_ITEM_START_INDEX(0), EVERYTIME_NODE_START_INDEX(0), diff --git a/backend/src/main/java/moim_today/global/constant/exception/MailExceptionConstant.java b/backend/src/main/java/moim_today/global/constant/exception/MailExceptionConstant.java index a59f4a13..b6be6796 100644 --- a/backend/src/main/java/moim_today/global/constant/exception/MailExceptionConstant.java +++ b/backend/src/main/java/moim_today/global/constant/exception/MailExceptionConstant.java @@ -5,7 +5,9 @@ public enum MailExceptionConstant { MAIL_SEND_ERROR("메일 전송 도중에 에러가 발생했습니다. 관리자에게 문의 바랍니다."), MAIL_CERTIFICATION_TOKEN_NOT_FOUND_ERROR("메일 인증 정보를 찾을 수 없습니다."), WRONG_EMAIL_FROM_ERROR("잘못된 이메일 형식입니다."), - MAIL_INVALID_FORMAT_ERROR("올바른 메일 형식이 아닙니다."); + MAIL_INVALID_FORMAT_ERROR("올바른 메일 형식이 아닙니다."), + + MAIL_SUBSCRIBE_NOT_FOUND_ERROR("메일 수신 여부가 존재하지 않습니다."); private final String message; diff --git a/backend/src/main/java/moim_today/global/constant/exception/MeetingExceptionConstant.java b/backend/src/main/java/moim_today/global/constant/exception/MeetingExceptionConstant.java index bf6e2059..a5877887 100644 --- a/backend/src/main/java/moim_today/global/constant/exception/MeetingExceptionConstant.java +++ b/backend/src/main/java/moim_today/global/constant/exception/MeetingExceptionConstant.java @@ -4,7 +4,7 @@ public enum MeetingExceptionConstant { MEETING_NOT_FOUND_ERROR("미팅이 존재하지 않습니다."), JOINED_MEETING_NOT_FOUND_ERROR("미팅 참석 정보가 존재하지 않습니다."), - + MEETING_COMMENT_FORBIDDEN_ERROR("댓글 작성자만 접근할 수 있습니다."), MEETING_FORBIDDEN_ERROR("해당 미팅에 대한 권한이 없습니다."); private final String message; diff --git a/backend/src/main/java/moim_today/global/response/CollectionResponse.java b/backend/src/main/java/moim_today/global/response/CollectionResponse.java index db6bf3e6..18bf5e66 100644 --- a/backend/src/main/java/moim_today/global/response/CollectionResponse.java +++ b/backend/src/main/java/moim_today/global/response/CollectionResponse.java @@ -3,7 +3,7 @@ public record CollectionResponse ( T data ) { - public static CollectionResponse of(final T data) { + public static CollectionResponse from(final T data) { return new CollectionResponse<>(data); } } diff --git a/backend/src/main/java/moim_today/implement/email_subscribe/EmailSubscribeAppender.java b/backend/src/main/java/moim_today/implement/email_subscribe/EmailSubscribeAppender.java new file mode 100644 index 00000000..8da7676e --- /dev/null +++ b/backend/src/main/java/moim_today/implement/email_subscribe/EmailSubscribeAppender.java @@ -0,0 +1,22 @@ +package moim_today.implement.email_subscribe; + +import moim_today.global.annotation.Implement; +import moim_today.persistence.entity.email_subscribe.EmailSubscribeJpaEntity; +import moim_today.persistence.repository.email_subscribe.EmailSubscribeRepository; +import org.springframework.transaction.annotation.Transactional; + +@Implement +public class EmailSubscribeAppender { + + private final EmailSubscribeRepository emailSubscribeRepository; + + public EmailSubscribeAppender(final EmailSubscribeRepository emailSubscribeRepository) { + this.emailSubscribeRepository = emailSubscribeRepository; + } + + @Transactional + public void saveEmailSubscription(final long memberId, final boolean subscribeStatus) { + EmailSubscribeJpaEntity emailSubscribeJpaEntity = EmailSubscribeJpaEntity.toEntity(memberId, subscribeStatus); + emailSubscribeRepository.save(emailSubscribeJpaEntity); + } +} diff --git a/backend/src/main/java/moim_today/implement/email_subscribe/EmailSubscribeUpdater.java b/backend/src/main/java/moim_today/implement/email_subscribe/EmailSubscribeUpdater.java new file mode 100644 index 00000000..883b85c0 --- /dev/null +++ b/backend/src/main/java/moim_today/implement/email_subscribe/EmailSubscribeUpdater.java @@ -0,0 +1,22 @@ +package moim_today.implement.email_subscribe; + +import moim_today.global.annotation.Implement; +import moim_today.persistence.entity.email_subscribe.EmailSubscribeJpaEntity; +import moim_today.persistence.repository.email_subscribe.EmailSubscribeRepository; +import org.springframework.transaction.annotation.Transactional; + +@Implement +public class EmailSubscribeUpdater { + + private final EmailSubscribeRepository emailSubscribeRepository; + + public EmailSubscribeUpdater(final EmailSubscribeRepository emailSubscribeRepository) { + this.emailSubscribeRepository = emailSubscribeRepository; + } + + @Transactional + public void updateSubscribeStatus(final long memberId, final boolean subscribeStatus) { + EmailSubscribeJpaEntity emailSubscribeJpaEntity = emailSubscribeRepository.getByMemberId(memberId); + emailSubscribeJpaEntity.updateSubscribeStatus(subscribeStatus); + } +} diff --git a/backend/src/main/java/moim_today/implement/email_subscribe/EmailSubscriptionFinder.java b/backend/src/main/java/moim_today/implement/email_subscribe/EmailSubscriptionFinder.java new file mode 100644 index 00000000..39df3f8b --- /dev/null +++ b/backend/src/main/java/moim_today/implement/email_subscribe/EmailSubscriptionFinder.java @@ -0,0 +1,20 @@ +package moim_today.implement.email_subscribe; + +import moim_today.global.annotation.Implement; +import moim_today.persistence.repository.email_subscribe.EmailSubscribeRepository; +import org.springframework.transaction.annotation.Transactional; + +@Implement +public class EmailSubscriptionFinder { + + private final EmailSubscribeRepository emailSubscribeRepository; + + public EmailSubscriptionFinder(final EmailSubscribeRepository emailSubscribeRepository) { + this.emailSubscribeRepository = emailSubscribeRepository; + } + + @Transactional(readOnly = true) + public boolean getSubscriptionStatus(final long memberId) { + return emailSubscribeRepository.getSubscriptionStatus(memberId); + } +} diff --git a/backend/src/main/java/moim_today/implement/mail/MailScheduler.java b/backend/src/main/java/moim_today/implement/mail/MailScheduler.java index 8a15d8dd..993ccc21 100644 --- a/backend/src/main/java/moim_today/implement/mail/MailScheduler.java +++ b/backend/src/main/java/moim_today/implement/mail/MailScheduler.java @@ -17,7 +17,7 @@ @Implement public class MailScheduler { - private static final int ONE_HOUR_IN_MILLISECONDS = 60 * 60 * 1000; + private static final String HOURLY_CRON_EXPRESSION = "0 0 * * * *"; private final MailSender mailSender; private final MeetingFinder meetingFinder; @@ -30,7 +30,7 @@ public MailScheduler(final MailSender mailSender, final MeetingFinder meetingFin this.joinedMeetingUpdater = joinedMeetingUpdater; } - @Scheduled(fixedRate = ONE_HOUR_IN_MILLISECONDS) + @Scheduled(cron = HOURLY_CRON_EXPRESSION) public void sendUpcomingMeetingMails() { LocalDateTime currentDateTime = LocalDateTime.now(); List upcomingNotices = meetingFinder.findUpcomingNotices(currentDateTime); diff --git a/backend/src/main/java/moim_today/implement/meeting/joined_meeting/JoinedMeetingAppender.java b/backend/src/main/java/moim_today/implement/meeting/joined_meeting/JoinedMeetingAppender.java index e07c7c9f..77367ffa 100644 --- a/backend/src/main/java/moim_today/implement/meeting/joined_meeting/JoinedMeetingAppender.java +++ b/backend/src/main/java/moim_today/implement/meeting/joined_meeting/JoinedMeetingAppender.java @@ -27,10 +27,13 @@ public void saveJoinedMeeting(final long moimId, final long meetingId) { List joinedMeetings = new ArrayList<>(); for (long memberId : memberIds) { - JoinedMeetingJpaEntity joinedMeeting = JoinedMeetingJpaEntity.toEntity(meetingId, memberId, true); - joinedMeetings.add(joinedMeeting); - } + boolean alreadyJoinedMeeting = joinedMeetingRepository.alreadyJoinedMeeting(memberId, meetingId); + if(!alreadyJoinedMeeting) { + JoinedMeetingJpaEntity joinedMeeting = JoinedMeetingJpaEntity.toEntity(meetingId, memberId, true); + joinedMeetings.add(joinedMeeting); + } + } joinedMeetingRepository.saveAll(joinedMeetings); } } diff --git a/backend/src/main/java/moim_today/implement/meeting/joined_meeting/JoinedMeetingRemover.java b/backend/src/main/java/moim_today/implement/meeting/joined_meeting/JoinedMeetingRemover.java index 122fc770..2f1a4bf3 100644 --- a/backend/src/main/java/moim_today/implement/meeting/joined_meeting/JoinedMeetingRemover.java +++ b/backend/src/main/java/moim_today/implement/meeting/joined_meeting/JoinedMeetingRemover.java @@ -22,6 +22,11 @@ public void deleteAllByMeetingIdIn(final List meetingIds) { } } + @Transactional + public void deleteAllByMeetingId(final long meetingId) { + joinedMeetingRepository.deleteAllByMeetingId(meetingId); + } + @Transactional public void deleteAllByMemberInMeeting(final long memberId, final List meetingIds) { if(!meetingIds.isEmpty()){ diff --git a/backend/src/main/java/moim_today/implement/meeting/joined_meeting/JoinedMeetingUpdater.java b/backend/src/main/java/moim_today/implement/meeting/joined_meeting/JoinedMeetingUpdater.java index 219e66b3..e17065e3 100644 --- a/backend/src/main/java/moim_today/implement/meeting/joined_meeting/JoinedMeetingUpdater.java +++ b/backend/src/main/java/moim_today/implement/meeting/joined_meeting/JoinedMeetingUpdater.java @@ -17,7 +17,7 @@ public JoinedMeetingUpdater(final JoinedMeetingRepository joinedMeetingRepositor @Transactional public void updateAttendance(final long memberId, final long meetingId, final boolean attendance) { JoinedMeetingJpaEntity joinedMeetingJpaEntity = - joinedMeetingRepository.findByMemberIdAndMeetingId(memberId, meetingId); + joinedMeetingRepository.getByMemberIdAndMeetingId(memberId, meetingId); joinedMeetingJpaEntity.updateAttendance(attendance); } diff --git a/backend/src/main/java/moim_today/implement/meeting/meeting/MeetingAppender.java b/backend/src/main/java/moim_today/implement/meeting/meeting/MeetingAppender.java index 43f17e8a..d05fedb5 100644 --- a/backend/src/main/java/moim_today/implement/meeting/meeting/MeetingAppender.java +++ b/backend/src/main/java/moim_today/implement/meeting/meeting/MeetingAppender.java @@ -15,7 +15,7 @@ public MeetingAppender(final MeetingRepository meetingRepository) { } @Transactional - public void saveMeeting(final MeetingJpaEntity meetingJpaEntity) { - meetingRepository.save(meetingJpaEntity); + public MeetingJpaEntity saveMeeting(final MeetingJpaEntity meetingJpaEntity) { + return meetingRepository.save(meetingJpaEntity); } } diff --git a/backend/src/main/java/moim_today/implement/meeting/meeting/MeetingFinder.java b/backend/src/main/java/moim_today/implement/meeting/meeting/MeetingFinder.java index ccbd4b64..9fdc01e3 100644 --- a/backend/src/main/java/moim_today/implement/meeting/meeting/MeetingFinder.java +++ b/backend/src/main/java/moim_today/implement/meeting/meeting/MeetingFinder.java @@ -2,8 +2,8 @@ import moim_today.domain.meeting.enums.MeetingStatus; import moim_today.dto.mail.UpcomingMeetingNoticeResponse; -import moim_today.dto.meeting.MeetingDetailResponse; -import moim_today.dto.meeting.MeetingSimpleDao; +import moim_today.dto.meeting.meeting.MeetingDetailResponse; +import moim_today.dto.meeting.meeting.MeetingSimpleDao; import moim_today.dto.member.MemberSimpleResponse; import moim_today.global.annotation.Implement; import moim_today.implement.meeting.joined_meeting.JoinedMeetingFinder; @@ -37,7 +37,7 @@ public List findAllByMoimId(final long moimId, final long memb final LocalDateTime currentDateTime) { if (meetingStatus.equals(MeetingStatus.ALL)) { return meetingRepository.findAllByMoimId(moimId, memberId, currentDateTime); - } else if(meetingStatus.equals(MeetingStatus.PAST)) { + } else if (meetingStatus.equals(MeetingStatus.PAST)) { return meetingRepository.findAllPastByMoimId(moimId, memberId, currentDateTime); } @@ -55,4 +55,9 @@ public MeetingDetailResponse findDetailsById(final long meetingId) { public List findUpcomingNotices(final LocalDateTime currentDateTime) { return meetingRepository.findUpcomingNotices(currentDateTime); } + + @Transactional(readOnly = true) + public long getMoimIdByMeetingId(final long meetingId) { + return meetingRepository.findMoimIdByMeetingId(meetingId); + } } diff --git a/backend/src/main/java/moim_today/implement/meeting/meeting/MeetingManager.java b/backend/src/main/java/moim_today/implement/meeting/meeting/MeetingManager.java index d38089c7..f3f732de 100644 --- a/backend/src/main/java/moim_today/implement/meeting/meeting/MeetingManager.java +++ b/backend/src/main/java/moim_today/implement/meeting/meeting/MeetingManager.java @@ -1,9 +1,11 @@ package moim_today.implement.meeting.meeting; import moim_today.domain.meeting.enums.MeetingCategory; -import moim_today.dto.meeting.MeetingCreateRequest; +import moim_today.dto.meeting.meeting.MeetingCreateResponse; +import moim_today.dto.meeting.meeting.MeetingCreateRequest; import moim_today.dto.moim.moim.MoimDateResponse; import moim_today.global.annotation.Implement; +import moim_today.global.error.ForbiddenException; import moim_today.implement.meeting.joined_meeting.JoinedMeetingAppender; import moim_today.implement.meeting.joined_meeting.JoinedMeetingFinder; import moim_today.implement.moim.moim.MoimFinder; @@ -17,7 +19,9 @@ import java.time.LocalTime; import java.util.List; -import static moim_today.global.constant.TimeConstant.*; +import static moim_today.global.constant.NumberConstant.SCHEDULE_MEETING_ID; +import static moim_today.global.constant.TimeConstant.ONE_WEEK; +import static moim_today.global.constant.exception.MoimExceptionConstant.ORGANIZER_FORBIDDEN_ERROR; @Implement @@ -40,46 +44,73 @@ public MeetingManager(final MeetingAppender meetingAppender, final MoimFinder mo } @Transactional - public void createMeeting(final MeetingCreateRequest meetingCreateRequest) { + public MeetingCreateResponse createMeeting(final long memberId, + final MeetingCreateRequest meetingCreateRequest, + final LocalDate currentDate) { + validateMemberIsHost(memberId, meetingCreateRequest); MeetingCategory meetingCategory = meetingCreateRequest.meetingCategory(); String moimTitle = moimFinder.getTitleById(meetingCreateRequest.moimId()); if (meetingCategory.equals(MeetingCategory.SINGLE)) { - createSingleMeeting(meetingCreateRequest, moimTitle); + return createSingleMeeting(meetingCreateRequest, moimTitle); + } else { + return createRegularMeeting(meetingCreateRequest, moimTitle, currentDate); + } + } - } else if (meetingCategory.equals(MeetingCategory.REGULAR)) { - createRegularMeeting(meetingCreateRequest, moimTitle); + private void validateMemberIsHost(final long memberId, final MeetingCreateRequest meetingCreateRequest) { + if (!moimFinder.isHost(memberId, meetingCreateRequest.moimId())) { + throw new ForbiddenException(ORGANIZER_FORBIDDEN_ERROR.message()); } } - private void createSingleMeeting(final MeetingCreateRequest meetingCreateRequest, final String moimTitle) { + private MeetingCreateResponse createSingleMeeting(final MeetingCreateRequest meetingCreateRequest, final String moimTitle) { MeetingJpaEntity meetingJpaEntity = meetingCreateRequest.toEntity( meetingCreateRequest.startDateTime(), meetingCreateRequest.endDateTime() ); - meetingAppender.saveMeeting(meetingJpaEntity); + MeetingJpaEntity saveEntity = meetingAppender.saveMeeting(meetingJpaEntity); joinedMeetingAppender.saveJoinedMeeting(meetingCreateRequest.moimId(), meetingJpaEntity.getId()); createSchedules(moimTitle, meetingJpaEntity); + + return MeetingCreateResponse.of(saveEntity.getId(), meetingCreateRequest); } - private void createRegularMeeting(final MeetingCreateRequest meetingCreateRequest, final String moimTitle) { + private MeetingCreateResponse createRegularMeeting(final MeetingCreateRequest meetingCreateRequest, + final String moimTitle, final LocalDate currentDate) { MoimDateResponse moimDateResponse = moimFinder.findMoimDate(meetingCreateRequest.moimId()); - LocalDate startDate = moimDateResponse.startDate(); - LocalDate endDate = moimDateResponse.endDate(); + LocalDate moimEndDate = moimDateResponse.endDate(); - LocalTime startTime = meetingCreateRequest.startDateTime().toLocalTime(); - LocalTime endTime = meetingCreateRequest.endDateTime().toLocalTime(); + LocalTime meetingStartTime = meetingCreateRequest.startDateTime().toLocalTime(); + LocalTime meetingEndTime = meetingCreateRequest.endDateTime().toLocalTime(); + LocalDate meetingStartDate = getMeetingStartDate(meetingCreateRequest, currentDate); - for (LocalDate date = startDate; !date.isAfter(endDate); date = date.plusWeeks(ONE_WEEK.time())) { - LocalDateTime startDateTime = LocalDateTime.of(date, startTime); - LocalDateTime endDateTime = LocalDateTime.of(date, endTime); + long firstMeetingId = SCHEDULE_MEETING_ID.value(); + + for (LocalDate date = meetingStartDate; !date.isAfter(moimEndDate); date = date.plusWeeks(ONE_WEEK.time())) { + LocalDateTime startDateTime = LocalDateTime.of(date, meetingStartTime); + LocalDateTime endDateTime = LocalDateTime.of(date, meetingEndTime); MeetingJpaEntity meetingJpaEntity = meetingCreateRequest.toEntity(startDateTime, endDateTime); - meetingAppender.saveMeeting(meetingJpaEntity); + MeetingJpaEntity saveEntity = meetingAppender.saveMeeting(meetingJpaEntity); + if(firstMeetingId == SCHEDULE_MEETING_ID.value()) { + firstMeetingId = saveEntity.getId(); + } + joinedMeetingAppender.saveJoinedMeeting(meetingCreateRequest.moimId(), meetingJpaEntity.getId()); createSchedules(moimTitle, meetingJpaEntity); } + + return MeetingCreateResponse.of(firstMeetingId, meetingCreateRequest); + } + + private LocalDate getMeetingStartDate(final MeetingCreateRequest meetingCreateRequest, + final LocalDate currentDate) { + LocalDate meetingStartDate = meetingCreateRequest.startDateTime().toLocalDate(); + meetingStartDate = meetingStartDate.isAfter(currentDate) ? meetingStartDate : currentDate; + + return meetingStartDate; } private void createSchedules(final String moimTitle, final MeetingJpaEntity meetingJpaEntity) { diff --git a/backend/src/main/java/moim_today/implement/meeting/meeting/MeetingRemover.java b/backend/src/main/java/moim_today/implement/meeting/meeting/MeetingRemover.java index 3d78cc9a..9fdf7f60 100644 --- a/backend/src/main/java/moim_today/implement/meeting/meeting/MeetingRemover.java +++ b/backend/src/main/java/moim_today/implement/meeting/meeting/MeetingRemover.java @@ -20,7 +20,7 @@ public MeetingRemover(final MeetingRepository meetingRepository) { @Transactional public void deleteMeeting(final long memberId, final long meetingId) { MeetingJpaEntity meetingJpaEntity = meetingRepository.getById(meetingId); - long hostId = meetingRepository.findHostIdByMeetingId(meetingId); + long hostId = meetingRepository.getHostIdByMeetingId(meetingId); validateHostId(memberId, hostId); meetingRepository.delete(meetingJpaEntity); diff --git a/backend/src/main/java/moim_today/implement/meeting/meeting/MeetingUpdater.java b/backend/src/main/java/moim_today/implement/meeting/meeting/MeetingUpdater.java new file mode 100644 index 00000000..8c56a5f5 --- /dev/null +++ b/backend/src/main/java/moim_today/implement/meeting/meeting/MeetingUpdater.java @@ -0,0 +1,34 @@ +package moim_today.implement.meeting.meeting; + +import moim_today.dto.meeting.meeting.MeetingUpdateRequest; +import moim_today.global.annotation.Implement; +import moim_today.global.error.ForbiddenException; +import moim_today.persistence.entity.meeting.meeting.MeetingJpaEntity; +import moim_today.persistence.repository.meeting.meeting.MeetingRepository; +import org.springframework.transaction.annotation.Transactional; + +import static moim_today.global.constant.exception.MeetingExceptionConstant.MEETING_FORBIDDEN_ERROR; + +@Implement +public class MeetingUpdater { + + private final MeetingRepository meetingRepository; + + public MeetingUpdater(final MeetingRepository meetingRepository) { + this.meetingRepository = meetingRepository; + } + + @Transactional + public void updateMeeting(final long memberId, final MeetingUpdateRequest meetingUpdateRequest) { + MeetingJpaEntity meetingJpaEntity = meetingRepository.getById(meetingUpdateRequest.meetingId()); + long hostId = meetingRepository.getHostIdByMeetingId(meetingUpdateRequest.meetingId()); + validateHostId(memberId, hostId); + meetingJpaEntity.updateMeeting(meetingUpdateRequest.agenda(), meetingUpdateRequest.place()); + } + + private void validateHostId(final long memberId, final long hostId) { + if (memberId != hostId) { + throw new ForbiddenException(MEETING_FORBIDDEN_ERROR.message()); + } + } +} diff --git a/backend/src/main/java/moim_today/implement/meeting/meeting_comment/MeetingCommentAppender.java b/backend/src/main/java/moim_today/implement/meeting/meeting_comment/MeetingCommentAppender.java new file mode 100644 index 00000000..5e424ca2 --- /dev/null +++ b/backend/src/main/java/moim_today/implement/meeting/meeting_comment/MeetingCommentAppender.java @@ -0,0 +1,23 @@ +package moim_today.implement.meeting.meeting_comment; + +import moim_today.dto.meeting.meeting_comment.MeetingCommentCreateRequest; +import moim_today.global.annotation.Implement; +import moim_today.persistence.entity.meeting.meeting_comment.MeetingCommentJpaEntity; +import moim_today.persistence.repository.meeting.meeting_comment.MeetingCommentRepository; +import org.springframework.transaction.annotation.Transactional; + +@Implement +public class MeetingCommentAppender { + + private final MeetingCommentRepository meetingCommentRepository; + + public MeetingCommentAppender(final MeetingCommentRepository meetingCommentRepository) { + this.meetingCommentRepository = meetingCommentRepository; + } + + @Transactional + public void createMeetingComment(final long memberId, final MeetingCommentCreateRequest meetingCommentCreateRequest) { + MeetingCommentJpaEntity meetingCommentJpaEntity = meetingCommentCreateRequest.toEntity(memberId); + meetingCommentRepository.save(meetingCommentJpaEntity); + } +} diff --git a/backend/src/main/java/moim_today/implement/meeting/meeting_comment/MeetingCommentFinder.java b/backend/src/main/java/moim_today/implement/meeting/meeting_comment/MeetingCommentFinder.java new file mode 100644 index 00000000..16da7081 --- /dev/null +++ b/backend/src/main/java/moim_today/implement/meeting/meeting_comment/MeetingCommentFinder.java @@ -0,0 +1,29 @@ +package moim_today.implement.meeting.meeting_comment; + +import moim_today.dto.meeting.meeting_comment.MeetingCommentResponse; +import moim_today.global.annotation.Implement; +import moim_today.persistence.entity.meeting.meeting_comment.MeetingCommentJpaEntity; +import moim_today.persistence.repository.meeting.meeting_comment.MeetingCommentRepository; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Implement +public class MeetingCommentFinder { + + private final MeetingCommentRepository meetingCommentRepository; + + public MeetingCommentFinder(final MeetingCommentRepository meetingCommentRepository) { + this.meetingCommentRepository = meetingCommentRepository; + } + + @Transactional(readOnly = true) + public List findAllByMeetingId(final long meetingId) { + return meetingCommentRepository.findAllByMeetingId(meetingId); + } + + @Transactional(readOnly = true) + public MeetingCommentJpaEntity getById(final long meetingCommentId) { + return meetingCommentRepository.getById(meetingCommentId); + } +} diff --git a/backend/src/main/java/moim_today/implement/meeting/meeting_comment/MeetingCommentRemover.java b/backend/src/main/java/moim_today/implement/meeting/meeting_comment/MeetingCommentRemover.java new file mode 100644 index 00000000..633e5f27 --- /dev/null +++ b/backend/src/main/java/moim_today/implement/meeting/meeting_comment/MeetingCommentRemover.java @@ -0,0 +1,20 @@ +package moim_today.implement.meeting.meeting_comment; + +import moim_today.global.annotation.Implement; +import moim_today.persistence.repository.meeting.meeting_comment.MeetingCommentRepository; +import org.springframework.transaction.annotation.Transactional; + +@Implement +public class MeetingCommentRemover { + + private final MeetingCommentRepository meetingCommentRepository; + + public MeetingCommentRemover(final MeetingCommentRepository meetingCommentRepository) { + this.meetingCommentRepository = meetingCommentRepository; + } + + @Transactional + public void deleteById(final long meetingCommentId) { + meetingCommentRepository.deleteById(meetingCommentId); + } +} diff --git a/backend/src/main/java/moim_today/implement/meeting/meeting_comment/MeetingCommentUpdater.java b/backend/src/main/java/moim_today/implement/meeting/meeting_comment/MeetingCommentUpdater.java index a80d8dfe..ec15c8ab 100644 --- a/backend/src/main/java/moim_today/implement/meeting/meeting_comment/MeetingCommentUpdater.java +++ b/backend/src/main/java/moim_today/implement/meeting/meeting_comment/MeetingCommentUpdater.java @@ -1,6 +1,8 @@ package moim_today.implement.meeting.meeting_comment; +import moim_today.dto.meeting.meeting_comment.MeetingCommentUpdateRequest; import moim_today.global.annotation.Implement; +import moim_today.persistence.entity.meeting.meeting_comment.MeetingCommentJpaEntity; import moim_today.persistence.repository.meeting.meeting_comment.MeetingCommentRepository; import org.springframework.transaction.annotation.Transactional; @@ -10,13 +12,22 @@ public class MeetingCommentUpdater { private final MeetingCommentRepository meetingCommentRepository; + private final MeetingCommentFinder meetingCommentFinder; - public MeetingCommentUpdater(final MeetingCommentRepository meetingCommentRepository) { + public MeetingCommentUpdater(final MeetingCommentRepository meetingCommentRepository, + final MeetingCommentFinder meetingCommentFinder) { this.meetingCommentRepository = meetingCommentRepository; + this.meetingCommentFinder = meetingCommentFinder; } @Transactional public void updateDeletedMembers(final long memberId, final List meetingIds) { meetingCommentRepository.updateDeletedMembers(memberId, meetingIds); } + + @Transactional + public void updateMeetingComment(final long meetingCommentId, final MeetingCommentUpdateRequest meetingCommentUpdateRequest) { + MeetingCommentJpaEntity meetingCommentJpaEntity = meetingCommentFinder.getById(meetingCommentId); + meetingCommentJpaEntity.updateMeetingComment(meetingCommentUpdateRequest); + } } diff --git a/backend/src/main/java/moim_today/implement/member/AuthManager.java b/backend/src/main/java/moim_today/implement/member/AuthManager.java index aa1ce758..bbc8eb6a 100644 --- a/backend/src/main/java/moim_today/implement/member/AuthManager.java +++ b/backend/src/main/java/moim_today/implement/member/AuthManager.java @@ -8,6 +8,7 @@ import moim_today.dto.auth.MemberSignUpRequest; import moim_today.global.annotation.Implement; import moim_today.global.error.NotFoundException; +import moim_today.implement.email_subscribe.EmailSubscribeAppender; import moim_today.persistence.entity.member.MemberJpaEntity; import moim_today.persistence.repository.member.MemberRepository; import org.springframework.security.crypto.password.PasswordEncoder; @@ -21,13 +22,16 @@ public class AuthManager { private final MemberRepository memberRepository; private final PasswordEncoder passwordEncoder; private final ObjectMapper objectMapper; + private final EmailSubscribeAppender emailSubscribeAppender; public AuthManager(final MemberRepository memberRepository, final PasswordEncoder passwordEncoder, - final ObjectMapper objectMapper) { + final ObjectMapper objectMapper, + final EmailSubscribeAppender emailSubscribeAppender) { this.memberRepository = memberRepository; this.passwordEncoder = passwordEncoder; this.objectMapper = objectMapper; + this.emailSubscribeAppender = emailSubscribeAppender; } @Transactional(readOnly = true) @@ -58,6 +62,7 @@ public void signUp(final MemberSignUpRequest memberSignUpRequest, final HttpServ MemberSession memberSession = MemberSession.from(saveMember); String memberSessionJson = memberSession.toJson(objectMapper); memberSession.setSession(request, memberSessionJson, false); + emailSubscribeAppender.saveEmailSubscription(memberSession.id(), true); } private String passwordEncode(final String password){ diff --git a/backend/src/main/java/moim_today/implement/moim/joined_moim/JoinedMoimFinder.java b/backend/src/main/java/moim_today/implement/moim/joined_moim/JoinedMoimFinder.java index 3fb9d80e..2fce11d3 100644 --- a/backend/src/main/java/moim_today/implement/moim/joined_moim/JoinedMoimFinder.java +++ b/backend/src/main/java/moim_today/implement/moim/joined_moim/JoinedMoimFinder.java @@ -47,6 +47,11 @@ public void validateMemberNotInMoim(final long moimId, final long memberId) { } } + @Transactional(readOnly = true) + public boolean isJoining(final long moimId, final long memberId) { + return joinedMoimRepository.isJoining(moimId, memberId); + } + public List findMoimIdsByMemberId(final long memberId) { return joinedMoimRepository.findMoimIdsByMemberId(memberId); } diff --git a/backend/src/main/java/moim_today/implement/moim/moim/MoimAppender.java b/backend/src/main/java/moim_today/implement/moim/moim/MoimAppender.java index 75ecfc71..1f5a21d5 100644 --- a/backend/src/main/java/moim_today/implement/moim/moim/MoimAppender.java +++ b/backend/src/main/java/moim_today/implement/moim/moim/MoimAppender.java @@ -2,7 +2,6 @@ import moim_today.dto.moim.moim.MoimCreateRequest; import moim_today.global.annotation.Implement; -import moim_today.implement.moim.joined_moim.JoinedMoimAppender; import moim_today.persistence.entity.moim.moim.MoimJpaEntity; import moim_today.persistence.repository.moim.moim.MoimRepository; import org.springframework.transaction.annotation.Transactional; @@ -12,12 +11,9 @@ public class MoimAppender { private final MoimRepository moimRepository; - private final JoinedMoimAppender joinedMoimAppender; - public MoimAppender(final MoimRepository moimRepository, - final JoinedMoimAppender joinedMoimAppender) { + public MoimAppender(final MoimRepository moimRepository) { this.moimRepository = moimRepository; - this.joinedMoimAppender = joinedMoimAppender; } @Transactional diff --git a/backend/src/main/java/moim_today/implement/moim/moim/MoimFinder.java b/backend/src/main/java/moim_today/implement/moim/moim/MoimFinder.java index 8c3c7ca0..fbe9b02d 100644 --- a/backend/src/main/java/moim_today/implement/moim/moim/MoimFinder.java +++ b/backend/src/main/java/moim_today/implement/moim/moim/MoimFinder.java @@ -4,6 +4,7 @@ import moim_today.dto.moim.moim.MoimDateResponse; import moim_today.dto.moim.moim.MoimMemberResponse; import moim_today.dto.moim.moim.MoimSimpleResponse; +import moim_today.dto.moim.moim.MyMoimResponse; import moim_today.dto.moim.moim.enums.MoimCategoryDto; import moim_today.global.annotation.Implement; import moim_today.global.error.BadRequestException; @@ -14,7 +15,7 @@ import moim_today.persistence.repository.moim.moim.MoimRepository; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; +import java.time.LocalDate; import java.util.List; import static moim_today.global.constant.exception.MoimExceptionConstant.MOIM_CAPACITY_ERROR; @@ -34,6 +35,12 @@ public MoimFinder(final JoinedMoimFinder joinedMoimFinder, this.moimRepository = moimRepository; } + @Transactional(readOnly = true) + public List findAllMyMoimResponse(final long memberId) { + List moimIds = joinedMoimFinder.findMoimIdsByMemberId(memberId); + return moimRepository.findAllMyMoimResponse(moimIds); + } + @Transactional(readOnly = true) public List findJoinedMoims(final long moimId) { return joinedMoimFinder.findByMoimId(moimId); @@ -66,8 +73,8 @@ public MoimDateResponse findMoimDate(final long moimId) { } @Transactional(readOnly = true) - public List findAllMoimResponse(final MoimCategoryDto moimCategoryDto, final MoimSortedFilter moimSortedFilter) { - return moimRepository.findAllMoimResponse(moimCategoryDto, moimSortedFilter); + public List findAllMoimResponses(final long universityId, final MoimCategoryDto moimCategoryDto, final MoimSortedFilter moimSortedFilter) { + return moimRepository.findAllMoimResponses(universityId, moimCategoryDto, moimSortedFilter); } @Transactional(readOnly = true) @@ -87,13 +94,16 @@ public void validateCapacity(final MoimJpaEntity moimJpaEntity) { } @Transactional(readOnly = true) - public List searchMoim(final String searchParam) { - return moimRepository.searchMoimBySearchParam(searchParam); + public List searchMoim(final long universityId, final String searchParam) { + return moimRepository.searchMoimBySearchParam(universityId, searchParam); + } + + @Transactional(readOnly = true) + public List findEndedMoimSimpleResponsesByMoimIds(final List moimIds, final LocalDate now) { + return moimRepository.findEndedMoimSimpleResponsesByMoimIds(moimIds, now); } - private List extractMemberIds(final List joinedMoimJpaEntities) { - List memberIds = new ArrayList<>(); - joinedMoimJpaEntities.forEach(e -> memberIds.add(e.getMemberId())); - return memberIds; + public List findInProgressMoimSimpleResponsesByMoimIds(final List moimIds, final LocalDate now) { + return moimRepository.findInProgressMoimSimpleResponsesByMoimIds(moimIds, now); } } diff --git a/backend/src/main/java/moim_today/implement/moim/moim/MoimManager.java b/backend/src/main/java/moim_today/implement/moim/moim/MoimManager.java index 0f13d388..d9948f10 100644 --- a/backend/src/main/java/moim_today/implement/moim/moim/MoimManager.java +++ b/backend/src/main/java/moim_today/implement/moim/moim/MoimManager.java @@ -1,6 +1,8 @@ package moim_today.implement.moim.moim; +import moim_today.dto.moim.moim.MoimSimpleResponse; import moim_today.global.annotation.Implement; +import moim_today.implement.meeting.joined_meeting.JoinedMeetingAppender; import moim_today.implement.meeting.joined_meeting.JoinedMeetingRemover; import moim_today.implement.meeting.meeting.MeetingFinder; import moim_today.implement.meeting.meeting_comment.MeetingCommentUpdater; @@ -12,6 +14,7 @@ import moim_today.persistence.entity.moim.moim.MoimJpaEntity; import org.springframework.transaction.annotation.Transactional; +import java.time.LocalDate; import java.util.List; @Implement @@ -20,8 +23,9 @@ public class MoimManager { private final JoinedMoimFinder joinedMoimFinder; private final JoinedMoimRemover joinedMoimRemover; private final TodoRemover todoRemover; - private final MeetingFinder meetingFinder; + private final MeetingFinder meetingFinder; private final JoinedMeetingRemover joinedMeetingRemover; + private final JoinedMeetingAppender joinedMeetingAppender; private final MeetingCommentUpdater meetingCommentUpdater; private final ScheduleRemover scheduleRemover; private final JoinedMoimAppender joinedMoimAppender; @@ -32,6 +36,7 @@ public MoimManager(final JoinedMoimFinder joinedMoimFinder, final TodoRemover todoRemover, final MeetingFinder meetingFinder, final JoinedMeetingRemover joinedMeetingRemover, + final JoinedMeetingAppender joinedMeetingAppender, final MeetingCommentUpdater meetingCommentUpdater, final ScheduleRemover scheduleRemover, final JoinedMoimAppender joinedMoimAppender, @@ -41,6 +46,7 @@ public MoimManager(final JoinedMoimFinder joinedMoimFinder, this.todoRemover = todoRemover; this.meetingFinder = meetingFinder; this.joinedMeetingRemover = joinedMeetingRemover; + this.joinedMeetingAppender = joinedMeetingAppender; this.meetingCommentUpdater = meetingCommentUpdater; this.scheduleRemover = scheduleRemover; this.joinedMoimAppender = joinedMoimAppender; @@ -69,15 +75,45 @@ public void appendMemberToMoim(final long requestMemberId, final long moimId) { joinedMoimFinder.validateMemberNotInMoim(moimId, requestMemberId); joinedMoimAppender.createJoinedMoim(requestMemberId, moimId); + List meetingIds = meetingFinder.findMeetingIdsByMoimId(moimId); + meetingIds.forEach(meetingId -> joinedMeetingAppender.saveJoinedMeeting(moimId, meetingId)); } @Transactional(readOnly = true) - public boolean isHost(final long memberId, final long moimId){ + public boolean isHost(final long memberId, final long moimId) { return moimFinder.isHost(memberId, moimId); } + @Transactional(readOnly = true) + public boolean isJoinedMoim(final long moimId, final long memberId) { + return joinedMoimFinder.isJoining(moimId, memberId); + } + @Transactional(readOnly = true) public String getTitleById(final Long moimId) { return moimFinder.getTitleById(moimId); } + + @Transactional(readOnly = true) + public List findAllJoinedMoimSimpleResponseByEndStatus(final long memberId, final LocalDate now, final boolean ended) { + List joinedMoims = joinedMoimFinder.findMoimIdsByMemberId(memberId); + return getMoimSimpleResponses(joinedMoims, now, ended); + } + + @Transactional(readOnly = true) + public List findAllHostMoimSimpleResponsesByEndStatus(final long hostMemberId, final LocalDate now, final boolean ended) { + List joinedMoims = joinedMoimFinder.findMoimIdsByMemberId(hostMemberId); + List hostMoims = joinedMoims.stream() + .filter(moimId -> moimFinder.isHost(hostMemberId, moimId)) + .toList(); + return getMoimSimpleResponses(hostMoims, now, ended); + } + + @Transactional(readOnly = true) + public List getMoimSimpleResponses(final List joinedMoims, final LocalDate now, final boolean ended) { + if (ended) { + return moimFinder.findEndedMoimSimpleResponsesByMoimIds(joinedMoims, now); + } + return moimFinder.findInProgressMoimSimpleResponsesByMoimIds(joinedMoims, now); + } } diff --git a/backend/src/main/java/moim_today/implement/schedule/schedule/ScheduleRemover.java b/backend/src/main/java/moim_today/implement/schedule/schedule/ScheduleRemover.java index 070dbab5..36586df3 100644 --- a/backend/src/main/java/moim_today/implement/schedule/schedule/ScheduleRemover.java +++ b/backend/src/main/java/moim_today/implement/schedule/schedule/ScheduleRemover.java @@ -30,6 +30,11 @@ public void deleteAllByMeetingIdIn(final List meetingIds) { } } + @Transactional + public void deleteAllByMeetingId(final long meetingId) { + scheduleRepository.deleteAllByMeetingId(meetingId); + } + @Transactional public void deleteAllByMemberInMeeting(final long memberId, final List meetingIds) { if(!meetingIds.isEmpty()){ diff --git a/backend/src/main/java/moim_today/persistence/entity/email_subscribe/EmailSubscribeJpaEntity.java b/backend/src/main/java/moim_today/persistence/entity/email_subscribe/EmailSubscribeJpaEntity.java new file mode 100644 index 00000000..65859290 --- /dev/null +++ b/backend/src/main/java/moim_today/persistence/entity/email_subscribe/EmailSubscribeJpaEntity.java @@ -0,0 +1,42 @@ +package moim_today.persistence.entity.email_subscribe; + +import jakarta.persistence.*; +import lombok.Builder; +import lombok.Getter; +import moim_today.global.annotation.Association; +import moim_today.global.base_entity.BaseTimeEntity; + +@Getter +@Table(name = "email_subscribe") +@Entity +public class EmailSubscribeJpaEntity extends BaseTimeEntity { + + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "email_subscribe_id") + private long id; + + @Association + private long memberId; + + private boolean subscribeStatus; + + protected EmailSubscribeJpaEntity() { + } + + @Builder + private EmailSubscribeJpaEntity(final long memberId, final boolean subscribeStatus) { + this.memberId = memberId; + this.subscribeStatus = subscribeStatus; + } + + public static EmailSubscribeJpaEntity toEntity(final long memberId, final boolean subscribeStatus) { + return EmailSubscribeJpaEntity.builder() + .memberId(memberId) + .subscribeStatus(subscribeStatus) + .build(); + } + + public void updateSubscribeStatus(final boolean subscribeStatus) { + this.subscribeStatus = subscribeStatus; + } +} diff --git a/backend/src/main/java/moim_today/persistence/entity/meeting/meeting/MeetingJpaEntity.java b/backend/src/main/java/moim_today/persistence/entity/meeting/meeting/MeetingJpaEntity.java index 802f63cb..c5a8e21a 100644 --- a/backend/src/main/java/moim_today/persistence/entity/meeting/meeting/MeetingJpaEntity.java +++ b/backend/src/main/java/moim_today/persistence/entity/meeting/meeting/MeetingJpaEntity.java @@ -40,4 +40,9 @@ private MeetingJpaEntity(final long moimId, final String agenda, final LocalDate this.endDateTime = endDateTime; this.place = place; } + + public void updateMeeting(final String agenda, final String place) { + this.agenda = agenda; + this.place = place; + } } diff --git a/backend/src/main/java/moim_today/persistence/entity/meeting/meeting_comment/MeetingCommentJpaEntity.java b/backend/src/main/java/moim_today/persistence/entity/meeting/meeting_comment/MeetingCommentJpaEntity.java index cb9505b5..9d5d362a 100644 --- a/backend/src/main/java/moim_today/persistence/entity/meeting/meeting_comment/MeetingCommentJpaEntity.java +++ b/backend/src/main/java/moim_today/persistence/entity/meeting/meeting_comment/MeetingCommentJpaEntity.java @@ -1,11 +1,14 @@ package moim_today.persistence.entity.meeting.meeting_comment; -import jakarta.annotation.Nullable; import jakarta.persistence.*; import lombok.Builder; import lombok.Getter; +import moim_today.dto.meeting.meeting_comment.MeetingCommentUpdateRequest; import moim_today.global.annotation.Association; import moim_today.global.base_entity.BaseTimeEntity; +import moim_today.global.error.ForbiddenException; + +import static moim_today.global.constant.exception.MeetingExceptionConstant.MEETING_COMMENT_FORBIDDEN_ERROR; @Getter @Table(name = "meeting_comment") @@ -38,4 +41,14 @@ private MeetingCommentJpaEntity(final long meetingId, final long parentId, this.memberId = memberId; this.contents = contents; } + + public void validateMember(final long memberId) { + if(this.memberId != memberId){ + throw new ForbiddenException(MEETING_COMMENT_FORBIDDEN_ERROR.message()); + } + } + + public void updateMeetingComment(final MeetingCommentUpdateRequest meetingCommentUpdateRequest) { + this.contents = meetingCommentUpdateRequest.contents(); + } } diff --git a/backend/src/main/java/moim_today/persistence/entity/moim/moim/MoimJpaEntity.java b/backend/src/main/java/moim_today/persistence/entity/moim/moim/MoimJpaEntity.java index f9a5b210..5a444dd8 100644 --- a/backend/src/main/java/moim_today/persistence/entity/moim/moim/MoimJpaEntity.java +++ b/backend/src/main/java/moim_today/persistence/entity/moim/moim/MoimJpaEntity.java @@ -11,6 +11,7 @@ import moim_today.global.error.ForbiddenException; import java.time.LocalDate; +import java.time.LocalDateTime; import static moim_today.global.constant.MoimConstant.DEFAULT_MOIM_IMAGE_URL; import static moim_today.global.constant.MoimConstant.DEFAULT_MOIM_PASSWORD; diff --git a/backend/src/main/java/moim_today/persistence/repository/email_subscribe/EmailSubscribeJpaRepository.java b/backend/src/main/java/moim_today/persistence/repository/email_subscribe/EmailSubscribeJpaRepository.java new file mode 100644 index 00000000..e766cfc1 --- /dev/null +++ b/backend/src/main/java/moim_today/persistence/repository/email_subscribe/EmailSubscribeJpaRepository.java @@ -0,0 +1,11 @@ +package moim_today.persistence.repository.email_subscribe; + +import moim_today.persistence.entity.email_subscribe.EmailSubscribeJpaEntity; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface EmailSubscribeJpaRepository extends JpaRepository { + + Optional findByMemberId(final long memberId); +} diff --git a/backend/src/main/java/moim_today/persistence/repository/email_subscribe/EmailSubscribeRepository.java b/backend/src/main/java/moim_today/persistence/repository/email_subscribe/EmailSubscribeRepository.java new file mode 100644 index 00000000..5d5e7497 --- /dev/null +++ b/backend/src/main/java/moim_today/persistence/repository/email_subscribe/EmailSubscribeRepository.java @@ -0,0 +1,17 @@ +package moim_today.persistence.repository.email_subscribe; + +import moim_today.persistence.entity.email_subscribe.EmailSubscribeJpaEntity; + + +public interface EmailSubscribeRepository { + + EmailSubscribeJpaEntity getById(final long emailSubscribeId); + + EmailSubscribeJpaEntity getByMemberId(final long memberId); + + EmailSubscribeJpaEntity save(final EmailSubscribeJpaEntity emailSubscribeJpaEntity); + + boolean getSubscriptionStatus(final long memberId); + + long count(); +} diff --git a/backend/src/main/java/moim_today/persistence/repository/email_subscribe/EmailSubscribeRepositoryImpl.java b/backend/src/main/java/moim_today/persistence/repository/email_subscribe/EmailSubscribeRepositoryImpl.java new file mode 100644 index 00000000..80a66240 --- /dev/null +++ b/backend/src/main/java/moim_today/persistence/repository/email_subscribe/EmailSubscribeRepositoryImpl.java @@ -0,0 +1,52 @@ +package moim_today.persistence.repository.email_subscribe; + +import com.querydsl.jpa.impl.JPAQueryFactory; +import moim_today.global.error.NotFoundException; +import moim_today.persistence.entity.email_subscribe.EmailSubscribeJpaEntity; +import org.springframework.stereotype.Repository; + +import static moim_today.global.constant.exception.MailExceptionConstant.MAIL_SUBSCRIBE_NOT_FOUND_ERROR; +import static moim_today.persistence.entity.email_subscribe.QEmailSubscribeJpaEntity.*; + +@Repository +public class EmailSubscribeRepositoryImpl implements EmailSubscribeRepository { + + private final EmailSubscribeJpaRepository emailSubscribeJpaRepository; + private final JPAQueryFactory queryFactory; + + public EmailSubscribeRepositoryImpl(final EmailSubscribeJpaRepository emailSubscribeJpaRepository, + final JPAQueryFactory queryFactory) { + this.emailSubscribeJpaRepository = emailSubscribeJpaRepository; + this.queryFactory = queryFactory; + } + + @Override + public EmailSubscribeJpaEntity getById(final long emailSubscribeId) { + return emailSubscribeJpaRepository.findById(emailSubscribeId) + .orElseThrow(() -> new NotFoundException(MAIL_SUBSCRIBE_NOT_FOUND_ERROR.message())); + } + + @Override + public EmailSubscribeJpaEntity getByMemberId(final long memberId) { + return emailSubscribeJpaRepository.findByMemberId(memberId) + .orElseThrow(() -> new NotFoundException(MAIL_SUBSCRIBE_NOT_FOUND_ERROR.message())); + } + + @Override + public EmailSubscribeJpaEntity save(final EmailSubscribeJpaEntity emailSubscribeJpaEntity) { + return emailSubscribeJpaRepository.save(emailSubscribeJpaEntity); + } + + @Override + public boolean getSubscriptionStatus(final long memberId) { + return queryFactory.select(emailSubscribeJpaEntity.subscribeStatus) + .from(emailSubscribeJpaEntity) + .where(emailSubscribeJpaEntity.memberId.eq(memberId)) + .fetchFirst(); + } + + @Override + public long count() { + return emailSubscribeJpaRepository.count(); + } +} diff --git a/backend/src/main/java/moim_today/persistence/repository/meeting/joined_meeting/JoinedMeetingJpaRepository.java b/backend/src/main/java/moim_today/persistence/repository/meeting/joined_meeting/JoinedMeetingJpaRepository.java index eae51039..790fae83 100644 --- a/backend/src/main/java/moim_today/persistence/repository/meeting/joined_meeting/JoinedMeetingJpaRepository.java +++ b/backend/src/main/java/moim_today/persistence/repository/meeting/joined_meeting/JoinedMeetingJpaRepository.java @@ -4,10 +4,13 @@ import org.springframework.data.jpa.repository.JpaRepository; import java.util.List; +import java.util.Optional; public interface JoinedMeetingJpaRepository extends JpaRepository { void deleteAllByMeetingIdIn(final List meetingIds); - JoinedMeetingJpaEntity findByMemberIdAndMeetingId(final long memberId, final long meetingId); + void deleteAllByMeetingId(final long meetingId); + + Optional findByMemberIdAndMeetingId(final long memberId, final long meetingId); } diff --git a/backend/src/main/java/moim_today/persistence/repository/meeting/joined_meeting/JoinedMeetingRepository.java b/backend/src/main/java/moim_today/persistence/repository/meeting/joined_meeting/JoinedMeetingRepository.java index 18f0003c..410763de 100644 --- a/backend/src/main/java/moim_today/persistence/repository/meeting/joined_meeting/JoinedMeetingRepository.java +++ b/backend/src/main/java/moim_today/persistence/repository/meeting/joined_meeting/JoinedMeetingRepository.java @@ -9,13 +9,15 @@ public interface JoinedMeetingRepository { void deleteAllByMeetingIdIn(final List meetingIds); + void deleteAllByMeetingId(final long meetingId); + JoinedMeetingJpaEntity save(final JoinedMeetingJpaEntity joinedMeetingJpaEntity); void saveAll(final List joinedMeetingJpaEntities); List findAllMemberIdByMeetingId(final long meetingId); - JoinedMeetingJpaEntity findByMemberIdAndMeetingId(final long memberId, final long meetingId); + JoinedMeetingJpaEntity getByMemberIdAndMeetingId(final long memberId, final long meetingId); List findAll(); @@ -26,4 +28,6 @@ public interface JoinedMeetingRepository { JoinedMeetingJpaEntity getById(final long joinedMeetingId); List findMembersJoinedMeeting(final long meetingId); + + boolean alreadyJoinedMeeting(final long memberId, final long meetingId); } diff --git a/backend/src/main/java/moim_today/persistence/repository/meeting/joined_meeting/JoinedMeetingRepositoryImpl.java b/backend/src/main/java/moim_today/persistence/repository/meeting/joined_meeting/JoinedMeetingRepositoryImpl.java index a2c83566..d2ffd048 100644 --- a/backend/src/main/java/moim_today/persistence/repository/meeting/joined_meeting/JoinedMeetingRepositoryImpl.java +++ b/backend/src/main/java/moim_today/persistence/repository/meeting/joined_meeting/JoinedMeetingRepositoryImpl.java @@ -30,6 +30,11 @@ public void deleteAllByMeetingIdIn(final List meetingIds) { joinedMeetingJpaRepository.deleteAllByMeetingIdIn(meetingIds); } + @Override + public void deleteAllByMeetingId(final long meetingId) { + joinedMeetingJpaRepository.deleteAllByMeetingId(meetingId); + } + @Override public JoinedMeetingJpaEntity save(final JoinedMeetingJpaEntity joinedMeetingJpaEntity) { return joinedMeetingJpaRepository.save(joinedMeetingJpaEntity); @@ -49,8 +54,9 @@ public List findAllMemberIdByMeetingId(final long meetingId) { } @Override - public JoinedMeetingJpaEntity findByMemberIdAndMeetingId(final long memberId, final long meetingId) { - return joinedMeetingJpaRepository.findByMemberIdAndMeetingId(memberId, meetingId); + public JoinedMeetingJpaEntity getByMemberIdAndMeetingId(final long memberId, final long meetingId) { + return joinedMeetingJpaRepository.findByMemberIdAndMeetingId(memberId, meetingId) + .orElseThrow(() -> new NotFoundException(JOINED_MEETING_NOT_FOUND_ERROR.message())); } @Override @@ -90,4 +96,12 @@ public List findMembersJoinedMeeting(final long meetingId) .where(joinedMeetingJpaEntity.meetingId.eq(meetingId)) .fetch(); } + + @Override + public boolean alreadyJoinedMeeting(final long memberId, final long meetingId) { + return queryFactory.selectFrom(joinedMeetingJpaEntity) + .where(joinedMeetingJpaEntity.memberId.eq(memberId) + .and(joinedMeetingJpaEntity.meetingId.eq(meetingId))) + .fetchOne() != null; + } } diff --git a/backend/src/main/java/moim_today/persistence/repository/meeting/meeting/MeetingRepository.java b/backend/src/main/java/moim_today/persistence/repository/meeting/meeting/MeetingRepository.java index e535fd68..888ffd6a 100644 --- a/backend/src/main/java/moim_today/persistence/repository/meeting/meeting/MeetingRepository.java +++ b/backend/src/main/java/moim_today/persistence/repository/meeting/meeting/MeetingRepository.java @@ -1,7 +1,7 @@ package moim_today.persistence.repository.meeting.meeting; import moim_today.dto.mail.UpcomingMeetingNoticeResponse; -import moim_today.dto.meeting.MeetingSimpleDao; +import moim_today.dto.meeting.meeting.MeetingSimpleDao; import moim_today.persistence.entity.meeting.meeting.MeetingJpaEntity; import java.time.LocalDateTime; @@ -17,7 +17,7 @@ public interface MeetingRepository { List findAllPastByMoimId(final long moimId, final long memberId, final LocalDateTime currentDateTime); - long findHostIdByMeetingId(final long meetingId); + long getHostIdByMeetingId(final long meetingId); List findUpcomingNotices(final LocalDateTime currentDateTime); @@ -28,4 +28,6 @@ public interface MeetingRepository { void delete(final MeetingJpaEntity meetingJpaEntity); long count(); + + long findMoimIdByMeetingId(final long meetingId); } diff --git a/backend/src/main/java/moim_today/persistence/repository/meeting/meeting/MeetingRepositoryImpl.java b/backend/src/main/java/moim_today/persistence/repository/meeting/meeting/MeetingRepositoryImpl.java index 11cdb430..334106d0 100644 --- a/backend/src/main/java/moim_today/persistence/repository/meeting/meeting/MeetingRepositoryImpl.java +++ b/backend/src/main/java/moim_today/persistence/repository/meeting/meeting/MeetingRepositoryImpl.java @@ -3,12 +3,12 @@ import com.querydsl.jpa.impl.JPAQueryFactory; import moim_today.dto.mail.QUpcomingMeetingNoticeResponse; import moim_today.dto.mail.UpcomingMeetingNoticeResponse; -import moim_today.dto.meeting.MeetingSimpleDao; -import moim_today.dto.meeting.QMeetingSimpleDao; +import moim_today.dto.meeting.meeting.MeetingSimpleDao; +import moim_today.dto.meeting.meeting.QMeetingSimpleDao; import moim_today.global.error.NotFoundException; +import moim_today.persistence.entity.email_subscribe.QEmailSubscribeJpaEntity; import moim_today.persistence.entity.meeting.meeting.MeetingJpaEntity; -import moim_today.persistence.entity.meeting.meeting.QMeetingJpaEntity; -import moim_today.persistence.entity.moim.moim.QMoimJpaEntity; +import moim_today.persistence.entity.member.QMemberJpaEntity; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; @@ -16,10 +16,11 @@ import java.util.List; import static moim_today.global.constant.exception.MeetingExceptionConstant.MEETING_NOT_FOUND_ERROR; -import static moim_today.persistence.entity.meeting.joined_meeting.QJoinedMeetingJpaEntity.*; +import static moim_today.persistence.entity.email_subscribe.QEmailSubscribeJpaEntity.*; +import static moim_today.persistence.entity.meeting.joined_meeting.QJoinedMeetingJpaEntity.joinedMeetingJpaEntity; import static moim_today.persistence.entity.meeting.meeting.QMeetingJpaEntity.meetingJpaEntity; -import static moim_today.persistence.entity.member.QMemberJpaEntity.*; -import static moim_today.persistence.entity.moim.moim.QMoimJpaEntity.*; +import static moim_today.persistence.entity.member.QMemberJpaEntity.memberJpaEntity; +import static moim_today.persistence.entity.moim.moim.QMoimJpaEntity.moimJpaEntity; @Repository public class MeetingRepositoryImpl implements MeetingRepository { @@ -54,9 +55,11 @@ public List findAllByMoimId(final long moimId, final long memb joinedMeetingJpaEntity.attendance )) .from(meetingJpaEntity) - .where(meetingJpaEntity.moimId.eq(moimId)) - .join(joinedMeetingJpaEntity).on(joinedMeetingJpaEntity.meetingId.eq(meetingJpaEntity.id) - .and(joinedMeetingJpaEntity.memberId.eq(memberId))) + .join(joinedMeetingJpaEntity).on(joinedMeetingJpaEntity.meetingId.eq(meetingJpaEntity.id)) + .where( + meetingJpaEntity.moimId.eq(moimId) + .and(joinedMeetingJpaEntity.memberId.eq(memberId)) + ) .orderBy(meetingJpaEntity.startDateTime.asc()) .fetch(); } @@ -64,17 +67,20 @@ public List findAllByMoimId(final long moimId, final long memb @Override public List findAllUpcomingByMoimId(final long moimId, final long memberId, final LocalDateTime currentDateTime) { - return queryFactory.select(new QMeetingSimpleDao( - meetingJpaEntity.id, - meetingJpaEntity.agenda, - meetingJpaEntity.startDateTime, - joinedMeetingJpaEntity.attendance - )) + return queryFactory.select( + new QMeetingSimpleDao( + meetingJpaEntity.id, + meetingJpaEntity.agenda, + meetingJpaEntity.startDateTime, + joinedMeetingJpaEntity.attendance + )) .from(meetingJpaEntity) - .where(meetingJpaEntity.moimId.eq(moimId) - .and(meetingJpaEntity.startDateTime.after(currentDateTime))) - .join(joinedMeetingJpaEntity).on(joinedMeetingJpaEntity.meetingId.eq(meetingJpaEntity.id) - .and(joinedMeetingJpaEntity.memberId.eq(memberId))) + .join(joinedMeetingJpaEntity).on(joinedMeetingJpaEntity.meetingId.eq(meetingJpaEntity.id)) + .where( + meetingJpaEntity.moimId.eq(moimId) + .and(meetingJpaEntity.startDateTime.after(currentDateTime)) + .and(joinedMeetingJpaEntity.memberId.eq(memberId)) + ) .orderBy(meetingJpaEntity.startDateTime.asc()) .fetch(); } @@ -82,27 +88,31 @@ public List findAllUpcomingByMoimId(final long moimId, final l @Override public List findAllPastByMoimId(final long moimId, final long memberId, final LocalDateTime currentDateTime) { - return queryFactory.select(new QMeetingSimpleDao( - meetingJpaEntity.id, - meetingJpaEntity.agenda, - meetingJpaEntity.startDateTime, - joinedMeetingJpaEntity.attendance - )) + return queryFactory.select( + new QMeetingSimpleDao( + meetingJpaEntity.id, + meetingJpaEntity.agenda, + meetingJpaEntity.startDateTime, + joinedMeetingJpaEntity.attendance + )) .from(meetingJpaEntity) - .join(joinedMeetingJpaEntity).on(joinedMeetingJpaEntity.meetingId.eq(meetingJpaEntity.id) - .and(joinedMeetingJpaEntity.memberId.eq(memberId))) - .where(meetingJpaEntity.moimId.eq(moimId) - .and(meetingJpaEntity.startDateTime.before(currentDateTime))) + .join(joinedMeetingJpaEntity).on(joinedMeetingJpaEntity.meetingId.eq(meetingJpaEntity.id)) + .where( + meetingJpaEntity.moimId.eq(moimId) + .and(meetingJpaEntity.startDateTime.before(currentDateTime)) + .and(joinedMeetingJpaEntity.memberId.eq(memberId)) + ) .orderBy(meetingJpaEntity.startDateTime.asc()) .fetch(); } @Override - public long findHostIdByMeetingId(final long meetingId) { + public long getHostIdByMeetingId(final long meetingId) { return queryFactory.select(moimJpaEntity.memberId) .from(meetingJpaEntity) .join(moimJpaEntity).on(moimJpaEntity.id.eq(meetingJpaEntity.moimId)) - .fetchFirst(); + .stream().findAny() + .orElseThrow(() -> new NotFoundException(MEETING_NOT_FOUND_ERROR.message())); } @Override @@ -124,10 +134,13 @@ public List findUpcomingNotices(final LocalDateTi .from(meetingJpaEntity) .innerJoin(joinedMeetingJpaEntity).on(joinedMeetingJpaEntity.meetingId.eq(meetingJpaEntity.id)) .innerJoin(memberJpaEntity).on(memberJpaEntity.id.eq(joinedMeetingJpaEntity.memberId)) + .innerJoin(emailSubscribeJpaEntity).on(memberJpaEntity.id.eq(emailSubscribeJpaEntity.memberId)) .where( meetingJpaEntity.startDateTime.loe(upcomingDateTime) .and(meetingJpaEntity.startDateTime.after(currentDateTime) - .and(joinedMeetingJpaEntity.upcomingNoticeSent.isFalse())) + .and(joinedMeetingJpaEntity.upcomingNoticeSent.isFalse()) + .and(emailSubscribeJpaEntity.subscribeStatus.isTrue()) + ) ) .fetch(); } @@ -152,4 +165,13 @@ public void delete(final MeetingJpaEntity meetingJpaEntity) { public long count() { return meetingJpaRepository.count(); } + + @Override + public long findMoimIdByMeetingId(final long meetingId) { + return queryFactory.select(meetingJpaEntity.moimId) + .from(meetingJpaEntity) + .where(meetingJpaEntity.id.eq(meetingId)) + .stream().findAny() + .orElseThrow(() -> new NotFoundException(MEETING_NOT_FOUND_ERROR.message())); + } } diff --git a/backend/src/main/java/moim_today/persistence/repository/meeting/meeting_comment/MeetingCommentRepository.java b/backend/src/main/java/moim_today/persistence/repository/meeting/meeting_comment/MeetingCommentRepository.java index ad0b5c47..6848eecd 100644 --- a/backend/src/main/java/moim_today/persistence/repository/meeting/meeting_comment/MeetingCommentRepository.java +++ b/backend/src/main/java/moim_today/persistence/repository/meeting/meeting_comment/MeetingCommentRepository.java @@ -1,6 +1,6 @@ package moim_today.persistence.repository.meeting.meeting_comment; -import moim_today.persistence.entity.meeting.meeting.MeetingJpaEntity; +import moim_today.dto.meeting.meeting_comment.MeetingCommentResponse; import moim_today.persistence.entity.meeting.meeting_comment.MeetingCommentJpaEntity; import java.util.List; @@ -12,4 +12,12 @@ public interface MeetingCommentRepository { void updateDeletedMembers(final long memberId, final List meetingIds); MeetingCommentJpaEntity findById(final long meetingCommentId); + + long count(); + + List findAllByMeetingId(final long meetingId); + + MeetingCommentJpaEntity getById(final long meetingCommentId); + + void deleteById(final long meetingCommentId); } diff --git a/backend/src/main/java/moim_today/persistence/repository/meeting/meeting_comment/MeetingCommentRepositoryImpl.java b/backend/src/main/java/moim_today/persistence/repository/meeting/meeting_comment/MeetingCommentRepositoryImpl.java index e45c6e7d..f77a43f2 100644 --- a/backend/src/main/java/moim_today/persistence/repository/meeting/meeting_comment/MeetingCommentRepositoryImpl.java +++ b/backend/src/main/java/moim_today/persistence/repository/meeting/meeting_comment/MeetingCommentRepositoryImpl.java @@ -1,6 +1,8 @@ package moim_today.persistence.repository.meeting.meeting_comment; import com.querydsl.jpa.impl.JPAQueryFactory; +import moim_today.dto.meeting.meeting_comment.MeetingCommentResponse; +import moim_today.dto.meeting.meeting_comment.QMeetingCommentResponse; import moim_today.global.error.NotFoundException; import moim_today.persistence.entity.meeting.meeting_comment.MeetingCommentJpaEntity; import org.springframework.stereotype.Repository; @@ -10,6 +12,7 @@ import static moim_today.global.constant.MemberConstant.UNKNOWN_MEMBER; import static moim_today.global.constant.exception.MeetingCommentExceptionConstant.MEETING_COMMENT_NOT_FOUND_ERROR; import static moim_today.persistence.entity.meeting.meeting_comment.QMeetingCommentJpaEntity.meetingCommentJpaEntity; +import static moim_today.persistence.entity.member.QMemberJpaEntity.memberJpaEntity; @Repository public class MeetingCommentRepositoryImpl implements MeetingCommentRepository { @@ -43,4 +46,34 @@ public void updateDeletedMembers(final long memberId, final List meetingId .execute(); } + @Override + public long count() { + return meetingCommentJpaRepository.count(); + } + + @Override + public List findAllByMeetingId(final long meetingId) { + return queryFactory.select(new QMeetingCommentResponse( + meetingCommentJpaEntity.id, + memberJpaEntity.username, + memberJpaEntity.memberProfileImageUrl, + meetingCommentJpaEntity.contents, + meetingCommentJpaEntity.createdAt + )) + .from(meetingCommentJpaEntity) + .join(memberJpaEntity).on(meetingCommentJpaEntity.memberId.eq(memberJpaEntity.id)) + .where(meetingCommentJpaEntity.meetingId.eq(meetingId)) + .fetch(); + } + + @Override + public MeetingCommentJpaEntity getById(final long meetingCommentId) { + return meetingCommentJpaRepository.findById(meetingCommentId) + .orElseThrow(() -> new NotFoundException(MEETING_COMMENT_NOT_FOUND_ERROR.message())); + } + + @Override + public void deleteById(final long meetingCommentId) { + meetingCommentJpaRepository.deleteById(meetingCommentId); + } } diff --git a/backend/src/main/java/moim_today/persistence/repository/moim/joined_moim/JoinedMoimJpaRepository.java b/backend/src/main/java/moim_today/persistence/repository/moim/joined_moim/JoinedMoimJpaRepository.java index f5d9e02d..d27de7a7 100644 --- a/backend/src/main/java/moim_today/persistence/repository/moim/joined_moim/JoinedMoimJpaRepository.java +++ b/backend/src/main/java/moim_today/persistence/repository/moim/joined_moim/JoinedMoimJpaRepository.java @@ -14,4 +14,6 @@ public interface JoinedMoimJpaRepository extends JpaRepository findAllByMemberId(final long memberId); } diff --git a/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepository.java b/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepository.java index fed4ae91..08131c64 100644 --- a/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepository.java +++ b/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepository.java @@ -3,9 +3,11 @@ import moim_today.domain.moim.MoimSortedFilter; import moim_today.dto.moim.moim.MoimDateResponse; import moim_today.dto.moim.moim.MoimSimpleResponse; +import moim_today.dto.moim.moim.MyMoimResponse; import moim_today.dto.moim.moim.enums.MoimCategoryDto; import moim_today.persistence.entity.moim.moim.MoimJpaEntity; +import java.time.LocalDate; import java.util.List; public interface MoimRepository { @@ -22,9 +24,15 @@ public interface MoimRepository { void deleteById(final long moimId); - List findAllMoimResponse(final MoimCategoryDto moimCategoryDto, final MoimSortedFilter moimSortedFilter); + List findAllMoimResponses(final long universityId, final MoimCategoryDto moimCategoryDto, final MoimSortedFilter moimSortedFilter); + + List findAllMyMoimResponse(final List moimIds); MoimJpaEntity getByIdWithPessimisticLock(final long moimId); - List searchMoimBySearchParam(final String searchParam); + List searchMoimBySearchParam(final long universityId, final String searchParam); + + List findEndedMoimSimpleResponsesByMoimIds(final List moimIds, final LocalDate now); + + List findInProgressMoimSimpleResponsesByMoimIds(final List moimIds, final LocalDate now); } diff --git a/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepositoryImpl.java b/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepositoryImpl.java index 36b5bd00..a664b591 100644 --- a/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepositoryImpl.java +++ b/backend/src/main/java/moim_today/persistence/repository/moim/moim/MoimRepositoryImpl.java @@ -6,19 +6,16 @@ import jakarta.persistence.LockModeType; import moim_today.domain.moim.MoimSortedFilter; import moim_today.domain.moim.enums.MoimCategory; -import moim_today.dto.moim.moim.MoimDateResponse; -import moim_today.dto.moim.moim.MoimSimpleResponse; -import moim_today.dto.moim.moim.QMoimDateResponse; -import moim_today.dto.moim.moim.QMoimSimpleResponse; +import moim_today.dto.moim.moim.*; import moim_today.dto.moim.moim.enums.MoimCategoryDto; import moim_today.global.error.NotFoundException; import moim_today.persistence.entity.moim.moim.MoimJpaEntity; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; -import java.util.Optional; - +import java.time.LocalDate; import java.util.List; +import java.util.Optional; import static moim_today.global.constant.SymbolConstant.PERCENT; import static moim_today.global.constant.exception.MoimExceptionConstant.MOIM_NOT_FOUND_ERROR; @@ -81,15 +78,15 @@ public void deleteById(final long moimId) { @Override public MoimJpaEntity getByIdWithPessimisticLock(final long moimId) { return Optional.ofNullable(queryFactory - .selectFrom(moimJpaEntity) - .where(moimJpaEntity.id.eq(moimId)) - .setLockMode(LockModeType.PESSIMISTIC_WRITE) - .fetchFirst()) + .selectFrom(moimJpaEntity) + .where(moimJpaEntity.id.eq(moimId)) + .setLockMode(LockModeType.PESSIMISTIC_WRITE) + .fetchFirst()) .orElseThrow(() -> new NotFoundException(MOIM_NOT_FOUND_ERROR.message())); } @Override - public List searchMoimBySearchParam(final String searchParam) { + public List searchMoimBySearchParam(final long universityId, final String searchParam) { return queryFactory.select(new QMoimSimpleResponse( moimJpaEntity.id, moimJpaEntity.title, @@ -100,13 +97,30 @@ public List searchMoimBySearchParam(final String searchParam moimJpaEntity.displayStatus )) .from(moimJpaEntity) - .where(moimJpaEntity.title.likeIgnoreCase(PERCENT.value() + searchParam.trim() + PERCENT.value())) + .where(moimJpaEntity.universityId.eq(universityId) + .and(moimJpaEntity.title.likeIgnoreCase(PERCENT.value() + searchParam.trim() + PERCENT.value())) + ) .fetch(); } @Override - public List findAllMoimResponse(final MoimCategoryDto moimCategoryDto, final MoimSortedFilter moimSortedFilter) { + public List findEndedMoimSimpleResponsesByMoimIds(final List moimIds, final LocalDate now) { + return queryFactory.select(new QMoimSimpleResponse( + moimJpaEntity.id, + moimJpaEntity.title, + moimJpaEntity.capacity, + moimJpaEntity.currentCount, + moimJpaEntity.imageUrl, + moimJpaEntity.moimCategory, + moimJpaEntity.displayStatus + )) + .from(moimJpaEntity) + .where(moimJpaEntity.id.in(moimIds).and(moimJpaEntity.endDate.before(now))) + .fetch(); + } + @Override + public List findInProgressMoimSimpleResponsesByMoimIds(final List moimIds, final LocalDate now) { return queryFactory.select(new QMoimSimpleResponse( moimJpaEntity.id, moimJpaEntity.title, @@ -117,11 +131,44 @@ public List findAllMoimResponse(final MoimCategoryDto moimCa moimJpaEntity.displayStatus )) .from(moimJpaEntity) - .where(applyMoimCategoryFilter(moimCategoryDto)) + .where(moimJpaEntity.id.in(moimIds).and(moimJpaEntity.endDate.goe(now))) + .fetch(); + } + + @Override + public List findAllMoimResponses(final long universityId, + final MoimCategoryDto moimCategoryDto, + final MoimSortedFilter moimSortedFilter) { + + return queryFactory.select(new QMoimSimpleResponse( + moimJpaEntity.id, + moimJpaEntity.title, + moimJpaEntity.capacity, + moimJpaEntity.currentCount, + moimJpaEntity.imageUrl, + moimJpaEntity.moimCategory, + moimJpaEntity.displayStatus + )) + .from(moimJpaEntity) + .where(moimJpaEntity.universityId.eq(universityId) + .and(applyMoimCategoryFilter(moimCategoryDto)) + ) .orderBy(createOrderBySpecifier(moimSortedFilter)) .fetch(); } + @Override + public List findAllMyMoimResponse(final List moimIds) { + return queryFactory.select( + new QMyMoimResponse( + moimJpaEntity.id, + moimJpaEntity.title + )) + .from(moimJpaEntity) + .where(moimJpaEntity.id.in(moimIds)) + .fetch(); + } + private BooleanExpression applyMoimCategoryFilter(final MoimCategoryDto moimCategoryDto) { if (moimCategoryDto == MoimCategoryDto.ALL) { return null; diff --git a/backend/src/main/java/moim_today/persistence/repository/schedule/schedule/ScheduleJpaRepository.java b/backend/src/main/java/moim_today/persistence/repository/schedule/schedule/ScheduleJpaRepository.java index 65bca9d9..74b64fa3 100644 --- a/backend/src/main/java/moim_today/persistence/repository/schedule/schedule/ScheduleJpaRepository.java +++ b/backend/src/main/java/moim_today/persistence/repository/schedule/schedule/ScheduleJpaRepository.java @@ -9,5 +9,7 @@ public interface ScheduleJpaRepository extends JpaRepository meetingIds); + void deleteAllByMeetingId(final long meetingId); + List findAllByMemberId(final long memberId); } diff --git a/backend/src/main/java/moim_today/persistence/repository/schedule/schedule/ScheduleRepository.java b/backend/src/main/java/moim_today/persistence/repository/schedule/schedule/ScheduleRepository.java index 7844cab9..133f22e6 100644 --- a/backend/src/main/java/moim_today/persistence/repository/schedule/schedule/ScheduleRepository.java +++ b/backend/src/main/java/moim_today/persistence/repository/schedule/schedule/ScheduleRepository.java @@ -35,4 +35,6 @@ public interface ScheduleRepository { void deleteAllByMeetingIdIn(final List meetingIds); void deleteAllByMemberInMeeting(final long memberId, final List meetingIds); + + void deleteAllByMeetingId(final long meetingId); } diff --git a/backend/src/main/java/moim_today/persistence/repository/schedule/schedule/ScheduleRepositoryImpl.java b/backend/src/main/java/moim_today/persistence/repository/schedule/schedule/ScheduleRepositoryImpl.java index eb35b889..a4012857 100644 --- a/backend/src/main/java/moim_today/persistence/repository/schedule/schedule/ScheduleRepositoryImpl.java +++ b/backend/src/main/java/moim_today/persistence/repository/schedule/schedule/ScheduleRepositoryImpl.java @@ -2,11 +2,8 @@ import com.querydsl.jpa.impl.JPAQueryFactory; import moim_today.domain.schedule.Schedule; -import moim_today.dto.moim.moim.QMoimMemberResponse; import moim_today.dto.schedule.*; import moim_today.global.error.NotFoundException; -import moim_today.persistence.entity.member.QMemberJpaEntity; -import moim_today.persistence.entity.schedule.schedule.QScheduleJpaEntity; import moim_today.persistence.entity.schedule.schedule.ScheduleJpaEntity; import org.springframework.jdbc.core.BatchPreparedStatementSetter; import org.springframework.jdbc.core.JdbcTemplate; @@ -184,4 +181,9 @@ public void deleteAllByMemberInMeeting(final long memberId, final List mee .and(scheduleJpaEntity.meetingId.in(meetingIds))) .execute(); } + + @Override + public void deleteAllByMeetingId(final long meetingId) { + scheduleJpaRepository.deleteAllByMeetingId(meetingId); + } } diff --git a/backend/src/main/java/moim_today/presentation/auth/AuthController.java b/backend/src/main/java/moim_today/presentation/auth/AuthController.java index 657e9191..a20e978c 100644 --- a/backend/src/main/java/moim_today/presentation/auth/AuthController.java +++ b/backend/src/main/java/moim_today/presentation/auth/AuthController.java @@ -3,14 +3,10 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.Valid; import moim_today.application.auth.AuthService; -import moim_today.domain.member.MemberSession; import moim_today.dto.auth.MemberLoginRequest; import moim_today.dto.auth.MemberSignUpRequest; -import moim_today.global.annotation.Login; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import moim_today.dto.auth.MemberSessionValidateResponse; +import org.springframework.web.bind.annotation.*; @RequestMapping("/api") @RestController @@ -29,13 +25,18 @@ public void login(@RequestBody final MemberLoginRequest memberLoginRequest, } @PostMapping("/logout") - public void logout(@Login final MemberSession memberSession, final HttpServletRequest request) { + public void logout(final HttpServletRequest request) { authService.logout(request); } @PostMapping("/sign-up") public void signUp(@Valid @RequestBody final MemberSignUpRequest memberSignUpRequest, - final HttpServletRequest request){ + final HttpServletRequest request) { authService.signUp(memberSignUpRequest, request); } + + @GetMapping("/session-validation") + public MemberSessionValidateResponse validateMemberSession(final HttpServletRequest SessionValidateResponse) { + return authService.validateMemberSession(SessionValidateResponse); + } } diff --git a/backend/src/main/java/moim_today/presentation/department/DepartmentController.java b/backend/src/main/java/moim_today/presentation/department/DepartmentController.java index 9f035900..9df5aedd 100644 --- a/backend/src/main/java/moim_today/presentation/department/DepartmentController.java +++ b/backend/src/main/java/moim_today/presentation/department/DepartmentController.java @@ -28,12 +28,12 @@ public void updateDepartmentInfo() { @GetMapping("/university-name") public CollectionResponse> getDepartmentsByUniversityName( @RequestParam(defaultValue = BLANK) final String universityName) { - return CollectionResponse.of(departmentService.getAllDepartmentByUniversityName(universityName)); + return CollectionResponse.from(departmentService.getAllDepartmentByUniversityName(universityName)); } @GetMapping("/university-id") public CollectionResponse> getDepartmentsByUniversityId( @RequestParam(defaultValue = NO_UNIVERSITY_ID) final long universityId) { - return CollectionResponse.of(departmentService.getAllDepartmentById(universityId)); + return CollectionResponse.from(departmentService.getAllDepartmentById(universityId)); } } \ No newline at end of file diff --git a/backend/src/main/java/moim_today/presentation/email_subscribe/EmailSubscribeController.java b/backend/src/main/java/moim_today/presentation/email_subscribe/EmailSubscribeController.java new file mode 100644 index 00000000..b729a829 --- /dev/null +++ b/backend/src/main/java/moim_today/presentation/email_subscribe/EmailSubscribeController.java @@ -0,0 +1,30 @@ +package moim_today.presentation.email_subscribe; + +import moim_today.application.email_subscribe.EmailSubscribeService; +import moim_today.domain.member.MemberSession; +import moim_today.dto.mail.EmailSubscribeRequest; +import moim_today.dto.mail.EmailSubscriptionResponse; +import moim_today.global.annotation.Login; +import org.springframework.web.bind.annotation.*; + +@RequestMapping("/api") +@RestController +public class EmailSubscribeController { + + private final EmailSubscribeService emailSubscribeService; + + public EmailSubscribeController(final EmailSubscribeService emailSubscribeService) { + this.emailSubscribeService = emailSubscribeService; + } + + @GetMapping("/email-subscription") + public EmailSubscriptionResponse getEmailSubscriptionStatus(@Login final MemberSession memberSession) { + return emailSubscribeService.getSubscriptionStatus(memberSession.id()); + } + + @PostMapping("/email-subscription") + public void updateEmailSubscribeStatus(@Login final MemberSession memberSession, + @RequestBody final EmailSubscribeRequest emailSubscribeRequest) { + emailSubscribeService.updateSubscribeStatus(memberSession.id(), emailSubscribeRequest.subscribeStatus()); + } +} diff --git a/backend/src/main/java/moim_today/presentation/meeting/joined_meeting/JoinedMeetingController.java b/backend/src/main/java/moim_today/presentation/meeting/joined_meeting/JoinedMeetingController.java index 2bf16264..456b87e3 100644 --- a/backend/src/main/java/moim_today/presentation/meeting/joined_meeting/JoinedMeetingController.java +++ b/backend/src/main/java/moim_today/presentation/meeting/joined_meeting/JoinedMeetingController.java @@ -18,7 +18,7 @@ public JoinedMeetingController(final JoinedMeetingService joinedMeetingService) @PostMapping("/members/meetings/{meetingId}/acceptance") public void acceptanceJoinMeeting(@Login final MemberSession memberSession, @PathVariable final long meetingId) { - joinedMeetingService.refuseJoinMeeting(memberSession.id(), meetingId); + joinedMeetingService.acceptanceJoinMeeting(memberSession.id(), meetingId); } @PostMapping("/members/meetings/{meetingId}/refusal") diff --git a/backend/src/main/java/moim_today/presentation/meeting/meeting/MeetingController.java b/backend/src/main/java/moim_today/presentation/meeting/meeting/MeetingController.java index 6c633287..1e137562 100644 --- a/backend/src/main/java/moim_today/presentation/meeting/meeting/MeetingController.java +++ b/backend/src/main/java/moim_today/presentation/meeting/meeting/MeetingController.java @@ -3,9 +3,7 @@ import moim_today.application.meeting.meeting.MeetingService; import moim_today.domain.meeting.enums.MeetingStatus; import moim_today.domain.member.MemberSession; -import moim_today.dto.meeting.MeetingCreateRequest; -import moim_today.dto.meeting.MeetingDetailResponse; -import moim_today.dto.meeting.MeetingSimpleResponse; +import moim_today.dto.meeting.meeting.*; import moim_today.global.annotation.Login; import moim_today.global.response.CollectionResponse; import org.springframework.web.bind.annotation.*; @@ -24,8 +22,10 @@ public MeetingController(final MeetingService meetingService) { } @PostMapping - public void createMeeting(@RequestBody final MeetingCreateRequest meetingCreateRequest) { - meetingService.createMeeting(meetingCreateRequest); + public MeetingCreateResponse createMeeting( + @Login final MemberSession memberSession, + @RequestBody final MeetingCreateRequest meetingCreateRequest) { + return meetingService.createMeeting(memberSession.id(), meetingCreateRequest); } @GetMapping("/{moimId}") @@ -35,7 +35,7 @@ public CollectionResponse> findAllByMoimId( @RequestParam final MeetingStatus meetingStatus) { List meetingSimpleResponses = meetingService.findAllByMoimId(moimId, memberSession.id(), meetingStatus); - return CollectionResponse.of(meetingSimpleResponses); + return CollectionResponse.from(meetingSimpleResponses); } @GetMapping("/detail/{meetingId}") @@ -43,6 +43,12 @@ public MeetingDetailResponse findDetailsByMoimId(@PathVariable final long meetin return meetingService.findDetailsById(meetingId); } + @PatchMapping + public void updateMeeting(@Login final MemberSession memberSession, + @RequestBody final MeetingUpdateRequest meetingUpdateRequest) { + meetingService.updateMeeting(memberSession.id(), meetingUpdateRequest); + } + @DeleteMapping("/{meetingId}") public void deleteMeeting(@Login final MemberSession memberSession, @PathVariable final long meetingId) { diff --git a/backend/src/main/java/moim_today/presentation/meeting/meeting_comment/MeetingCommentController.java b/backend/src/main/java/moim_today/presentation/meeting/meeting_comment/MeetingCommentController.java new file mode 100644 index 00000000..3c9c3671 --- /dev/null +++ b/backend/src/main/java/moim_today/presentation/meeting/meeting_comment/MeetingCommentController.java @@ -0,0 +1,48 @@ +package moim_today.presentation.meeting.meeting_comment; + +import moim_today.application.meeting.meeting_comment.MeetingCommentService; +import moim_today.domain.member.MemberSession; +import moim_today.dto.meeting.meeting_comment.MeetingCommentCreateRequest; +import moim_today.dto.meeting.meeting_comment.MeetingCommentDeleteRequest; +import moim_today.dto.meeting.meeting_comment.MeetingCommentResponse; +import moim_today.dto.meeting.meeting_comment.MeetingCommentUpdateRequest; +import moim_today.global.annotation.Login; +import moim_today.global.response.CollectionResponse; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RequestMapping("/api/meeting-comments") +@RestController +public class MeetingCommentController { + + private final MeetingCommentService meetingCommentService; + + public MeetingCommentController(final MeetingCommentService meetingCommentService) { + this.meetingCommentService = meetingCommentService; + } + + @PostMapping + public void createMeetingComment(@Login final MemberSession memberSession, + @RequestBody final MeetingCommentCreateRequest meetingCommentCreateRequest) { + meetingCommentService.createMeetingComment(memberSession.id(), meetingCommentCreateRequest); + } + + @GetMapping("/{meetingId}") + public CollectionResponse> findAllByMeetingId(@Login final MemberSession memberSession, + @PathVariable final long meetingId) { + return CollectionResponse.from(meetingCommentService.findAllByMeetingId(memberSession.id(), meetingId)); + } + + @PatchMapping + public void updateMeetingComment(@Login final MemberSession memberSession, + @RequestBody final MeetingCommentUpdateRequest meetingCommentUpdateRequest) { + meetingCommentService.updateMeetingComment(memberSession.id(), meetingCommentUpdateRequest); + } + + @DeleteMapping + public void deleteMeetingComment(@Login final MemberSession memberSession, + @RequestBody final MeetingCommentDeleteRequest deleteMeetingCommentRequest) { + meetingCommentService.deleteMeetingComment(memberSession.id(), deleteMeetingCommentRequest.meetingCommentId()); + } +} diff --git a/backend/src/main/java/moim_today/presentation/member/MemberController.java b/backend/src/main/java/moim_today/presentation/member/MemberController.java index 2397148f..844d90a5 100644 --- a/backend/src/main/java/moim_today/presentation/member/MemberController.java +++ b/backend/src/main/java/moim_today/presentation/member/MemberController.java @@ -51,6 +51,12 @@ public MemberHostResponse isHost(@Login final MemberSession memberSession, return memberService.isHost(memberSession.id(), moimId); } + @GetMapping("/{moimId}/joining") + public MemberJoinedMoimResponse isJoinedMoim(@Login final MemberSession memberSession, + @PathVariable final long moimId) { + return memberService.isJoinedMoim(moimId, memberSession.id()); + } + @GetMapping("/host-profile/{moimId}") public MemberSimpleResponse getHostProfileByMoimId(@PathVariable final long moimId) { return memberService.getHostProfileByMoimId(moimId); diff --git a/backend/src/main/java/moim_today/presentation/moim/MoimController.java b/backend/src/main/java/moim_today/presentation/moim/MoimController.java index b02ea40d..7006cb12 100644 --- a/backend/src/main/java/moim_today/presentation/moim/MoimController.java +++ b/backend/src/main/java/moim_today/presentation/moim/MoimController.java @@ -31,9 +31,27 @@ public MoimController(final MoimService moimService, this.moimNoticeService = moimNoticeService; } + @GetMapping + public CollectionResponse> findAllMyJoinedMoimResponse(@Login final MemberSession memberSession) { + List myMoimResponses = moimService.findAllMyJoinedMoimResponse(memberSession.id()); + return CollectionResponse.from(myMoimResponses); + } + + @GetMapping("/joined/simple") + public CollectionResponse> findAllMyJoinedMoimSimpleResponse( + @Login final MemberSession memberSession, + @RequestParam final Boolean ended, + @RequestParam(required = false, defaultValue = "false") final Boolean onlyHost){ + List myMoimSimpleResponses = moimService.findAllMyJoinedMoimSimpleResponse( + memberSession.id(), ended, onlyHost + ); + return CollectionResponse.from(myMoimSimpleResponses); + } + + @PostMapping public MoimIdResponse createMoim(@Login final MemberSession memberSession, - @RequestBody final MoimCreateRequest moimCreateRequest) { + @RequestBody final MoimCreateRequest moimCreateRequest) { return moimService.createMoim(memberSession.id(), memberSession.universityId(), moimCreateRequest); } @@ -50,9 +68,11 @@ public MoimDetailResponse getMoimDetail(@PathVariable final long moimId, } @GetMapping("/simple") - public CollectionResponse> findAllMoimResponse(@RequestParam final MoimCategoryDto moimCategoryDto, - @RequestParam final MoimSortedFilter moimSortedFilter) { - return CollectionResponse.of(moimService.findAllMoimResponse(moimCategoryDto, moimSortedFilter)); + public CollectionResponse> findAllMoimResponses( + @Login final MemberSession memberSession, + @RequestParam final MoimCategoryDto moimCategoryDto, + @RequestParam final MoimSortedFilter moimSortedFilter) { + return CollectionResponse.from(moimService.findAllMoimResponses(memberSession.universityId(), moimCategoryDto, moimSortedFilter)); } @PatchMapping @@ -100,7 +120,7 @@ public void joinMoim(@Login final MemberSession memberSession, @GetMapping("/notices/simple") public CollectionResponse> findAllMoimNotice(@Login final MemberSession memberSession, @RequestParam final long moimId) { - return CollectionResponse.of(moimNoticeService.findAllMoimNotice(memberSession.id(), moimId)); + return CollectionResponse.from(moimNoticeService.findAllMoimNotice(memberSession.id(), moimId)); } @GetMapping("/notices/detail") @@ -122,12 +142,14 @@ public void deleteMoimNotice(@Login final MemberSession memberSession, } @GetMapping("/search") - public CollectionResponse> searchMoim(@RequestParam final String searchParam) { - return CollectionResponse.of(moimService.searchMoim(searchParam)); + public CollectionResponse> searchMoim( + @Login final MemberSession memberSession, + @RequestParam final String searchParam) { + return CollectionResponse.from(moimService.searchMoim(memberSession.universityId(), searchParam)); } @GetMapping("/categories") public CollectionResponse getMoimCategories() { - return CollectionResponse.of(MoimCategory.values()); + return CollectionResponse.from(MoimCategory.values()); } } diff --git a/backend/src/main/java/moim_today/presentation/schedule/ScheduleController.java b/backend/src/main/java/moim_today/presentation/schedule/ScheduleController.java index 68cdf83a..3432e8a6 100644 --- a/backend/src/main/java/moim_today/presentation/schedule/ScheduleController.java +++ b/backend/src/main/java/moim_today/presentation/schedule/ScheduleController.java @@ -26,7 +26,7 @@ public ScheduleController(final ScheduleService scheduleService) { public CollectionResponse> findAllByWeekly(@Login final MemberSession memberSession, @RequestParam final LocalDate startDate) { List scheduleResponses = scheduleService.findAllByWeekly(memberSession.id(), startDate); - return CollectionResponse.of(scheduleResponses); + return CollectionResponse.from(scheduleResponses); } @GetMapping("/weekly/available-time/moims/{moimId}") @@ -35,7 +35,7 @@ public CollectionResponse> findAvailableTimeIn @RequestParam final LocalDate startDate) { List availableTimeInMoimResponses = scheduleService.findWeeklyAvailableTimeInMoim(moimId, startDate); - return CollectionResponse.of(availableTimeInMoimResponses); + return CollectionResponse.from(availableTimeInMoimResponses); } @GetMapping("/weekly/available-time/members/{memberId}") @@ -44,14 +44,14 @@ public CollectionResponse> findAvailableTim @RequestParam final LocalDate startDate) { List availableTimeInMoimResponses = scheduleService.findWeeklyAvailableTimeForMember(memberId, startDate); - return CollectionResponse.of(availableTimeInMoimResponses); + return CollectionResponse.from(availableTimeInMoimResponses); } @GetMapping("/monthly") public CollectionResponse> findAllByMonthly(@Login final MemberSession memberSession, @RequestParam final YearMonth yearMonth) { List scheduleResponses = scheduleService.findAllByMonthly(memberSession.id(), yearMonth); - return CollectionResponse.of(scheduleResponses); + return CollectionResponse.from(scheduleResponses); } @PostMapping("/timetable") diff --git a/backend/src/main/java/moim_today/presentation/todo/TodoController.java b/backend/src/main/java/moim_today/presentation/todo/TodoController.java index 23700159..3bf24f9d 100644 --- a/backend/src/main/java/moim_today/presentation/todo/TodoController.java +++ b/backend/src/main/java/moim_today/presentation/todo/TodoController.java @@ -32,7 +32,7 @@ public CollectionResponse> findAllTodoByMemberId( @Login final MemberSession memberSession, @RequestParam final YearMonth startDate, @RequestParam final int months){ - return CollectionResponse.of(todoService.findAllMembersTodos(memberSession.id(), startDate, months)); + return CollectionResponse.from(todoService.findAllMembersTodos(memberSession.id(), startDate, months)); } @GetMapping("moim/{moimId}") @@ -42,7 +42,7 @@ public CollectionResponse> findAllMembersTodosInMoim( @RequestParam final YearMonth startDate, @RequestParam final int months) { - return CollectionResponse.of(todoService.findAllMembersTodosInMoim(memberSession.id(), moimId, startDate, months)); + return CollectionResponse.from(todoService.findAllMembersTodosInMoim(memberSession.id(), moimId, startDate, months)); } @GetMapping("/{todoId}") diff --git a/backend/src/main/java/moim_today/presentation/university/UniversityController.java b/backend/src/main/java/moim_today/presentation/university/UniversityController.java index 7eba1de6..35862e40 100644 --- a/backend/src/main/java/moim_today/presentation/university/UniversityController.java +++ b/backend/src/main/java/moim_today/presentation/university/UniversityController.java @@ -27,6 +27,6 @@ public void fetchUniversityInfo(){ @GetMapping public CollectionResponse> getUniversity(){ - return CollectionResponse.of(universityService.getUniversities()); + return CollectionResponse.from(universityService.getUniversities()); } } diff --git a/backend/src/test/java/moim_today/domain/member/MemberSessionTest.java b/backend/src/test/java/moim_today/domain/member/MemberSessionTest.java new file mode 100644 index 00000000..5568cb3c --- /dev/null +++ b/backend/src/test/java/moim_today/domain/member/MemberSessionTest.java @@ -0,0 +1,109 @@ +package moim_today.domain.member; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.http.HttpSession; +import moim_today.dto.auth.MemberSessionValidateResponse; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.mock.web.MockHttpServletRequest; + +import static moim_today.global.constant.MemberSessionConstant.MEMBER_SESSION; +import static moim_today.util.TestConstant.*; +import static org.assertj.core.api.Assertions.*; + + +class MemberSessionTest { + + @DisplayName("세션 정보를 생성한다.") + @Test + void setSession() throws JsonProcessingException { + // given + MemberSession memberSession = new MemberSession( + MEMBER_ID.longValue(), + UNIV_ID.longValue(), + DEPARTMENT_ID.longValue(), + USERNAME.value(), + PROFILE_IMAGE_URL.value() + ); + + ObjectMapper objectMapper = new ObjectMapper(); + MockHttpServletRequest request = new MockHttpServletRequest(); + String memberSessionJson = objectMapper.writeValueAsString(memberSession); + + // when + memberSession.setSession(request, memberSessionJson, true); + + // then + HttpSession session = request.getSession(false); + assertThat(session).isNotNull(); + } + + @DisplayName("세션에 있는 정보가 일치하는지 확인한다.") + @Test + void setSessionCorrect() throws JsonProcessingException { + // given + MemberSession memberSession = new MemberSession( + MEMBER_ID.longValue(), + UNIV_ID.longValue(), + DEPARTMENT_ID.longValue(), + USERNAME.value(), + PROFILE_IMAGE_URL.value() + ); + + ObjectMapper objectMapper = new ObjectMapper(); + MockHttpServletRequest request = new MockHttpServletRequest(); + String memberSessionJson = objectMapper.writeValueAsString(memberSession); + + // when + memberSession.setSession(request, memberSessionJson, true); + HttpSession session = request.getSession(false); + assert session != null; + String sessionAttribute = (String) session.getAttribute(MEMBER_SESSION.value()); + MemberSession findSession = objectMapper.readValue(sessionAttribute, MemberSession.class); + + // then + assertThat(findSession.id()).isEqualTo(MEMBER_ID.longValue()); + assertThat(findSession.universityId()).isEqualTo(UNIV_ID.longValue()); + assertThat(findSession.departmentId()).isEqualTo(DEPARTMENT_ID.longValue()); + assertThat(findSession.username()).isEqualTo(USERNAME.value()); + assertThat(findSession.memberProfileImageUrl()).isEqualTo(PROFILE_IMAGE_URL.value()); + } + + @DisplayName("세션이 존재하면 true를 반환한다.") + @Test + void validateMemberSession() throws JsonProcessingException { + // given + MemberSession memberSession = new MemberSession( + MEMBER_ID.longValue(), + UNIV_ID.longValue(), + DEPARTMENT_ID.longValue(), + USERNAME.value(), + PROFILE_IMAGE_URL.value() + ); + + ObjectMapper objectMapper = new ObjectMapper(); + MockHttpServletRequest request = new MockHttpServletRequest(); + String memberSessionJson = objectMapper.writeValueAsString(memberSession); + memberSession.setSession(request, memberSessionJson, true); + + // when + MemberSessionValidateResponse memberSessionValidateResponse = MemberSession.validateMemberSession(request); + + // then + assertThat(memberSessionValidateResponse.isValidateMemberSession()).isTrue(); + } + + @DisplayName("세션이 존재하지 않으면 false 반환한다.") + @Test + void validateMemberSessionFail() { + // given + MockHttpServletRequest request = new MockHttpServletRequest(); + + // when + MemberSessionValidateResponse memberSessionValidateResponse = MemberSession.validateMemberSession(request); + + // then + assertThat(memberSessionValidateResponse.isValidateMemberSession()).isFalse(); + } +} \ No newline at end of file diff --git a/backend/src/test/java/moim_today/domain/schedule/ScheduleLocalDateTest.java b/backend/src/test/java/moim_today/domain/schedule/ScheduleLocalDateTest.java new file mode 100644 index 00000000..f108a0ea --- /dev/null +++ b/backend/src/test/java/moim_today/domain/schedule/ScheduleLocalDateTest.java @@ -0,0 +1,44 @@ +package moim_today.domain.schedule; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +import static org.assertj.core.api.Assertions.assertThat; + +class ScheduleLocalDateTest { + + @DisplayName("날짜 정보를 입력받아 해당 날짜의 자정 시간으로 반환한다.") + @Test + void atWeeklyStartDateTime() { + // given + LocalDate localDate = LocalDate.of(2024, 3, 4); + ScheduleLocalDate scheduleLocalDate = ScheduleLocalDate.from(localDate); + + // when + LocalDateTime startDateTime = scheduleLocalDate.atWeeklyStartDateTime(); + + // then + assertThat(startDateTime).isEqualTo( + LocalDateTime.of(2024, 3, 4, 0, 0, 0) + ); + } + + @DisplayName("날짜 정보를 입력받아 해당 날짜의 7일 후의 자정전 시간으로 반환한다.") + @Test + void atWeeklyEndDateTime() { + // given + LocalDate localDate = LocalDate.of(2024, 3, 4); + ScheduleLocalDate scheduleLocalDate = ScheduleLocalDate.from(localDate); + + // when + LocalDateTime startDateTime = scheduleLocalDate.atWeeklyEndDateTime(); + + // then + assertThat(startDateTime).isEqualTo( + LocalDateTime.of(2024, 3, 10, 23, 59, 59, 999999999) + ); + } +} \ No newline at end of file diff --git a/backend/src/test/java/moim_today/domain/schedule/ScheduleYearMonthTest.java b/backend/src/test/java/moim_today/domain/schedule/ScheduleYearMonthTest.java new file mode 100644 index 00000000..49b1a3e4 --- /dev/null +++ b/backend/src/test/java/moim_today/domain/schedule/ScheduleYearMonthTest.java @@ -0,0 +1,44 @@ +package moim_today.domain.schedule; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.time.LocalDateTime; +import java.time.YearMonth; + +import static org.assertj.core.api.Assertions.*; + +class ScheduleYearMonthTest { + + @DisplayName("당월 1일 자정 시간을 반환한다.") + @Test + void atMonthlyStartDateTime() { + // given + YearMonth yearMonth = YearMonth.of(2024, 3); + ScheduleYearMonth scheduleYearMonth = ScheduleYearMonth.from(yearMonth); + + // when + LocalDateTime startDateTime = scheduleYearMonth.atMonthlyStartDateTime(); + + // then + assertThat(startDateTime).isEqualTo( + LocalDateTime.of(2024, 3, 1, 0, 0, 0) + ); + } + + @DisplayName("다음달 1일 자정전 시간을 반환한다.") + @Test + void atMonthlyEndDateTime() { + // given + YearMonth yearMonth = YearMonth.of(2024, 3); + ScheduleYearMonth scheduleYearMonth = ScheduleYearMonth.from(yearMonth); + + // when + LocalDateTime startDateTime = scheduleYearMonth.atMonthlyEndDateTime(); + + // then + assertThat(startDateTime).isEqualTo( + LocalDateTime.of(2024, 3, 31, 23, 59, 59, 999999999) + ); + } +} \ No newline at end of file diff --git a/backend/src/test/java/moim_today/domain/schedule/enums/AvailableColorHexTest.java b/backend/src/test/java/moim_today/domain/schedule/enums/AvailableColorHexTest.java new file mode 100644 index 00000000..3adf8e3b --- /dev/null +++ b/backend/src/test/java/moim_today/domain/schedule/enums/AvailableColorHexTest.java @@ -0,0 +1,54 @@ +package moim_today.domain.schedule.enums; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.*; + + +class AvailableColorHexTest { + + @DisplayName("인덱스에 따른 각각의 색상 정보를 반환한다.") + @Test + void getHexByCount() { + // when + String hexByCount0 = AvailableColorHex.getHexByCount(0); + String hexByCount1 = AvailableColorHex.getHexByCount(1); + String hexByCount2 = AvailableColorHex.getHexByCount(2); + String hexByCount3 = AvailableColorHex.getHexByCount(3); + String hexByCount4 = AvailableColorHex.getHexByCount(4); + String hexByCount5 = AvailableColorHex.getHexByCount(5); + String hexByCount6 = AvailableColorHex.getHexByCount(6); + String hexByCount7 = AvailableColorHex.getHexByCount(7); + String hexByCount8 = AvailableColorHex.getHexByCount(8); + String hexByCount9 = AvailableColorHex.getHexByCount(9); + String hexByCount10 = AvailableColorHex.getHexByCount(10); + + // then + assertThat(hexByCount0).isEqualTo(AvailableColorHex.WHITE.colorHex()); + assertThat(hexByCount1).isEqualTo(AvailableColorHex.VERY_LIGHT_RED.colorHex()); + assertThat(hexByCount2).isEqualTo(AvailableColorHex.LIGHT_RED.colorHex()); + assertThat(hexByCount3).isEqualTo(AvailableColorHex.PALE_RED.colorHex()); + assertThat(hexByCount4).isEqualTo(AvailableColorHex.SALMON.colorHex()); + assertThat(hexByCount5).isEqualTo(AvailableColorHex.CORAL.colorHex()); + assertThat(hexByCount6).isEqualTo(AvailableColorHex.BRIGHT_RED.colorHex()); + assertThat(hexByCount7).isEqualTo(AvailableColorHex.CRIMSON.colorHex()); + assertThat(hexByCount8).isEqualTo(AvailableColorHex.DARK_RED.colorHex()); + assertThat(hexByCount9).isEqualTo(AvailableColorHex.DEEP_RED.colorHex()); + assertThat(hexByCount10).isEqualTo(AvailableColorHex.VERY_DARK_RED.colorHex()); + } + + @DisplayName("인덱스가 색상의 개수인 10을 넘어가면 가장 마지막 색상을 반환한다.") + @Test + void getHexByCountOverIndex() { + // when + String hexByCount11 = AvailableColorHex.getHexByCount(11); + String hexByCount12 = AvailableColorHex.getHexByCount(12); + String hexByCount13 = AvailableColorHex.getHexByCount(13); + + // then + assertThat(hexByCount11).isEqualTo(AvailableColorHex.VERY_DARK_RED.colorHex()); + assertThat(hexByCount12).isEqualTo(AvailableColorHex.VERY_DARK_RED.colorHex()); + assertThat(hexByCount13).isEqualTo(AvailableColorHex.VERY_DARK_RED.colorHex()); + } +} \ No newline at end of file diff --git a/backend/src/test/java/moim_today/domain/schedule/enums/ColorHexTest.java b/backend/src/test/java/moim_today/domain/schedule/enums/ColorHexTest.java new file mode 100644 index 00000000..aa9c476b --- /dev/null +++ b/backend/src/test/java/moim_today/domain/schedule/enums/ColorHexTest.java @@ -0,0 +1,55 @@ +package moim_today.domain.schedule.enums; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.*; + +class ColorHexTest { + + @DisplayName("인덱스에 따른 각각의 색상 정보를 반환한다.") + @Test + void getHexByCount() { + // when + ColorHex hexByCount0 = ColorHex.getHexByCount(0); + ColorHex hexByCount1 = ColorHex.getHexByCount(1); + ColorHex hexByCount2 = ColorHex.getHexByCount(2); + ColorHex hexByCount3 = ColorHex.getHexByCount(3); + ColorHex hexByCount4 = ColorHex.getHexByCount(4); + ColorHex hexByCount5 = ColorHex.getHexByCount(5); + + ColorHex hexByCount20 = ColorHex.getHexByCount(19); + + // then + assertThat(hexByCount0).isEqualTo(ColorHex.RED); + assertThat(hexByCount1).isEqualTo(ColorHex.GREEN); + assertThat(hexByCount2).isEqualTo(ColorHex.BLUE); + assertThat(hexByCount3).isEqualTo(ColorHex.YELLOW); + assertThat(hexByCount4).isEqualTo(ColorHex.MAGENTA); + assertThat(hexByCount5).isEqualTo(ColorHex.PURPLE); + + assertThat(hexByCount20).isEqualTo(ColorHex.CORAL); + } + + @DisplayName("인덱스가 색상의 개수인 20을 넘어가면 처음 인덱스에서 다시 시작한다.") + @Test + void getHexByCountOverIndex() { + // when + ColorHex hexByCount21 = ColorHex.getHexByCount(20); + ColorHex hexByCount22 = ColorHex.getHexByCount(21); + ColorHex hexByCount23 = ColorHex.getHexByCount(22); + ColorHex hexByCount24 = ColorHex.getHexByCount(23); + ColorHex hexByCount25 = ColorHex.getHexByCount(24); + + ColorHex hexByCount41 = ColorHex.getHexByCount(40); + + // then + assertThat(hexByCount21).isEqualTo(ColorHex.RED); + assertThat(hexByCount22).isEqualTo(ColorHex.GREEN); + assertThat(hexByCount23).isEqualTo(ColorHex.BLUE); + assertThat(hexByCount24).isEqualTo(ColorHex.YELLOW); + assertThat(hexByCount25).isEqualTo(ColorHex.MAGENTA); + + assertThat(hexByCount41).isEqualTo(ColorHex.RED); + } +} \ No newline at end of file diff --git a/backend/src/test/java/moim_today/fake_class/auth/FakeAuthService.java b/backend/src/test/java/moim_today/fake_class/auth/FakeAuthService.java index 52ee227f..da44fd80 100644 --- a/backend/src/test/java/moim_today/fake_class/auth/FakeAuthService.java +++ b/backend/src/test/java/moim_today/fake_class/auth/FakeAuthService.java @@ -3,6 +3,7 @@ import moim_today.application.auth.AuthService; import moim_today.dto.auth.MemberLoginRequest; import moim_today.dto.auth.MemberSignUpRequest; +import moim_today.dto.auth.MemberSessionValidateResponse; import moim_today.global.error.NotFoundException; import moim_today.persistence.entity.member.MemberJpaEntity; import jakarta.servlet.http.HttpServletRequest; @@ -44,4 +45,9 @@ public void signUp(final MemberSignUpRequest memberSignUpRequest, final HttpServ public void logout(final HttpServletRequest request) { } + + @Override + public MemberSessionValidateResponse validateMemberSession(final HttpServletRequest request) { + return new MemberSessionValidateResponse(true); + } } diff --git a/backend/src/test/java/moim_today/fake_class/email_subscribe/FakeEmailSubscribeService.java b/backend/src/test/java/moim_today/fake_class/email_subscribe/FakeEmailSubscribeService.java new file mode 100644 index 00000000..1fdcd655 --- /dev/null +++ b/backend/src/test/java/moim_today/fake_class/email_subscribe/FakeEmailSubscribeService.java @@ -0,0 +1,17 @@ +package moim_today.fake_class.email_subscribe; + +import moim_today.application.email_subscribe.EmailSubscribeService; +import moim_today.dto.mail.EmailSubscriptionResponse; + +public class FakeEmailSubscribeService implements EmailSubscribeService { + + @Override + public void updateSubscribeStatus(final long memberId, final boolean subscribedStatus) { + + } + + @Override + public EmailSubscriptionResponse getSubscriptionStatus(final long memberId) { + return EmailSubscriptionResponse.of(true); + } +} diff --git a/backend/src/test/java/moim_today/fake_class/meeting/joined_meeting/FakeJoinedMeetingService.java b/backend/src/test/java/moim_today/fake_class/meeting/joined_meeting/FakeJoinedMeetingService.java index 8e70c8d8..e070482a 100644 --- a/backend/src/test/java/moim_today/fake_class/meeting/joined_meeting/FakeJoinedMeetingService.java +++ b/backend/src/test/java/moim_today/fake_class/meeting/joined_meeting/FakeJoinedMeetingService.java @@ -13,4 +13,9 @@ public void acceptanceJoinMeeting(final long memberId, final long meetingId) { public void refuseJoinMeeting(final long memberId, final long meetingId) { } + + @Override + public void deleteAllByMeetingId(final long meetingId) { + + } } diff --git a/backend/src/test/java/moim_today/fake_class/meeting/meeting/FakeMeetingService.java b/backend/src/test/java/moim_today/fake_class/meeting/meeting/FakeMeetingService.java index 13de6c8a..1beba52d 100644 --- a/backend/src/test/java/moim_today/fake_class/meeting/meeting/FakeMeetingService.java +++ b/backend/src/test/java/moim_today/fake_class/meeting/meeting/FakeMeetingService.java @@ -2,9 +2,7 @@ import moim_today.application.meeting.meeting.MeetingService; import moim_today.domain.meeting.enums.MeetingStatus; -import moim_today.dto.meeting.MeetingCreateRequest; -import moim_today.dto.meeting.MeetingDetailResponse; -import moim_today.dto.meeting.MeetingSimpleResponse; +import moim_today.dto.meeting.meeting.*; import moim_today.dto.member.MemberSimpleResponse; import moim_today.global.error.ForbiddenException; import moim_today.util.TestConstant; @@ -19,8 +17,8 @@ public class FakeMeetingService implements MeetingService { @Override - public void createMeeting(final MeetingCreateRequest meetingCreateRequest) { - + public MeetingCreateResponse createMeeting(final long memberId, final MeetingCreateRequest meetingCreateRequest) { + return MeetingCreateResponse.of(MEETING_ID.longValue(), meetingCreateRequest); } @Override @@ -80,6 +78,13 @@ public MeetingDetailResponse findDetailsById(final long meetingId) { .build(); } + @Override + public void updateMeeting(final long memberId, final MeetingUpdateRequest meetingUpdateRequest) { + if (meetingUpdateRequest.meetingId() != MEETING_ID.longValue()) { + throw new ForbiddenException(MEETING_FORBIDDEN_ERROR.message()); + } + } + @Override public void deleteMeeting(final long memberId, final long meetingId) { if (meetingId != MEETING_ID.longValue()) { diff --git a/backend/src/test/java/moim_today/fake_class/meeting/meeting_comment/FakeMeetingCommentService.java b/backend/src/test/java/moim_today/fake_class/meeting/meeting_comment/FakeMeetingCommentService.java new file mode 100644 index 00000000..6f86d411 --- /dev/null +++ b/backend/src/test/java/moim_today/fake_class/meeting/meeting_comment/FakeMeetingCommentService.java @@ -0,0 +1,62 @@ +package moim_today.fake_class.meeting.meeting_comment; + +import moim_today.application.meeting.meeting_comment.MeetingCommentService; +import moim_today.dto.meeting.meeting_comment.MeetingCommentCreateRequest; +import moim_today.dto.meeting.meeting_comment.MeetingCommentResponse; +import moim_today.dto.meeting.meeting_comment.MeetingCommentUpdateRequest; +import moim_today.global.error.NotFoundException; + +import java.time.LocalDateTime; +import java.util.List; + +import static moim_today.global.constant.exception.MeetingExceptionConstant.MEETING_NOT_FOUND_ERROR; +import static moim_today.util.TestConstant.*; + +public class FakeMeetingCommentService implements MeetingCommentService { + + @Override + public void createMeetingComment(final long memberId, final MeetingCommentCreateRequest meetingCommentCreateRequest) { + if (meetingCommentCreateRequest.meetingId() == NOT_FOUND_MEETING_ID.longValue()) { + throw new NotFoundException(MEETING_NOT_FOUND_ERROR.message()); + } + } + + @Override + public List findAllByMeetingId(final long memberId, final long meetingId) { + MeetingCommentResponse commentResponse1 = MeetingCommentResponse.builder() + .meetingCommentId(MEETING_COMMENT_ID.longValue()) + .username(USERNAME.value()) + .imageUrl(PROFILE_IMAGE_URL.value()) + .contents(MEETING_COMMENT_CONTENTS.value()) + .createdAt(LocalDateTime.now()) + .build(); + + MeetingCommentResponse commentResponse2 = MeetingCommentResponse.builder() + .meetingCommentId(MEETING_COMMENT_ID.longValue() + 1) + .username(USERNAME.value()) + .imageUrl(PROFILE_IMAGE_URL.value()) + .contents(MEETING_COMMENT_CONTENTS.value()) + .createdAt(LocalDateTime.now()) + .build(); + + MeetingCommentResponse commentResponse3 = MeetingCommentResponse.builder() + .meetingCommentId(MEETING_COMMENT_ID.longValue() + 2) + .username(USERNAME.value()) + .imageUrl(PROFILE_IMAGE_URL.value()) + .contents(MEETING_COMMENT_CONTENTS.value()) + .createdAt(LocalDateTime.now()) + .build(); + + return List.of(commentResponse1, commentResponse2, commentResponse3); + } + + @Override + public void updateMeetingComment(final long memberId, final MeetingCommentUpdateRequest meetingCommentUpdateRequest) { + + } + + @Override + public void deleteMeetingComment(final long memberId, final long meetingCommentId) { + + } +} diff --git a/backend/src/test/java/moim_today/fake_class/member/FakeMemberService.java b/backend/src/test/java/moim_today/fake_class/member/FakeMemberService.java index 83d77cde..0053a7bd 100644 --- a/backend/src/test/java/moim_today/fake_class/member/FakeMemberService.java +++ b/backend/src/test/java/moim_today/fake_class/member/FakeMemberService.java @@ -65,6 +65,12 @@ public MemberHostResponse isHost(final long memberId, final long moimId) { .build(); } + @Override + public MemberJoinedMoimResponse isJoinedMoim(final long moimId, final long memberId) { + boolean isJoinedMoim = true; + return MemberJoinedMoimResponse.from(isJoinedMoim); + } + @Override public MemberSimpleResponse getHostProfileByMoimId(final long moimId) { return MemberSimpleResponse.builder() diff --git a/backend/src/test/java/moim_today/fake_class/moim/FakeMoimService.java b/backend/src/test/java/moim_today/fake_class/moim/FakeMoimService.java index 879c3872..c3e31dc5 100644 --- a/backend/src/test/java/moim_today/fake_class/moim/FakeMoimService.java +++ b/backend/src/test/java/moim_today/fake_class/moim/FakeMoimService.java @@ -22,6 +22,21 @@ public class FakeMoimService implements MoimService { + @Override + public List findAllMyJoinedMoimResponse(final long memberId) { + MyMoimResponse myMoimResponse1 = MyMoimResponse.builder() + .moimId(1L) + .title(MOIM_TITLE.value()) + .build(); + + MyMoimResponse myMoimResponse2 = MyMoimResponse.builder() + .moimId(2L) + .title(MOIM_TITLE.value()) + .build(); + + return List.of(myMoimResponse1, myMoimResponse2); + } + @Override public MoimIdResponse createMoim(final long memberId, final long universityId, final MoimCreateRequest moimCreateRequest) { return MoimIdResponse.from(MOIM_ID.longValue()); @@ -131,7 +146,34 @@ else if(moimJoinRequest.moimId() == MOIM_ID.longValue() + 3L){ } @Override - public List findAllMoimResponse(final MoimCategoryDto moimCategoryDto, final MoimSortedFilter moimSortedFilter) { + public List findAllMoimResponses(final long universityId, + final MoimCategoryDto moimCategoryDto, + final MoimSortedFilter moimSortedFilter) { + MoimSimpleResponse moimSimpleResponse1 = MoimSimpleResponse.builder() + .moimId(1L) + .title(MOIM_TITLE.value()) + .capacity(CAPACITY.intValue()) + .currentCount(CURRENT_COUNT.intValue()) + .imageUrl(MOIM_IMAGE_URL.value()) + .moimCategory(MoimCategory.STUDY) + .displayStatus(DisplayStatus.PUBLIC) + .build(); + + MoimSimpleResponse moimSimpleResponse2 = MoimSimpleResponse.builder() + .moimId(2L) + .title(MOIM_TITLE.value()) + .capacity(CAPACITY.intValue()) + .currentCount(CURRENT_COUNT.intValue()) + .imageUrl(MOIM_IMAGE_URL.value()) + .moimCategory(MoimCategory.STUDY) + .displayStatus(DisplayStatus.PUBLIC) + .build(); + + return List.of(moimSimpleResponse1, moimSimpleResponse2); + } + + @Override + public List searchMoim(final long universityId, final String searchParam) { MoimSimpleResponse moimSimpleResponse1 = MoimSimpleResponse.builder() .moimId(1L) .title(MOIM_TITLE.value()) @@ -156,7 +198,9 @@ public List findAllMoimResponse(final MoimCategoryDto moimCa } @Override - public List searchMoim(final String searchParam) { + public List findAllMyJoinedMoimSimpleResponse(final long memberId, + final boolean ended, + final boolean onlyHost) { MoimSimpleResponse moimSimpleResponse1 = MoimSimpleResponse.builder() .moimId(1L) .title(MOIM_TITLE.value()) diff --git a/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java b/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java index 5e64ac04..0b4842bd 100644 --- a/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java +++ b/backend/src/test/java/moim_today/fake_class/schedule/FakeScheduleService.java @@ -201,4 +201,9 @@ public void deleteSchedule(final long memberId, final long scheduleId) { throw new ForbiddenException(SCHEDULE_FORBIDDEN.message()); } } + + @Override + public void deleteAllByMeetingId(final long meetingId) { + + } } diff --git a/backend/src/test/java/moim_today/global/response/CollectionResponseTest.java b/backend/src/test/java/moim_today/global/response/CollectionResponseTest.java index 25e1a7cb..bda0ee96 100644 --- a/backend/src/test/java/moim_today/global/response/CollectionResponseTest.java +++ b/backend/src/test/java/moim_today/global/response/CollectionResponseTest.java @@ -21,7 +21,7 @@ class CollectionResponseTest { members.add(memberB); //when - CollectionResponse> arrayListCollectionResponse = CollectionResponse.of(members); + CollectionResponse> arrayListCollectionResponse = CollectionResponse.from(members); //then assertThat(arrayListCollectionResponse.data()).contains(memberA, memberB); diff --git a/backend/src/test/java/moim_today/implement/email_subscribe/EmailSubscribeAppenderTest.java b/backend/src/test/java/moim_today/implement/email_subscribe/EmailSubscribeAppenderTest.java new file mode 100644 index 00000000..d0e9a5b1 --- /dev/null +++ b/backend/src/test/java/moim_today/implement/email_subscribe/EmailSubscribeAppenderTest.java @@ -0,0 +1,33 @@ +package moim_today.implement.email_subscribe; + +import moim_today.persistence.entity.email_subscribe.EmailSubscribeJpaEntity; +import moim_today.util.ImplementTest; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import static moim_today.util.TestConstant.*; +import static org.assertj.core.api.Assertions.*; + +class EmailSubscribeAppenderTest extends ImplementTest { + + @Autowired + private EmailSubscribeAppender emailSubscribeAppender; + + @DisplayName("이메일 수신 여부 정보를 저장한다.") + @Test + void saveEmailSubscription() { + // given + long memberId = MEMBER_ID.longValue(); + boolean subscriptionStatus = true; + + // when + emailSubscribeAppender.saveEmailSubscription(memberId, subscriptionStatus); + + // then + EmailSubscribeJpaEntity findEntity = emailSubscribeRepository.getByMemberId(memberId); + + assertThat(emailSubscribeRepository.count()).isEqualTo(1); + assertThat(findEntity.isSubscribeStatus()).isTrue(); + } +} \ No newline at end of file diff --git a/backend/src/test/java/moim_today/implement/email_subscribe/EmailSubscribeUpdaterTest.java b/backend/src/test/java/moim_today/implement/email_subscribe/EmailSubscribeUpdaterTest.java new file mode 100644 index 00000000..cc2047b6 --- /dev/null +++ b/backend/src/test/java/moim_today/implement/email_subscribe/EmailSubscribeUpdaterTest.java @@ -0,0 +1,38 @@ +package moim_today.implement.email_subscribe; + +import moim_today.persistence.entity.email_subscribe.EmailSubscribeJpaEntity; +import moim_today.util.ImplementTest; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import static moim_today.util.TestConstant.*; +import static org.assertj.core.api.Assertions.*; + + +class EmailSubscribeUpdaterTest extends ImplementTest { + + @Autowired + private EmailSubscribeUpdater emailSubscribeUpdater; + + @DisplayName("이메일 수신 여부 설정을 변경한다.") + @Test + void updateSubscribeStatus() { + // given + long memberId = MEMBER_ID.longValue(); + + EmailSubscribeJpaEntity emailSubscribeJpaEntity = EmailSubscribeJpaEntity.builder() + .memberId(memberId) + .subscribeStatus(true) + .build(); + + emailSubscribeRepository.save(emailSubscribeJpaEntity); + + // when + emailSubscribeUpdater.updateSubscribeStatus(memberId, false); + + // then + EmailSubscribeJpaEntity findEntity = emailSubscribeRepository.getById(emailSubscribeJpaEntity.getId()); + assertThat(findEntity.isSubscribeStatus()).isFalse(); + } +} \ No newline at end of file diff --git a/backend/src/test/java/moim_today/implement/email_subscribe/EmailSubscriptionFinderTest.java b/backend/src/test/java/moim_today/implement/email_subscribe/EmailSubscriptionFinderTest.java new file mode 100644 index 00000000..3468bc64 --- /dev/null +++ b/backend/src/test/java/moim_today/implement/email_subscribe/EmailSubscriptionFinderTest.java @@ -0,0 +1,36 @@ +package moim_today.implement.email_subscribe; + +import moim_today.persistence.entity.email_subscribe.EmailSubscribeJpaEntity; +import moim_today.util.ImplementTest; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import static moim_today.util.TestConstant.*; +import static org.assertj.core.api.Assertions.*; + +class EmailSubscriptionFinderTest extends ImplementTest { + + @Autowired + private EmailSubscriptionFinder emailSubscriptionFinder; + + @DisplayName("해당 회원의 이메일 수신 여부를 조회한다.") + @Test + void getSubscriptionStatus() { + // given + long memberId = MEMBER_ID.longValue(); + + EmailSubscribeJpaEntity emailSubscribeJpaEntity = EmailSubscribeJpaEntity.builder() + .memberId(memberId) + .subscribeStatus(true) + .build(); + + emailSubscribeRepository.save(emailSubscribeJpaEntity); + + // when + boolean subscriptionStatus = emailSubscriptionFinder.getSubscriptionStatus(memberId); + + // then + assertThat(subscriptionStatus).isTrue(); + } +} \ No newline at end of file diff --git a/backend/src/test/java/moim_today/implement/meeting/joined_meeting/JoinedMeetingRemoverTest.java b/backend/src/test/java/moim_today/implement/meeting/joined_meeting/JoinedMeetingRemoverTest.java index e64cc588..488b65fb 100644 --- a/backend/src/test/java/moim_today/implement/meeting/joined_meeting/JoinedMeetingRemoverTest.java +++ b/backend/src/test/java/moim_today/implement/meeting/joined_meeting/JoinedMeetingRemoverTest.java @@ -1,7 +1,9 @@ package moim_today.implement.meeting.joined_meeting; import moim_today.persistence.entity.meeting.joined_meeting.JoinedMeetingJpaEntity; +import moim_today.persistence.entity.meeting.meeting.MeetingJpaEntity; import moim_today.util.ImplementTest; +import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -91,6 +93,34 @@ void deleteAllByMemberInMeeting() { assertThat(joinedMeetingRepository.count()).isEqualTo(0L); } + @DisplayName("해당 미팅의 참여 정보를 삭제한다.") + @Test + void deleteAllByMeetingId() { + // given 1 + MeetingJpaEntity meetingJpaEntity = MeetingJpaEntity.builder() + .build(); + + meetingRepository.save(meetingJpaEntity); + + // given 2 + JoinedMeetingJpaEntity joinedMeetingJpaEntity1 = JoinedMeetingJpaEntity.builder() + .meetingId(meetingJpaEntity.getId()) + .build(); + + JoinedMeetingJpaEntity joinedMeetingJpaEntity2 = JoinedMeetingJpaEntity.builder() + .meetingId(meetingJpaEntity.getId()) + .build(); + + joinedMeetingRepository.save(joinedMeetingJpaEntity1); + joinedMeetingRepository.save(joinedMeetingJpaEntity2); + + // when + joinedMeetingRemover.deleteAllByMeetingId(meetingJpaEntity.getId()); + + // then + assertThat(joinedMeetingRepository.count()).isEqualTo(0); + } + @DisplayName("미팅에서 특정 멤버만 삭제된다") @Test void deleteOnlySpecifiedMemberInMeeting() { diff --git a/backend/src/test/java/moim_today/implement/meeting/meeting/MeetingAppenderTest.java b/backend/src/test/java/moim_today/implement/meeting/meeting/MeetingAppenderTest.java index 3c7a7f69..16728a2a 100644 --- a/backend/src/test/java/moim_today/implement/meeting/meeting/MeetingAppenderTest.java +++ b/backend/src/test/java/moim_today/implement/meeting/meeting/MeetingAppenderTest.java @@ -29,16 +29,14 @@ void saveMeeting() { .build(); // when - meetingAppender.saveMeeting(meetingJpaEntity); + MeetingJpaEntity saveEntity = meetingAppender.saveMeeting(meetingJpaEntity); // then - MeetingJpaEntity findEntity = meetingRepository.getById(meetingJpaEntity.getId()); - assertThat(meetingRepository.count()).isEqualTo(1); - assertThat(findEntity.getMoimId()).isEqualTo(Long.valueOf(MOIM_ID.value())); - assertThat(findEntity.getAgenda()).isEqualTo(MEETING_AGENDA.value()); - assertThat(findEntity.getStartDateTime()).isEqualTo(LocalDateTime.of(2024,3,4, 10, 0, 0)); - assertThat(findEntity.getEndDateTime()).isEqualTo(LocalDateTime.of(2024,6,30, 10, 0, 0)); - assertThat(findEntity.getPlace()).isEqualTo(MEETING_PLACE.value()); + assertThat(saveEntity.getMoimId()).isEqualTo(Long.valueOf(MOIM_ID.value())); + assertThat(saveEntity.getAgenda()).isEqualTo(MEETING_AGENDA.value()); + assertThat(saveEntity.getStartDateTime()).isEqualTo(LocalDateTime.of(2024,3,4, 10, 0, 0)); + assertThat(saveEntity.getEndDateTime()).isEqualTo(LocalDateTime.of(2024,6,30, 10, 0, 0)); + assertThat(saveEntity.getPlace()).isEqualTo(MEETING_PLACE.value()); } } \ No newline at end of file diff --git a/backend/src/test/java/moim_today/implement/meeting/meeting/MeetingFinderTest.java b/backend/src/test/java/moim_today/implement/meeting/meeting/MeetingFinderTest.java index 43bf0d26..cc432816 100644 --- a/backend/src/test/java/moim_today/implement/meeting/meeting/MeetingFinderTest.java +++ b/backend/src/test/java/moim_today/implement/meeting/meeting/MeetingFinderTest.java @@ -2,8 +2,10 @@ import moim_today.domain.meeting.enums.MeetingStatus; import moim_today.dto.mail.UpcomingMeetingNoticeResponse; -import moim_today.dto.meeting.MeetingDetailResponse; -import moim_today.dto.meeting.MeetingSimpleDao; +import moim_today.dto.meeting.meeting.MeetingDetailResponse; +import moim_today.dto.meeting.meeting.MeetingSimpleDao; +import moim_today.global.error.NotFoundException; +import moim_today.persistence.entity.email_subscribe.EmailSubscribeJpaEntity; import moim_today.persistence.entity.meeting.joined_meeting.JoinedMeetingJpaEntity; import moim_today.persistence.entity.meeting.meeting.MeetingJpaEntity; import moim_today.persistence.entity.member.MemberJpaEntity; @@ -15,9 +17,10 @@ import java.time.LocalDateTime; import java.util.List; +import static moim_today.global.constant.exception.MeetingExceptionConstant.MEETING_NOT_FOUND_ERROR; import static moim_today.util.TestConstant.*; -import static moim_today.util.TestConstant.MOIM_ID; -import static org.assertj.core.api.Assertions.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; class MeetingFinderTest extends ImplementTest { @@ -306,7 +309,6 @@ void findAllPastByMoimIdOrderByStartDateTimeAsc() { assertThat(meetingSimpleDaos.get(1).agenda()).isEqualTo(SECOND_CREATED_MEETING_AGENDA.value()); } - @DisplayName("하나의 모임의 모든 미팅의 엔티티 정보를 반환한다.") @Test void findAllByMoimId() { @@ -454,6 +456,13 @@ void findUpcomingNotices() { joinedMeetingRepository.save(joinedMeetingJpaEntity); + EmailSubscribeJpaEntity emailSubscribeJpaEntity = EmailSubscribeJpaEntity.builder() + .memberId(memberJpaEntity.getId()) + .subscribeStatus(true) + .build(); + + emailSubscribeRepository.save(emailSubscribeJpaEntity); + // when List upcomingNotices = meetingFinder.findUpcomingNotices(currentDateTime); @@ -469,6 +478,100 @@ void findUpcomingNotices() { assertThat(upcomingNotice.attendance()).isEqualTo(joinedMeetingJpaEntity.isAttendance()); } + @DisplayName("이메일 수신 여부를 수락한 사람만 다가오는 미팅 정보를 조회한다.") + @Test + void findUpcomingNoticesOnlySubscribeStatusTrue() { + // given 1 + LocalDateTime currentDateTime = LocalDateTime.of(2024, 3, 4, 8, 0, 0); + + // given 2 + MemberJpaEntity memberJpaEntity = MemberJpaEntity.builder() + .email(EMAIL.value()) + .build(); + + memberRepository.save(memberJpaEntity); + + // given 3 + MeetingJpaEntity meetingJpaEntity = MeetingJpaEntity.builder() + .agenda(MEETING_AGENDA.value()) + .startDateTime(LocalDateTime.of(2024, 3, 4, 10, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 3, 4, 12, 0, 0)) + .place(MEETING_PLACE.value()) + .build(); + + meetingRepository.save(meetingJpaEntity); + + // given 4 + JoinedMeetingJpaEntity joinedMeetingJpaEntity = JoinedMeetingJpaEntity.builder() + .meetingId(meetingJpaEntity.getId()) + .memberId(memberJpaEntity.getId()) + .attendance(true) + .upcomingNoticeSent(false) + .build(); + + joinedMeetingRepository.save(joinedMeetingJpaEntity); + + EmailSubscribeJpaEntity emailSubscribeJpaEntity = EmailSubscribeJpaEntity.builder() + .memberId(memberJpaEntity.getId()) + .subscribeStatus(true) + .build(); + + emailSubscribeRepository.save(emailSubscribeJpaEntity); + + // when + List upcomingNotices = meetingFinder.findUpcomingNotices(currentDateTime); + + // then + assertThat(upcomingNotices.size()).isEqualTo(1); + } + + @DisplayName("이메일 수신 여부를 거절한 사람은 다가오는 미팅 정보가 조회되지 않는다.") + @Test + void findUpcomingNoticesOnlySubscribeStatusFalse() { + // given 1 + LocalDateTime currentDateTime = LocalDateTime.of(2024, 3, 4, 8, 0, 0); + + // given 2 + MemberJpaEntity memberJpaEntity = MemberJpaEntity.builder() + .email(EMAIL.value()) + .build(); + + memberRepository.save(memberJpaEntity); + + // given 3 + MeetingJpaEntity meetingJpaEntity = MeetingJpaEntity.builder() + .agenda(MEETING_AGENDA.value()) + .startDateTime(LocalDateTime.of(2024, 3, 4, 10, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 3, 4, 12, 0, 0)) + .place(MEETING_PLACE.value()) + .build(); + + meetingRepository.save(meetingJpaEntity); + + // given 4 + JoinedMeetingJpaEntity joinedMeetingJpaEntity = JoinedMeetingJpaEntity.builder() + .meetingId(meetingJpaEntity.getId()) + .memberId(memberJpaEntity.getId()) + .attendance(true) + .upcomingNoticeSent(false) + .build(); + + joinedMeetingRepository.save(joinedMeetingJpaEntity); + + EmailSubscribeJpaEntity emailSubscribeJpaEntity = EmailSubscribeJpaEntity.builder() + .memberId(memberJpaEntity.getId()) + .subscribeStatus(false) + .build(); + + emailSubscribeRepository.save(emailSubscribeJpaEntity); + + // when + List upcomingNotices = meetingFinder.findUpcomingNotices(currentDateTime); + + // then + assertThat(upcomingNotices.size()).isEqualTo(0); + } + @DisplayName("다가오는 미팅은 시작 시간이 현재 시간보다 뒤에 있는 시간대를 조회한다.") @Test void findUpcomingNoticesOnlyAfter() { @@ -518,6 +621,13 @@ void findUpcomingNoticesOnlyAfter() { joinedMeetingRepository.save(beforeJoinedMeetingJpaEntity); joinedMeetingRepository.save(afterJoinedMeetingJpaEntity); + EmailSubscribeJpaEntity emailSubscribeJpaEntity = EmailSubscribeJpaEntity.builder() + .memberId(memberJpaEntity.getId()) + .subscribeStatus(true) + .build(); + + emailSubscribeRepository.save(emailSubscribeJpaEntity); + // when List upcomingNotices = meetingFinder.findUpcomingNotices(currentDateTime); @@ -574,6 +684,13 @@ void findUpcomingNoticesUntilAfter24Hours() { joinedMeetingRepository.save(beforeJoinedMeetingJpaEntity); joinedMeetingRepository.save(afterJoinedMeetingJpaEntity); + EmailSubscribeJpaEntity emailSubscribeJpaEntity = EmailSubscribeJpaEntity.builder() + .memberId(memberJpaEntity.getId()) + .subscribeStatus(true) + .build(); + + emailSubscribeRepository.save(emailSubscribeJpaEntity); + // when List upcomingNotices = meetingFinder.findUpcomingNotices(currentDateTime); @@ -630,10 +747,46 @@ void findUpcomingNoticesOnlyUpcomingNoticeSentFalse() { joinedMeetingRepository.save(beforeJoinedMeetingJpaEntity); joinedMeetingRepository.save(afterJoinedMeetingJpaEntity); + EmailSubscribeJpaEntity emailSubscribeJpaEntity = EmailSubscribeJpaEntity.builder() + .memberId(memberJpaEntity.getId()) + .subscribeStatus(true) + .build(); + + emailSubscribeRepository.save(emailSubscribeJpaEntity); + // when List upcomingNotices = meetingFinder.findUpcomingNotices(currentDateTime); // then assertThat(upcomingNotices.size()).isEqualTo(1); } + + @DisplayName("미팅 Id로 모임 Id를 조회한다.") + @Test + void getMoimIdByMeetingId() { + // given + long expectedMoimId = MOIM_ID.longValue(); + + MeetingJpaEntity meetingJpaEntity = MeetingJpaEntity.builder() + .moimId(expectedMoimId) + .build(); + + meetingRepository.save(meetingJpaEntity); + long meetingId = meetingJpaEntity.getId(); + + // when + long actualMoimId = meetingFinder.getMoimIdByMeetingId(meetingId); + + // then + assertThat(expectedMoimId).isEqualTo(actualMoimId); + } + + @DisplayName("미팅 Id로 모임 Id를 조회할때, 미팅이 존재하지 않으면 예외가 발생한다.") + @Test + void getMoimIdByMeetingIdThrowsNotFoundException() { + // expected + assertThatThrownBy(() -> meetingFinder.getMoimIdByMeetingId(MEETING_ID.longValue())) + .isInstanceOf(NotFoundException.class) + .hasMessage(MEETING_NOT_FOUND_ERROR.message()); + } } diff --git a/backend/src/test/java/moim_today/implement/meeting/meeting/MeetingManagerTest.java b/backend/src/test/java/moim_today/implement/meeting/meeting/MeetingManagerTest.java index 00556a4a..803e12e2 100644 --- a/backend/src/test/java/moim_today/implement/meeting/meeting/MeetingManagerTest.java +++ b/backend/src/test/java/moim_today/implement/meeting/meeting/MeetingManagerTest.java @@ -1,7 +1,9 @@ package moim_today.implement.meeting.meeting; import moim_today.domain.meeting.enums.MeetingCategory; -import moim_today.dto.meeting.MeetingCreateRequest; +import moim_today.dto.meeting.meeting.MeetingCreateResponse; +import moim_today.dto.meeting.meeting.MeetingCreateRequest; +import moim_today.persistence.entity.member.MemberJpaEntity; import moim_today.persistence.entity.moim.joined_moim.JoinedMoimJpaEntity; import moim_today.persistence.entity.moim.moim.MoimJpaEntity; import moim_today.persistence.entity.schedule.schedule.ScheduleJpaEntity; @@ -15,9 +17,7 @@ import java.time.temporal.ChronoUnit; import static moim_today.util.TestConstant.*; -import static moim_today.util.TestConstant.MEETING_AGENDA; -import static moim_today.util.TestConstant.MEETING_PLACE; -import static org.assertj.core.api.Assertions.*; +import static org.assertj.core.api.Assertions.assertThat; class MeetingManagerTest extends ImplementTest { @@ -28,8 +28,16 @@ class MeetingManagerTest extends ImplementTest { @Test void createSingleMeeting() { // given 1 + MemberJpaEntity memberJpaEntity = MemberJpaEntity.builder() + .build(); + + memberRepository.save(memberJpaEntity); + long memberId = memberJpaEntity.getId(); + + // given 2 MoimJpaEntity moimJpaEntity = MoimJpaEntity.builder() .title(MOIM_TITLE.value()) + .memberId(memberId) .build(); moimRepository.save(moimJpaEntity); @@ -44,18 +52,71 @@ void createSingleMeeting() { .meetingCategory(MeetingCategory.SINGLE) .build(); + // given 3 + LocalDate currentDate = LocalDate.of(2024, 3, 4); + // when - meetingManager.createMeeting(meetingCreateRequest); + MeetingCreateResponse meetingCreateResponse = meetingManager.createMeeting(memberId, meetingCreateRequest, currentDate); // then assertThat(meetingRepository.count()).isEqualTo(1); + assertThat(meetingCreateResponse.agenda()).isEqualTo(MEETING_AGENDA.value()); + assertThat(meetingCreateResponse.startDateTime()).isEqualTo(LocalDateTime.of(2024, 3, 4, 10, 0, 0)); + assertThat(meetingCreateResponse.endDateTime()).isEqualTo(LocalDateTime.of(2024, 3, 4, 12, 0, 0)); + assertThat(meetingCreateResponse.place()).isEqualTo(MEETING_PLACE.value()); + assertThat(meetingCreateResponse.meetingCategory()).isEqualTo(MeetingCategory.SINGLE); } - @DisplayName("정기 미팅을 생성한다.") + @DisplayName("현재 날짜부터 정기 미팅을 생성한다.") @Test - void createRegularMeeting() { + void createRegularMeetingFromCurrentDate() { // given 1 long memberId = 1; + LocalDate currentDate = LocalDate.of(2024, 3, 30); + LocalDate startDate = LocalDate.of(2024, 3, 4); + LocalDate endDate = LocalDate.of(2024, 6, 30); + + MoimJpaEntity moimJpaEntity = MoimJpaEntity.builder() + .memberId(memberId) + .startDate(startDate) + .endDate(endDate) + .build(); + + moimRepository.save(moimJpaEntity); + + // given 2 + MeetingCreateRequest meetingCreateRequest = MeetingCreateRequest.builder() + .moimId(moimJpaEntity.getId()) + .agenda(MEETING_AGENDA.value()) + .startDateTime(LocalDateTime.of(2024, 3, 4, 10, 0, 0)) + .endDateTime(LocalDateTime.of(2024, 3, 4, 12, 0, 0)) + .place(MEETING_PLACE.value()) + .meetingCategory(MeetingCategory.REGULAR) + .build(); + + // when + MeetingCreateResponse meetingCreateResponse = meetingManager.createMeeting(memberId, meetingCreateRequest, currentDate); + + // then + long between = ChronoUnit.WEEKS.between(currentDate, endDate) + 1; + assertThat(meetingRepository.count()).isEqualTo(between); + assertThat(meetingCreateResponse.agenda()).isEqualTo(MEETING_AGENDA.value()); + assertThat(meetingCreateResponse.startDateTime()).isEqualTo(LocalDateTime.of(2024, 3, 4, 10, 0, 0)); + assertThat(meetingCreateResponse.endDateTime()).isEqualTo(LocalDateTime.of(2024, 3, 4, 12, 0, 0)); + assertThat(meetingCreateResponse.place()).isEqualTo(MEETING_PLACE.value()); + assertThat(meetingCreateResponse.meetingCategory()).isEqualTo(MeetingCategory.REGULAR); + } + + @DisplayName("미팅 시작 날짜부터 정기 미팅을 생성한다.") + @Test + void createRegularMeetingFromStartDate() { + // given 1 + MemberJpaEntity memberJpaEntity = MemberJpaEntity.builder() + .build(); + + memberRepository.save(memberJpaEntity); + long memberId = memberJpaEntity.getId(); + LocalDate currentDate = LocalDate.of(2024, 2, 1); LocalDate startDate = LocalDate.of(2024, 3, 4); LocalDate endDate = LocalDate.of(2024, 6, 30); @@ -78,18 +139,28 @@ void createRegularMeeting() { .build(); // when - meetingManager.createMeeting(meetingCreateRequest); + MeetingCreateResponse meetingCreateResponse = meetingManager.createMeeting(memberId, meetingCreateRequest, currentDate); // then long between = ChronoUnit.WEEKS.between(startDate, endDate) + 1; assertThat(meetingRepository.count()).isEqualTo(between); + assertThat(meetingCreateResponse.agenda()).isEqualTo(MEETING_AGENDA.value()); + assertThat(meetingCreateResponse.startDateTime()).isEqualTo(LocalDateTime.of(2024, 3, 4, 10, 0, 0)); + assertThat(meetingCreateResponse.endDateTime()).isEqualTo(LocalDateTime.of(2024, 3, 4, 12, 0, 0)); + assertThat(meetingCreateResponse.place()).isEqualTo(MEETING_PLACE.value()); + assertThat(meetingCreateResponse.meetingCategory()).isEqualTo(MeetingCategory.REGULAR); } @DisplayName("일회 미팅 생성시 참여 정보, 스케줄 정보를 등록한다.") @Test void createSingleMeetingWithJoinedAndSchedule() { // given 1 - long memberId = 1; + MemberJpaEntity memberJpaEntity = MemberJpaEntity.builder() + .build(); + + memberRepository.save(memberJpaEntity); + long memberId = memberJpaEntity.getId(); + LocalDate currentDate = LocalDate.of(2024, 3, 30); LocalDate startDate = LocalDate.of(2024, 3, 4); LocalDate endDate = LocalDate.of(2024, 6, 30); @@ -122,7 +193,7 @@ void createSingleMeetingWithJoinedAndSchedule() { .build(); // when - meetingManager.createMeeting(meetingCreateRequest); + meetingManager.createMeeting(memberId, meetingCreateRequest, currentDate); // then assertThat(meetingRepository.count()).isEqualTo(1); @@ -134,7 +205,12 @@ void createSingleMeetingWithJoinedAndSchedule() { @Test void createRegularMeetingWithJoinedAndSchedule() { // given 1 - long memberId = 1; + MemberJpaEntity memberJpaEntity = MemberJpaEntity.builder() + .build(); + + memberRepository.save(memberJpaEntity); + long memberId = memberJpaEntity.getId(); + LocalDate currentDate = LocalDate.of(2024, 3, 30); LocalDate startDate = LocalDate.of(2024, 3, 4); LocalDate endDate = LocalDate.of(2024, 6, 30); @@ -167,10 +243,10 @@ void createRegularMeetingWithJoinedAndSchedule() { .build(); // when - meetingManager.createMeeting(meetingCreateRequest); + meetingManager.createMeeting(memberId, meetingCreateRequest, currentDate); // then - long between = ChronoUnit.WEEKS.between(startDate, endDate) + 1; + long between = ChronoUnit.WEEKS.between(currentDate, endDate) + 1; assertThat(meetingRepository.count()).isEqualTo(between); assertThat(joinedMeetingRepository.count()).isEqualTo(10 * between); assertThat(scheduleRepository.count()).isEqualTo(10 * between); @@ -180,7 +256,12 @@ void createRegularMeetingWithJoinedAndSchedule() { @Test void createMeetingScheduleIfNotExist() { // given 1 - long memberId = 1; + MemberJpaEntity memberJpaEntity = MemberJpaEntity.builder() + .build(); + + memberRepository.save(memberJpaEntity); + long memberId = memberJpaEntity.getId(); + LocalDate currentDate = LocalDate.of(2024, 3, 30); LocalDate startDate = LocalDate.of(2024, 3, 4); LocalDate endDate = LocalDate.of(2024, 6, 30); @@ -220,7 +301,7 @@ void createMeetingScheduleIfNotExist() { .build(); // when - meetingManager.createMeeting(meetingCreateRequest); + meetingManager.createMeeting(memberId, meetingCreateRequest, currentDate); // then assertThat(meetingRepository.count()).isEqualTo(1); diff --git a/backend/src/test/java/moim_today/implement/meeting/meeting/MeetingUpdaterTest.java b/backend/src/test/java/moim_today/implement/meeting/meeting/MeetingUpdaterTest.java new file mode 100644 index 00000000..723b1d71 --- /dev/null +++ b/backend/src/test/java/moim_today/implement/meeting/meeting/MeetingUpdaterTest.java @@ -0,0 +1,93 @@ +package moim_today.implement.meeting.meeting; + +import moim_today.dto.meeting.meeting.MeetingUpdateRequest; +import moim_today.global.error.ForbiddenException; +import moim_today.persistence.entity.meeting.meeting.MeetingJpaEntity; +import moim_today.persistence.entity.moim.moim.MoimJpaEntity; +import moim_today.util.ImplementTest; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import static moim_today.global.constant.exception.MeetingExceptionConstant.MEETING_FORBIDDEN_ERROR; +import static moim_today.util.TestConstant.*; +import static org.assertj.core.api.Assertions.*; + + +class MeetingUpdaterTest extends ImplementTest { + + @Autowired + protected MeetingUpdater meetingUpdater; + + @DisplayName("미팅 정보를 업데이트한다.") + @Test + void updateMeeting() { + // given 1 + long memberId = MEMBER_ID.longValue(); + + MoimJpaEntity moimJpaEntity = MoimJpaEntity.builder() + .memberId(memberId) + .build(); + + moimRepository.save(moimJpaEntity); + + // given 2 + MeetingJpaEntity meetingJpaEntity = MeetingJpaEntity.builder() + .moimId(moimJpaEntity.getId()) + .agenda(MEETING_AGENDA.value()) + .place(MEETING_PLACE.value()) + .build(); + + meetingRepository.save(meetingJpaEntity); + + // given 3 + String newAgenda = "newAgenda"; + String newPlace = "newPlace"; + + MeetingUpdateRequest meetingUpdateRequest = + MeetingUpdateRequest.of(meetingJpaEntity.getId(), newAgenda, newPlace); + + // when + meetingUpdater.updateMeeting(memberId, meetingUpdateRequest); + + // then + MeetingJpaEntity findEntity = meetingRepository.getById(meetingJpaEntity.getId()); + assertThat(findEntity.getAgenda()).isEqualTo(newAgenda); + assertThat(findEntity.getPlace()).isEqualTo(newPlace); + } + + @DisplayName("해당 미팅 생성자가 아니면 미팅을 수정할 수 없다.") + @Test + void updateMeetingFail() { + // given 1 + long memberId = MEMBER_ID.longValue(); + long otherMemberId = 9999L; + + MoimJpaEntity moimJpaEntity = MoimJpaEntity.builder() + .memberId(memberId) + .build(); + + moimRepository.save(moimJpaEntity); + + // given 2 + MeetingJpaEntity meetingJpaEntity = MeetingJpaEntity.builder() + .moimId(moimJpaEntity.getId()) + .agenda(MEETING_AGENDA.value()) + .place(MEETING_PLACE.value()) + .build(); + + meetingRepository.save(meetingJpaEntity); + + // given 3 + String newAgenda = "newAgenda"; + String newPlace = "newPlace"; + + MeetingUpdateRequest meetingUpdateRequest = + MeetingUpdateRequest.of(meetingJpaEntity.getId(), newAgenda, newPlace); + + // when && then + assertThatThrownBy(() -> meetingUpdater.updateMeeting(otherMemberId, meetingUpdateRequest)) + .isInstanceOf(ForbiddenException.class) + .hasMessage(MEETING_FORBIDDEN_ERROR.message()); + } +} \ No newline at end of file diff --git a/backend/src/test/java/moim_today/implement/meeting/meeting_comment/MeetingCommentAppenderTest.java b/backend/src/test/java/moim_today/implement/meeting/meeting_comment/MeetingCommentAppenderTest.java new file mode 100644 index 00000000..ecc234a9 --- /dev/null +++ b/backend/src/test/java/moim_today/implement/meeting/meeting_comment/MeetingCommentAppenderTest.java @@ -0,0 +1,36 @@ +package moim_today.implement.meeting.meeting_comment; + +import moim_today.dto.meeting.meeting_comment.MeetingCommentCreateRequest; +import moim_today.persistence.entity.meeting.meeting_comment.MeetingCommentJpaEntity; +import moim_today.util.ImplementTest; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import static moim_today.util.TestConstant.*; +import static org.assertj.core.api.Assertions.*; + +class MeetingCommentAppenderTest extends ImplementTest { + + @Autowired + private MeetingCommentAppender meetingCommentAppender; + + @DisplayName("미팅에 댓글을 작성한다.") + @Test + void createMeetingComment(){ + //given + long memberId = MEMBER_ID.longValue(); + + MeetingCommentCreateRequest meetingCommentCreateRequest = MeetingCommentCreateRequest.builder() + .meetingId(MEETING_ID.longValue()) + .contents(MEETING_COMMENT_CONTENTS.value()) + .build(); + + //when + meetingCommentAppender.createMeetingComment(memberId, meetingCommentCreateRequest); + + //then + assertThat(meetingCommentRepository.count()).isEqualTo(1); + } +} \ No newline at end of file diff --git a/backend/src/test/java/moim_today/implement/meeting/meeting_comment/MeetingCommentFinderTest.java b/backend/src/test/java/moim_today/implement/meeting/meeting_comment/MeetingCommentFinderTest.java new file mode 100644 index 00000000..e43531af --- /dev/null +++ b/backend/src/test/java/moim_today/implement/meeting/meeting_comment/MeetingCommentFinderTest.java @@ -0,0 +1,95 @@ +package moim_today.implement.meeting.meeting_comment; + +import moim_today.dto.meeting.meeting_comment.MeetingCommentResponse; +import moim_today.global.error.NotFoundException; +import moim_today.persistence.entity.meeting.meeting_comment.MeetingCommentJpaEntity; +import moim_today.persistence.entity.member.MemberJpaEntity; +import moim_today.util.ImplementTest; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; + +import static moim_today.global.constant.exception.MeetingCommentExceptionConstant.MEETING_COMMENT_NOT_FOUND_ERROR; +import static moim_today.util.TestConstant.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class MeetingCommentFinderTest extends ImplementTest { + + @Autowired + private MeetingCommentFinder meetingCommentFinder; + + @DisplayName("미팅의 댓글 목록을 조회한다.") + @Test + void findAllByMeetingIdTest(){ + // given1 + MemberJpaEntity memberJpaEntity = MemberJpaEntity.builder() + .username(USERNAME.value()) + .memberProfileImageUrl(PROFILE_IMAGE_URL.value()) + .build(); + + memberRepository.save(memberJpaEntity); + long memberId = memberJpaEntity.getId(); + + // given2 + long meetingId = MEETING_ID.longValue(); + long otherMeetingId = meetingId + 1; + + MeetingCommentJpaEntity commentJpaEntityA = MeetingCommentJpaEntity.builder() + .meetingId(meetingId) + .memberId(memberId) + .contents(MEETING_COMMENT_CONTENTS.value()) + .build(); + + MeetingCommentJpaEntity commentJpaEntityB = MeetingCommentJpaEntity.builder() + .meetingId(meetingId) + .memberId(memberId) + .contents(MEETING_COMMENT_CONTENTS.value()) + .build(); + + MeetingCommentJpaEntity commentJpaEntityC = MeetingCommentJpaEntity.builder() + .meetingId(otherMeetingId) + .memberId(memberId) + .contents(MEETING_COMMENT_CONTENTS.value()) + .build(); + + meetingCommentRepository.save(commentJpaEntityA); + meetingCommentRepository.save(commentJpaEntityB); + meetingCommentRepository.save(commentJpaEntityC); + + //when + List findMeetingComments = meetingCommentFinder.findAllByMeetingId(meetingId); + + //then + assertThat(findMeetingComments.size()).isEqualTo(2); + } + + @DisplayName("댓글 Id로 조회한다.") + @Test + void getById(){ + // given + MeetingCommentJpaEntity commentJpaEntity = MeetingCommentJpaEntity.builder() + .contents(MEETING_COMMENT_CONTENTS.value()) + .build(); + + meetingCommentRepository.save(commentJpaEntity); + long commentId = commentJpaEntity.getId(); + + //when + MeetingCommentJpaEntity meetingCommentJpaEntity = meetingCommentFinder.getById(commentId); + + //then + assertThat(meetingCommentJpaEntity.getContents()).isEqualTo(MEETING_COMMENT_CONTENTS.value()); + } + + @DisplayName("댓글 Id로 조회할 때, 없으면 예외가 발생한다.") + @Test + void getByIdThrowNotFoundException(){ + // expected + assertThatThrownBy(() -> meetingCommentFinder.getById(MEETING_ID.longValue())) + .isInstanceOf(NotFoundException.class) + .hasMessage(MEETING_COMMENT_NOT_FOUND_ERROR.message()); + } +} \ No newline at end of file diff --git a/backend/src/test/java/moim_today/implement/meeting/meeting_comment/MeetingCommentRemoverTest.java b/backend/src/test/java/moim_today/implement/meeting/meeting_comment/MeetingCommentRemoverTest.java new file mode 100644 index 00000000..e4682eb8 --- /dev/null +++ b/backend/src/test/java/moim_today/implement/meeting/meeting_comment/MeetingCommentRemoverTest.java @@ -0,0 +1,32 @@ +package moim_today.implement.meeting.meeting_comment; + +import moim_today.persistence.entity.meeting.meeting_comment.MeetingCommentJpaEntity; +import moim_today.util.ImplementTest; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import static org.assertj.core.api.Assertions.assertThat; + +class MeetingCommentRemoverTest extends ImplementTest { + + @Autowired + private MeetingCommentRemover meetingCommentRemover; + + @DisplayName("댓글을 삭제한다.") + @Test + void deleteMeetingComment(){ + //given + MeetingCommentJpaEntity meetingCommentJpaEntity = MeetingCommentJpaEntity.builder() + .build(); + + meetingCommentRepository.save(meetingCommentJpaEntity); + long commentId = meetingCommentJpaEntity.getId(); + + //when + meetingCommentRemover.deleteById(commentId); + + //then + assertThat(meetingCommentRepository.count()).isEqualTo(0); + } +} \ No newline at end of file diff --git a/backend/src/test/java/moim_today/implement/meeting/meeting_comment/MeetingCommentUpdaterTest.java b/backend/src/test/java/moim_today/implement/meeting/meeting_comment/MeetingCommentUpdaterTest.java index 47fc7e41..892c22e2 100644 --- a/backend/src/test/java/moim_today/implement/meeting/meeting_comment/MeetingCommentUpdaterTest.java +++ b/backend/src/test/java/moim_today/implement/meeting/meeting_comment/MeetingCommentUpdaterTest.java @@ -1,5 +1,6 @@ package moim_today.implement.meeting.meeting_comment; +import moim_today.dto.meeting.meeting_comment.MeetingCommentUpdateRequest; import moim_today.persistence.entity.meeting.meeting_comment.MeetingCommentJpaEntity; import moim_today.util.ImplementTest; import org.junit.jupiter.api.DisplayName; @@ -8,8 +9,7 @@ import java.util.List; -import static moim_today.util.TestConstant.MEETING_ID; -import static moim_today.util.TestConstant.MEMBER_ID; +import static moim_today.util.TestConstant.*; import static org.assertj.core.api.Assertions.assertThat; class MeetingCommentUpdaterTest extends ImplementTest { @@ -99,4 +99,27 @@ void updateOnlyDeletedMembers() { .getMemberId(); assertThat(findMeetingCommentId2).isEqualTo(stillInMemberId2); } + + @DisplayName("댓글을 수정한다.") + @Test + void updateMeetingComment(){ + //given + MeetingCommentJpaEntity meetingCommentJpaEntity = MeetingCommentJpaEntity.builder() + .build(); + + meetingCommentRepository.save(meetingCommentJpaEntity); + long commentId = meetingCommentJpaEntity.getId(); + String commentContents = MEETING_COMMENT_CONTENTS.value(); + + MeetingCommentUpdateRequest meetingCommentUpdateRequest = MeetingCommentUpdateRequest.builder() + .meetingCommentId(commentId) + .contents(commentContents).build(); + + //when + meetingCommentUpdater.updateMeetingComment(commentId, meetingCommentUpdateRequest); + + //then + MeetingCommentJpaEntity updatedMeetingComment = meetingCommentRepository.getById(commentId); + assertThat(updatedMeetingComment.getContents()).isEqualTo(commentContents); + } } \ No newline at end of file diff --git a/backend/src/test/java/moim_today/implement/member/AuthManagerTest.java b/backend/src/test/java/moim_today/implement/member/AuthManagerTest.java index ed703a52..91732698 100644 --- a/backend/src/test/java/moim_today/implement/member/AuthManagerTest.java +++ b/backend/src/test/java/moim_today/implement/member/AuthManagerTest.java @@ -126,7 +126,7 @@ void logoutTest() { @DisplayName("정상적으로 회원가입을 완료하면 멤버 데이터를 넣고 세션에 등록한다") @Test - void register() throws JsonProcessingException { + void signUp() throws JsonProcessingException { // given LocalDate birthDate = LocalDate.now(); MockHttpServletRequest mockHttpServletRequest = new MockHttpServletRequest(); @@ -152,5 +152,6 @@ void register() throws JsonProcessingException { assertThat(memberSessionObject).isNotBlank(); MemberSession memberSession = objectMapper.readValue(memberSessionObject, MemberSession.class); assertThat(memberSession.username()).isEqualTo(USERNAME.value()); + assertThat(emailSubscribeRepository.count()).isEqualTo(1); } } \ No newline at end of file diff --git a/backend/src/test/java/moim_today/implement/moim/joined_moim/JoinedMoimFinderTest.java b/backend/src/test/java/moim_today/implement/moim/joined_moim/JoinedMoimFinderTest.java index 891e9570..bf1a857d 100644 --- a/backend/src/test/java/moim_today/implement/moim/joined_moim/JoinedMoimFinderTest.java +++ b/backend/src/test/java/moim_today/implement/moim/joined_moim/JoinedMoimFinderTest.java @@ -4,6 +4,7 @@ import moim_today.persistence.entity.moim.joined_moim.JoinedMoimJpaEntity; import moim_today.persistence.entity.moim.moim.MoimJpaEntity; import moim_today.util.ImplementTest; +import moim_today.util.TestConstant; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -195,4 +196,39 @@ void validateJoinedMemberForbiddenTest() { .isInstanceOf(NotFoundException.class) .hasMessage(JOINED_MOIM_MEMBER_NOT_FOUND.message()); } + + @DisplayName("모임에 참여한 회원은 true를 반환한다.") + @Test + void isJoiningTrue() { + // given + long moimId = MOIM_ID.longValue(); + long memberId = MEMBER_ID.longValue(); + + JoinedMoimJpaEntity joinedMoimJpaEntity = JoinedMoimJpaEntity.builder() + .moimId(moimId) + .memberId(memberId) + .build(); + + joinedMoimRepository.save(joinedMoimJpaEntity); + + // when + boolean isJoined = joinedMoimFinder.isJoining(moimId, memberId); + + // then + assertThat(isJoined).isTrue(); + } + + @DisplayName("모임에 참여하지 않은 회원은 false 반환한다.") + @Test + void isJoiningFalse() { + // given + long moimId = MOIM_ID.longValue(); + long memberId = MEMBER_ID.longValue(); + + // when + boolean isJoined = joinedMoimFinder.isJoining(moimId, memberId); + + // then + assertThat(isJoined).isFalse(); + } } \ No newline at end of file diff --git a/backend/src/test/java/moim_today/implement/moim/moim/MoimFinderTest.java b/backend/src/test/java/moim_today/implement/moim/moim/MoimFinderTest.java index 6ca0b671..d310d6eb 100644 --- a/backend/src/test/java/moim_today/implement/moim/moim/MoimFinderTest.java +++ b/backend/src/test/java/moim_today/implement/moim/moim/MoimFinderTest.java @@ -5,6 +5,7 @@ import moim_today.dto.moim.moim.MoimDateResponse; import moim_today.dto.moim.moim.MoimMemberResponse; import moim_today.dto.moim.moim.MoimSimpleResponse; +import moim_today.dto.moim.moim.MyMoimResponse; import moim_today.dto.moim.moim.enums.MoimCategoryDto; import moim_today.global.error.BadRequestException; import moim_today.global.error.NotFoundException; @@ -35,6 +36,48 @@ class MoimFinderTest extends ImplementTest { private final int MOIM_MEMBER_SIZE = 3; + @DisplayName("회원이 참여한 모임의 정보를 가져온다.") + @Test + void findAllMyMoimResponse() { + // given 1 + MemberJpaEntity memberJpaEntity = MemberJpaEntity.builder() + .build(); + + memberRepository.save(memberJpaEntity); + + // given 2 + MoimJpaEntity moimJpaEntity1 = MoimJpaEntity.builder() + .title(MOIM_TITLE.value()) + .build(); + + MoimJpaEntity moimJpaEntity2 = MoimJpaEntity.builder() + .title(MOIM_TITLE.value()) + .build(); + + moimRepository.save(moimJpaEntity1); + moimRepository.save(moimJpaEntity2); + + // given 3 + JoinedMoimJpaEntity joinedMoimJpaEntity1 = JoinedMoimJpaEntity.builder() + .memberId(memberJpaEntity.getId()) + .moimId(moimJpaEntity1.getId()) + .build(); + + JoinedMoimJpaEntity joinedMoimJpaEntity2 = JoinedMoimJpaEntity.builder() + .memberId(memberJpaEntity.getId()) + .moimId(moimJpaEntity2.getId()) + .build(); + + joinedMoimRepository.save(joinedMoimJpaEntity1); + joinedMoimRepository.save(joinedMoimJpaEntity2); + + // when + List myMoimResponses = moimFinder.findAllMyMoimResponse(memberJpaEntity.getId()); + + // then + assertThat(myMoimResponses.size()).isEqualTo(2); + } + @DisplayName("모임을 조회하면 모임 엔티티를 반환한다.") @Test void getByIdTest() { @@ -205,7 +248,10 @@ void findMoimDate() { @Test void findAllMoim() throws InterruptedException { // given + long universityId = UNIV_ID.longValue(); + MoimJpaEntity firstCreatedMoimJpaEntity = MoimJpaEntity.builder() + .universityId(universityId) .title(FIRST_CREATED_MOIM_TITLE.value()) .moimCategory(MoimCategory.TEAM_PROJECT) .build(); @@ -214,7 +260,10 @@ void findAllMoim() throws InterruptedException { Thread.sleep(10); + Thread.sleep(10); + MoimJpaEntity secondCreatedMoimJpaEntity = MoimJpaEntity.builder() + .universityId(universityId) .title(SECOND_CREATED_MOIM_TITLE.value()) .moimCategory(MoimCategory.STUDY) .build(); @@ -225,7 +274,7 @@ void findAllMoim() throws InterruptedException { MoimSortedFilter moimSortedFilter = null; // when - List moimSimpleResponses = moimFinder.findAllMoimResponse(moimCategoryDto, moimSortedFilter); + List moimSimpleResponses = moimFinder.findAllMoimResponses(universityId, moimCategoryDto, moimSortedFilter); // then assertThat(moimSimpleResponses.size()).isEqualTo(2); @@ -237,7 +286,10 @@ void findAllMoim() throws InterruptedException { @Test void findAllMoimOrderByCreatedAt() throws InterruptedException { // given + long universityId = UNIV_ID.longValue(); + MoimJpaEntity firstCreatedMoimJpaEntity = MoimJpaEntity.builder() + .universityId(universityId) .title(FIRST_CREATED_MOIM_TITLE.value()) .moimCategory(MoimCategory.TEAM_PROJECT) .build(); @@ -246,7 +298,10 @@ void findAllMoimOrderByCreatedAt() throws InterruptedException { Thread.sleep(10); + Thread.sleep(10); + MoimJpaEntity secondCreatedMoimJpaEntity = MoimJpaEntity.builder() + .universityId(universityId) .title(SECOND_CREATED_MOIM_TITLE.value()) .moimCategory(MoimCategory.STUDY) .build(); @@ -257,7 +312,7 @@ void findAllMoimOrderByCreatedAt() throws InterruptedException { MoimSortedFilter moimSortedFilter = MoimSortedFilter.CREATED_AT; // when - List moimSimpleResponses = moimFinder.findAllMoimResponse(moimCategoryDto, moimSortedFilter); + List moimSimpleResponses = moimFinder.findAllMoimResponses(universityId, moimCategoryDto, moimSortedFilter); // then assertThat(moimSimpleResponses.size()).isEqualTo(2); @@ -269,7 +324,10 @@ void findAllMoimOrderByCreatedAt() throws InterruptedException { @Test void findAllMoimOrderByViews() { // given + long universityId = UNIV_ID.longValue(); + MoimJpaEntity firstCreatedMoimJpaEntity = MoimJpaEntity.builder() + .universityId(universityId) .title(FIRST_CREATED_MOIM_TITLE.value()) .views(10) .build(); @@ -277,6 +335,7 @@ void findAllMoimOrderByViews() { moimRepository.save(firstCreatedMoimJpaEntity); MoimJpaEntity secondCreatedMoimJpaEntity = MoimJpaEntity.builder() + .universityId(universityId) .title(SECOND_CREATED_MOIM_TITLE.value()) .views(20) .build(); @@ -287,7 +346,7 @@ void findAllMoimOrderByViews() { MoimSortedFilter moimSortedFilter = MoimSortedFilter.VIEWS; // when - List moimSimpleResponses = moimFinder.findAllMoimResponse(moimCategoryDto, moimSortedFilter); + List moimSimpleResponses = moimFinder.findAllMoimResponses(universityId, moimCategoryDto, moimSortedFilter); // then assertThat(moimSimpleResponses.size()).isEqualTo(2); @@ -299,7 +358,10 @@ void findAllMoimOrderByViews() { @Test void findAllMoimByCategory() { // given + long universityId = UNIV_ID.longValue(); + MoimJpaEntity firstCreatedMoimJpaEntity = MoimJpaEntity.builder() + .universityId(universityId) .title(FIRST_CREATED_MOIM_TITLE.value()) .moimCategory(MoimCategory.TEAM_PROJECT) .build(); @@ -307,6 +369,7 @@ void findAllMoimByCategory() { moimRepository.save(firstCreatedMoimJpaEntity); MoimJpaEntity secondCreatedMoimJpaEntity = MoimJpaEntity.builder() + .universityId(universityId) .title(SECOND_CREATED_MOIM_TITLE.value()) .moimCategory(MoimCategory.STUDY) .build(); @@ -317,7 +380,41 @@ void findAllMoimByCategory() { MoimSortedFilter moimSortedFilter = null; // when - List moimSimpleResponses = moimFinder.findAllMoimResponse(moimCategoryDto, moimSortedFilter); + List moimSimpleResponses = moimFinder.findAllMoimResponses(universityId, moimCategoryDto, moimSortedFilter); + + // then + assertThat(moimSimpleResponses.size()).isEqualTo(1); + assertThat(moimSimpleResponses.get(0).title()).isEqualTo(FIRST_CREATED_MOIM_TITLE.value()); + } + + @DisplayName("자신이 속한 대학교의 모임리스트만 가져온다.") + @Test + void findAllMoimByCategoryByUniversityId() { + // given + long universityId = UNIV_ID.longValue(); + long otherUniversityId = UNIV_ID.longValue() + 1; + + MoimJpaEntity firstCreatedMoimJpaEntity = MoimJpaEntity.builder() + .universityId(universityId) + .title(FIRST_CREATED_MOIM_TITLE.value()) + .moimCategory(MoimCategory.TEAM_PROJECT) + .build(); + + moimRepository.save(firstCreatedMoimJpaEntity); + + MoimJpaEntity secondCreatedMoimJpaEntity = MoimJpaEntity.builder() + .universityId(otherUniversityId) + .title(SECOND_CREATED_MOIM_TITLE.value()) + .moimCategory(MoimCategory.STUDY) + .build(); + + moimRepository.save(secondCreatedMoimJpaEntity); + + MoimCategoryDto moimCategoryDto = MoimCategoryDto.ALL; + MoimSortedFilter moimSortedFilter = null; + + // when + List moimSimpleResponses = moimFinder.findAllMoimResponses(universityId, moimCategoryDto, moimSortedFilter); // then assertThat(moimSimpleResponses.size()).isEqualTo(1); @@ -428,17 +525,22 @@ void validateCapacityDoesNotThrowError() { @Test void searchMoimBySearchParam() { // given1 + long universityId = UNIV_ID.longValue(); + MoimJpaEntity moimA = MoimJpaEntity.builder() + .universityId(universityId) .title("appleMango") .build(); // given2 MoimJpaEntity moimB = MoimJpaEntity.builder() + .universityId(universityId) .title(" " + "apple" + " " + "mango" + " ") .build(); // given3 MoimJpaEntity moimC = MoimJpaEntity.builder() + .universityId(universityId) .title("apple" + " " + "mango") .build(); @@ -447,11 +549,11 @@ void searchMoimBySearchParam() { moimRepository.save(moimC); //when - List appleResponses = moimFinder.searchMoim("apple"); - List mangoResponses = moimFinder.searchMoim("mango"); - List blankResponses = moimFinder.searchMoim(" "); - List noneResponses = moimFinder.searchMoim("none"); - List applemangoResponses = moimFinder.searchMoim("apple mango"); + List appleResponses = moimFinder.searchMoim(universityId, "apple"); + List mangoResponses = moimFinder.searchMoim(universityId, "mango"); + List blankResponses = moimFinder.searchMoim(universityId, " "); + List noneResponses = moimFinder.searchMoim(universityId, "none"); + List applemangoResponses = moimFinder.searchMoim(universityId, "apple mango"); //then assertThat(appleResponses.size()).isEqualTo(3); @@ -461,6 +563,123 @@ void searchMoimBySearchParam() { assertThat(applemangoResponses.size()).isEqualTo(2); } + @DisplayName("다른 대학 모임은 검색되지 않는다.") + @Test + void searchMoimBySearchParamAndUniversityId() { + // given1 + long universityId = UNIV_ID.longValue(); + long otherUniversityId = UNIV_ID.longValue() + 1; + + MoimJpaEntity moimA = MoimJpaEntity.builder() + .universityId(universityId) + .title("appleMango") + .build(); + + // given2 + MoimJpaEntity moimB = MoimJpaEntity.builder() + .universityId(universityId) + .title(" " + "apple" + " " + "mango" + " ") + .build(); + + // given3 + MoimJpaEntity moimC = MoimJpaEntity.builder() + .universityId(otherUniversityId) + .title("apple" + " " + "mango") + .build(); + + moimRepository.save(moimA); + moimRepository.save(moimB); + moimRepository.save(moimC); + + //when + List appleResponses = moimFinder.searchMoim(universityId, "apple"); + List mangoResponses = moimFinder.searchMoim(universityId, "mango"); + List blankResponses = moimFinder.searchMoim(universityId, " "); + List noneResponses = moimFinder.searchMoim(universityId, "none"); + List applemangoResponses = moimFinder.searchMoim(otherUniversityId, "apple mango"); + + //then + assertThat(appleResponses.size()).isEqualTo(2); + assertThat(mangoResponses.size()).isEqualTo(2); + assertThat(blankResponses.size()).isEqualTo(2); + assertThat(noneResponses.size()).isEqualTo(0); + assertThat(applemangoResponses.size()).isEqualTo(1); + } + + @DisplayName("모임들 중 완료된 모임을 반환한다.") + @Test + void findEndedMoimSimpleResponsesByMoimIds() { + MemberJpaEntity saveMember = saveRandomMember(); + + LocalDate localDate1 = LocalDate.of(2023, 5, 12); + LocalDate localDate2 = LocalDate.of(2024, 5, 16); + LocalDate localDate3 = LocalDate.of(2025, 6, 5); + + MoimJpaEntity moimJpaEntity1 = MoimJpaEntity.builder() + .memberId(saveMember.getId()) + .endDate(localDate1) + .build(); + MoimJpaEntity moimJpaEntity2 = MoimJpaEntity.builder() + .memberId(saveMember.getId()) + .endDate(localDate2) + .build(); + MoimJpaEntity moimJpaEntity3 = MoimJpaEntity.builder() + .memberId(saveMember.getId()) + .endDate(localDate3) + .build(); + + moimRepository.save(moimJpaEntity1); + moimRepository.save(moimJpaEntity2); + moimRepository.save(moimJpaEntity3); + + List moimIds = List.of(moimJpaEntity1.getId(), moimJpaEntity2.getId(), moimJpaEntity3.getId()); + + List endedMoims1 = moimFinder.findEndedMoimSimpleResponsesByMoimIds( + moimIds, LocalDate.of(2024, 5, 16)); + List endedMoims2 = moimFinder.findEndedMoimSimpleResponsesByMoimIds( + moimIds, LocalDate.of(2025, 6, 4)); + + assertThat(endedMoims1.size()).isEqualTo(1); + assertThat(endedMoims2.size()).isEqualTo(2); + } + + @DisplayName("모임들 중 진행중인 모임을 반환한다.") + @Test + void findInProgressMoimSimpleResponsesByMoimIds() { + MemberJpaEntity saveMember = saveRandomMember(); + + LocalDate localDate1 = LocalDate.of(2023, 5, 12); + LocalDate localDate2 = LocalDate.of(2024, 5, 16); + LocalDate localDate3 = LocalDate.of(2025, 6, 5); + + MoimJpaEntity moimJpaEntity1 = MoimJpaEntity.builder() + .memberId(saveMember.getId()) + .endDate(localDate1) + .build(); + MoimJpaEntity moimJpaEntity2 = MoimJpaEntity.builder() + .memberId(saveMember.getId()) + .endDate(localDate2) + .build(); + MoimJpaEntity moimJpaEntity3 = MoimJpaEntity.builder() + .memberId(saveMember.getId()) + .endDate(localDate3) + .build(); + + moimRepository.save(moimJpaEntity1); + moimRepository.save(moimJpaEntity2); + moimRepository.save(moimJpaEntity3); + + List moimIds = List.of(moimJpaEntity1.getId(), moimJpaEntity2.getId(), moimJpaEntity3.getId()); + + List inProgressMoims1 = moimFinder.findInProgressMoimSimpleResponsesByMoimIds( + moimIds, LocalDate.of(2024, 5, 16)); + List inProgressMoims2 = moimFinder.findInProgressMoimSimpleResponsesByMoimIds( + moimIds, LocalDate.of(2025, 6, 4)); + + assertThat(inProgressMoims1.size()).isEqualTo(2); + assertThat(inProgressMoims2.size()).isEqualTo(1); + } + private MemberJpaEntity saveRandomMember() { MemberJpaEntity memberJpaEntity = MemberJpaEntity.builder() .username(USERNAME + String.valueOf(random.nextInt(10))) diff --git a/backend/src/test/java/moim_today/implement/moim/moim/MoimManagerTest.java b/backend/src/test/java/moim_today/implement/moim/moim/MoimManagerTest.java index b7b25121..dd2a02ff 100644 --- a/backend/src/test/java/moim_today/implement/moim/moim/MoimManagerTest.java +++ b/backend/src/test/java/moim_today/implement/moim/moim/MoimManagerTest.java @@ -1,16 +1,22 @@ package moim_today.implement.moim.moim; +import moim_today.dto.moim.moim.MoimSimpleResponse; +import moim_today.persistence.entity.member.MemberJpaEntity; +import moim_today.persistence.entity.moim.joined_moim.JoinedMoimJpaEntity; import moim_today.persistence.entity.moim.moim.MoimJpaEntity; import moim_today.util.ImplementTest; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import java.time.LocalDate; +import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import static moim_today.util.TestConstant.MEMBER_ID; +import static moim_today.util.TestConstant.USERNAME; import static org.assertj.core.api.Assertions.assertThat; class MoimManagerTest extends ImplementTest { @@ -54,4 +60,218 @@ void validateConcurrencyTest() throws Exception{ long joinedMembersCount = joinedMoimRepository.findAllJoinedMemberId(savedMoimId).size(); assertThat(joinedMembersCount).isEqualTo(MOIM_MAXIMUM_PEOPLE); } + + @DisplayName("자신이 참여한 모임들 중 완료 여부에 따라 반환한다.") + @Test + void findAllJoinedMoimSimpleResponseByEndStatus() { + // given1 + MemberJpaEntity member1 = MemberJpaEntity.builder() + .username(USERNAME.value()) + .build(); + + memberRepository.save(member1); + + LocalDate localDate1 = LocalDate.of(2023, 5, 12); + LocalDate localDate2 = LocalDate.of(2024, 5, 16); + LocalDate localDate3 = LocalDate.of(2025, 6, 5); + + // given2 + MoimJpaEntity moimJpaEntity1 = MoimJpaEntity.builder() + .memberId(member1.getId()) + .endDate(localDate1) + .build(); + MoimJpaEntity moimJpaEntity2 = MoimJpaEntity.builder() + .memberId(member1.getId()) + .endDate(localDate2) + .build(); + MoimJpaEntity moimJpaEntity3 = MoimJpaEntity.builder() + .memberId(member1.getId()) + .endDate(localDate3) + .build(); + + moimRepository.save(moimJpaEntity1); + moimRepository.save(moimJpaEntity2); + moimRepository.save(moimJpaEntity3); + + // given3 + JoinedMoimJpaEntity j1 = JoinedMoimJpaEntity.builder() + .memberId(member1.getId()) + .moimId(moimJpaEntity1.getId()) + .build(); + JoinedMoimJpaEntity j2 = JoinedMoimJpaEntity.builder() + .memberId(member1.getId()) + .moimId(moimJpaEntity2.getId()) + .build(); + JoinedMoimJpaEntity j3 = JoinedMoimJpaEntity.builder() + .memberId(member1.getId()) + .moimId(moimJpaEntity3.getId()) + .build(); + + joinedMoimRepository.save(j1); + joinedMoimRepository.save(j2); + joinedMoimRepository.save(j3); + + // when + List endedMoims = moimManager.findAllJoinedMoimSimpleResponseByEndStatus( + member1.getId(), LocalDate.of(2024, 5, 16), true); + List inProgressMoims = moimManager.findAllJoinedMoimSimpleResponseByEndStatus( + member1.getId(), LocalDate.of(2024, 5, 16), false); + + // then + assertThat(endedMoims.size()).isEqualTo(1); + assertThat(inProgressMoims.size()).isEqualTo(2); + } + @DisplayName("다른 멤버의 모임들을 제외한 자신이 참여한 모임들 중 완료 여부에 따라 반환한다.") + @Test + void findAllJoinedMoimSimpleResponseExceptOtherMembers() { + // given + MemberJpaEntity me = MemberJpaEntity.builder() + .username(USERNAME.value()) + .build(); + MemberJpaEntity other = MemberJpaEntity.builder() + .username(USERNAME.value()+"1") + .build(); + + memberRepository.save(me); + memberRepository.save(other); + + LocalDate localDate1 = LocalDate.of(2023, 5, 12); + LocalDate localDate2 = LocalDate.of(2024, 5, 16); + + MoimJpaEntity myMoim1 = MoimJpaEntity.builder() + .memberId(me.getId()) + .endDate(localDate1) + .build(); + MoimJpaEntity myMoim2 = MoimJpaEntity.builder() + .memberId(me.getId()) + .endDate(localDate2) + .build(); + MoimJpaEntity otherMoim1 = MoimJpaEntity.builder() + .memberId(other.getId()) + .endDate(localDate1) + .build(); + MoimJpaEntity otherMoim2 = MoimJpaEntity.builder() + .memberId(other.getId()) + .endDate(localDate2) + .build(); + + moimRepository.save(myMoim1); + moimRepository.save(myMoim2); + moimRepository.save(otherMoim1); + moimRepository.save(otherMoim2); + + JoinedMoimJpaEntity j1 = JoinedMoimJpaEntity.builder() + .memberId(me.getId()) + .moimId(myMoim1.getId()) + .build(); + JoinedMoimJpaEntity j2 = JoinedMoimJpaEntity.builder() + .memberId(me.getId()) + .moimId(myMoim2.getId()) + .build(); + JoinedMoimJpaEntity j3 = JoinedMoimJpaEntity.builder() + .memberId(other.getId()) + .moimId(otherMoim1.getId()) + .build(); + JoinedMoimJpaEntity j4 = JoinedMoimJpaEntity.builder() + .memberId(other.getId()) + .moimId(otherMoim2.getId()) + .build(); + + joinedMoimRepository.save(j1); + joinedMoimRepository.save(j2); + joinedMoimRepository.save(j3); + joinedMoimRepository.save(j4); + + // when + List myEndedMoims = moimManager.findAllJoinedMoimSimpleResponseByEndStatus( + me.getId(), LocalDate.of(2023,5,12), true); + List myInProgressMoims = moimManager.findAllJoinedMoimSimpleResponseByEndStatus( + me.getId(), LocalDate.of(2023, 5, 12), false); + + // then + assertThat(myEndedMoims.size()).isEqualTo(0); + assertThat(myInProgressMoims.size()).isEqualTo(2); + } + + @DisplayName("자신이 호스트인 모임들의 정보만 완료 여부에 따라 가져온다") + @Test + void findAllHostMoimSimpleResponsesByEndStatus() { + // given + MemberJpaEntity me = MemberJpaEntity.builder() + .username(USERNAME.value()) + .build(); + MemberJpaEntity other = MemberJpaEntity.builder() + .username(USERNAME.value()+"1") + .build(); + + memberRepository.save(me); + memberRepository.save(other); + + LocalDate localDate1 = LocalDate.of(2023, 5, 12); + LocalDate localDate2 = LocalDate.of(2024, 5, 16); + + MoimJpaEntity myMoim1 = MoimJpaEntity.builder() + .memberId(me.getId()) + .endDate(localDate1) + .build(); + MoimJpaEntity myMoim2 = MoimJpaEntity.builder() + .memberId(me.getId()) + .endDate(localDate2) + .build(); + MoimJpaEntity otherMoim1 = MoimJpaEntity.builder() + .memberId(other.getId()) + .endDate(localDate1) + .build(); + MoimJpaEntity otherMoim2 = MoimJpaEntity.builder() + .memberId(other.getId()) + .endDate(localDate2) + .build(); + + moimRepository.save(myMoim1); + moimRepository.save(myMoim2); + moimRepository.save(otherMoim1); + moimRepository.save(otherMoim2); + + JoinedMoimJpaEntity j1 = JoinedMoimJpaEntity.builder() + .memberId(me.getId()) + .moimId(myMoim1.getId()) + .build(); + JoinedMoimJpaEntity j2 = JoinedMoimJpaEntity.builder() + .memberId(me.getId()) + .moimId(myMoim2.getId()) + .build(); + JoinedMoimJpaEntity j3 = JoinedMoimJpaEntity.builder() + .memberId(other.getId()) + .moimId(otherMoim1.getId()) + .build(); + JoinedMoimJpaEntity j4 = JoinedMoimJpaEntity.builder() + .memberId(other.getId()) + .moimId(otherMoim2.getId()) + .build(); + JoinedMoimJpaEntity j5 = JoinedMoimJpaEntity.builder() + .memberId(me.getId()) + .moimId(otherMoim1.getId()) + .build(); + JoinedMoimJpaEntity j6 = JoinedMoimJpaEntity.builder() + .memberId(me.getId()) + .moimId(otherMoim2.getId()) + .build(); + + joinedMoimRepository.save(j1); + joinedMoimRepository.save(j2); + joinedMoimRepository.save(j3); + joinedMoimRepository.save(j4); + joinedMoimRepository.save(j5); + joinedMoimRepository.save(j6); + + // when + List myEndedMoims = moimManager.findAllHostMoimSimpleResponsesByEndStatus( + me.getId(), LocalDate.of(2023,5,12), true); + List myInProgressMoims = moimManager.findAllHostMoimSimpleResponsesByEndStatus( + me.getId(), LocalDate.of(2023, 5, 12), false); + + // then + assertThat(myEndedMoims.size()).isEqualTo(0); + assertThat(myInProgressMoims.size()).isEqualTo(2); + } } \ No newline at end of file diff --git a/backend/src/test/java/moim_today/implement/moim/moim/MoimRemoverTest.java b/backend/src/test/java/moim_today/implement/moim/moim/MoimRemoverTest.java index b8b6419d..812ac01b 100644 --- a/backend/src/test/java/moim_today/implement/moim/moim/MoimRemoverTest.java +++ b/backend/src/test/java/moim_today/implement/moim/moim/MoimRemoverTest.java @@ -6,6 +6,7 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import static moim_today.util.TestConstant.MOIM_ID; import static org.assertj.core.api.Assertions.assertThat; class MoimRemoverTest extends ImplementTest { @@ -29,4 +30,17 @@ void deleteMoimTest(){ //then assertThat(moimRepository.count()).isEqualTo(0); } + + @DisplayName("모임이 존재하지 않아도 삭제시 예외가 발생하지 않는다.") + @Test + void deleteMoimWithNotExist(){ + //given + long moimId = MOIM_ID.longValue(); + + //when + moimRemover.deleteById(moimId); + + //then + assertThat(moimRepository.count()).isEqualTo(0); + } } diff --git a/backend/src/test/java/moim_today/implement/schedule/schedule/ScheduleRemoverTest.java b/backend/src/test/java/moim_today/implement/schedule/schedule/ScheduleRemoverTest.java index faa2132d..0fb27d9f 100644 --- a/backend/src/test/java/moim_today/implement/schedule/schedule/ScheduleRemoverTest.java +++ b/backend/src/test/java/moim_today/implement/schedule/schedule/ScheduleRemoverTest.java @@ -2,8 +2,10 @@ import moim_today.global.error.ForbiddenException; import moim_today.global.error.NotFoundException; +import moim_today.persistence.entity.meeting.meeting.MeetingJpaEntity; import moim_today.persistence.entity.schedule.schedule.ScheduleJpaEntity; import moim_today.util.ImplementTest; +import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -105,6 +107,34 @@ void deleteSchedulesByMeetingIdsTest() { assertThat(scheduleRepository.count()).isEqualTo(1L); } + @DisplayName("미팅에 있는 모든 스케줄을 삭제한다.") + @Test + void deleteAllByMeetingId() { + // given 1 + MeetingJpaEntity meetingJpaEntity = MeetingJpaEntity.builder() + .build(); + + meetingRepository.save(meetingJpaEntity); + + // given 2 + ScheduleJpaEntity scheduleJpaEntity1 = ScheduleJpaEntity.builder() + .meetingId(meetingJpaEntity.getId()) + .build(); + + ScheduleJpaEntity scheduleJpaEntity2 = ScheduleJpaEntity.builder() + .meetingId(meetingJpaEntity.getId()) + .build(); + + scheduleRepository.save(scheduleJpaEntity1); + scheduleRepository.save(scheduleJpaEntity2); + + // when + scheduleRemover.deleteAllByMeetingId(meetingJpaEntity.getId()); + + // then + assertThat(scheduleRepository.count()).isEqualTo(0); + } + @DisplayName("한 멤버의 미팅에 참여하는 기록들을 삭제한다") @Test void deleteAllByMemberInMeeting() { diff --git a/backend/src/test/java/moim_today/persistence/entity/email_subscribe/EmailSubscribeJpaEntityTest.java b/backend/src/test/java/moim_today/persistence/entity/email_subscribe/EmailSubscribeJpaEntityTest.java new file mode 100644 index 00000000..4413f91b --- /dev/null +++ b/backend/src/test/java/moim_today/persistence/entity/email_subscribe/EmailSubscribeJpaEntityTest.java @@ -0,0 +1,24 @@ +package moim_today.persistence.entity.email_subscribe; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.*; + +class EmailSubscribeJpaEntityTest { + + @DisplayName("이메일 수신 여부 설정을 변경한다.") + @Test + void updateSubscribeStatus() { + // given + EmailSubscribeJpaEntity emailSubscribeJpaEntity = EmailSubscribeJpaEntity.builder() + .subscribeStatus(true) + .build(); + + // when + emailSubscribeJpaEntity.updateSubscribeStatus(false); + + // then + assertThat(emailSubscribeJpaEntity.isSubscribeStatus()).isFalse(); + } +} \ No newline at end of file diff --git a/backend/src/test/java/moim_today/persistence/entity/meeting/meeting/MeetingJpaEntityTest.java b/backend/src/test/java/moim_today/persistence/entity/meeting/meeting/MeetingJpaEntityTest.java new file mode 100644 index 00000000..ac42dd0c --- /dev/null +++ b/backend/src/test/java/moim_today/persistence/entity/meeting/meeting/MeetingJpaEntityTest.java @@ -0,0 +1,33 @@ +package moim_today.persistence.entity.meeting.meeting; + +import moim_today.persistence.entity.moim.moim.MoimJpaEntity; +import moim_today.util.TestConstant; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static moim_today.util.TestConstant.*; +import static org.assertj.core.api.Assertions.*; + + +class MeetingJpaEntityTest { + + @DisplayName("미팅 정보를 수정한다.") + @Test + void updateMeeting() { + // given + MeetingJpaEntity meetingJpaEntity = MeetingJpaEntity.builder() + .agenda(MEETING_AGENDA.value()) + .place(MEETING_PLACE.value()) + .build(); + + String newAgenda = "newAgenda"; + String newPlace = "newPlace"; + + // when + meetingJpaEntity.updateMeeting(newAgenda, newPlace); + + // then + assertThat(meetingJpaEntity.getAgenda()).isEqualTo(newAgenda); + assertThat(meetingJpaEntity.getPlace()).isEqualTo(newPlace); + } +} \ No newline at end of file diff --git a/backend/src/test/java/moim_today/persistence/entity/meeting/meeting_comment/MeetingCommentJpaEntityTest.java b/backend/src/test/java/moim_today/persistence/entity/meeting/meeting_comment/MeetingCommentJpaEntityTest.java new file mode 100644 index 00000000..50461dcd --- /dev/null +++ b/backend/src/test/java/moim_today/persistence/entity/meeting/meeting_comment/MeetingCommentJpaEntityTest.java @@ -0,0 +1,44 @@ +package moim_today.persistence.entity.meeting.meeting_comment; + +import moim_today.global.error.ForbiddenException; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static moim_today.global.constant.exception.MeetingExceptionConstant.MEETING_COMMENT_FORBIDDEN_ERROR; +import static moim_today.util.TestConstant.MEMBER_ID; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class MeetingCommentJpaEntityTest { + + @DisplayName("댓글 작성자가 맞다면 검증에 성공한다.") + @Test + void validateMember() { + //given + long memberId = MEMBER_ID.longValue(); + MeetingCommentJpaEntity meetingCommentJpaEntity = MeetingCommentJpaEntity.builder() + .memberId(memberId) + .build(); + + //expected + assertThatCode(() -> meetingCommentJpaEntity.validateMember(memberId)) + .doesNotThrowAnyException(); + } + + @DisplayName("댓글 작성자가 아니라면 검증에 실패한다.") + @Test + void validateMemberFailure() { + //given + long memberId = MEMBER_ID.longValue(); + long otherMemberId = MEMBER_ID.longValue() + 1; + MeetingCommentJpaEntity meetingCommentJpaEntity = MeetingCommentJpaEntity.builder() + .memberId(memberId) + .build(); + + //expected + assertThatThrownBy(() -> meetingCommentJpaEntity.validateMember(otherMemberId)) + .isInstanceOf(ForbiddenException.class) + .hasMessage(MEETING_COMMENT_FORBIDDEN_ERROR.message()); + } + +} \ No newline at end of file diff --git a/backend/src/test/java/moim_today/presentation/auth/AuthControllerTest.java b/backend/src/test/java/moim_today/presentation/auth/AuthControllerTest.java index 31140e1c..601bd889 100644 --- a/backend/src/test/java/moim_today/presentation/auth/AuthControllerTest.java +++ b/backend/src/test/java/moim_today/presentation/auth/AuthControllerTest.java @@ -17,6 +17,7 @@ import static com.epages.restdocs.apispec.ResourceDocumentation.resource; import static moim_today.util.TestConstant.*; import static org.springframework.http.MediaType.APPLICATION_JSON; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; import static org.springframework.restdocs.payload.JsonFieldType.*; import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; @@ -56,7 +57,7 @@ void loginTest() throws Exception { )); } - @DisplayName("이메일/비밀번호가 틀리면 예오가 발생한다.") + @DisplayName("이메일/비밀번호가 틀리면 예외가 발생한다.") @Test void loginTestFail() throws Exception { MemberLoginRequest memberLoginRequest = new MemberLoginRequest(WRONG_EMAIL.value(), WRONG_PASSWORD.value(), true); @@ -138,4 +139,21 @@ void registerTest() throws Exception { .build()) )); } + + @DisplayName("로그인 세션이 유효한지를 검증한다.") + @Test + void validateMemberSession() throws Exception { + mockMvc.perform(get("/api/session-validation")) + .andExpect(status().isOk()) + .andDo(document("회원 세션 인증 성공", + resource(ResourceSnippetParameters.builder() + .tag("인증") + .summary("회원 세션 인증") + .responseFields( + fieldWithPath("isValidateMemberSession").type(BOOLEAN).description("세션 인증 여부") + ) + .build() + ) + )); + } } diff --git a/backend/src/test/java/moim_today/presentation/email_subscribe/EmailSubscribeControllerTest.java b/backend/src/test/java/moim_today/presentation/email_subscribe/EmailSubscribeControllerTest.java new file mode 100644 index 00000000..393aaadb --- /dev/null +++ b/backend/src/test/java/moim_today/presentation/email_subscribe/EmailSubscribeControllerTest.java @@ -0,0 +1,70 @@ +package moim_today.presentation.email_subscribe; + +import com.epages.restdocs.apispec.ResourceSnippetParameters; +import moim_today.application.email_subscribe.EmailSubscribeService; +import moim_today.dto.mail.EmailSubscribeRequest; +import moim_today.fake_class.email_subscribe.FakeEmailSubscribeService; +import moim_today.util.ControllerTest; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + + +import static com.epages.restdocs.apispec.ResourceDocumentation.resource; +import static org.springframework.http.MediaType.APPLICATION_JSON; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; +import static org.springframework.restdocs.payload.JsonFieldType.*; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +class EmailSubscribeControllerTest extends ControllerTest { + + private final EmailSubscribeService emailSubscribeService = new FakeEmailSubscribeService(); + + @Override + protected Object initController() { + return new EmailSubscribeController(emailSubscribeService); + } + + @DisplayName("해당 회원의 이메일 수신 여부 정보를 조회한다.") + @Test + void getEmailSubscriptionStatus() throws Exception { + mockMvc.perform( + get("/api/email-subscription") + ) + .andExpect(status().isOk()) + .andDo(document("해당 회원의 이메일 수신 여부를 조회한다.", + resource(ResourceSnippetParameters.builder() + .tag("미팅") + .summary("이메일 수신 정보 조회") + .responseFields( + fieldWithPath("subscribeStatus").type(BOOLEAN).description("수신 여부") + ) + .build() + ))); + } + + @DisplayName("이메일 수신 여부 정보를 변경한다.") + @Test + void updateEmailSubscribeStatus() throws Exception { + EmailSubscribeRequest emailSubscribeRequest = EmailSubscribeRequest.of(true); + String json = objectMapper.writeValueAsString(emailSubscribeRequest); + + mockMvc.perform( + post("/api/email-subscription") + .contentType(APPLICATION_JSON) + .content(json) + ) + .andExpect(status().isOk()) + .andDo(document("이메일 수신 여부를 변경한다.", + resource(ResourceSnippetParameters.builder() + .tag("미팅") + .summary("이메일 수신 정보 변경") + .requestFields( + fieldWithPath("subscribeStatus").type(BOOLEAN).description("수신 여부") + ) + .build() + ))); + } +} \ No newline at end of file diff --git a/backend/src/test/java/moim_today/presentation/meeting/meeting/MeetingControllerTest.java b/backend/src/test/java/moim_today/presentation/meeting/meeting/MeetingControllerTest.java index 99a24f17..5c4973cd 100644 --- a/backend/src/test/java/moim_today/presentation/meeting/meeting/MeetingControllerTest.java +++ b/backend/src/test/java/moim_today/presentation/meeting/meeting/MeetingControllerTest.java @@ -4,10 +4,12 @@ import moim_today.application.meeting.meeting.MeetingService; import moim_today.domain.meeting.enums.MeetingCategory; import moim_today.domain.meeting.enums.MeetingStatus; -import moim_today.dto.meeting.MeetingCreateRequest; +import moim_today.dto.meeting.meeting.MeetingCreateRequest; +import moim_today.dto.meeting.meeting.MeetingUpdateRequest; import moim_today.fake_class.meeting.meeting.FakeMeetingService; import moim_today.util.ControllerTest; import moim_today.util.EnumDocsUtils; +import moim_today.util.TestConstant; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -65,6 +67,14 @@ void createSingleMeeting() throws Exception { fieldWithPath("place").type(STRING).description("미팅 장소"), fieldWithPath("meetingCategory").type(STRING).description("미팅 카테고리") ) + .responseFields( + fieldWithPath("meetingId").type(NUMBER).description("미팅 id"), + fieldWithPath("agenda").type(STRING).description("미팅 의제"), + fieldWithPath("startDateTime").type(STRING).description("미팅 시작 시간"), + fieldWithPath("endDateTime").type(STRING).description("미팅 종료 시간"), + fieldWithPath("place").type(STRING).description("미팅 장소"), + fieldWithPath("meetingCategory").type(STRING).description("미팅 카테고리") + ) .build() ))); } @@ -101,6 +111,14 @@ void createRegularMeeting() throws Exception { fieldWithPath("place").type(STRING).description("미팅 장소"), fieldWithPath("meetingCategory").type(STRING).description("미팅 카테고리") ) + .responseFields( + fieldWithPath("meetingId").type(NUMBER).description("미팅 id"), + fieldWithPath("agenda").type(STRING).description("미팅 의제"), + fieldWithPath("startDateTime").type(STRING).description("미팅 시작 시간"), + fieldWithPath("endDateTime").type(STRING).description("미팅 종료 시간"), + fieldWithPath("place").type(STRING).description("미팅 장소"), + fieldWithPath("meetingCategory").type(STRING).description("미팅 카테고리") + ) .build() ))); } @@ -210,6 +228,66 @@ void findDetailsById() throws Exception { ))); } + @DisplayName("미팅 정보를 수정한다.") + @Test + void updateMeeting() throws Exception { + MeetingUpdateRequest meetingUpdateRequest = MeetingUpdateRequest.builder() + .meetingId(MEETING_ID.longValue()) + .agenda(MEETING_AGENDA.value()) + .place(MEETING_PLACE.value()) + .build(); + + String json = objectMapper.writeValueAsString(meetingUpdateRequest); + + mockMvc.perform( + patch("/api/meetings") + .contentType(APPLICATION_JSON) + .content(json) + ) + .andExpect(status().isOk()) + .andDo(document("미팅 정보 수정 성공", + resource(ResourceSnippetParameters.builder() + .tag("미팅") + .summary("미팅 정보 수정") + .requestFields( + fieldWithPath("meetingId").type(NUMBER).description("미팅 id"), + fieldWithPath("agenda").type(STRING).description("미팅 의제"), + fieldWithPath("place").type(STRING).description("미팅 장소") + ) + .build() + ))); + } + + @DisplayName("해당 미팅의 주최자가 아닌 사람은 미팅을 수정할 수 없다.") + @Test + void updateMeetingFail() throws Exception { + MeetingUpdateRequest meetingUpdateRequest = MeetingUpdateRequest.builder() + .meetingId(9999L) + .agenda(MEETING_AGENDA.value()) + .place(MEETING_PLACE.value()) + .build(); + + String json = objectMapper.writeValueAsString(meetingUpdateRequest); + + mockMvc.perform( + patch("/api/meetings") + .contentType(APPLICATION_JSON) + .content(json) + ) + .andExpect(status().isForbidden()) + .andDo(document("미팅 수정 실패 - 주최자가 아님", + resource(ResourceSnippetParameters.builder() + .tag("미팅") + .summary("미팅 정보 수정") + .requestFields( + fieldWithPath("meetingId").type(NUMBER).description("미팅 id"), + fieldWithPath("agenda").type(STRING).description("미팅 의제"), + fieldWithPath("place").type(STRING).description("미팅 장소") + ) + .build() + ))); + } + @DisplayName("미팅을 삭제한다.") @Test void deleteMeeting() throws Exception { diff --git a/backend/src/test/java/moim_today/presentation/meeting/meeting_comment/MeetingCommentControllerTest.java b/backend/src/test/java/moim_today/presentation/meeting/meeting_comment/MeetingCommentControllerTest.java new file mode 100644 index 00000000..a674944c --- /dev/null +++ b/backend/src/test/java/moim_today/presentation/meeting/meeting_comment/MeetingCommentControllerTest.java @@ -0,0 +1,151 @@ +package moim_today.presentation.meeting.meeting_comment; + +import com.epages.restdocs.apispec.ResourceSnippetParameters; +import moim_today.application.meeting.meeting_comment.MeetingCommentService; +import moim_today.dto.meeting.meeting_comment.MeetingCommentCreateRequest; +import moim_today.dto.meeting.meeting_comment.MeetingCommentDeleteRequest; +import moim_today.dto.meeting.meeting_comment.MeetingCommentUpdateRequest; +import moim_today.fake_class.meeting.meeting_comment.FakeMeetingCommentService; +import moim_today.util.ControllerTest; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.http.MediaType; +import org.springframework.restdocs.payload.JsonFieldType; + +import static com.epages.restdocs.apispec.ResourceDocumentation.resource; +import static com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatTypes.NUMBER; +import static com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatTypes.STRING; +import static moim_today.util.TestConstant.*; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +class MeetingCommentControllerTest extends ControllerTest { + + private final MeetingCommentService meetingCommentService = new FakeMeetingCommentService(); + + @Override + protected Object initController() { + return new MeetingCommentController(meetingCommentService); + } + + @DisplayName("미팅에 댓글을 작성한다.") + @Test + void createMeetingComment() throws Exception { + MeetingCommentCreateRequest meetingCommentCreateRequest = MeetingCommentCreateRequest.builder() + .meetingId(MEETING_ID.longValue()) + .contents(MEETING_COMMENT_CONTENTS.value()) + .build(); + + mockMvc.perform(post("/api/meeting-comments") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(meetingCommentCreateRequest))) + .andExpect(status().isOk()) + .andDo(document("미팅 댓글 작성 성공", + resource(ResourceSnippetParameters.builder() + .tag("미팅 댓글") + .summary("미팅 댓글 작성") + .requestFields( + fieldWithPath("meetingId").type(NUMBER).description("미팅 Id"), + fieldWithPath("contents").type(STRING).description("댓글 내용") + ) + .build() + ))); + } + + @DisplayName("미팅이 존재하지 않으면 댓글 작성에 실패한다.") + @Test + void createMeetingCommentNotExistMeeting() throws Exception { + MeetingCommentCreateRequest meetingCommentCreateRequest = MeetingCommentCreateRequest.builder() + .meetingId(NOT_FOUND_MEETING_ID.longValue()) + .contents(MEETING_COMMENT_CONTENTS.value()) + .build(); + + mockMvc.perform(post("/api/meeting-comments") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(meetingCommentCreateRequest))) + .andExpect(status().isNotFound()) + .andDo(document("미팅 댓글 작성 실패 - 존재하지 않는 미팅", + resource(ResourceSnippetParameters.builder() + .tag("미팅 댓글") + .summary("미팅 댓글 작성") + .requestFields( + fieldWithPath("meetingId").type(NUMBER).description("존재하지 않는 미팅 Id"), + fieldWithPath("contents").type(STRING).description("댓글 내용") + ) + .responseFields( + fieldWithPath("statusCode").type(JsonFieldType.STRING).description("상태 코드"), + fieldWithPath("message").type(JsonFieldType.STRING).description("오류 메세지") + ) + .build() + ))); + + } + + @DisplayName("미팅의 댓글 목록을 불러온다.") + @Test + void findAllMeetingCommentsByMeetingId() throws Exception { + long meetingId = MEETING_ID.longValue(); + + mockMvc.perform(get("/api/meeting-comments/{meetingId}", meetingId)) + .andExpect(status().isOk()) + .andDo(document("미팅 댓글 목록 조회 성공", + resource(ResourceSnippetParameters.builder() + .tag("미팅 댓글") + .summary("미팅 댓글 목록 조회") + .responseFields( + fieldWithPath("data[0].meetingCommentId").type(NUMBER).description("댓글 Id"), + fieldWithPath("data[0].username").type(STRING).description("작성자"), + fieldWithPath("data[0].imageUrl").type(STRING).description("작성자 프로필 사진 Url"), + fieldWithPath("data[0].contents").type(STRING).description("댓글 내용"), + fieldWithPath("data[0].createdAt").type(STRING).description("생성 일자") + ) + .build() + ))); + } + + @DisplayName("미팅의 댓글을 수정한다.") + @Test + void updateMeetingComments() throws Exception { + MeetingCommentUpdateRequest meetingCommentUpdateRequest = MeetingCommentUpdateRequest.builder() + .meetingCommentId(MEETING_COMMENT_ID.longValue()) + .contents(MEETING_COMMENT_CONTENTS.value()) + .build(); + + mockMvc.perform(patch("/api/meeting-comments/") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(meetingCommentUpdateRequest))) + .andExpect(status().isOk()) + .andDo(document("미팅 댓글 수정 성공", + resource(ResourceSnippetParameters.builder() + .tag("미팅 댓글") + .summary("미팅 댓글 수정") + .requestFields( + fieldWithPath("meetingCommentId").type(NUMBER).description("수정할 댓글 Id"), + fieldWithPath("contents").type(STRING).description("수정할 댓글 내용") + ) + .build() + ))); + } + + @DisplayName("미팅의 댓글을 삭제한다.") + @Test + void deleteMeetingComment() throws Exception { + MeetingCommentDeleteRequest meetingCommentDeleteRequest = new MeetingCommentDeleteRequest(MEETING_COMMENT_ID.longValue()); + + mockMvc.perform(delete("/api/meeting-comments/") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(meetingCommentDeleteRequest))) + .andExpect(status().isOk()) + .andDo(document("미팅 댓글 삭제 성공", + resource(ResourceSnippetParameters.builder() + .tag("미팅 댓글") + .summary("미팅 댓글 삭제") + .requestFields( + fieldWithPath("meetingCommentId").type(NUMBER).description("삭제할 댓글 Id") + ) + .build() + ))); + } +} \ No newline at end of file diff --git a/backend/src/test/java/moim_today/presentation/member/MemberControllerTest.java b/backend/src/test/java/moim_today/presentation/member/MemberControllerTest.java index fd20274a..30beab7c 100644 --- a/backend/src/test/java/moim_today/presentation/member/MemberControllerTest.java +++ b/backend/src/test/java/moim_today/presentation/member/MemberControllerTest.java @@ -9,6 +9,7 @@ import moim_today.dto.member.ProfileUpdateRequest; import moim_today.fake_class.member.FakeMemberService; import moim_today.util.ControllerTest; +import moim_today.util.TestConstant; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.mock.web.MockMultipartFile; @@ -210,9 +211,9 @@ void updateProfileImage() throws Exception { @DisplayName("멤버가 모임의 호스트인지 검사한다") @Test - void isHostTest() throws Exception { + void isHost() throws Exception { mockMvc.perform( - get("/api/members/{moimId}/hosts", 1L) + get("/api/members/{moimId}/hosts", MOIM_ID.longValue()) .param("moimId", MOIM_ID.value()) .contentType(APPLICATION_JSON) ) @@ -231,4 +232,26 @@ void isHostTest() throws Exception { ))); } + @DisplayName("회원이 참여한 모임인지 확인한다.") + @Test + void isJoinedMoim() throws Exception { + mockMvc.perform( + get("/api/members/{moimId}/joining", MOIM_ID.longValue()) + .param("moimId", MOIM_ID.value()) + .contentType(APPLICATION_JSON) + ) + .andExpect(status().isOk()) + .andDo(document("회원이 참여한 모임인지 검사", + pathParameters( + parameterWithName("moimId").description("모임 id") + ), + resource(ResourceSnippetParameters.builder() + .tag("회원") + .summary("회원이 참여한 모임인지 검사") + .responseFields( + fieldWithPath("isJoined").type(BOOLEAN).description("모임 참여 여부") + ) + .build() + ))); + } } diff --git a/backend/src/test/java/moim_today/presentation/moim/MoimControllerTest.java b/backend/src/test/java/moim_today/presentation/moim/MoimControllerTest.java index ba920bb3..ead3ce25 100644 --- a/backend/src/test/java/moim_today/presentation/moim/MoimControllerTest.java +++ b/backend/src/test/java/moim_today/presentation/moim/MoimControllerTest.java @@ -42,6 +42,25 @@ protected Object initController() { return new MoimController(fakeMoimService, fakeMoimNoticeService); } + @DisplayName("로그인한 회원이 참여한 모임리스트를 조회한다.") + @Test + void findAllMyMoimResponse() throws Exception { + mockMvc.perform( + get("/api/moims") + ) + .andExpect(status().isOk()) + .andDo(document("로그인한 회원이 참여한 모임 리스트 조회", + resource(ResourceSnippetParameters.builder() + .tag("모임") + .summary("로그인한 회원이 참여한 모임 리스트 간단한 정보 조회") + .responseFields( + fieldWithPath("data[0].moimId").type(NUMBER).description("모임 Id"), + fieldWithPath("data[0].title").type(STRING).description("모임명") + ) + .build() + ))); + } + @DisplayName("모임을 생성한다.") @Test void createPrivateMoimApiTest() throws Exception { @@ -789,4 +808,64 @@ void returnCategoriesTest() throws Exception { .build() ))); } + + @DisplayName("로그인한 회원이 참여한 모임들을 완료 여부에 따라 카드 정보로 반환한다") + @Test + void findAllMyJoinedMoimSimpleResponse() throws Exception { + + mockMvc.perform(get("/api/moims/joined/simple") + .queryParam("ended", "false")) + .andExpect(status().isOk()) + .andDo(document("자신이 참여한 모임 리스트를 완료 여부로 조회 성공", + resource(ResourceSnippetParameters.builder() + .tag("모임") + .summary("로그인한 회원이 참여한 모임 리스트 자세한 정보 조회") + .queryParameters( + parameterWithName("ended").description("완료된 모임을 찾을 지 여부 - [true, false]") + ) + .responseFields( + fieldWithPath("data[0].moimId").type(NUMBER).description("모임 Id"), + fieldWithPath("data[0].title").type(STRING).description("모임명"), + fieldWithPath("data[0].capacity").type(NUMBER).description("모집 인원"), + fieldWithPath("data[0].currentCount").type(NUMBER).description("현재 인원"), + fieldWithPath("data[0].imageUrl").type(STRING).description("모임 사진 URL"), + fieldWithPath("data[0].moimCategory").type(VARIES).description(String.format("카테고리 - %s", + EnumDocsUtils.getEnumNames(MoimCategory.class))), + fieldWithPath("data[0].displayStatus").type(VARIES).description(String.format("공개 여부 - %s", + EnumDocsUtils.getEnumNames(DisplayStatus.class))) + ) + .build()) + )); + } + + @DisplayName("로그인한 회원이 호스트인 모임들을 완료 여부에 따라 카드 정보로 반환한다") + @Test + void findAllHostMoimSimpleResponse() throws Exception { + + mockMvc.perform(get("/api/moims/joined/simple") + .queryParam("ended", "false") + .queryParam("onlyHost","true")) + .andExpect(status().isOk()) + .andDo(document("자신이 호스트인 모임 리스트를 완료 여부로 조회 성공", + resource(ResourceSnippetParameters.builder() + .tag("모임") + .summary("로그인한 회원이 호스트인 모임 리스트 자세한 정보 조회") + .queryParameters( + parameterWithName("ended").description("완료된 모임을 찾을 지 여부 - [true, false]"), + parameterWithName("onlyHost").optional().description("자신이 호스트인 모임만 찾을 지 여부 - [true, false] , default : false") + ) + .responseFields( + fieldWithPath("data[0].moimId").type(NUMBER).description("모임 Id"), + fieldWithPath("data[0].title").type(STRING).description("모임명"), + fieldWithPath("data[0].capacity").type(NUMBER).description("모집 인원"), + fieldWithPath("data[0].currentCount").type(NUMBER).description("현재 인원"), + fieldWithPath("data[0].imageUrl").type(STRING).description("모임 사진 URL"), + fieldWithPath("data[0].moimCategory").type(VARIES).description(String.format("카테고리 - %s", + EnumDocsUtils.getEnumNames(MoimCategory.class))), + fieldWithPath("data[0].displayStatus").type(VARIES).description(String.format("공개 여부 - %s", + EnumDocsUtils.getEnumNames(DisplayStatus.class))) + ) + .build()) + )); + } } diff --git a/backend/src/test/java/moim_today/util/ImplementTest.java b/backend/src/test/java/moim_today/util/ImplementTest.java index 674324b9..dac801ee 100644 --- a/backend/src/test/java/moim_today/util/ImplementTest.java +++ b/backend/src/test/java/moim_today/util/ImplementTest.java @@ -4,6 +4,7 @@ import moim_today.persistence.repository.certification.email.EmailCertificationRepository; import moim_today.persistence.repository.certification.password.PasswordCertificationRepository; import moim_today.persistence.repository.department.DepartmentRepository; +import moim_today.persistence.repository.email_subscribe.EmailSubscribeRepository; import moim_today.persistence.repository.meeting.joined_meeting.JoinedMeetingRepository; import moim_today.persistence.repository.meeting.meeting.MeetingRepository; import moim_today.persistence.repository.meeting.meeting_comment.MeetingCommentRepository; @@ -76,6 +77,9 @@ public abstract class ImplementTest { @Autowired protected MeetingCommentRepository meetingCommentRepository; + @Autowired + protected EmailSubscribeRepository emailSubscribeRepository; + @BeforeEach void setUpDatabase() { databaseCleaner.cleanUp(); diff --git a/backend/src/test/java/moim_today/util/TestConstant.java b/backend/src/test/java/moim_today/util/TestConstant.java index d12fbb79..9a2105d3 100644 --- a/backend/src/test/java/moim_today/util/TestConstant.java +++ b/backend/src/test/java/moim_today/util/TestConstant.java @@ -77,8 +77,11 @@ public enum TestConstant { //미팅 MEETING_ID("123"), + NOT_FOUND_MEETING_ID("0"), MEETING_AGENDA("meeting agenda"), MEETING_PLACE("meeting place"), + MEETING_COMMENT_ID("456"), + MEETING_COMMENT_CONTENTS("meeting comment contents"), FIRST_CREATED_MEETING_AGENDA("first agenda"), SECOND_CREATED_MEETING_AGENDA("second agenda"),