diff --git a/src/main/java/side/onetime/controller/ScheduleController.java b/src/main/java/side/onetime/controller/ScheduleController.java index 265dc3f..2c23214 100644 --- a/src/main/java/side/onetime/controller/ScheduleController.java +++ b/src/main/java/side/onetime/controller/ScheduleController.java @@ -53,7 +53,7 @@ public ResponseEntity>> ge return ApiResponse.onSuccess(SuccessStatus._GET_ALL_DAY_SCHEDULES, perDaySchedulesResponses); } - // 개인 요일 스케줄 조회 API + // 개인 요일 스케줄 조회 API (비로그인) @GetMapping("/day/{event_id}/{member_id}") public ResponseEntity> getMemberDaySchedules( @PathVariable("event_id") String eventId, @@ -63,6 +63,16 @@ public ResponseEntity> getMembe return ApiResponse.onSuccess(SuccessStatus._GET_MEMBER_DAY_SCHEDULES, perDaySchedulesResponse); } + // 개인 요일 스케줄 조회 API (로그인) + @GetMapping("/day/{event_id}/user") + public ResponseEntity> getUserDaySchedules( + @PathVariable("event_id") String eventId, + @RequestHeader(value = "Authorization") String authorizationHeader) { + + ScheduleDto.PerDaySchedulesResponse perDaySchedulesResponse = scheduleService.getUserDaySchedules(eventId, authorizationHeader); + return ApiResponse.onSuccess(SuccessStatus._GET_USER_DAY_SCHEDULES, perDaySchedulesResponse); + } + // 멤버 필터링 요일 스케줄 조회 API @GetMapping("/day/action-filtering") public ResponseEntity>> getFilteredDaySchedules( @@ -81,7 +91,7 @@ public ResponseEntity>> g return ApiResponse.onSuccess(SuccessStatus._GET_ALL_DATE_SCHEDULES, perDateSchedulesResponses); } - // 개인 날짜 스케줄 조회 API + // 개인 날짜 스케줄 조회 API (비로그인) @GetMapping("/date/{event_id}/{member_id}") public ResponseEntity> getMemberDateSchedules( @PathVariable("event_id") String eventId, @@ -91,6 +101,16 @@ public ResponseEntity> getMemb return ApiResponse.onSuccess(SuccessStatus._GET_MEMBER_DATE_SCHEDULES, perDateSchedulesResponse); } + // 개인 날짜 스케줄 조회 API (로그인) + @GetMapping("/date/{event_id}/user") + public ResponseEntity> getUserDateSchedules( + @PathVariable("event_id") String eventId, + @RequestHeader(value = "Authorization") String authorizationHeader) { + + ScheduleDto.PerDateSchedulesResponse perDateSchedulesResponse = scheduleService.getUserDateSchedules(eventId, authorizationHeader); + return ApiResponse.onSuccess(SuccessStatus._GET_USER_DATE_SCHEDULES, perDateSchedulesResponse); + } + // 멤버 필터링 날짜 스케줄 조회 API @GetMapping("/date/action-filtering") public ResponseEntity>> getFilteredDateSchedules( diff --git a/src/main/java/side/onetime/dto/EventDto.java b/src/main/java/side/onetime/dto/EventDto.java index 1a6e14b..4c7cbea 100644 --- a/src/main/java/side/onetime/dto/EventDto.java +++ b/src/main/java/side/onetime/dto/EventDto.java @@ -10,9 +10,11 @@ import side.onetime.domain.Event; import side.onetime.domain.Member; import side.onetime.domain.Schedule; +import side.onetime.domain.User; import side.onetime.global.common.constant.Category; import java.time.LocalTime; +import java.util.ArrayList; import java.util.List; import java.util.UUID; import java.util.stream.Collectors; @@ -91,10 +93,18 @@ public static GetEventResponse of(Event event, List ranges) { public static class GetParticipantsResponse { private List names; - public static GetParticipantsResponse of(List members) { - List names = members.stream() + public static GetParticipantsResponse of(List members, List users) { + List names = new ArrayList<>(); + + // 멤버 이름 추가 + names.addAll(members.stream() .map(Member::getName) - .collect(Collectors.toList()); + .collect(Collectors.toList())); + + // 유저 닉네임 추가 + names.addAll(users.stream() + .map(User::getNickname) + .collect(Collectors.toList())); return GetParticipantsResponse.builder() .names(names) diff --git a/src/main/java/side/onetime/dto/ScheduleDto.java b/src/main/java/side/onetime/dto/ScheduleDto.java index 9c4595d..a3ef31e 100644 --- a/src/main/java/side/onetime/dto/ScheduleDto.java +++ b/src/main/java/side/onetime/dto/ScheduleDto.java @@ -8,7 +8,6 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import side.onetime.domain.Member; import side.onetime.domain.Selection; import java.util.ArrayList; @@ -98,9 +97,9 @@ public static class PerDaySchedulesResponse { @JsonProperty("schedules") private List daySchedules; - public static PerDaySchedulesResponse of(Member member, List daySchedules) { + public static PerDaySchedulesResponse of(String name, List daySchedules) { return PerDaySchedulesResponse.builder() - .name(member.getName()) + .name(name) .daySchedules(daySchedules) .build(); } @@ -117,9 +116,9 @@ public static class PerDateSchedulesResponse { @JsonProperty("schedules") private List dateSchedules; - public static PerDateSchedulesResponse of(Member member, List dateSchedules) { + public static PerDateSchedulesResponse of(String name, List dateSchedules) { return PerDateSchedulesResponse.builder() - .name(member.getName()) + .name(name) .dateSchedules(dateSchedules) .build(); } diff --git a/src/main/java/side/onetime/global/common/constant/SuccessStatus.java b/src/main/java/side/onetime/global/common/constant/SuccessStatus.java index eaa3f4c..bae16e9 100644 --- a/src/main/java/side/onetime/global/common/constant/SuccessStatus.java +++ b/src/main/java/side/onetime/global/common/constant/SuccessStatus.java @@ -25,9 +25,11 @@ public enum SuccessStatus implements BaseCode { _CREATED_DAY_SCHEDULES(HttpStatus.CREATED, "201", "요일 스케줄 등록에 성공했습니다."), _CREATED_DATE_SCHEDULES(HttpStatus.CREATED, "201", "날짜 스케줄 등록에 성공했습니다."), _GET_ALL_DAY_SCHEDULES(HttpStatus.OK, "200", "전체 요일 스케줄 조회에 성공했습니다."), - _GET_MEMBER_DAY_SCHEDULES(HttpStatus.OK, "200", "개인 요일 스케줄 조회에 성공했습니다."), + _GET_MEMBER_DAY_SCHEDULES(HttpStatus.OK, "200", "개인(비로그인) 요일 스케줄 조회에 성공했습니다."), + _GET_USER_DAY_SCHEDULES(HttpStatus.OK, "200", "개인(로그인) 요일 스케줄 조회에 성공했습니다."), _GET_ALL_DATE_SCHEDULES(HttpStatus.OK, "200", "전체 날짜 스케줄 조회에 성공했습니다."), - _GET_MEMBER_DATE_SCHEDULES(HttpStatus.OK, "200", "개인 날짜 스케줄 조회에 성공했습니다."), + _GET_MEMBER_DATE_SCHEDULES(HttpStatus.OK, "200", "개인(비로그인)날짜 스케줄 조회에 성공했습니다."), + _GET_USER_DATE_SCHEDULES(HttpStatus.OK, "200", "개인(로그인) 날짜 스케줄 조회에 성공했습니다."), _GET_FILTERED_DAY_SCHEDULES(HttpStatus.OK, "200", "멤버 필터링 요일 스케줄 조회에 성공했습니다."), _GET_FILTERED_DATE_SCHEDULES(HttpStatus.OK, "200", "멤버 필터링 날짜 스케줄 조회에 성공했습니다."), // URL diff --git a/src/main/java/side/onetime/repository/EventParticipationRepository.java b/src/main/java/side/onetime/repository/EventParticipationRepository.java index 2b51da6..893644e 100644 --- a/src/main/java/side/onetime/repository/EventParticipationRepository.java +++ b/src/main/java/side/onetime/repository/EventParticipationRepository.java @@ -1,7 +1,11 @@ package side.onetime.repository; import org.springframework.data.jpa.repository.JpaRepository; +import side.onetime.domain.Event; import side.onetime.domain.EventParticipation; +import java.util.List; + public interface EventParticipationRepository extends JpaRepository { + List findAllByEvent(Event event); } \ No newline at end of file diff --git a/src/main/java/side/onetime/service/EventService.java b/src/main/java/side/onetime/service/EventService.java index a3ea72d..4df76ad 100644 --- a/src/main/java/side/onetime/service/EventService.java +++ b/src/main/java/side/onetime/service/EventService.java @@ -131,9 +131,16 @@ public EventDto.GetEventResponse getEvent(String eventId) { public EventDto.GetParticipantsResponse getParticipants(String eventId) { Event event = eventRepository.findByEventId(UUID.fromString(eventId)) .orElseThrow(() -> new EventException(EventErrorResult._NOT_FOUND_EVENT)); + + // 이벤트에 참여하는 모든 멤버 List members = event.getMembers(); + // 이벤트에 참여하는 모든 유저 + List eventParticipations = eventParticipationRepository.findAllByEvent(event); + List users = eventParticipations.stream() + .map(EventParticipation::getUser) + .toList(); - return EventDto.GetParticipantsResponse.of(members); + return EventDto.GetParticipantsResponse.of(members, users); } // 가장 많이 되는 시간 조회 메서드 @@ -142,31 +149,54 @@ public List getMostPossibleTime(String eventId) { Event event = eventRepository.findByEventId(UUID.fromString(eventId)) .orElseThrow(() -> new EventException(EventErrorResult._NOT_FOUND_EVENT)); + // 이벤트에 참여하는 모든 멤버 List members = event.getMembers(); List allMembersName = members.stream() .map(Member::getName) .toList(); + // 이벤트에 참여하는 모든 유저 + List eventParticipations = eventParticipationRepository.findAllByEvent(event); + List users = eventParticipations.stream() + .map(EventParticipation::getUser) + .toList(); + List allUserNicknames = users.stream() + .map(User::getNickname) + .toList(); + List selections = selectionRepository.findAllSelectionsByEvent(event); + // 스케줄과 선택된 참여자 이름 매핑 Map> scheduleToNamesMap = buildScheduleToNamesMap(selections); + int mostPossibleCnt = scheduleToNamesMap.values().stream() .mapToInt(List::size) .max() .orElse(0); - List mostPossibleTimes = buildMostPossibleTimes(scheduleToNamesMap, mostPossibleCnt, allMembersName, event.getCategory()); + // 멤버와 유저 전체 이름 합치기 + List allParticipants = new ArrayList<>(allMembersName); + allParticipants.addAll(allUserNicknames); + + List mostPossibleTimes = buildMostPossibleTimes(scheduleToNamesMap, mostPossibleCnt, allParticipants, event.getCategory()); return DateUtil.sortMostPossibleTimes(mostPossibleTimes, event.getCategory()); } - // 스케줄과 선택된 참여자 이름 매핑 + // 스케줄과 선택된 참여자 이름 매핑 (멤버 이름 / 유저 닉네임) private Map> buildScheduleToNamesMap(List selections) { return selections.stream() .collect(Collectors.groupingBy( Selection::getSchedule, LinkedHashMap::new, - Collectors.mapping(selection -> selection.getMember().getName(), Collectors.toList()) + Collectors.mapping(selection -> { + if (selection.getMember() != null) { + return selection.getMember().getName(); + } else if (selection.getUser() != null) { + return selection.getUser().getNickname(); + } + return null; + }, Collectors.toList()) )); } diff --git a/src/main/java/side/onetime/service/ScheduleService.java b/src/main/java/side/onetime/service/ScheduleService.java index abd82fc..5bdeb7a 100644 --- a/src/main/java/side/onetime/service/ScheduleService.java +++ b/src/main/java/side/onetime/service/ScheduleService.java @@ -16,6 +16,7 @@ @RequiredArgsConstructor public class ScheduleService { private final EventRepository eventRepository; + private final EventParticipationRepository eventParticipationRepository; private final MemberRepository memberRepository; private final ScheduleRepository scheduleRepository; private final SelectionRepository selectionRepository; @@ -153,10 +154,17 @@ public List getAllDaySchedules(String event Event event = eventRepository.findByEventId(UUID.fromString(eventId)) .orElseThrow(() -> new EventException(EventErrorResult._NOT_FOUND_EVENT)); + // 이벤트에 참여하는 모든 멤버 List members = memberRepository.findAllWithSelectionsAndSchedulesByEvent(event); + // 이벤트에 참여하는 모든 유저 + List eventParticipations = eventParticipationRepository.findAllByEvent(event); + List users = eventParticipations.stream() + .map(EventParticipation::getUser) + .toList(); List perDaySchedulesResponses = new ArrayList<>(); + // 멤버 스케줄 추가 for (Member member : members) { Map> groupedSelectionsByDay = member.getSelections().stream() .collect(Collectors.groupingBy( @@ -168,12 +176,29 @@ public List getAllDaySchedules(String event List daySchedules = groupedSelectionsByDay.entrySet().stream() .map(entry -> ScheduleDto.DaySchedule.of(entry.getValue())) .collect(Collectors.toList()); - perDaySchedulesResponses.add(ScheduleDto.PerDaySchedulesResponse.of(member, daySchedules)); + perDaySchedulesResponses.add(ScheduleDto.PerDaySchedulesResponse.of(member.getName(), daySchedules)); } + + // 유저 스케줄 추가 + for (User user : users) { + Map> groupedSelectionsByDay = user.getSelections().stream() + .filter(selection -> selection.getSchedule().getEvent().equals(event)) + .collect(Collectors.groupingBy( + selection -> selection.getSchedule().getDay(), + LinkedHashMap::new, + Collectors.toList() + )); + + List daySchedules = groupedSelectionsByDay.entrySet().stream() + .map(entry -> ScheduleDto.DaySchedule.of(entry.getValue())) + .collect(Collectors.toList()); + perDaySchedulesResponses.add(ScheduleDto.PerDaySchedulesResponse.of(user.getNickname(), daySchedules)); + } + return perDaySchedulesResponses; } - // 개인 요일 스케줄 반환 메서드 + // 개인 요일 스케줄 반환 메서드 (비로그인) @Transactional public ScheduleDto.PerDaySchedulesResponse getMemberDaySchedules(String eventId, String memberId) { Event event = eventRepository.findByEventId(UUID.fromString(eventId)) @@ -193,7 +218,30 @@ public ScheduleDto.PerDaySchedulesResponse getMemberDaySchedules(String eventId, .map(entry -> ScheduleDto.DaySchedule.of(entry.getValue())) .collect(Collectors.toList()); - return ScheduleDto.PerDaySchedulesResponse.of(member, daySchedules); + return ScheduleDto.PerDaySchedulesResponse.of(member.getName(), daySchedules); + } + + // 개인 요일 스케줄 반환 메서드 (로그인) + @Transactional + public ScheduleDto.PerDaySchedulesResponse getUserDaySchedules(String eventId, String authorizationHeader) { + Event event = eventRepository.findByEventId(UUID.fromString(eventId)) + .orElseThrow(() -> new EventException(EventErrorResult._NOT_FOUND_EVENT)); + + User user = jwtUtil.getUserFromHeader(authorizationHeader); + + Map> groupedSelectionsByDay = user.getSelections().stream() + .filter(selection -> selection.getSchedule().getEvent().equals(event)) + .collect(Collectors.groupingBy( + selection -> selection.getSchedule().getDay(), + LinkedHashMap::new, + Collectors.toList() + )); + + List daySchedules = groupedSelectionsByDay.entrySet().stream() + .map(entry -> ScheduleDto.DaySchedule.of(entry.getValue())) + .collect(Collectors.toList()); + + return ScheduleDto.PerDaySchedulesResponse.of(user.getNickname(), daySchedules); } // 전체 날짜 스케줄 반환 메서드 @@ -202,10 +250,17 @@ public List getAllDateSchedules(String eve Event event = eventRepository.findByEventId(UUID.fromString(eventId)) .orElseThrow(() -> new EventException(EventErrorResult._NOT_FOUND_EVENT)); + // 이벤트에 참여하는 모든 멤버 List members = memberRepository.findAllWithSelectionsAndSchedulesByEvent(event); + // 이벤트에 참여하는 모든 유저 + List eventParticipations = eventParticipationRepository.findAllByEvent(event); + List users = eventParticipations.stream() + .map(EventParticipation::getUser) + .toList(); List perDateSchedulesResponses = new ArrayList<>(); + // 멤버 스케줄 추가 for (Member member : members) { Map> groupedSelectionsByDate = member.getSelections().stream() .collect(Collectors.groupingBy( @@ -217,12 +272,29 @@ public List getAllDateSchedules(String eve List dateSchedules = groupedSelectionsByDate.entrySet().stream() .map(entry -> ScheduleDto.DateSchedule.of(entry.getValue())) .collect(Collectors.toList()); - perDateSchedulesResponses.add(ScheduleDto.PerDateSchedulesResponse.of(member, dateSchedules)); + perDateSchedulesResponses.add(ScheduleDto.PerDateSchedulesResponse.of(member.getName(), dateSchedules)); } + + // 유저 스케줄 추가 + for (User user : users) { + Map> groupedSelectionsByDate = user.getSelections().stream() + .filter(selection -> selection.getSchedule().getEvent().equals(event)) + .collect(Collectors.groupingBy( + selection -> selection.getSchedule().getDate(), + LinkedHashMap::new, + Collectors.toList() + )); + + List dateSchedules = groupedSelectionsByDate.entrySet().stream() + .map(entry -> ScheduleDto.DateSchedule.of(entry.getValue())) + .collect(Collectors.toList()); + perDateSchedulesResponses.add(ScheduleDto.PerDateSchedulesResponse.of(user.getNickname(), dateSchedules)); + } + return perDateSchedulesResponses; } - // 개인 날짜 스케줄 반환 메서드 + // 개인 날짜 스케줄 반환 메서드 (비로그인) @Transactional public ScheduleDto.PerDateSchedulesResponse getMemberDateSchedules(String eventId, String memberId) { Event event = eventRepository.findByEventId(UUID.fromString(eventId)) @@ -242,7 +314,30 @@ public ScheduleDto.PerDateSchedulesResponse getMemberDateSchedules(String eventI .map(entry -> ScheduleDto.DateSchedule.of(entry.getValue())) .collect(Collectors.toList()); - return ScheduleDto.PerDateSchedulesResponse.of(member, dateSchedules); + return ScheduleDto.PerDateSchedulesResponse.of(member.getName(), dateSchedules); + } + + // 개인 날짜 스케줄 반환 메서드 (로그인) + @Transactional + public ScheduleDto.PerDateSchedulesResponse getUserDateSchedules(String eventId, String authorizationHeader) { + Event event = eventRepository.findByEventId(UUID.fromString(eventId)) + .orElseThrow(() -> new EventException(EventErrorResult._NOT_FOUND_EVENT)); + + User user = jwtUtil.getUserFromHeader(authorizationHeader); + + Map> groupedSelectionsByDate = user.getSelections().stream() + .filter(selection -> selection.getSchedule().getEvent().equals(event)) + .collect(Collectors.groupingBy( + selection -> selection.getSchedule().getDate(), + LinkedHashMap::new, + Collectors.toList() + )); + + List dateSchedules = groupedSelectionsByDate.entrySet().stream() + .map(entry -> ScheduleDto.DateSchedule.of(entry.getValue())) + .collect(Collectors.toList()); + + return ScheduleDto.PerDateSchedulesResponse.of(user.getNickname(), dateSchedules); } // 멤버 필터링 요일 스케줄 반환 메서드 @@ -266,7 +361,7 @@ public List getFilteredDaySchedules(Schedul List daySchedules = groupedSelectionsByDay.entrySet().stream() .map(entry -> ScheduleDto.DaySchedule.of(entry.getValue())) .collect(Collectors.toList()); - perDaySchedulesResponses.add(ScheduleDto.PerDaySchedulesResponse.of(member, daySchedules)); + perDaySchedulesResponses.add(ScheduleDto.PerDaySchedulesResponse.of(member.getName(), daySchedules)); } return perDaySchedulesResponses; } @@ -292,7 +387,7 @@ public List getFilteredDateSchedules(Sched List dateSchedules = groupedSelectionsByDate.entrySet().stream() .map(entry -> ScheduleDto.DateSchedule.of(entry.getValue())) .collect(Collectors.toList()); - perDateSchedulesResponses.add(ScheduleDto.PerDateSchedulesResponse.of(member, dateSchedules)); + perDateSchedulesResponses.add(ScheduleDto.PerDateSchedulesResponse.of(member.getName(), dateSchedules)); } return perDateSchedulesResponses; }