diff --git a/src/main/java/com/meetup/teame/backend/domain/activity/entity/Activity.java b/src/main/java/com/meetup/teame/backend/domain/activity/entity/Activity.java index b3f276b..609b6a5 100644 --- a/src/main/java/com/meetup/teame/backend/domain/activity/entity/Activity.java +++ b/src/main/java/com/meetup/teame/backend/domain/activity/entity/Activity.java @@ -39,6 +39,9 @@ public class Activity { @Comment("활동 일시") private LocalDateTime time; + @Comment("활동 소요 시간(분)") + private Long duration; + @Comment("참여 인원") private Long currentParticipants; diff --git a/src/main/java/com/meetup/teame/backend/domain/chatroom/repository/custom/DirectChatRoomRepositoryCustom.java b/src/main/java/com/meetup/teame/backend/domain/chatroom/repository/custom/DirectChatRoomRepositoryCustom.java index a9daec4..db13a20 100644 --- a/src/main/java/com/meetup/teame/backend/domain/chatroom/repository/custom/DirectChatRoomRepositoryCustom.java +++ b/src/main/java/com/meetup/teame/backend/domain/chatroom/repository/custom/DirectChatRoomRepositoryCustom.java @@ -13,4 +13,6 @@ public interface DirectChatRoomRepositoryCustom { List findForUser(User user); List findUpdatableRooms(); + + List findAppointmentForUserInMonth(User who, int year, int month); } diff --git a/src/main/java/com/meetup/teame/backend/domain/chatroom/repository/custom/DirectChatRoomRepositoryImpl.java b/src/main/java/com/meetup/teame/backend/domain/chatroom/repository/custom/DirectChatRoomRepositoryImpl.java index b5a74b9..3a064d7 100644 --- a/src/main/java/com/meetup/teame/backend/domain/chatroom/repository/custom/DirectChatRoomRepositoryImpl.java +++ b/src/main/java/com/meetup/teame/backend/domain/chatroom/repository/custom/DirectChatRoomRepositoryImpl.java @@ -47,4 +47,17 @@ public List findUpdatableRooms() { .where(directChatRoom.nextAppointment.appointmentDate.before(LocalDate.now())) .fetch(); } + + @Override + public List findAppointmentForUserInMonth(User who, int year, int month) { + return jpaQueryFactory + .selectFrom(directChatRoom) + .join(directChatRoom.userChatRooms, userChatRoom) + .join(userChatRoom.user, user) + .where(user.eq(who) + .and(directChatRoom.nextAppointment.appointmentDate.year().eq(year)) + .and(directChatRoom.nextAppointment.appointmentDate.month().eq(month))) + .orderBy(directChatRoom.updatedAt.desc()) + .fetch(); + } } diff --git a/src/main/java/com/meetup/teame/backend/domain/chatroom/repository/custom/GroupChatRoomRepositoryCustom.java b/src/main/java/com/meetup/teame/backend/domain/chatroom/repository/custom/GroupChatRoomRepositoryCustom.java index 85c1a4f..0faca42 100644 --- a/src/main/java/com/meetup/teame/backend/domain/chatroom/repository/custom/GroupChatRoomRepositoryCustom.java +++ b/src/main/java/com/meetup/teame/backend/domain/chatroom/repository/custom/GroupChatRoomRepositoryCustom.java @@ -10,4 +10,8 @@ public interface GroupChatRoomRepositoryCustom { List findForUser(User user); List findUpdatableRooms(); + + List findAppointmentForUserInMonth(User who, int year, int month); + + List findActivityForUserInMonth(User who, int year, int month); } diff --git a/src/main/java/com/meetup/teame/backend/domain/chatroom/repository/custom/GroupChatRoomRepositoryImpl.java b/src/main/java/com/meetup/teame/backend/domain/chatroom/repository/custom/GroupChatRoomRepositoryImpl.java index 7f762ce..4d79ec7 100644 --- a/src/main/java/com/meetup/teame/backend/domain/chatroom/repository/custom/GroupChatRoomRepositoryImpl.java +++ b/src/main/java/com/meetup/teame/backend/domain/chatroom/repository/custom/GroupChatRoomRepositoryImpl.java @@ -39,4 +39,30 @@ public List findUpdatableRooms() { .where(groupChatRoom.nextAppointment.appointmentDate.before(LocalDate.now())) .fetch(); } + + @Override + public List findAppointmentForUserInMonth(User who, int year, int month) { + return jpaQueryFactory + .selectFrom(groupChatRoom) + .join(groupChatRoom.userChatRooms, userChatRoom) + .join(userChatRoom.user, user) + .where(user.eq(who) + .and(groupChatRoom.nextAppointment.appointmentDate.year().eq(year)) + .and(groupChatRoom.nextAppointment.appointmentDate.month().eq(month))) + .orderBy(groupChatRoom.updatedAt.desc()) + .fetch(); + } + + @Override + public List findActivityForUserInMonth(User who, int year, int month) { + return jpaQueryFactory + .selectFrom(groupChatRoom) + .join(groupChatRoom.userChatRooms, userChatRoom) + .join(userChatRoom.user, user) + .where(user.eq(who) + .and(groupChatRoom.activity.time.year().eq(year)) + .and(groupChatRoom.activity.time.month().eq(month))) + .orderBy(groupChatRoom.updatedAt.desc()) + .fetch(); + } } diff --git a/src/main/java/com/meetup/teame/backend/domain/user/controller/UserController.java b/src/main/java/com/meetup/teame/backend/domain/user/controller/UserController.java index 8cf75ec..320275a 100644 --- a/src/main/java/com/meetup/teame/backend/domain/user/controller/UserController.java +++ b/src/main/java/com/meetup/teame/backend/domain/user/controller/UserController.java @@ -2,7 +2,9 @@ import com.meetup.teame.backend.domain.review.dto.response.ReviewRes; import com.meetup.teame.backend.domain.user.dto.request.OnboardingReq; +import com.meetup.teame.backend.domain.user.dto.request.ReadCalenderReq; import com.meetup.teame.backend.domain.user.dto.request.UpdateUserReq; +import com.meetup.teame.backend.domain.user.dto.response.ReadCalenderRes; import com.meetup.teame.backend.domain.user.dto.response.ReadMainRes; import com.meetup.teame.backend.domain.user.dto.response.UserInfoRes; import com.meetup.teame.backend.domain.user.service.UserService; @@ -25,9 +27,9 @@ public class UserController { @Operation(summary = "메인 페이지 조회", description = """ 현재 로그인한 유저의 메인 페이지를 조회합니다. - 아직 로그인이 없어서 임시로 고정된 더미 유저의 데이터를 전달하는 식으로 구현되어 있습니다. + 임시로 고정된 더미 유저의 데이터를 전달하는 식으로 구현되어 있습니다. - 추후 로그인 적용 시에는 jwt토큰도 같이 전달해서 요청해주셔야 합니다. + jwt토큰도 같이 전달해서 요청해주셔야 합니다. """) @GetMapping("/main") public ResponseEntity readMainPage() { @@ -38,9 +40,9 @@ public ResponseEntity readMainPage() { @Operation(summary = "온보딩 정보 등록", description = """ 유저의 온보딩 정보를 등록합니다. - 아직 로그인이 없어서 임시로 고정된 더미 유저의 온보딩 정보를 등록하는 식으로 구현되어 있습니다. + 임시로 고정된 더미 유저의 온보딩 정보를 등록하는 식으로 구현되어 있습니다. - 추후 로그인 적용 시에는 jwt토큰도 같이 전달해서 요청해주셔야 합니다. + jwt토큰도 같이 전달해서 요청해주셔야 합니다. 현재 온보딩 정보로 입력 가능한 성격 유형 ("잔잔한", "활발한", "평화로운", "자연친화적인", "창의적인", "학문적인", "예술적인", "배울 수 있는") @@ -53,6 +55,26 @@ public ResponseEntity setUserPersonality(@RequestBody @Valid OnboardingReq .ok().build(); } + + @Operation(summary = "마이페이지 캘린더 조회", description = """ + 유저의 캘린더 정보를 조회합니다. + + 임시로 고정된 더미 유저의 캘린더 정보를 조회하는 식으로 구현되어 있습니다. + + jwt토큰도 같이 전달해서 요청해주셔야 합니다. + + url 쿼리 파라미터로 다음과 같은 값을 전달해 주셔야 합니다. + + year : 년도 + + month : 월 + """) + @GetMapping("/mypage/calender") + public ResponseEntity readCalender(@ModelAttribute @Valid ReadCalenderReq readCalenderReq) { + return ResponseEntity + .ok(userService.readCalender(readCalenderReq)); + } + @Operation(summary = "사용자 기본 정보 조회", description = """ 사용자의 기본 정보를 볼 수 있는 api입니다. diff --git a/src/main/java/com/meetup/teame/backend/domain/user/dto/request/ReadCalenderReq.java b/src/main/java/com/meetup/teame/backend/domain/user/dto/request/ReadCalenderReq.java new file mode 100644 index 0000000..3d2416a --- /dev/null +++ b/src/main/java/com/meetup/teame/backend/domain/user/dto/request/ReadCalenderReq.java @@ -0,0 +1,22 @@ +package com.meetup.teame.backend.domain.user.dto.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@Getter +public class ReadCalenderReq { + @NotBlank(message="year is required.") + @Schema(example = "2024") + private Integer year; + + @NotBlank(message="month is required.") + @Schema(example = "5") + private Integer month; +} diff --git a/src/main/java/com/meetup/teame/backend/domain/user/dto/response/AppointmentRes.java b/src/main/java/com/meetup/teame/backend/domain/user/dto/response/AppointmentRes.java new file mode 100644 index 0000000..a874db1 --- /dev/null +++ b/src/main/java/com/meetup/teame/backend/domain/user/dto/response/AppointmentRes.java @@ -0,0 +1,52 @@ +package com.meetup.teame.backend.domain.user.dto.response; + +import com.meetup.teame.backend.domain.activity.entity.Activity; +import com.meetup.teame.backend.domain.chatroom.entity.Appointment; +import com.meetup.teame.backend.domain.chatroom.entity.DirectChatRoom; +import com.meetup.teame.backend.domain.chatroom.entity.GroupChatRoom; +import lombok.*; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.Locale; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Builder +public class AppointmentRes { + private LocalDate date; + private String tag; + private String description; + private String about; + + public static AppointmentRes ofActivity(GroupChatRoom groupChatRoom) { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("a h시 m분", new Locale("ko", "KR")); + String startTime = groupChatRoom.getActivity().getTime().format(formatter); + String endTIme = groupChatRoom.getActivity().getTime().plusMinutes(groupChatRoom.getActivity().getDuration()).format(formatter); + return AppointmentRes.builder() + .date(groupChatRoom.getActivity().getTime().toLocalDate()) + .tag(groupChatRoom.getActivity().getTitle()) + .description(groupChatRoom.getActivity().getTitle() + " 활동 참여하기") + .about(groupChatRoom.getActivity().getLocation() + ", " + startTime + " ~ " + endTIme) + .build(); + } + + public static AppointmentRes ofDirectChatRoom(DirectChatRoom directChatRoom) { + return AppointmentRes.builder() + .date(directChatRoom.getNextAppointment().getAppointmentDate()) + .tag(directChatRoom.getExperience().getDescription()) + .description(directChatRoom.getExperience().getDescription() + " 배움 나누기") + .about(directChatRoom.getNextAppointment().getAppointmentLocation()) + .build(); + } + + public static AppointmentRes ofGroupChatRoom(GroupChatRoom groupChatRoom) { + return AppointmentRes.builder() + .date(groupChatRoom.getNextAppointment().getAppointmentDate()) + .tag(groupChatRoom.getActivity().getTitle()) + .description(groupChatRoom.getActivity().getTitle() + " 약속") + .about(groupChatRoom.getNextAppointment().getAppointmentLocation()) + .build(); + } +} diff --git a/src/main/java/com/meetup/teame/backend/domain/user/dto/response/ReadCalenderRes.java b/src/main/java/com/meetup/teame/backend/domain/user/dto/response/ReadCalenderRes.java new file mode 100644 index 0000000..1288bb0 --- /dev/null +++ b/src/main/java/com/meetup/teame/backend/domain/user/dto/response/ReadCalenderRes.java @@ -0,0 +1,36 @@ +package com.meetup.teame.backend.domain.user.dto.response; + +import com.meetup.teame.backend.domain.chatroom.entity.Appointment; +import com.meetup.teame.backend.domain.chatroom.entity.DirectChatRoom; +import com.meetup.teame.backend.domain.chatroom.entity.GroupChatRoom; +import lombok.*; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Builder +public class ReadCalenderRes { + List appointments; + + public static ReadCalenderRes of(List groupChatRoomsByActivity, List directChatRooms, List groupChatRooms) { + List appointments = new ArrayList<>(); + appointments.addAll(groupChatRoomsByActivity.stream() + .map(AppointmentRes::ofActivity) + .toList()); + appointments.addAll(directChatRooms.stream() + .map(AppointmentRes::ofDirectChatRoom) + .toList()); + appointments.addAll(groupChatRooms.stream() + .map(AppointmentRes::ofGroupChatRoom) + .toList()); + appointments.sort((a, b) -> a.getDate().compareTo(b.getDate())); + + return ReadCalenderRes.builder() + .appointments(appointments) + .build(); + } +} diff --git a/src/main/java/com/meetup/teame/backend/domain/user/service/UserService.java b/src/main/java/com/meetup/teame/backend/domain/user/service/UserService.java index 9a3bc5c..effe6c8 100644 --- a/src/main/java/com/meetup/teame/backend/domain/user/service/UserService.java +++ b/src/main/java/com/meetup/teame/backend/domain/user/service/UserService.java @@ -2,13 +2,17 @@ import com.meetup.teame.backend.domain.activity.repository.ActivityRepository; import com.meetup.teame.backend.domain.auth.oauth.dto.CreateUserRequest; +import com.meetup.teame.backend.domain.chatroom.repository.DirectChatRoomRepository; +import com.meetup.teame.backend.domain.chatroom.repository.GroupChatRoomRepository; import com.meetup.teame.backend.domain.experience.repository.ExperienceRepository; import com.meetup.teame.backend.domain.personality.Personality; import com.meetup.teame.backend.domain.review.dto.response.ReviewRes; import com.meetup.teame.backend.domain.review.entity.Review; import com.meetup.teame.backend.domain.review.repository.ReviewRepository; import com.meetup.teame.backend.domain.user.dto.request.OnboardingReq; +import com.meetup.teame.backend.domain.user.dto.request.ReadCalenderReq; import com.meetup.teame.backend.domain.user.dto.request.UpdateUserReq; +import com.meetup.teame.backend.domain.user.dto.response.ReadCalenderRes; import com.meetup.teame.backend.domain.user.dto.response.ReadMainRes; import com.meetup.teame.backend.domain.user.dto.response.UserInfoRes; import com.meetup.teame.backend.domain.user.entity.Gender; @@ -33,6 +37,8 @@ public class UserService { private final UserRepository userRepository; private final ActivityRepository activityRepository; private final ExperienceRepository experienceRepository; + private final DirectChatRoomRepository directChatRoomRepository; + private final GroupChatRoomRepository groupChatRoomRepository; private final ReviewRepository reviewRepository; public ReadMainRes readMainPage() { @@ -54,7 +60,7 @@ public User createUser(CreateUserRequest request) { return User.builder() .name(request.getName()) .email(request.getEmail()) - .gender(Objects.equals(request.getGender(), "male") ? Gender.MALE:Gender.FEMALE) + .gender(Objects.equals(request.getGender(), "male") ? Gender.MALE : Gender.FEMALE) .age(age) .location(request.getLocation()) .point(0L) @@ -104,4 +110,15 @@ public void setUserPersonality(OnboardingReq onboardingReq) { .toList(); user.setPersonalities(personalities); } + + public ReadCalenderRes readCalender(ReadCalenderReq readCalenderReq) { + //todo 현재는 더미 유저지만 추후에는 SecurityContextHolder 정보를 조회해서 유저 정보를 가져와야 함 + User user = userRepository.findById(5L) + .orElseThrow(() -> new CustomException(ExceptionContent.NOT_FOUND_USER)); + return ReadCalenderRes.of( + groupChatRoomRepository.findActivityForUserInMonth(user, readCalenderReq.getYear(), readCalenderReq.getMonth()), + directChatRoomRepository.findAppointmentForUserInMonth(user, readCalenderReq.getYear(), readCalenderReq.getMonth()), + groupChatRoomRepository.findAppointmentForUserInMonth(user, readCalenderReq.getYear(), readCalenderReq.getMonth()) + ); + } }