mirror of
https://github.com/hwanny1128/HGZero.git
synced 2025-12-06 23:06:23 +00:00
feat: rag용 회의록확정 event 발행 및 meeting 참석자 데이터 삭제 에러 개선
This commit is contained in:
parent
8aea75c718
commit
44ae9c546f
@ -341,6 +341,36 @@ public class MinutesService implements
|
|||||||
log.warn("참석자 수 계산 실패 - meetingId: {}", minutes.getMeetingId(), e);
|
log.warn("참석자 수 계산 실패 - meetingId: {}", minutes.getMeetingId(), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 섹션 정보 변환
|
||||||
|
List<com.unicorn.hgzero.meeting.biz.dto.SectionDTO> sectionDTOs = null;
|
||||||
|
try {
|
||||||
|
List<MinutesSection> sections = minutes.getSections();
|
||||||
|
|
||||||
|
// Minutes 도메인에 섹션이 없으면 DB에서 조회
|
||||||
|
if (sections == null || sections.isEmpty()) {
|
||||||
|
sections = minutesSectionReader.findByMinutesIdOrderByOrder(minutes.getMinutesId());
|
||||||
|
}
|
||||||
|
|
||||||
|
// MinutesSection을 SectionDTO로 변환
|
||||||
|
if (sections != null && !sections.isEmpty()) {
|
||||||
|
sectionDTOs = sections.stream()
|
||||||
|
.map(section -> com.unicorn.hgzero.meeting.biz.dto.SectionDTO.builder()
|
||||||
|
.sectionId(section.getSectionId())
|
||||||
|
.minutesId(section.getMinutesId())
|
||||||
|
.title(section.getTitle())
|
||||||
|
.content(section.getContent())
|
||||||
|
.sectionOrder(section.getOrder())
|
||||||
|
.sectionType(section.getType())
|
||||||
|
.isVerified(section.getVerified())
|
||||||
|
.isLocked(section.getLocked())
|
||||||
|
.lockedBy(section.getLockedBy())
|
||||||
|
.build())
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("섹션 정보 변환 실패 - minutesId: {}", minutes.getMinutesId(), e);
|
||||||
|
}
|
||||||
|
|
||||||
return MinutesDTO.builder()
|
return MinutesDTO.builder()
|
||||||
.minutesId(minutes.getMinutesId())
|
.minutesId(minutes.getMinutesId())
|
||||||
.meetingId(minutes.getMeetingId())
|
.meetingId(minutes.getMeetingId())
|
||||||
@ -356,6 +386,7 @@ public class MinutesService implements
|
|||||||
.completedTodoCount(completedTodoCount)
|
.completedTodoCount(completedTodoCount)
|
||||||
.participantCount(participantCount)
|
.participantCount(participantCount)
|
||||||
.memo("") // 메모 필드는 추후 구현
|
.memo("") // 메모 필드는 추후 구현
|
||||||
|
.sections(sectionDTOs) // 섹션 정보 추가
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -52,7 +52,8 @@ public class CacheService {
|
|||||||
redisTemplate.opsForValue().set(key, value, Duration.ofSeconds(ttl));
|
redisTemplate.opsForValue().set(key, value, Duration.ofSeconds(ttl));
|
||||||
log.debug("회의 정보 캐시 저장 - meetingId: {}", meetingId);
|
log.debug("회의 정보 캐시 저장 - meetingId: {}", meetingId);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("회의 정보 캐시 저장 실패 - meetingId: {}", meetingId, e);
|
log.warn("회의 정보 캐시 저장 실패 (서비스는 정상 동작) - meetingId: {}, 에러: {}",
|
||||||
|
meetingId, e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +73,8 @@ public class CacheService {
|
|||||||
return objectMapper.readValue(value, clazz);
|
return objectMapper.readValue(value, clazz);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("회의 정보 캐시 조회 실패 - meetingId: {}", meetingId, e);
|
log.warn("회의 정보 캐시 조회 실패 (DB에서 조회) - meetingId: {}, 에러: {}",
|
||||||
|
meetingId, e.getMessage());
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -91,7 +93,8 @@ public class CacheService {
|
|||||||
redisTemplate.opsForValue().set(key, value, Duration.ofSeconds(ttl));
|
redisTemplate.opsForValue().set(key, value, Duration.ofSeconds(ttl));
|
||||||
log.debug("회의록 정보 캐시 저장 - minutesId: {}", minutesId);
|
log.debug("회의록 정보 캐시 저장 - minutesId: {}", minutesId);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("회의록 정보 캐시 저장 실패 - minutesId: {}", minutesId, e);
|
log.warn("회의록 정보 캐시 저장 실패 (서비스는 정상 동작) - minutesId: {}, 에러: {}",
|
||||||
|
minutesId, e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,7 +114,8 @@ public class CacheService {
|
|||||||
return objectMapper.readValue(value, clazz);
|
return objectMapper.readValue(value, clazz);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("회의록 정보 캐시 조회 실패 - minutesId: {}", minutesId, e);
|
log.warn("회의록 정보 캐시 조회 실패 (DB에서 조회) - minutesId: {}, 에러: {}",
|
||||||
|
minutesId, e.getMessage());
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -130,7 +134,8 @@ public class CacheService {
|
|||||||
redisTemplate.opsForValue().set(key, value, Duration.ofSeconds(ttl));
|
redisTemplate.opsForValue().set(key, value, Duration.ofSeconds(ttl));
|
||||||
log.debug("대시보드 데이터 캐시 저장 - userId: {}", userId);
|
log.debug("대시보드 데이터 캐시 저장 - userId: {}", userId);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("대시보드 데이터 캐시 저장 실패 - userId: {}", userId, e);
|
log.warn("대시보드 데이터 캐시 저장 실패 (서비스는 정상 동작) - userId: {}, 에러: {}",
|
||||||
|
userId, e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,7 +155,8 @@ public class CacheService {
|
|||||||
return objectMapper.readValue(value, clazz);
|
return objectMapper.readValue(value, clazz);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("대시보드 데이터 캐시 조회 실패 - userId: {}", userId, e);
|
log.warn("대시보드 데이터 캐시 조회 실패 (DB에서 조회) - userId: {}, 에러: {}",
|
||||||
|
userId, e.getMessage());
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -169,7 +175,8 @@ public class CacheService {
|
|||||||
redisTemplate.opsForValue().set(key, value, Duration.ofSeconds(ttl));
|
redisTemplate.opsForValue().set(key, value, Duration.ofSeconds(ttl));
|
||||||
log.debug("세션 정보 캐시 저장 - sessionId: {}", sessionId);
|
log.debug("세션 정보 캐시 저장 - sessionId: {}", sessionId);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("세션 정보 캐시 저장 실패 - sessionId: {}", sessionId, e);
|
log.warn("세션 정보 캐시 저장 실패 (서비스는 정상 동작) - sessionId: {}, 에러: {}",
|
||||||
|
sessionId, e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,7 +196,8 @@ public class CacheService {
|
|||||||
return objectMapper.readValue(value, clazz);
|
return objectMapper.readValue(value, clazz);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("세션 정보 캐시 조회 실패 - sessionId: {}", sessionId, e);
|
log.warn("세션 정보 캐시 조회 실패 - sessionId: {}, 에러: {}",
|
||||||
|
sessionId, e.getMessage());
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -206,7 +214,7 @@ public class CacheService {
|
|||||||
redisTemplate.delete(key);
|
redisTemplate.delete(key);
|
||||||
log.debug("캐시 삭제 - key: {}", key);
|
log.debug("캐시 삭제 - key: {}", key);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("캐시 삭제 실패 - key: {}", prefix + id, e);
|
log.warn("캐시 삭제 실패 - key: {}, 에러: {}", prefix + id, e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,7 +231,7 @@ public class CacheService {
|
|||||||
log.debug("패턴 캐시 삭제 - pattern: {}, count: {}", pattern, keys.size());
|
log.debug("패턴 캐시 삭제 - pattern: {}, count: {}", pattern, keys.size());
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("패턴 캐시 삭제 실패 - pattern: {}", pattern, e);
|
log.warn("패턴 캐시 삭제 실패 - pattern: {}, 에러: {}", pattern, e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,7 +242,7 @@ public class CacheService {
|
|||||||
redisTemplate.opsForValue().set(MINUTES_LIST_PREFIX + cacheKey, value, Duration.ofMinutes(10));
|
redisTemplate.opsForValue().set(MINUTES_LIST_PREFIX + cacheKey, value, Duration.ofMinutes(10));
|
||||||
log.debug("회의록 목록 캐시 저장 - key: {}", cacheKey);
|
log.debug("회의록 목록 캐시 저장 - key: {}", cacheKey);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("회의록 목록 캐시 저장 실패 - key: {}", cacheKey, e);
|
log.warn("회의록 목록 캐시 저장 실패 (서비스는 정상 동작) - key: {}, 에러: {}", cacheKey, e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -245,7 +253,7 @@ public class CacheService {
|
|||||||
return objectMapper.readValue(value, MinutesListResponse.class);
|
return objectMapper.readValue(value, MinutesListResponse.class);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("회의록 목록 캐시 조회 실패 - key: {}", cacheKey, e);
|
log.warn("회의록 목록 캐시 조회 실패 (DB에서 조회) - key: {}, 에러: {}", cacheKey, e.getMessage());
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -256,7 +264,7 @@ public class CacheService {
|
|||||||
redisTemplate.opsForValue().set(MINUTES_DETAIL_PREFIX + minutesId, value, Duration.ofMinutes(5));
|
redisTemplate.opsForValue().set(MINUTES_DETAIL_PREFIX + minutesId, value, Duration.ofMinutes(5));
|
||||||
log.debug("회의록 상세 캐시 저장 - minutesId: {}", minutesId);
|
log.debug("회의록 상세 캐시 저장 - minutesId: {}", minutesId);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("회의록 상세 캐시 저장 실패 - minutesId: {}", minutesId, e);
|
log.warn("회의록 상세 캐시 저장 실패 (서비스는 정상 동작) - minutesId: {}, 에러: {}", minutesId, e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,7 +275,7 @@ public class CacheService {
|
|||||||
return objectMapper.readValue(value, MinutesDetailResponse.class);
|
return objectMapper.readValue(value, MinutesDetailResponse.class);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("회의록 상세 캐시 조회 실패 - minutesId: {}", minutesId, e);
|
log.warn("회의록 상세 캐시 조회 실패 (DB에서 조회) - minutesId: {}, 에러: {}", minutesId, e.getMessage());
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -289,7 +297,7 @@ public class CacheService {
|
|||||||
redisTemplate.opsForValue().set(TODO_LIST_PREFIX + cacheKey, value, Duration.ofMinutes(10));
|
redisTemplate.opsForValue().set(TODO_LIST_PREFIX + cacheKey, value, Duration.ofMinutes(10));
|
||||||
log.debug("Todo 목록 캐시 저장 - key: {}", cacheKey);
|
log.debug("Todo 목록 캐시 저장 - key: {}", cacheKey);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("Todo 목록 캐시 저장 실패 - key: {}", cacheKey, e);
|
log.warn("Todo 목록 캐시 저장 실패 (서비스는 정상 동작) - key: {}, 에러: {}", cacheKey, e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,7 +308,7 @@ public class CacheService {
|
|||||||
return objectMapper.readValue(value, TodoListResponse.class);
|
return objectMapper.readValue(value, TodoListResponse.class);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("Todo 목록 캐시 조회 실패 - key: {}", cacheKey, e);
|
log.warn("Todo 목록 캐시 조회 실패 (DB에서 조회) - key: {}, 에러: {}", cacheKey, e.getMessage());
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -327,7 +335,7 @@ public class CacheService {
|
|||||||
redisTemplate.opsForValue().set(TEMPLATE_LIST_PREFIX + cacheKey, value, Duration.ofHours(1));
|
redisTemplate.opsForValue().set(TEMPLATE_LIST_PREFIX + cacheKey, value, Duration.ofHours(1));
|
||||||
log.debug("템플릿 목록 캐시 저장 - key: {}", cacheKey);
|
log.debug("템플릿 목록 캐시 저장 - key: {}", cacheKey);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("템플릿 목록 캐시 저장 실패 - key: {}", cacheKey, e);
|
log.warn("템플릿 목록 캐시 저장 실패 (서비스는 정상 동작) - key: {}, 에러: {}", cacheKey, e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -338,7 +346,7 @@ public class CacheService {
|
|||||||
return objectMapper.readValue(value, TemplateListResponse.class);
|
return objectMapper.readValue(value, TemplateListResponse.class);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("템플릿 목록 캐시 조회 실패 - key: {}", cacheKey, e);
|
log.warn("템플릿 목록 캐시 조회 실패 (DB에서 조회) - key: {}, 에러: {}", cacheKey, e.getMessage());
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -349,7 +357,7 @@ public class CacheService {
|
|||||||
redisTemplate.opsForValue().set(TEMPLATE_DETAIL_PREFIX + templateId, value, Duration.ofHours(1));
|
redisTemplate.opsForValue().set(TEMPLATE_DETAIL_PREFIX + templateId, value, Duration.ofHours(1));
|
||||||
log.debug("템플릿 상세 캐시 저장 - templateId: {}", templateId);
|
log.debug("템플릿 상세 캐시 저장 - templateId: {}", templateId);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("템플릿 상세 캐시 저장 실패 - templateId: {}", templateId, e);
|
log.warn("템플릿 상세 캐시 저장 실패 (서비스는 정상 동작) - templateId: {}, 에러: {}", templateId, e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -360,7 +368,7 @@ public class CacheService {
|
|||||||
return objectMapper.readValue(value, TemplateDetailResponse.class);
|
return objectMapper.readValue(value, TemplateDetailResponse.class);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("템플릿 상세 캐시 조회 실패 - templateId: {}", templateId, e);
|
log.warn("템플릿 상세 캐시 조회 실패 (DB에서 조회) - templateId: {}, 에러: {}", templateId, e.getMessage());
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -372,7 +380,7 @@ public class CacheService {
|
|||||||
redisTemplate.opsForValue().set(AI_ANALYSIS_PREFIX + minutesId, value, Duration.ofHours(1));
|
redisTemplate.opsForValue().set(AI_ANALYSIS_PREFIX + minutesId, value, Duration.ofHours(1));
|
||||||
log.debug("AI 분석 결과 캐시 저장 - minutesId: {}", minutesId);
|
log.debug("AI 분석 결과 캐시 저장 - minutesId: {}", minutesId);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("AI 분석 결과 캐시 저장 실패 - minutesId: {}", minutesId, e);
|
log.warn("AI 분석 결과 캐시 저장 실패 (서비스는 정상 동작) - minutesId: {}, 에러: {}", minutesId, e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -385,7 +393,7 @@ public class CacheService {
|
|||||||
return Optional.of(analysis);
|
return Optional.of(analysis);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("AI 분석 결과 캐시 조회 실패 - minutesId: {}", minutesId, e);
|
log.warn("AI 분석 결과 캐시 조회 실패 (새로 생성) - minutesId: {}, 에러: {}", minutesId, e.getMessage());
|
||||||
}
|
}
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
@ -395,7 +403,7 @@ public class CacheService {
|
|||||||
redisTemplate.delete(AI_ANALYSIS_PREFIX + minutesId);
|
redisTemplate.delete(AI_ANALYSIS_PREFIX + minutesId);
|
||||||
log.debug("AI 분석 캐시 삭제 - minutesId: {}", minutesId);
|
log.debug("AI 분석 캐시 삭제 - minutesId: {}", minutesId);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("AI 분석 캐시 삭제 실패 - minutesId: {}", minutesId, e);
|
log.warn("AI 분석 캐시 삭제 실패 - minutesId: {}, 에러: {}", minutesId, e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -19,6 +19,8 @@ import com.unicorn.hgzero.meeting.infra.event.publisher.EventPublisher;
|
|||||||
import com.unicorn.hgzero.meeting.infra.gateway.AiServiceGateway;
|
import com.unicorn.hgzero.meeting.infra.gateway.AiServiceGateway;
|
||||||
import com.unicorn.hgzero.meeting.biz.dto.AiAnalysisDTO;
|
import com.unicorn.hgzero.meeting.biz.dto.AiAnalysisDTO;
|
||||||
import com.unicorn.hgzero.meeting.infra.event.dto.MinutesAnalysisRequestEvent;
|
import com.unicorn.hgzero.meeting.infra.event.dto.MinutesAnalysisRequestEvent;
|
||||||
|
import com.unicorn.hgzero.meeting.infra.event.dto.MinutesFinalizedEvent;
|
||||||
|
import com.unicorn.hgzero.meeting.infra.event.dto.MinutesSectionDTO;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||||
@ -242,9 +244,60 @@ public class MinutesController {
|
|||||||
// 캐시 무효화 (목록 캐시)
|
// 캐시 무효화 (목록 캐시)
|
||||||
cacheService.evictCacheMinutesList(userId);
|
cacheService.evictCacheMinutesList(userId);
|
||||||
|
|
||||||
// 회의록 확정 이벤트 발행
|
// 회의록 확정 이벤트 발행 (알림용 - 기존)
|
||||||
eventPublisher.publishMinutesFinalized(minutesId, finalizedMinutes.getTitle(), userId, userName);
|
eventPublisher.publishMinutesFinalized(minutesId, finalizedMinutes.getTitle(), userId, userName);
|
||||||
|
|
||||||
|
// RAG 서비스용 회의록 확정 이벤트 발행 (완전한 데이터 포함)
|
||||||
|
try {
|
||||||
|
// 회의 정보 조회
|
||||||
|
Meeting meeting = meetingService.getMeeting(finalizedMinutes.getMeetingId());
|
||||||
|
|
||||||
|
// 섹션 정보 변환
|
||||||
|
List<MinutesSectionDTO> sectionDTOs = finalizedMinutes.getSections().stream()
|
||||||
|
.map(section -> MinutesSectionDTO.builder()
|
||||||
|
.sectionId(section.getSectionId())
|
||||||
|
.type(section.getSectionType())
|
||||||
|
.title(section.getTitle())
|
||||||
|
.content(section.getContent())
|
||||||
|
.order(section.getSectionOrder())
|
||||||
|
.verified(section.getIsVerified())
|
||||||
|
.build())
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
// MinutesFinalizedEvent 생성
|
||||||
|
MinutesFinalizedEvent ragEvent = MinutesFinalizedEvent.builder()
|
||||||
|
.timestamp(LocalDateTime.now())
|
||||||
|
.data(MinutesFinalizedEvent.MinutesData.builder()
|
||||||
|
// Meeting 정보
|
||||||
|
.meetingId(meeting.getMeetingId())
|
||||||
|
.title(meeting.getTitle())
|
||||||
|
.purpose(meeting.getPurpose())
|
||||||
|
.description(meeting.getDescription())
|
||||||
|
.scheduledAt(meeting.getScheduledAt())
|
||||||
|
.location(meeting.getLocation())
|
||||||
|
.organizerId(meeting.getOrganizerId())
|
||||||
|
// Minutes 정보
|
||||||
|
.minutesId(finalizedMinutes.getMinutesId())
|
||||||
|
.status(finalizedMinutes.getStatus())
|
||||||
|
.version(finalizedMinutes.getVersion())
|
||||||
|
.createdBy(finalizedMinutes.getCreatedBy())
|
||||||
|
.finalizedBy(userId)
|
||||||
|
.finalizedAt(finalizedMinutes.getFinalizedAt())
|
||||||
|
// 섹션 정보
|
||||||
|
.sections(sectionDTOs)
|
||||||
|
.build())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// RAG용 이벤트 발행
|
||||||
|
eventPublisher.publishMinutesFinalizedForRAG(ragEvent);
|
||||||
|
log.info("RAG용 회의록 확정 이벤트 발행 완료 - minutesId: {}, meetingId: {}",
|
||||||
|
minutesId, meeting.getMeetingId());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("RAG용 회의록 확정 이벤트 발행 실패 - minutesId: {}, error: {}",
|
||||||
|
minutesId, e.getMessage(), e);
|
||||||
|
// RAG 이벤트 발행 실패는 무시하고 진행 (회의록 확정 자체는 성공)
|
||||||
|
}
|
||||||
|
|
||||||
log.info("회의록 확정 성공 - minutesId: {}", minutesId);
|
log.info("회의록 확정 성공 - minutesId: {}", minutesId);
|
||||||
return ResponseEntity.ok(ApiResponse.success(response));
|
return ResponseEntity.ok(ApiResponse.success(response));
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,58 @@
|
|||||||
|
package com.unicorn.hgzero.meeting.infra.event.dto;
|
||||||
|
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 회의록 확정 이벤트
|
||||||
|
* RAG 서비스에서 회의록 embedding 생성 및 저장을 위한 이벤트
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Builder
|
||||||
|
public class MinutesFinalizedEvent {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 이벤트 타입
|
||||||
|
*/
|
||||||
|
private final String eventType = "MINUTES_FINALIZED";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 이벤트 발생 시간
|
||||||
|
*/
|
||||||
|
private final LocalDateTime timestamp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 이벤트 데이터
|
||||||
|
*/
|
||||||
|
private final MinutesData data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 회의록 상세 데이터
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Builder
|
||||||
|
public static class MinutesData {
|
||||||
|
// Meeting 정보
|
||||||
|
private final String meetingId;
|
||||||
|
private final String title;
|
||||||
|
private final String purpose;
|
||||||
|
private final String description;
|
||||||
|
private final LocalDateTime scheduledAt;
|
||||||
|
private final String location;
|
||||||
|
private final String organizerId;
|
||||||
|
|
||||||
|
// Minutes 정보
|
||||||
|
private final String minutesId;
|
||||||
|
private final String status;
|
||||||
|
private final Integer version;
|
||||||
|
private final String createdBy;
|
||||||
|
private final String finalizedBy;
|
||||||
|
private final LocalDateTime finalizedAt;
|
||||||
|
|
||||||
|
// 섹션 정보
|
||||||
|
private final List<MinutesSectionDTO> sections;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
package com.unicorn.hgzero.meeting.infra.event.dto;
|
||||||
|
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 회의록 섹션 DTO
|
||||||
|
* Event Hub 메시지에 포함될 섹션 정보
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Builder
|
||||||
|
public class MinutesSectionDTO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 섹션 ID
|
||||||
|
*/
|
||||||
|
private final String sectionId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 섹션 타입 (DISCUSSION, DECISION, ACTION_ITEM 등)
|
||||||
|
*/
|
||||||
|
private final String type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 섹션 제목
|
||||||
|
*/
|
||||||
|
private final String title;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 섹션 내용
|
||||||
|
*/
|
||||||
|
private final String content;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 섹션 순서
|
||||||
|
*/
|
||||||
|
private final Integer order;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 검증 여부
|
||||||
|
*/
|
||||||
|
private final Boolean verified;
|
||||||
|
}
|
||||||
@ -11,6 +11,7 @@ import com.unicorn.hgzero.meeting.infra.event.dto.MeetingEndedEvent;
|
|||||||
import com.unicorn.hgzero.meeting.infra.event.dto.TodoAssignedEvent;
|
import com.unicorn.hgzero.meeting.infra.event.dto.TodoAssignedEvent;
|
||||||
import com.unicorn.hgzero.meeting.infra.event.dto.NotificationRequestEvent;
|
import com.unicorn.hgzero.meeting.infra.event.dto.NotificationRequestEvent;
|
||||||
import com.unicorn.hgzero.meeting.infra.event.dto.MinutesAnalysisRequestEvent;
|
import com.unicorn.hgzero.meeting.infra.event.dto.MinutesAnalysisRequestEvent;
|
||||||
|
import com.unicorn.hgzero.meeting.infra.event.dto.MinutesFinalizedEvent;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -157,6 +158,16 @@ public class EventHubPublisher implements EventPublisher {
|
|||||||
EventHubConstants.EVENT_TYPE_MINUTES_ANALYSIS_REQUEST);
|
EventHubConstants.EVENT_TYPE_MINUTES_ANALYSIS_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void publishMinutesFinalizedForRAG(MinutesFinalizedEvent event) {
|
||||||
|
publishEvent(event, event.getData().getMinutesId(),
|
||||||
|
EventHubConstants.TOPIC_MINUTES,
|
||||||
|
EventHubConstants.EVENT_TYPE_MINUTES_FINALIZED);
|
||||||
|
|
||||||
|
log.info("RAG용 회의록 확정 이벤트 발행 완료 - minutesId: {}, meetingId: {}",
|
||||||
|
event.getData().getMinutesId(), event.getData().getMeetingId());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 이벤트 발행 공통 메서드
|
* 이벤트 발행 공통 메서드
|
||||||
*
|
*
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import com.unicorn.hgzero.meeting.infra.event.dto.MeetingEndedEvent;
|
|||||||
import com.unicorn.hgzero.meeting.infra.event.dto.TodoAssignedEvent;
|
import com.unicorn.hgzero.meeting.infra.event.dto.TodoAssignedEvent;
|
||||||
import com.unicorn.hgzero.meeting.infra.event.dto.NotificationRequestEvent;
|
import com.unicorn.hgzero.meeting.infra.event.dto.NotificationRequestEvent;
|
||||||
import com.unicorn.hgzero.meeting.infra.event.dto.MinutesAnalysisRequestEvent;
|
import com.unicorn.hgzero.meeting.infra.event.dto.MinutesAnalysisRequestEvent;
|
||||||
|
import com.unicorn.hgzero.meeting.infra.event.dto.MinutesFinalizedEvent;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -62,6 +63,13 @@ public interface EventPublisher {
|
|||||||
*/
|
*/
|
||||||
void publishMinutesFinalized(String minutesId, String title, String finalizedBy, String finalizedByName);
|
void publishMinutesFinalized(String minutesId, String title, String finalizedBy, String finalizedByName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 회의록 확정 이벤트 발행 (RAG 서비스용 완전한 이벤트)
|
||||||
|
*
|
||||||
|
* @param event 회의록 확정 이벤트 (전체 데이터 포함)
|
||||||
|
*/
|
||||||
|
void publishMinutesFinalizedForRAG(MinutesFinalizedEvent event);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 회의 생성 알림 발행 (편의 메서드)
|
* 회의 생성 알림 발행 (편의 메서드)
|
||||||
* 참석자에게 회의 초대 이메일 발송
|
* 참석자에게 회의 초대 이메일 발송
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import com.unicorn.hgzero.meeting.infra.event.dto.MeetingEndedEvent;
|
|||||||
import com.unicorn.hgzero.meeting.infra.event.dto.TodoAssignedEvent;
|
import com.unicorn.hgzero.meeting.infra.event.dto.TodoAssignedEvent;
|
||||||
import com.unicorn.hgzero.meeting.infra.event.dto.NotificationRequestEvent;
|
import com.unicorn.hgzero.meeting.infra.event.dto.NotificationRequestEvent;
|
||||||
import com.unicorn.hgzero.meeting.infra.event.dto.MinutesAnalysisRequestEvent;
|
import com.unicorn.hgzero.meeting.infra.event.dto.MinutesAnalysisRequestEvent;
|
||||||
|
import com.unicorn.hgzero.meeting.infra.event.dto.MinutesFinalizedEvent;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.context.annotation.Primary;
|
import org.springframework.context.annotation.Primary;
|
||||||
@ -72,4 +73,10 @@ public class NoOpEventPublisher implements EventPublisher {
|
|||||||
public void publishMinutesAnalysisRequest(MinutesAnalysisRequestEvent event) {
|
public void publishMinutesAnalysisRequest(MinutesAnalysisRequestEvent event) {
|
||||||
log.debug("[NoOp] Minutes analysis request event: minutesId={}", event.getMinutesId());
|
log.debug("[NoOp] Minutes analysis request event: minutesId={}", event.getMinutesId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void publishMinutesFinalizedForRAG(MinutesFinalizedEvent event) {
|
||||||
|
log.debug("[NoOp] Minutes finalized for RAG: minutesId={}, meetingId={}",
|
||||||
|
event.getData().getMinutesId(), event.getData().getMeetingId());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -65,7 +65,7 @@ public class MeetingEntity extends BaseTimeEntity {
|
|||||||
/**
|
/**
|
||||||
* 회의 참석자 목록 (일대다 관계)
|
* 회의 참석자 목록 (일대다 관계)
|
||||||
*/
|
*/
|
||||||
@OneToMany(mappedBy = "meeting", cascade = CascadeType.ALL, orphanRemoval = true)
|
@OneToMany(mappedBy = "meeting", cascade = CascadeType.ALL, orphanRemoval = false)
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
private List<MeetingParticipantEntity> participants = new ArrayList<>();
|
private List<MeetingParticipantEntity> participants = new ArrayList<>();
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user