mirror of
https://github.com/hwanny1128/HGZero.git
synced 2025-12-06 23:06:23 +00:00
Chore: 회의록 상세조회 API - db 변경사항 적용
This commit is contained in:
parent
d0aa6353da
commit
7e2094bcbc
File diff suppressed because it is too large
Load Diff
@ -45,21 +45,6 @@ public class AgendaSection {
|
|||||||
*/
|
*/
|
||||||
private String aiSummaryShort;
|
private String aiSummaryShort;
|
||||||
|
|
||||||
/**
|
|
||||||
* 논의사항 (JSON 형태로 저장)
|
|
||||||
*/
|
|
||||||
private String discussions;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 결정사항 (JSON 형태로 저장)
|
|
||||||
*/
|
|
||||||
private String decisions;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 의견 (JSON 형태로 저장)
|
|
||||||
*/
|
|
||||||
private String opinions;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 보류사항 (JSON 형태로 저장)
|
* 보류사항 (JSON 형태로 저장)
|
||||||
*/
|
*/
|
||||||
@ -70,6 +55,11 @@ public class AgendaSection {
|
|||||||
*/
|
*/
|
||||||
private String todos;
|
private String todos;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 요약 (안건 내용)
|
||||||
|
*/
|
||||||
|
private String summary;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 생성일시
|
* 생성일시
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -81,6 +81,11 @@ public class Minutes {
|
|||||||
*/
|
*/
|
||||||
private LocalDateTime finalizedAt;
|
private LocalDateTime finalizedAt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 결정사항
|
||||||
|
*/
|
||||||
|
private String decisions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 회의록 확정 가능 여부 검증
|
* 회의록 확정 가능 여부 검증
|
||||||
*
|
*
|
||||||
|
|||||||
@ -136,6 +136,11 @@ public class MinutesDTO {
|
|||||||
*/
|
*/
|
||||||
private final List<TodoInfo> todos;
|
private final List<TodoInfo> todos;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 결정사항
|
||||||
|
*/
|
||||||
|
private final String decisions;
|
||||||
|
|
||||||
// 중첩 클래스들
|
// 중첩 클래스들
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
|
|||||||
@ -371,6 +371,10 @@ public class MinutesService implements
|
|||||||
log.warn("섹션 정보 변환 실패 - minutesId: {}", minutes.getMinutesId(), e);
|
log.warn("섹션 정보 변환 실패 - minutesId: {}", minutes.getMinutesId(), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// decisions 값 로깅
|
||||||
|
log.info("Minutes decisions 값 확인 - minutesId: {}, decisions: {}",
|
||||||
|
minutes.getMinutesId(), minutes.getDecisions());
|
||||||
|
|
||||||
return MinutesDTO.builder()
|
return MinutesDTO.builder()
|
||||||
.minutesId(minutes.getMinutesId())
|
.minutesId(minutes.getMinutesId())
|
||||||
.meetingId(minutes.getMeetingId())
|
.meetingId(minutes.getMeetingId())
|
||||||
@ -387,6 +391,7 @@ public class MinutesService implements
|
|||||||
.participantCount(participantCount)
|
.participantCount(participantCount)
|
||||||
.memo("") // 메모 필드는 추후 구현
|
.memo("") // 메모 필드는 추후 구현
|
||||||
.sections(sectionDTOs) // 섹션 정보 추가
|
.sections(sectionDTOs) // 섹션 정보 추가
|
||||||
|
.decisions(minutes.getDecisions()) // decisions 필드 추가
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -840,8 +840,10 @@ public class MinutesController {
|
|||||||
.todoCount(todoProgress.getTotalCount())
|
.todoCount(todoProgress.getTotalCount())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
// 결정사항 추출
|
// minutes 테이블의 decisions 텍스트 사용
|
||||||
List<MinutesDetailResponse.Decision> decisions = extractDecisions(agendas);
|
String decisions = minutesDTO.getDecisions() != null ? minutesDTO.getDecisions() : "";
|
||||||
|
log.info("Dashboard decisions 값 확인 - minutesId: {}, decisions: {}",
|
||||||
|
minutesDTO.getMinutesId(), decisions);
|
||||||
|
|
||||||
// AI 기반 관련회의록 조회 (캐시 우선)
|
// AI 기반 관련회의록 조회 (캐시 우선)
|
||||||
List<MinutesDetailResponse.RelatedMinutes> relatedMinutes = getRelatedMinutesFromAI(minutesDTO.getMinutesId());
|
List<MinutesDetailResponse.RelatedMinutes> relatedMinutes = getRelatedMinutesFromAI(minutesDTO.getMinutesId());
|
||||||
@ -883,29 +885,12 @@ public class MinutesController {
|
|||||||
|
|
||||||
MinutesSection minutesSection = (MinutesSection) section;
|
MinutesSection minutesSection = (MinutesSection) section;
|
||||||
|
|
||||||
// AI 요약 정보 구성 (현재는 기본값 사용)
|
|
||||||
MinutesDetailResponse.AiSummary aiSummary = MinutesDetailResponse.AiSummary.builder()
|
|
||||||
.content(minutesSection.getContent() != null ? minutesSection.getContent() : "AI 요약 정보 없음")
|
|
||||||
.generatedAt(LocalDateTime.now().minusMinutes(30))
|
|
||||||
.modifiedAt(LocalDateTime.now().minusMinutes(10))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
// 안건 상세 내용 구성
|
|
||||||
MinutesDetailResponse.AgendaDetails details = MinutesDetailResponse.AgendaDetails.builder()
|
|
||||||
.discussions(parseDiscussions(minutesSection.getContent()))
|
|
||||||
.decisions(parseDecisions(minutesSection.getContent()))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
return MinutesDetailResponse.AgendaInfo.builder()
|
return MinutesDetailResponse.AgendaInfo.builder()
|
||||||
.agendaId(minutesSection.getSectionId())
|
.agendaId(minutesSection.getSectionId())
|
||||||
.title(minutesSection.getTitle() != null ? minutesSection.getTitle() : "제목 없음")
|
.title(minutesSection.getTitle() != null ? minutesSection.getTitle() : "제목 없음")
|
||||||
.orderIndex(minutesSection.getOrder() != null ? minutesSection.getOrder() : 1)
|
.orderIndex(minutesSection.getOrder() != null ? minutesSection.getOrder() : 1)
|
||||||
.isVerified(minutesSection.isVerified())
|
.aiSummary("") // MinutesSection에는 AI 요약이 없음
|
||||||
.verifiedBy(minutesSection.isVerified() ? "시스템" : null)
|
.content(minutesSection.getContent() != null ? minutesSection.getContent() : "")
|
||||||
.verifiedAt(minutesSection.isVerified() ? LocalDateTime.now().minusHours(1) : null)
|
|
||||||
.aiSummary(aiSummary)
|
|
||||||
.details(details)
|
|
||||||
.relatedMinutes(new ArrayList<>()) // 관련 회의록은 별도 로직 필요
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -913,69 +898,15 @@ public class MinutesController {
|
|||||||
* AgendaSection을 AgendaInfo로 변환
|
* AgendaSection을 AgendaInfo로 변환
|
||||||
*/
|
*/
|
||||||
private MinutesDetailResponse.AgendaInfo convertAgendaSectionToAgendaInfo(AgendaSection agendaSection) {
|
private MinutesDetailResponse.AgendaInfo convertAgendaSectionToAgendaInfo(AgendaSection agendaSection) {
|
||||||
// AI 요약 정보 구성
|
|
||||||
MinutesDetailResponse.AiSummary aiSummary = MinutesDetailResponse.AiSummary.builder()
|
|
||||||
.content(agendaSection.getAiSummaryShort() != null ? agendaSection.getAiSummaryShort() : "")
|
|
||||||
.generatedAt(agendaSection.getCreatedAt() != null ? agendaSection.getCreatedAt() : LocalDateTime.now())
|
|
||||||
.modifiedAt(agendaSection.getUpdatedAt() != null ? agendaSection.getUpdatedAt() : LocalDateTime.now())
|
|
||||||
.build();
|
|
||||||
|
|
||||||
// 안건 상세 내용 구성
|
|
||||||
// discussions는 이제 TEXT 타입이므로 별도 파싱 로직 적용
|
|
||||||
List<String> discussionsList = parseDiscussionsText(agendaSection.getDiscussions());
|
|
||||||
// decisions는 JSON 문자열로 저장되어 있으므로 파싱 필요
|
|
||||||
List<String> decisionsList = parseJsonToList(agendaSection.getDecisions());
|
|
||||||
|
|
||||||
MinutesDetailResponse.AgendaDetails details = MinutesDetailResponse.AgendaDetails.builder()
|
|
||||||
.discussions(discussionsList)
|
|
||||||
.decisions(decisionsList)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
return MinutesDetailResponse.AgendaInfo.builder()
|
return MinutesDetailResponse.AgendaInfo.builder()
|
||||||
.agendaId(agendaSection.getId())
|
.agendaId(agendaSection.getId())
|
||||||
.title(agendaSection.getAgendaTitle() != null ? agendaSection.getAgendaTitle() : "제목 없음")
|
.title(agendaSection.getAgendaTitle() != null ? agendaSection.getAgendaTitle() : "제목 없음")
|
||||||
.orderIndex(agendaSection.getAgendaNumber() != null ? agendaSection.getAgendaNumber() : 1)
|
.orderIndex(agendaSection.getAgendaNumber() != null ? agendaSection.getAgendaNumber() : 1)
|
||||||
.isVerified(true) // agenda_sections는 기본적으로 검증된 데이터
|
.aiSummary(agendaSection.getAiSummaryShort() != null ? agendaSection.getAiSummaryShort() : "")
|
||||||
.verifiedBy("AI")
|
.content(agendaSection.getSummary() != null ? agendaSection.getSummary() : "")
|
||||||
.verifiedAt(agendaSection.getCreatedAt())
|
|
||||||
.aiSummary(aiSummary)
|
|
||||||
.details(details)
|
|
||||||
.relatedMinutes(new ArrayList<>()) // 관련 회의록은 별도 로직 필요
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* JSON 문자열을 List<String>으로 파싱
|
|
||||||
*/
|
|
||||||
private List<String> parseJsonToList(String json) {
|
|
||||||
if (json == null || json.isEmpty()) {
|
|
||||||
return new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 간단한 JSON 배열 파싱
|
|
||||||
json = json.trim();
|
|
||||||
if (json.startsWith("[") && json.endsWith("]")) {
|
|
||||||
json = json.substring(1, json.length() - 1);
|
|
||||||
if (json.isEmpty()) {
|
|
||||||
return new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 쉼표로 분리하고 따옴표 제거
|
|
||||||
return Arrays.stream(json.split(","))
|
|
||||||
.map(s -> s.trim())
|
|
||||||
.map(s -> s.startsWith("\"") && s.endsWith("\"") ? s.substring(1, s.length() - 1) : s)
|
|
||||||
.filter(s -> !s.isEmpty())
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
// JSON 형식이 아니면 그대로 한 줄로 반환
|
|
||||||
return List.of(json);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.warn("JSON 파싱 실패: {}", json, e);
|
|
||||||
return List.of(json); // 파싱 실패시 원본 텍스트를 그대로 반환
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private MinutesDetailResponse.SimpleTodo convertToSimpleTodo(Object todo) {
|
private MinutesDetailResponse.SimpleTodo convertToSimpleTodo(Object todo) {
|
||||||
@ -1016,10 +947,10 @@ public class MinutesController {
|
|||||||
List<MinutesDetailResponse.KeyPoint> keyPoints = new ArrayList<>();
|
List<MinutesDetailResponse.KeyPoint> keyPoints = new ArrayList<>();
|
||||||
for (int i = 0; i < agendas.size() && i < 4; i++) {
|
for (int i = 0; i < agendas.size() && i < 4; i++) {
|
||||||
MinutesDetailResponse.AgendaInfo agenda = agendas.get(i);
|
MinutesDetailResponse.AgendaInfo agenda = agendas.get(i);
|
||||||
if (agenda.getAiSummary() != null) {
|
if (agenda.getAiSummary() != null && !agenda.getAiSummary().isEmpty()) {
|
||||||
keyPoints.add(MinutesDetailResponse.KeyPoint.builder()
|
keyPoints.add(MinutesDetailResponse.KeyPoint.builder()
|
||||||
.index(i + 1)
|
.index(i + 1)
|
||||||
.content(agenda.getAiSummary().getContent())
|
.content(agenda.getAiSummary())
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1032,85 +963,6 @@ public class MinutesController {
|
|||||||
return keyPoints;
|
return keyPoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 회의록 섹션 내용에서 논의사항 추출
|
|
||||||
*/
|
|
||||||
private List<String> parseDiscussions(String content) {
|
|
||||||
if (content == null || content.trim().isEmpty()) {
|
|
||||||
return List.of("논의 내용 없음");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 간단한 패턴으로 논의사항 추출 (실제로는 AI 파싱 필요)
|
|
||||||
Pattern pattern = Pattern.compile("논의[::]\\s*(.+?)(?=결정|\\n|$)", Pattern.CASE_INSENSITIVE);
|
|
||||||
Matcher matcher = pattern.matcher(content);
|
|
||||||
List<String> discussions = new ArrayList<>();
|
|
||||||
|
|
||||||
while (matcher.find()) {
|
|
||||||
discussions.add(matcher.group(1).trim());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (discussions.isEmpty()) {
|
|
||||||
// 전체 내용을 논의사항으로 처리
|
|
||||||
discussions.add(content.length() > 100 ? content.substring(0, 100) + "..." : content);
|
|
||||||
}
|
|
||||||
|
|
||||||
return discussions;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* AgendaSection의 discussions TEXT 필드 파싱
|
|
||||||
*/
|
|
||||||
private List<String> parseDiscussionsText(String discussions) {
|
|
||||||
if (discussions == null || discussions.trim().isEmpty()) {
|
|
||||||
return new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
// **논의 사항:** 형식으로 저장된 텍스트 파싱
|
|
||||||
List<String> discussionsList = new ArrayList<>();
|
|
||||||
|
|
||||||
// 줄바꿈으로 분리하고 - 로 시작하는 항목 추출
|
|
||||||
String[] lines = discussions.split("\n");
|
|
||||||
for (String line : lines) {
|
|
||||||
line = line.trim();
|
|
||||||
if (line.startsWith("-") || line.startsWith("•") || line.startsWith("*")) {
|
|
||||||
// 불릿 포인트 제거
|
|
||||||
String item = line.substring(1).trim();
|
|
||||||
if (!item.isEmpty()) {
|
|
||||||
discussionsList.add(item);
|
|
||||||
}
|
|
||||||
} else if (!line.isEmpty() && !line.contains("논의") && !line.contains(":**")) {
|
|
||||||
// 불릿 포인트가 없는 텍스트도 포함
|
|
||||||
discussionsList.add(line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (discussionsList.isEmpty()) {
|
|
||||||
// 구조화되지 않은 경우 전체 텍스트 반환
|
|
||||||
discussionsList.add(discussions.trim());
|
|
||||||
}
|
|
||||||
|
|
||||||
return discussionsList;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 회의록 섹션 내용에서 결정사항 추출
|
|
||||||
*/
|
|
||||||
private List<String> parseDecisions(String content) {
|
|
||||||
if (content == null || content.trim().isEmpty()) {
|
|
||||||
return new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 간단한 패턴으로 결정사항 추출 (실제로는 AI 파싱 필요)
|
|
||||||
Pattern pattern = Pattern.compile("결정[::]\\s*(.+?)(?=논의|\\n|$)", Pattern.CASE_INSENSITIVE);
|
|
||||||
Matcher matcher = pattern.matcher(content);
|
|
||||||
List<String> decisions = new ArrayList<>();
|
|
||||||
|
|
||||||
while (matcher.find()) {
|
|
||||||
decisions.add(matcher.group(1).trim());
|
|
||||||
}
|
|
||||||
|
|
||||||
return decisions;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 담당자 이름 조회 (실제로는 User 서비스에서 조회 필요)
|
* 담당자 이름 조회 (실제로는 User 서비스에서 조회 필요)
|
||||||
@ -1163,26 +1015,6 @@ public class MinutesController {
|
|||||||
return List.of("#AI회의록", "#음성인식", "#협업도구", "#스타트업", "#베타출시");
|
return List.of("#AI회의록", "#음성인식", "#협업도구", "#스타트업", "#베타출시");
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<MinutesDetailResponse.Decision> extractDecisions(List<MinutesDetailResponse.AgendaInfo> agendas) {
|
|
||||||
List<MinutesDetailResponse.Decision> decisions = new ArrayList<>();
|
|
||||||
|
|
||||||
for (MinutesDetailResponse.AgendaInfo agenda : agendas) {
|
|
||||||
if (agenda.getDetails() != null && agenda.getDetails().getDecisions() != null) {
|
|
||||||
for (String decision : agenda.getDetails().getDecisions()) {
|
|
||||||
decisions.add(MinutesDetailResponse.Decision.builder()
|
|
||||||
.content(decision)
|
|
||||||
.decidedBy("김민준")
|
|
||||||
.decidedAt(LocalDateTime.now().minusHours(2))
|
|
||||||
.background("안건 논의 결과")
|
|
||||||
.build());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 실제 데이터만 사용
|
|
||||||
|
|
||||||
return decisions;
|
|
||||||
}
|
|
||||||
|
|
||||||
// === 샘플 데이터 생성 메소드들 ===
|
// === 샘플 데이터 생성 메소드들 ===
|
||||||
|
|
||||||
@ -1297,7 +1129,7 @@ public class MinutesController {
|
|||||||
.keyPoints(keyPoints)
|
.keyPoints(keyPoints)
|
||||||
.keywords(result.getKeywords() != null ? result.getKeywords() : dashboard.getKeywords())
|
.keywords(result.getKeywords() != null ? result.getKeywords() : dashboard.getKeywords())
|
||||||
.stats(dashboard.getStats())
|
.stats(dashboard.getStats())
|
||||||
.decisions(convertAiDecisions(result.getDecisions()))
|
.decisions(dashboard.getDecisions()) // AI 분석에서는 decisions를 변경하지 않음
|
||||||
.todoProgress(dashboard.getTodoProgress())
|
.todoProgress(dashboard.getTodoProgress())
|
||||||
.relatedMinutes(convertAiRelatedMinutes(result.getRelatedMinutes()))
|
.relatedMinutes(convertAiRelatedMinutes(result.getRelatedMinutes()))
|
||||||
.build();
|
.build();
|
||||||
@ -1326,23 +1158,6 @@ public class MinutesController {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* AI 결정사항을 Response 형식으로 변환
|
|
||||||
*/
|
|
||||||
private List<MinutesDetailResponse.Decision> convertAiDecisions(List<AiAnalysisDTO.Decision> aiDecisions) {
|
|
||||||
if (aiDecisions == null) {
|
|
||||||
return new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
return aiDecisions.stream()
|
|
||||||
.map(decision -> MinutesDetailResponse.Decision.builder()
|
|
||||||
.content(decision.getContent())
|
|
||||||
.decidedBy("AI 분석")
|
|
||||||
.decidedAt(LocalDateTime.now())
|
|
||||||
.background("AI가 회의록에서 추출한 결정사항")
|
|
||||||
.build())
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AI 관련회의록을 Response 형식으로 변환
|
* AI 관련회의록을 Response 형식으로 변환
|
||||||
@ -1366,10 +1181,6 @@ public class MinutesController {
|
|||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Response 객체 필드 복사 (불변 객체 업데이트용)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AI 분석 요청 이벤트 발행
|
* AI 분석 요청 이벤트 발행
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -72,7 +72,7 @@ public class MinutesDetailResponse {
|
|||||||
private List<KeyPoint> keyPoints; // 핵심내용
|
private List<KeyPoint> keyPoints; // 핵심내용
|
||||||
private List<String> keywords; // 키워드 태그
|
private List<String> keywords; // 키워드 태그
|
||||||
private Statistics stats; // 통계 정보
|
private Statistics stats; // 통계 정보
|
||||||
private List<Decision> decisions; // 결정사항
|
private String decisions; // 결정사항 (minutes 테이블의 decisions 텍스트)
|
||||||
private TodoProgress todoProgress; // Todo 진행상황
|
private TodoProgress todoProgress; // Todo 진행상황
|
||||||
private List<RelatedMinutes> relatedMinutes; // 관련회의록
|
private List<RelatedMinutes> relatedMinutes; // 관련회의록
|
||||||
}
|
}
|
||||||
@ -97,16 +97,6 @@ public class MinutesDetailResponse {
|
|||||||
private int todoCount;
|
private int todoCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Builder
|
|
||||||
@NoArgsConstructor
|
|
||||||
@AllArgsConstructor
|
|
||||||
public static class Decision {
|
|
||||||
private String content;
|
|
||||||
private String decidedBy;
|
|
||||||
private LocalDateTime decidedAt;
|
|
||||||
private String background;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Builder
|
@Builder
|
||||||
@ -155,36 +145,8 @@ public class MinutesDetailResponse {
|
|||||||
private String agendaId;
|
private String agendaId;
|
||||||
private String title;
|
private String title;
|
||||||
private int orderIndex;
|
private int orderIndex;
|
||||||
private boolean isVerified;
|
private String aiSummary; // agenda_sections.ai_summary_short
|
||||||
private String verifiedBy;
|
private String content; // agenda_sections.summary
|
||||||
private LocalDateTime verifiedAt;
|
|
||||||
|
|
||||||
// AI 요약
|
|
||||||
private AiSummary aiSummary;
|
|
||||||
|
|
||||||
// 안건 상세 내용
|
|
||||||
private AgendaDetails details;
|
|
||||||
|
|
||||||
// 관련회의록
|
|
||||||
private List<RelatedMinutes> relatedMinutes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Builder
|
|
||||||
@NoArgsConstructor
|
|
||||||
@AllArgsConstructor
|
|
||||||
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; // 결정 사항
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -39,21 +39,15 @@ public class AgendaSectionEntity extends BaseTimeEntity {
|
|||||||
@Column(name = "ai_summary_short", columnDefinition = "TEXT")
|
@Column(name = "ai_summary_short", columnDefinition = "TEXT")
|
||||||
private String aiSummaryShort;
|
private String aiSummaryShort;
|
||||||
|
|
||||||
@Column(name = "discussions", columnDefinition = "TEXT")
|
|
||||||
private String discussions;
|
|
||||||
|
|
||||||
@Column(name = "decisions", columnDefinition = "json")
|
|
||||||
private String decisions;
|
|
||||||
|
|
||||||
@Column(name = "pending_items", columnDefinition = "json")
|
@Column(name = "pending_items", columnDefinition = "json")
|
||||||
private String pendingItems;
|
private String pendingItems;
|
||||||
|
|
||||||
@Column(name = "opinions", columnDefinition = "json")
|
|
||||||
private String opinions;
|
|
||||||
|
|
||||||
@Column(name = "todos", columnDefinition = "json")
|
@Column(name = "todos", columnDefinition = "json")
|
||||||
private String todos;
|
private String todos;
|
||||||
|
|
||||||
|
@Column(name = "summary", columnDefinition = "TEXT")
|
||||||
|
private String summary;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Domain 객체로 변환
|
* Domain 객체로 변환
|
||||||
*/
|
*/
|
||||||
@ -65,11 +59,9 @@ public class AgendaSectionEntity extends BaseTimeEntity {
|
|||||||
.agendaNumber(this.agendaNumber)
|
.agendaNumber(this.agendaNumber)
|
||||||
.agendaTitle(this.agendaTitle)
|
.agendaTitle(this.agendaTitle)
|
||||||
.aiSummaryShort(this.aiSummaryShort)
|
.aiSummaryShort(this.aiSummaryShort)
|
||||||
.discussions(this.discussions)
|
|
||||||
.decisions(this.decisions)
|
|
||||||
.pendingItems(this.pendingItems)
|
.pendingItems(this.pendingItems)
|
||||||
.opinions(this.opinions)
|
|
||||||
.todos(this.todos)
|
.todos(this.todos)
|
||||||
|
.summary(this.summary)
|
||||||
.createdAt(this.getCreatedAt())
|
.createdAt(this.getCreatedAt())
|
||||||
.updatedAt(this.getUpdatedAt())
|
.updatedAt(this.getUpdatedAt())
|
||||||
.build();
|
.build();
|
||||||
@ -86,11 +78,9 @@ public class AgendaSectionEntity extends BaseTimeEntity {
|
|||||||
.agendaNumber(section.getAgendaNumber())
|
.agendaNumber(section.getAgendaNumber())
|
||||||
.agendaTitle(section.getAgendaTitle())
|
.agendaTitle(section.getAgendaTitle())
|
||||||
.aiSummaryShort(section.getAiSummaryShort())
|
.aiSummaryShort(section.getAiSummaryShort())
|
||||||
.discussions(section.getDiscussions())
|
|
||||||
.decisions(section.getDecisions())
|
|
||||||
.pendingItems(section.getPendingItems())
|
.pendingItems(section.getPendingItems())
|
||||||
.opinions(section.getOpinions())
|
|
||||||
.todos(section.getTodos())
|
.todos(section.getTodos())
|
||||||
|
.summary(section.getSummary())
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -55,6 +55,12 @@ public class MinutesEntity extends BaseTimeEntity {
|
|||||||
@Column(name = "finalized_at")
|
@Column(name = "finalized_at")
|
||||||
private LocalDateTime finalizedAt;
|
private LocalDateTime finalizedAt;
|
||||||
|
|
||||||
|
@Column(name = "decisions", columnDefinition = "TEXT")
|
||||||
|
private String decisions;
|
||||||
|
|
||||||
|
@Column(name = "user_id", length = 100)
|
||||||
|
private String userId;
|
||||||
|
|
||||||
public Minutes toDomain() {
|
public Minutes toDomain() {
|
||||||
return Minutes.builder()
|
return Minutes.builder()
|
||||||
.minutesId(this.minutesId)
|
.minutesId(this.minutesId)
|
||||||
@ -70,6 +76,7 @@ public class MinutesEntity extends BaseTimeEntity {
|
|||||||
.lastModifiedAt(this.getUpdatedAt())
|
.lastModifiedAt(this.getUpdatedAt())
|
||||||
.finalizedBy(this.finalizedBy)
|
.finalizedBy(this.finalizedBy)
|
||||||
.finalizedAt(this.finalizedAt)
|
.finalizedAt(this.finalizedAt)
|
||||||
|
.decisions(this.decisions)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,6 +95,7 @@ public class MinutesEntity extends BaseTimeEntity {
|
|||||||
.createdBy(minutes.getCreatedBy())
|
.createdBy(minutes.getCreatedBy())
|
||||||
.finalizedBy(minutes.getFinalizedBy())
|
.finalizedBy(minutes.getFinalizedBy())
|
||||||
.finalizedAt(minutes.getFinalizedAt())
|
.finalizedAt(minutes.getFinalizedAt())
|
||||||
|
.decisions(minutes.getDecisions())
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user