mirror of
https://github.com/hwanny1128/HGZero.git
synced 2026-06-13 04:49:11 +00:00
Feat: 회의록 상세 조회 API (mock) 구현
This commit is contained in:
+291
-71
@@ -126,23 +126,13 @@ public class MinutesController {
|
||||
log.info("회의록 상세 조회 요청 - userId: {}, minutesId: {}", userId, minutesId);
|
||||
|
||||
try {
|
||||
// 캐시 확인
|
||||
MinutesDetailResponse cachedResponse = cacheService.getCachedMinutesDetail(minutesId);
|
||||
if (cachedResponse != null) {
|
||||
log.debug("캐시된 회의록 상세 반환 - minutesId: {}", minutesId);
|
||||
return ResponseEntity.ok(ApiResponse.success(cachedResponse));
|
||||
}
|
||||
|
||||
// 회의록 조회
|
||||
MinutesDTO minutesDTO = minutesService.getMinutesById(minutesId);
|
||||
|
||||
// 응답 DTO 생성
|
||||
MinutesDetailResponse response = convertToMinutesDetailResponse(minutesDTO);
|
||||
// Mock 데이터 생성 (프론트엔드 테스트용)
|
||||
MinutesDetailResponse response = createMockMinutesDetail(minutesId, userId);
|
||||
|
||||
// 캐시 저장
|
||||
cacheService.cacheMinutesDetail(minutesId, response);
|
||||
|
||||
log.info("회의록 상세 조회 성공 - minutesId: {}", minutesId);
|
||||
log.info("회의록 상세 조회 성공 (Mock) - minutesId: {}", minutesId);
|
||||
return ResponseEntity.ok(ApiResponse.success(response));
|
||||
|
||||
} catch (Exception e) {
|
||||
@@ -584,74 +574,304 @@ public class MinutesController {
|
||||
.build();
|
||||
}
|
||||
|
||||
private MinutesDetailResponse convertToMinutesDetailResponse(MinutesDTO minutesDTO) {
|
||||
/**
|
||||
* Mock 회의록 상세 데이터 생성 (프로토타입 기반 - 대시보드/회의록 탭 구조)
|
||||
*/
|
||||
private MinutesDetailResponse createMockMinutesDetail(String minutesId, String userId) {
|
||||
return MinutesDetailResponse.builder()
|
||||
.minutesId(minutesDTO.getMinutesId())
|
||||
.title(minutesDTO.getTitle())
|
||||
.memo(minutesDTO.getMemo())
|
||||
.status(minutesDTO.getStatus())
|
||||
.version(minutesDTO.getVersion())
|
||||
.createdAt(minutesDTO.getCreatedAt())
|
||||
.lastModifiedAt(minutesDTO.getLastModifiedAt())
|
||||
.createdBy(minutesDTO.getCreatedBy())
|
||||
.lastModifiedBy(minutesDTO.getLastModifiedBy())
|
||||
.meeting(convertToMeetingInfo(minutesDTO.getMeeting()))
|
||||
.sections(convertToSectionInfoList(minutesDTO.getSectionsInfo()))
|
||||
.todos(convertToTodoInfoList(minutesDTO.getTodos()))
|
||||
.minutesId(minutesId)
|
||||
.title("2025년 1분기 제품 기획 회의록")
|
||||
.memo("본 회의는 AI 기반 회의록 자동화 서비스 개발을 위한 전략 회의입니다.")
|
||||
.status("FINALIZED")
|
||||
.version(3)
|
||||
.createdAt(LocalDateTime.of(2025, 10, 25, 14, 0))
|
||||
.lastModifiedAt(LocalDateTime.of(2025, 10, 25, 17, 30))
|
||||
.createdBy("김민준")
|
||||
.lastModifiedBy("김민준")
|
||||
.meeting(createMockMeetingInfo())
|
||||
.dashboard(createMockDashboardInfo())
|
||||
.agendas(createMockAgendaInfo())
|
||||
.build();
|
||||
}
|
||||
|
||||
private MinutesDetailResponse.MeetingInfo convertToMeetingInfo(MinutesDTO.MeetingInfo meetingInfo) {
|
||||
if (meetingInfo == null) return null;
|
||||
|
||||
/**
|
||||
* Mock 회의 정보 생성 (프로토타입 기반)
|
||||
*/
|
||||
private MinutesDetailResponse.MeetingInfo createMockMeetingInfo() {
|
||||
return MinutesDetailResponse.MeetingInfo.builder()
|
||||
.meetingId(meetingInfo.getMeetingId())
|
||||
.title(meetingInfo.getTitle())
|
||||
.scheduledAt(meetingInfo.getScheduledAt())
|
||||
.startedAt(meetingInfo.getStartedAt())
|
||||
.endedAt(meetingInfo.getEndedAt())
|
||||
.organizerId(meetingInfo.getOrganizerId())
|
||||
.organizerName(meetingInfo.getOrganizerName())
|
||||
.meetingId("meeting-001")
|
||||
.title("2025년 1분기 제품 기획 회의")
|
||||
.scheduledAt(LocalDateTime.of(2025, 10, 25, 14, 0))
|
||||
.startedAt(LocalDateTime.of(2025, 10, 25, 14, 0))
|
||||
.endedAt(LocalDateTime.of(2025, 10, 25, 15, 30))
|
||||
.organizerId("김민준")
|
||||
.organizerName("김민준")
|
||||
.location("본사 2층 대회의실")
|
||||
.durationMinutes(90)
|
||||
.participants(List.of(
|
||||
MinutesDetailResponse.Participant.builder()
|
||||
.userId("김민준")
|
||||
.name("김민준")
|
||||
.role("작성자")
|
||||
.avatarColor("avatar-green")
|
||||
.build(),
|
||||
MinutesDetailResponse.Participant.builder()
|
||||
.userId("박서연")
|
||||
.name("박서연")
|
||||
.role("참여자")
|
||||
.avatarColor("avatar-blue")
|
||||
.build(),
|
||||
MinutesDetailResponse.Participant.builder()
|
||||
.userId("이준호")
|
||||
.name("이준호")
|
||||
.role("참여자")
|
||||
.avatarColor("avatar-yellow")
|
||||
.build(),
|
||||
MinutesDetailResponse.Participant.builder()
|
||||
.userId("최유진")
|
||||
.name("최유진")
|
||||
.role("참여자")
|
||||
.avatarColor("avatar-pink")
|
||||
.build()
|
||||
))
|
||||
.build();
|
||||
}
|
||||
|
||||
private List<MinutesDetailResponse.SectionInfo> convertToSectionInfoList(
|
||||
List<MinutesDTO.SectionInfo> sections) {
|
||||
if (sections == null) return List.of();
|
||||
|
||||
return sections.stream()
|
||||
.map(section -> MinutesDetailResponse.SectionInfo.builder()
|
||||
.sectionId(section.getSectionId())
|
||||
.title(section.getTitle())
|
||||
.content(section.getContent())
|
||||
.orderIndex(section.getOrderIndex())
|
||||
.isLocked(section.isLocked())
|
||||
.isVerified(section.isVerified())
|
||||
.lockedBy(section.getLockedBy())
|
||||
.lockedAt(section.getLockedAt())
|
||||
.verifiedBy(section.getVerifiedBy())
|
||||
.verifiedAt(section.getVerifiedAt())
|
||||
.build())
|
||||
.collect(Collectors.toList());
|
||||
/**
|
||||
* Mock 대시보드 정보 생성 (프로토타입 기반)
|
||||
*/
|
||||
private MinutesDetailResponse.DashboardInfo createMockDashboardInfo() {
|
||||
return MinutesDetailResponse.DashboardInfo.builder()
|
||||
.keyPoints(List.of(
|
||||
MinutesDetailResponse.KeyPoint.builder()
|
||||
.index(1)
|
||||
.content("AI 기반 회의록 자동화 서비스 출시 결정. 타겟은 중소기업 및 스타트업.")
|
||||
.build(),
|
||||
MinutesDetailResponse.KeyPoint.builder()
|
||||
.index(2)
|
||||
.content("주요 기능: 음성인식, AI 요약, Todo 자동 추출, 실시간 검증 및 협업.")
|
||||
.build(),
|
||||
MinutesDetailResponse.KeyPoint.builder()
|
||||
.index(3)
|
||||
.content("개발 기간 3개월 (Phase 1-3), 베타 출시일 2025년 12월 1일.")
|
||||
.build(),
|
||||
MinutesDetailResponse.KeyPoint.builder()
|
||||
.index(4)
|
||||
.content("프리 런칭 캠페인 11월 진행, 초기 100팀 무료 제공 후 유료 전환.")
|
||||
.build()
|
||||
))
|
||||
.keywords(List.of("#AI회의록", "#음성인식", "#협업도구", "#스타트업", "#베타출시"))
|
||||
.stats(MinutesDetailResponse.Statistics.builder()
|
||||
.participantCount(4)
|
||||
.durationMinutes(90)
|
||||
.agendaCount(3)
|
||||
.todoCount(5)
|
||||
.build())
|
||||
.decisions(List.of(
|
||||
MinutesDetailResponse.Decision.builder()
|
||||
.content("베타 버전 출시일: 2025년 12월 1일")
|
||||
.decidedBy("김민준")
|
||||
.decidedAt(LocalDateTime.of(2025, 10, 25, 15, 30))
|
||||
.background("개발 일정 및 시장 진입 시기를 고려하여 12월 초 출시가 최적. Q4 마무리 전 베타 피드백 확보 가능.")
|
||||
.build(),
|
||||
MinutesDetailResponse.Decision.builder()
|
||||
.content("타겟 고객: 중소기업 및 스타트업")
|
||||
.decidedBy("박서연")
|
||||
.decidedAt(LocalDateTime.of(2025, 10, 25, 14, 45))
|
||||
.background("사용자 인터뷰 결과, 중소기업과 스타트업이 회의록 작성에 가장 많은 시간을 소비하며 자동화 니즈가 높음.")
|
||||
.build()
|
||||
))
|
||||
.todoProgress(createMockTodoProgress())
|
||||
.relatedMinutes(createMockRelatedMinutes())
|
||||
.build();
|
||||
}
|
||||
|
||||
private List<MinutesDetailResponse.TodoInfo> convertToTodoInfoList(
|
||||
List<MinutesDTO.TodoInfo> todos) {
|
||||
if (todos == null) return List.of();
|
||||
/**
|
||||
* Mock Todo 진행상황 생성 (프로토타입 기반 - 간단한 텍스트)
|
||||
*/
|
||||
private MinutesDetailResponse.TodoProgress createMockTodoProgress() {
|
||||
List<MinutesDetailResponse.SimpleTodo> todos = List.of(
|
||||
MinutesDetailResponse.SimpleTodo.builder()
|
||||
.todoId("todo-001")
|
||||
.title("API 명세서 작성")
|
||||
.assigneeName("이준호")
|
||||
.status("IN_PROGRESS")
|
||||
.priority("HIGH")
|
||||
.dueDate(LocalDateTime.of(2025, 10, 23, 18, 0))
|
||||
.dueDayStatus("D-2")
|
||||
.build(),
|
||||
MinutesDetailResponse.SimpleTodo.builder()
|
||||
.todoId("todo-002")
|
||||
.title("데이터베이스 스키마 설계")
|
||||
.assigneeName("이준호")
|
||||
.status("OVERDUE")
|
||||
.priority("HIGH")
|
||||
.dueDate(LocalDateTime.of(2025, 10, 20, 18, 0))
|
||||
.dueDayStatus("D+1 (지연)")
|
||||
.build(),
|
||||
MinutesDetailResponse.SimpleTodo.builder()
|
||||
.todoId("todo-003")
|
||||
.title("UI 프로토타입 디자인")
|
||||
.assigneeName("최유진")
|
||||
.status("IN_PROGRESS")
|
||||
.priority("MEDIUM")
|
||||
.dueDate(LocalDateTime.of(2025, 10, 28, 18, 0))
|
||||
.dueDayStatus("D-7")
|
||||
.build(),
|
||||
MinutesDetailResponse.SimpleTodo.builder()
|
||||
.todoId("todo-004")
|
||||
.title("사용자 피드백 분석")
|
||||
.assigneeName("김민준")
|
||||
.status("COMPLETED")
|
||||
.priority("MEDIUM")
|
||||
.dueDate(LocalDateTime.of(2025, 10, 19, 18, 0))
|
||||
.dueDayStatus("완료")
|
||||
.build(),
|
||||
MinutesDetailResponse.SimpleTodo.builder()
|
||||
.todoId("todo-005")
|
||||
.title("예산 편성안 검토")
|
||||
.assigneeName("김민준")
|
||||
.status("IN_PROGRESS")
|
||||
.priority("HIGH")
|
||||
.dueDate(LocalDateTime.of(2025, 10, 22, 18, 0))
|
||||
.dueDayStatus("D-1")
|
||||
.build()
|
||||
);
|
||||
|
||||
int completedCount = (int) todos.stream().filter(t -> "COMPLETED".equals(t.getStatus())).count();
|
||||
|
||||
return todos.stream()
|
||||
.map(todo -> MinutesDetailResponse.TodoInfo.builder()
|
||||
.todoId(todo.getTodoId())
|
||||
.title(todo.getTitle())
|
||||
.description(todo.getDescription())
|
||||
.assigneeId(todo.getAssigneeId())
|
||||
.assigneeName(todo.getAssigneeName())
|
||||
.priority(todo.getPriority())
|
||||
.status(todo.getStatus())
|
||||
.dueDate(todo.getDueDate())
|
||||
.completedAt(todo.getCompletedAt())
|
||||
.completedBy(todo.getCompletedBy())
|
||||
.build())
|
||||
.collect(Collectors.toList());
|
||||
return MinutesDetailResponse.TodoProgress.builder()
|
||||
.totalCount(todos.size())
|
||||
.completedCount(completedCount)
|
||||
.progressPercentage((completedCount * 100) / todos.size())
|
||||
.todos(todos)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock 관련회의록 생성 (프로토타입 기반)
|
||||
*/
|
||||
private List<MinutesDetailResponse.RelatedMinutes> createMockRelatedMinutes() {
|
||||
return List.of(
|
||||
MinutesDetailResponse.RelatedMinutes.builder()
|
||||
.minutesId("minutes-related-001")
|
||||
.title("AI 기능 개선 회의")
|
||||
.meetingDate(LocalDateTime.of(2025, 10, 23, 15, 0))
|
||||
.author("이준호")
|
||||
.relevancePercentage(92)
|
||||
.relevanceLevel("HIGH")
|
||||
.summary("AI 요약 정확도 개선 방안 논의. BERT 모델 도입 및 학습 데이터 확보 계획 수립.")
|
||||
.build(),
|
||||
MinutesDetailResponse.RelatedMinutes.builder()
|
||||
.minutesId("minutes-related-002")
|
||||
.title("개발 리소스 계획 회의")
|
||||
.meetingDate(LocalDateTime.of(2025, 10, 22, 11, 0))
|
||||
.author("김민준")
|
||||
.relevancePercentage(88)
|
||||
.relevanceLevel("MEDIUM")
|
||||
.summary("Q4 개발 리소스 현황 및 배분 계획. 신규 프로젝트 우선순위 협의.")
|
||||
.build(),
|
||||
MinutesDetailResponse.RelatedMinutes.builder()
|
||||
.minutesId("minutes-related-003")
|
||||
.title("경쟁사 분석 회의")
|
||||
.meetingDate(LocalDateTime.of(2025, 10, 20, 10, 0))
|
||||
.author("박서연")
|
||||
.relevancePercentage(78)
|
||||
.relevanceLevel("MEDIUM")
|
||||
.summary("경쟁사 A, B, C 분석 결과. 우리의 차별점은 실시간 협업 및 검증 기능.")
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock 안건 정보 생성 (프로토타입 기반 - 회의록 탭)
|
||||
*/
|
||||
private List<MinutesDetailResponse.AgendaInfo> createMockAgendaInfo() {
|
||||
return List.of(
|
||||
MinutesDetailResponse.AgendaInfo.builder()
|
||||
.agendaId("agenda-001")
|
||||
.title("1. 신제품 기획 방향")
|
||||
.orderIndex(1)
|
||||
.isVerified(true)
|
||||
.verifiedBy("박서연")
|
||||
.verifiedAt(LocalDateTime.of(2025, 10, 25, 16, 30))
|
||||
.aiSummary(MinutesDetailResponse.AiSummary.builder()
|
||||
.content("신제품은 AI 기반 회의록 자동화 서비스로 결정. 타겟은 중소기업 및 스타트업이며, 주요 기능은 음성인식, AI 요약, Todo 추출입니다. 경쟁사 대비 차별점은 실시간 검증 및 협업 기능입니다.")
|
||||
.generatedAt(LocalDateTime.of(2025, 10, 25, 16, 30))
|
||||
.modifiedAt(LocalDateTime.of(2025, 10, 25, 17, 0))
|
||||
.build())
|
||||
.details(MinutesDetailResponse.AgendaDetails.builder()
|
||||
.discussions(List.of(
|
||||
"AI 기반 회의록 자동화 서비스 출시 결정",
|
||||
"타겟 고객: 중소기업, 스타트업",
|
||||
"주요 기능: 음성인식, AI 요약, Todo 자동 추출",
|
||||
"차별화 포인트: 실시간 검증, 협업 기능"
|
||||
))
|
||||
.decisions(List.of(
|
||||
"베타 버전 출시일: 2025년 12월 1일",
|
||||
"초기 목표 사용자: 100개 팀"
|
||||
))
|
||||
.build())
|
||||
.relatedMinutes(createMockRelatedMinutes().subList(0, 3))
|
||||
.build(),
|
||||
MinutesDetailResponse.AgendaInfo.builder()
|
||||
.agendaId("agenda-002")
|
||||
.title("2. 개발 일정 및 리소스")
|
||||
.orderIndex(2)
|
||||
.isVerified(true)
|
||||
.verifiedBy("이준호")
|
||||
.verifiedAt(LocalDateTime.of(2025, 10, 25, 16, 32))
|
||||
.aiSummary(MinutesDetailResponse.AiSummary.builder()
|
||||
.content("개발 기간은 3개월로 설정. 백엔드 2명, 프론트 2명, AI 엔지니어 1명 투입. 주간 스프린트로 진행하며, 2주마다 베타 테스트 실시.")
|
||||
.generatedAt(LocalDateTime.of(2025, 10, 25, 16, 32))
|
||||
.build())
|
||||
.details(MinutesDetailResponse.AgendaDetails.builder()
|
||||
.discussions(List.of(
|
||||
"Phase 1 (11월): 핵심 기능 개발 (음성인식, AI 요약)",
|
||||
"Phase 2 (12월): 협업 기능 개발 (검증, 공유)",
|
||||
"Phase 3 (1월): 베타 테스트 및 최적화"
|
||||
))
|
||||
.decisions(List.of(
|
||||
"백엔드 개발자 2명",
|
||||
"프론트엔드 개발자 2명",
|
||||
"AI 엔지니어 1명"
|
||||
))
|
||||
.build())
|
||||
.relatedMinutes(createMockRelatedMinutes().subList(1, 2))
|
||||
.build(),
|
||||
MinutesDetailResponse.AgendaInfo.builder()
|
||||
.agendaId("agenda-003")
|
||||
.title("3. 마케팅 전략")
|
||||
.orderIndex(3)
|
||||
.isVerified(true)
|
||||
.verifiedBy("최유진")
|
||||
.verifiedAt(LocalDateTime.of(2025, 10, 25, 16, 35))
|
||||
.aiSummary(MinutesDetailResponse.AiSummary.builder()
|
||||
.content("베타 출시 전 프리 런칭 캠페인 진행. 주요 채널은 LinkedIn 및 스타트업 커뮤니티. 초기 100팀 무료 제공 후 유료 전환 유도.")
|
||||
.generatedAt(LocalDateTime.of(2025, 10, 25, 16, 35))
|
||||
.build())
|
||||
.details(MinutesDetailResponse.AgendaDetails.builder()
|
||||
.discussions(List.of(
|
||||
"기간: 11월 1일 ~ 11월 30일",
|
||||
"채널: LinkedIn, Product Hunt, 스타트업 커뮤니티",
|
||||
"목표: 500명 사전 신청"
|
||||
))
|
||||
.decisions(List.of(
|
||||
"초기 100팀 무료 제공",
|
||||
"피드백 수집 및 개선",
|
||||
"1월부터 유료 전환"
|
||||
))
|
||||
.build())
|
||||
.relatedMinutes(List.of())
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private MinutesDetailResponse convertToMinutesDetailResponse(MinutesDTO minutesDTO) {
|
||||
// Mock 데이터로 대체 (프로토타입용)
|
||||
return createMockMinutesDetail(minutesDTO.getMinutesId(), "user123");
|
||||
}
|
||||
|
||||
}
|
||||
+127
-23
@@ -9,7 +9,7 @@ import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 회의록 상세 조회 응답 DTO
|
||||
* 회의록 상세 조회 응답 DTO (프로토타입 기반 - 대시보드/회의록 탭 구조)
|
||||
*/
|
||||
@Getter
|
||||
@Builder
|
||||
@@ -27,14 +27,14 @@ public class MinutesDetailResponse {
|
||||
private String createdBy;
|
||||
private String lastModifiedBy;
|
||||
|
||||
// 회의 정보
|
||||
// 회의 기본 정보
|
||||
private MeetingInfo meeting;
|
||||
|
||||
// 섹션 목록
|
||||
private List<SectionInfo> sections;
|
||||
// 대시보드 탭 정보
|
||||
private DashboardInfo dashboard;
|
||||
|
||||
// Todo 목록
|
||||
private List<TodoInfo> todos;
|
||||
// 회의록 탭 정보 (안건별 상세)
|
||||
private List<AgendaInfo> agendas;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@@ -48,39 +48,143 @@ public class MinutesDetailResponse {
|
||||
private LocalDateTime endedAt;
|
||||
private String organizerId;
|
||||
private String organizerName;
|
||||
private String location;
|
||||
private int durationMinutes;
|
||||
private List<Participant> participants;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class SectionInfo {
|
||||
private String sectionId;
|
||||
private String title;
|
||||
public static class Participant {
|
||||
private String userId;
|
||||
private String name;
|
||||
private String role; // 작성자, 참여자
|
||||
private String avatarColor; // avatar-green, avatar-blue, etc.
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class DashboardInfo {
|
||||
private List<KeyPoint> keyPoints; // 핵심내용
|
||||
private List<String> keywords; // 키워드 태그
|
||||
private Statistics stats; // 통계 정보
|
||||
private List<Decision> decisions; // 결정사항
|
||||
private TodoProgress todoProgress; // Todo 진행상황
|
||||
private List<RelatedMinutes> relatedMinutes; // 관련회의록
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class KeyPoint {
|
||||
private int index;
|
||||
private String content;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class Statistics {
|
||||
private int participantCount;
|
||||
private int durationMinutes;
|
||||
private int agendaCount;
|
||||
private int todoCount;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class Decision {
|
||||
private String content;
|
||||
private String decidedBy;
|
||||
private LocalDateTime decidedAt;
|
||||
private String background;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class TodoProgress {
|
||||
private int totalCount;
|
||||
private int completedCount;
|
||||
private int progressPercentage;
|
||||
private List<SimpleTodo> todos; // 간단한 Todo 목록 (한줄 텍스트)
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class SimpleTodo {
|
||||
private String todoId;
|
||||
private String title; // 간단한 한줄 텍스트
|
||||
private String assigneeName;
|
||||
private String status; // IN_PROGRESS, COMPLETED, OVERDUE
|
||||
private String priority; // HIGH, MEDIUM, LOW
|
||||
private LocalDateTime dueDate;
|
||||
private String dueDayStatus; // D-2, D+1, 완료 등
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class RelatedMinutes {
|
||||
private String minutesId;
|
||||
private String title;
|
||||
private LocalDateTime meetingDate;
|
||||
private String author;
|
||||
private int relevancePercentage;
|
||||
private String relevanceLevel; // HIGH, MEDIUM, LOW
|
||||
private String summary;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class AgendaInfo {
|
||||
private String agendaId;
|
||||
private String title;
|
||||
private int orderIndex;
|
||||
private boolean isLocked;
|
||||
private boolean isVerified;
|
||||
private String lockedBy;
|
||||
private LocalDateTime lockedAt;
|
||||
private String verifiedBy;
|
||||
private LocalDateTime verifiedAt;
|
||||
|
||||
// AI 요약
|
||||
private AiSummary aiSummary;
|
||||
|
||||
// 안건 상세 내용
|
||||
private AgendaDetails details;
|
||||
|
||||
// 관련회의록
|
||||
private List<RelatedMinutes> relatedMinutes;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class TodoInfo {
|
||||
private String todoId;
|
||||
private String title;
|
||||
private String description;
|
||||
private String assigneeId;
|
||||
private String assigneeName;
|
||||
private String priority;
|
||||
private String status;
|
||||
private LocalDateTime dueDate;
|
||||
private LocalDateTime completedAt;
|
||||
private String completedBy;
|
||||
public static class AiSummary {
|
||||
private String content;
|
||||
private LocalDateTime generatedAt;
|
||||
private LocalDateTime modifiedAt;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class AgendaDetails {
|
||||
private List<String> discussions; // 논의 사항
|
||||
private List<String> decisions; // 결정 사항
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user