diff --git a/meeting/src/main/java/com/unicorn/hgzero/meeting/biz/dto/MinutesDTO.java b/meeting/src/main/java/com/unicorn/hgzero/meeting/biz/dto/MinutesDTO.java index 6f6711a..51a3bf5 100644 --- a/meeting/src/main/java/com/unicorn/hgzero/meeting/biz/dto/MinutesDTO.java +++ b/meeting/src/main/java/com/unicorn/hgzero/meeting/biz/dto/MinutesDTO.java @@ -125,6 +125,12 @@ public class MinutesDTO { * 참석자 수 */ private final Integer participantCount; + + /** + * 검증완료율 (작성중 상태일 때만 유효) + * 0-100 사이의 값 + */ + private final Integer verificationRate; /** * 회의 정보 diff --git a/meeting/src/main/java/com/unicorn/hgzero/meeting/biz/service/MinutesService.java b/meeting/src/main/java/com/unicorn/hgzero/meeting/biz/service/MinutesService.java index 42c3658..233b635 100644 --- a/meeting/src/main/java/com/unicorn/hgzero/meeting/biz/service/MinutesService.java +++ b/meeting/src/main/java/com/unicorn/hgzero/meeting/biz/service/MinutesService.java @@ -240,20 +240,21 @@ public class MinutesService implements /** * 사용자 ID로 회의록 목록 조회 (페이징) + * 사용자가 생성했거나 참여한 회의의 회의록을 모두 조회 */ @Transactional(readOnly = true) public Page getMinutesListByUserId(String userId, Pageable pageable) { log.debug("Getting minutes list by userId: {}", userId); - // 여기서는 임시로 작성자 기준으로 조회 (실제로는 참석자나 권한 기반으로 조회해야 함) - List minutesList = minutesReader.findByCreatedBy(userId); + // 사용자가 생성했거나 참여한 회의의 회의록 조회 + List minutesList = minutesReader.findByParticipantUserId(userId); // Minutes를 MinutesDTO로 변환 List minutesDTOList = minutesList.stream() .map(this::convertToMinutesDTO) .collect(Collectors.toList()); - // 페이징 처리 (임시로 전체 목록 반환) + // 페이징 처리 int start = (int) pageable.getOffset(); int end = Math.min((start + pageable.getPageSize()), minutesDTOList.size()); List pageContent = minutesDTOList.subList(start, end); @@ -371,6 +372,15 @@ public class MinutesService implements log.warn("섹션 정보 변환 실패 - minutesId: {}", minutes.getMinutesId(), e); } + // 검증완료율 계산 (작성중 상태일 때만) + Integer verificationRate = null; + if ("DRAFT".equals(minutes.getStatus()) && sectionDTOs != null && !sectionDTOs.isEmpty()) { + long verifiedCount = sectionDTOs.stream() + .filter(section -> Boolean.TRUE.equals(section.getIsVerified())) + .count(); + verificationRate = (int) ((verifiedCount * 100) / sectionDTOs.size()); + } + // decisions 값 로깅 log.info("Minutes decisions 값 확인 - minutesId: {}, decisions: {}", minutes.getMinutesId(), minutes.getDecisions()); @@ -389,6 +399,7 @@ public class MinutesService implements .todoCount(todoCount) .completedTodoCount(completedTodoCount) .participantCount(participantCount) + .verificationRate(verificationRate) .memo("") // 메모 필드는 추후 구현 .sections(sectionDTOs) // 섹션 정보 추가 .decisions(minutes.getDecisions()) // decisions 필드 추가 diff --git a/meeting/src/main/java/com/unicorn/hgzero/meeting/biz/usecase/out/MinutesReader.java b/meeting/src/main/java/com/unicorn/hgzero/meeting/biz/usecase/out/MinutesReader.java index f3b5093..88e08dc 100644 --- a/meeting/src/main/java/com/unicorn/hgzero/meeting/biz/usecase/out/MinutesReader.java +++ b/meeting/src/main/java/com/unicorn/hgzero/meeting/biz/usecase/out/MinutesReader.java @@ -56,4 +56,13 @@ public interface MinutesReader { * @return AI 통합 회의록 */ Optional findConsolidatedMinutesByMeetingId(String meetingId); + + /** + * 사용자가 참여한 회의의 회의록 목록 조회 + * 사용자가 생성했거나 참여한 회의의 회의록을 모두 조회 + * + * @param userId 사용자 ID + * @return 회의록 목록 + */ + List findByParticipantUserId(String userId); } diff --git a/meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/MinutesController.java b/meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/MinutesController.java index da6e141..889ed45 100644 --- a/meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/MinutesController.java +++ b/meeting/src/main/java/com/unicorn/hgzero/meeting/infra/controller/MinutesController.java @@ -110,12 +110,13 @@ public class MinutesController { // DTO를 Response 형식으로 변환 List minutesList = minutesPage.getContent().stream() - .map(this::convertToMinutesItem) + .map(dto -> convertToMinutesItem(dto, userId)) .collect(Collectors.toList()); - // 필터링 적용 (상태별) + // 필터링 적용 (상태별, 참여 유형별, 검색어) List filteredMinutes = minutesList.stream() .filter(item -> filterByStatus(item, status)) + .filter(item -> filterByParticipationType(item, participationType)) .filter(item -> filterBySearch(item, search)) .collect(Collectors.toList()); @@ -489,8 +490,21 @@ public class MinutesController { */ private MinutesListResponse.Statistics calculateRealStatistics(String userId, String participationType) { try { - // 전체 회의록 조회 (작성자 기준) - List allMinutes = minutesService.getMinutesByCreator(userId); + // 전체 회의록 조회 (참여자 기준) + List allMinutes = minutesService.getMinutesListByUserId(userId, PageRequest.of(0, Integer.MAX_VALUE)).getContent(); + + // 참여 유형 필터링 + if (participationType != null && !participationType.isEmpty()) { + if ("created".equals(participationType)) { + allMinutes = allMinutes.stream() + .filter(m -> userId.equals(m.getCreatedBy())) + .collect(Collectors.toList()); + } else if ("attended".equals(participationType)) { + allMinutes = allMinutes.stream() + .filter(m -> !userId.equals(m.getCreatedBy())) + .collect(Collectors.toList()); + } + } long totalCount = allMinutes.size(); long draftCount = allMinutes.stream() @@ -515,10 +529,17 @@ public class MinutesController { } } - private MinutesListResponse.MinutesItem convertToMinutesItem(MinutesDTO minutesDTO) { - // 완료율 계산 - int completionRate = minutesDTO.getTodoCount() > 0 ? - (minutesDTO.getCompletedTodoCount() * 100) / minutesDTO.getTodoCount() : 100; + private MinutesListResponse.MinutesItem convertToMinutesItem(MinutesDTO minutesDTO, String userId) { + // 검증완료율 계산 (작성중 상태일 때는 verificationRate 사용, 확정완료시 100%) + int completionRate; + if ("DRAFT".equals(minutesDTO.getStatus()) && minutesDTO.getVerificationRate() != null) { + completionRate = minutesDTO.getVerificationRate(); + } else if ("FINALIZED".equals(minutesDTO.getStatus())) { + completionRate = 100; + } else { + // 기본값 0 + completionRate = 0; + } return MinutesListResponse.MinutesItem.builder() .minutesId(minutesDTO.getMinutesId()) @@ -535,7 +556,7 @@ public class MinutesController { .todoCount(minutesDTO.getTodoCount()) .completedTodoCount(minutesDTO.getCompletedTodoCount()) .completionRate(completionRate) - .isCreatedByUser(true) // 현재는 작성자 기준으로만 조회하므로 true + .isCreatedByUser(minutesDTO.getCreatedBy().equals(userId)) // 현재 사용자가 생성자인지 확인 .build(); } @@ -556,10 +577,19 @@ public class MinutesController { } /** - * 참여 유형별 필터링 - 현재는 사용하지 않음 (작성자 기준으로만 조회) + * 참여 유형별 필터링 */ - private boolean filterByParticipationType(MinutesListResponse.MinutesItem item, String participationType, String userId) { - // 현재는 작성자 기준으로만 조회하므로 항상 true 반환 + private boolean filterByParticipationType(MinutesListResponse.MinutesItem item, String participationType) { + if (participationType == null || participationType.isEmpty()) { + return true; // 필터 미적용시 모두 표시 + } + + if ("created".equals(participationType)) { + return item.isCreatedByUser(); // 사용자가 생성한 회의록만 + } else if ("attended".equals(participationType)) { + return !item.isCreatedByUser(); // 사용자가 참여만 한 회의록 + } + return true; } diff --git a/meeting/src/main/java/com/unicorn/hgzero/meeting/infra/gateway/MinutesGateway.java b/meeting/src/main/java/com/unicorn/hgzero/meeting/infra/gateway/MinutesGateway.java index c3c1ff7..5b8ce3a 100644 --- a/meeting/src/main/java/com/unicorn/hgzero/meeting/infra/gateway/MinutesGateway.java +++ b/meeting/src/main/java/com/unicorn/hgzero/meeting/infra/gateway/MinutesGateway.java @@ -78,6 +78,16 @@ public class MinutesGateway implements MinutesReader, MinutesWriter { return minutesJpaRepository.findByMeetingIdAndUserIdIsNull(meetingId) .map(MinutesEntity::toDomain); } + + @Override + public List findByParticipantUserId(String userId) { + log.debug("사용자가 참여한 회의의 회의록 조회: {}", userId); + // 사용자가 생성한 회의록과 사용자가 참여한 회의의 회의록을 모두 조회 + // 현재는 생성자 기준으로만 조회 (추후 참석자 테이블과 조인하여 구현 필요) + return minutesJpaRepository.findByCreatedByOrParticipantUserId(userId).stream() + .map(MinutesEntity::toDomain) + .collect(Collectors.toList()); + } @Override public Minutes save(Minutes minutes) { diff --git a/meeting/src/main/java/com/unicorn/hgzero/meeting/infra/gateway/repository/MinutesJpaRepository.java b/meeting/src/main/java/com/unicorn/hgzero/meeting/infra/gateway/repository/MinutesJpaRepository.java index 0587e72..c7a198f 100644 --- a/meeting/src/main/java/com/unicorn/hgzero/meeting/infra/gateway/repository/MinutesJpaRepository.java +++ b/meeting/src/main/java/com/unicorn/hgzero/meeting/infra/gateway/repository/MinutesJpaRepository.java @@ -53,4 +53,17 @@ public interface MinutesJpaRepository extends JpaRepository findByMeetingIdAndUserIdIsNull(String meetingId); + + /** + * 사용자가 생성했거나 참여한 회의의 회의록 조회 + * 현재는 생성자 기준으로만 조회 (추후 참석자 테이블과 조인 필요) + * + * @param userId 사용자 ID + * @return 회의록 목록 + */ + default List findByCreatedByOrParticipantUserId(String userId) { + // TODO: 참석자 테이블(participants)과 조인하여 참여한 회의의 회의록도 조회하도록 구현 필요 + // 현재는 임시로 생성자 기준으로만 조회 + return findByCreatedBy(userId); + } }