Chore: 회의 종료 API 실제 데이터 연동

This commit is contained in:
cyjadela 2025-10-27 16:48:17 +09:00
parent 43792c1674
commit e5337385f4
8 changed files with 3652 additions and 7 deletions

File diff suppressed because it is too large Load Diff

View File

@ -28,6 +28,7 @@ import org.springframework.transaction.annotation.Transactional;
import java.time.Duration; import java.time.Duration;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.UUID; import java.util.UUID;
/** /**
@ -328,9 +329,20 @@ public class MeetingService implements
log.debug("Found minutes: {}", minutes.getTitle()); log.debug("Found minutes: {}", minutes.getTitle());
} }
// 5. 기본 분석 정보 생성 (실제 AI 분석은 AI 서비스에서 비동기 처리) // 5. 기존 분석 데이터 확인 사용 또는 새로 생성
MeetingAnalysis analysis = createBasicAnalysis(meeting, minutes); Optional<MeetingAnalysis> existingAnalysis = meetingAnalysisReader.findLatestByMeetingId(meetingId);
meetingAnalysisWriter.save(analysis); MeetingAnalysis analysis;
if (existingAnalysis.isPresent()) {
// 기존 분석 데이터가 있으면 사용
analysis = existingAnalysis.get();
log.info("Using existing analysis data for meeting: {}", meetingId);
} else {
// 기존 분석 데이터가 없으면 새로 생성
analysis = createBasicAnalysis(meeting, minutes);
meetingAnalysisWriter.save(analysis);
log.info("Created new analysis data for meeting: {}", meetingId);
}
// TODO: AI 서비스에 비동기 분석 요청 전송 // TODO: AI 서비스에 비동기 분석 요청 전송
// aiAnalysisClient.requestAnalysis(meeting.getMeetingId(), minutes.getMinutesId()); // aiAnalysisClient.requestAnalysis(meeting.getMeetingId(), minutes.getMinutesId());

View File

@ -14,6 +14,11 @@ public interface MeetingAnalysisReader {
*/ */
Optional<MeetingAnalysis> findByMeetingId(String meetingId); Optional<MeetingAnalysis> findByMeetingId(String meetingId);
/**
* 회의 ID로 가장 최근 분석 결과 조회
*/
Optional<MeetingAnalysis> findLatestByMeetingId(String meetingId);
/** /**
* 분석 ID로 분석 결과 조회 * 분석 ID로 분석 결과 조회
*/ */

View File

@ -42,6 +42,13 @@ public class MeetingAnalysisGateway implements MeetingAnalysisReader, MeetingAna
.map(MeetingAnalysisEntity::toDomain); .map(MeetingAnalysisEntity::toDomain);
} }
@Override
public Optional<MeetingAnalysis> findLatestByMeetingId(String meetingId) {
log.debug("Finding latest meeting analysis by meetingId: {}", meetingId);
return repository.findFirstByMeetingIdOrderByCreatedAtDesc(meetingId)
.map(MeetingAnalysisEntity::toDomain);
}
@Override @Override
public MeetingAnalysis save(MeetingAnalysis analysis) { public MeetingAnalysis save(MeetingAnalysis analysis) {
log.debug("Saving meeting analysis: {}", analysis.getAnalysisId()); log.debug("Saving meeting analysis: {}", analysis.getAnalysisId());

View File

@ -6,6 +6,8 @@ import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List; import java.util.List;
@ -52,33 +54,68 @@ public class MeetingAnalysisEntity {
* Entity를 도메인으로 변환 * Entity를 도메인으로 변환
*/ */
public MeetingAnalysis toDomain() { public MeetingAnalysis toDomain() {
// JSON 파싱은 실제 구현에서는 ObjectMapper 사용 List<MeetingAnalysis.AgendaAnalysis> agendaAnalyses = parseAgendaAnalyses();
// 현재는 Mock으로 처리
return MeetingAnalysis.builder() return MeetingAnalysis.builder()
.analysisId(this.analysisId) .analysisId(this.analysisId)
.meetingId(this.meetingId) .meetingId(this.meetingId)
.minutesId(this.minutesId) .minutesId(this.minutesId)
.keywords(this.keywords) .keywords(this.keywords)
.agendaAnalyses(List.of()) // Mock .agendaAnalyses(agendaAnalyses)
.status(this.status) .status(this.status)
.completedAt(this.completedAt) .completedAt(this.completedAt)
.createdAt(this.createdAt) .createdAt(this.createdAt)
.build(); .build();
} }
/**
* JSON 문자열을 AgendaAnalysis 리스트로 파싱
*/
private List<MeetingAnalysis.AgendaAnalysis> parseAgendaAnalyses() {
if (agendaAnalysesJson == null || agendaAnalysesJson.trim().isEmpty() || "{}".equals(agendaAnalysesJson.trim())) {
return List.of();
}
try {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readValue(agendaAnalysesJson, new TypeReference<List<MeetingAnalysis.AgendaAnalysis>>() {});
} catch (Exception e) {
// JSON 파싱 실패 리스트 반환
return List.of();
}
}
/** /**
* 도메인에서 Entity로 변환 * 도메인에서 Entity로 변환
*/ */
public static MeetingAnalysisEntity fromDomain(MeetingAnalysis domain) { public static MeetingAnalysisEntity fromDomain(MeetingAnalysis domain) {
String agendaAnalysesJson = convertAgendaAnalysesToJson(domain.getAgendaAnalyses());
return MeetingAnalysisEntity.builder() return MeetingAnalysisEntity.builder()
.analysisId(domain.getAnalysisId()) .analysisId(domain.getAnalysisId())
.meetingId(domain.getMeetingId()) .meetingId(domain.getMeetingId())
.minutesId(domain.getMinutesId()) .minutesId(domain.getMinutesId())
.keywords(domain.getKeywords()) .keywords(domain.getKeywords())
.agendaAnalysesJson("{}") // Mock JSON .agendaAnalysesJson(agendaAnalysesJson)
.status(domain.getStatus()) .status(domain.getStatus())
.completedAt(domain.getCompletedAt()) .completedAt(domain.getCompletedAt())
.createdAt(domain.getCreatedAt()) .createdAt(domain.getCreatedAt())
.build(); .build();
} }
/**
* AgendaAnalysis 리스트를 JSON 문자열로 변환
*/
private static String convertAgendaAnalysesToJson(List<MeetingAnalysis.AgendaAnalysis> agendaAnalyses) {
if (agendaAnalyses == null || agendaAnalyses.isEmpty()) {
return "[]";
}
try {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.writeValueAsString(agendaAnalyses);
} catch (Exception e) {
return "[]";
}
}
} }

View File

@ -21,4 +21,9 @@ public interface MeetingAnalysisJpaRepository extends JpaRepository<MeetingAnaly
* 회의록 ID로 분석 결과 조회 * 회의록 ID로 분석 결과 조회
*/ */
Optional<MeetingAnalysisEntity> findByMinutesId(String minutesId); Optional<MeetingAnalysisEntity> findByMinutesId(String minutesId);
/**
* 회의 ID로 가장 최근 분석 결과 조회
*/
Optional<MeetingAnalysisEntity> findFirstByMeetingIdOrderByCreatedAtDesc(String meetingId);
} }