Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,6 @@
@Tag(name = "Decision", description = "결정사항 관련 API")
public class DecisionController {

@GetMapping("/{decisionId}/applications")
@Operation(summary = "적용사항 목록 조회 API", description = "특정 결정사항의 적용사항 목록을 조회하는 API입니다.")
public ApiResponse<List<ApplicationResponse.ApplicationDTO>> getApplications(
@PathVariable Long decisionId) {
return ApiResponse.onSuccess(null);
}

@GetMapping("/{decisionId}/reliability")
@Operation(summary = "신뢰도 조회 API", description = "특정 결정사항의 신뢰도 정보를 조회하는 API입니다.")
public ApiResponse<DecisionResponse.ReliabilityDTO> getReliability(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@ public class ApplicationResponse {
@Schema(description = "적용사항 항목")
public static class ApplicationDTO {

@Schema(description = "결정사항 ID", example = "1")
private Long decisionId;

@Schema(description = "적용사항 ID", example = "1")
private Long applicationId;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.whylog.server.domain.decision.dto;

import io.swagger.v3.oas.annotations.media.Schema;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
Expand All @@ -21,8 +22,8 @@ public static class DecisionListDTO {
@Schema(description = "회의 명", example = "백엔드 비상대책회의")
private String name;

@Schema(description = "적용사항 개수", example = "3")
private Integer applicationCount;
@Schema(description = "적용사항 목록")
private List<ApplicationResponse.ApplicationDTO> applications;
}

@Getter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ public class Application extends BaseEntity {
@JoinColumn(name = "decision_id", nullable = false)
private Decision decision;

@Column(name = "name")
private String name;

// @OneToMany(mappedBy = "application", cascade = CascadeType.ALL, orphanRemoval = true)
// private final List<ApplicationTimeline> applicationTimelines = new ArrayList<>();
//
Expand All @@ -41,4 +44,11 @@ public class Application extends BaseEntity {
//
// @OneToMany(mappedBy = "application", cascade = CascadeType.ALL, orphanRemoval = true)
// private final List<ApplicationBase> applicationBases = new ArrayList<>();

public static Application create(Decision decision, String name) {
Application application = new Application();
application.decision = decision;
application.name = name;
return application;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,11 @@ public class Decision extends BaseEntity {
//
// @OneToMany(mappedBy = "decision", cascade = CascadeType.ALL, orphanRemoval = true)
// private final List<EffectRatio> effectRatios = new ArrayList<>();

public static Decision create(Meeting meeting, boolean isCreated) {
Decision decision = new Decision();
decision.meeting = meeting;
decision.isCreated = isCreated;
return decision;
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package com.whylog.server.domain.decision.repository;

import com.whylog.server.domain.decision.entity.Decision;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

public interface DecisionRepository extends JpaRepository<Decision, Long> {

Optional<Decision> findByMeetingId(Long meetingId);

@Modifying
@Query("DELETE FROM Application a WHERE a.decision.meeting.team.id = :teamId")
void deleteApplicationsByTeamId(@Param("teamId") Long teamId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.whylog.server.domain.decision.entity.Application;
import com.whylog.server.domain.decision.entity.Decision;
import com.whylog.server.domain.decision.repository.ApplicationRepository;
import com.whylog.server.domain.decision.repository.DecisionRepository;
import com.whylog.server.domain.meeting.dto.MeetingResponse;
import com.whylog.server.domain.meeting.entity.Dialogue;
import com.whylog.server.domain.meeting.entity.Meeting;
Expand Down Expand Up @@ -51,6 +55,8 @@ public class MeetingAnalysisService {
private final MeetingAudioReplayService meetingAudioReplayService;
private final MeetingAudioFileService meetingAudioFileService;
private final FastApiTranscribeClient fastApiTranscribeClient;
private final ApplicationRepository applicationRepository;
private final DecisionRepository decisionRepository;
private final MeetingAnalysisRepository meetingAnalysisRepository;
private final DialogueRepository dialogueRepository;
private final TransactionTemplate transactionTemplate;
Expand Down Expand Up @@ -179,6 +185,8 @@ private void persistMeetingAnalysis(Meeting meeting, TranscribeApplicationRunRes
TranscribeApplicationRunResponse.AnalysisResultResponse analysisResult = runResult.analysisResult();
TranscribeApplicationRunResponse.OverallAnalysisResponse overallAnalysis =
analysisResult != null ? analysisResult.overallAnalysis() : null;
List<TranscribeApplicationRunResponse.ApplicationResponse> applications =
analysisResult != null && analysisResult.applications() != null ? analysisResult.applications() : List.of();
MeetingAnalysis.MeetingAnalysisPayload payload = buildMeetingAnalysisPayload(overallAnalysis);

transactionTemplate.executeWithoutResult(status -> {
Expand All @@ -195,13 +203,42 @@ private void persistMeetingAnalysis(Meeting meeting, TranscribeApplicationRunRes
dialogueRepository.saveAll(dialogues);
dialogues.forEach(managedMeeting::addDialogue);
}

Decision decision = createDecisionIfAbsent(managedMeeting);
replaceApplications(managedMeeting.getId(), decision, applications);
});

log.info("회의 오디오 분석 저장 완료: meetingId={}, transcriptSegmentCount={}", meeting.getId(), transcriptSegments.size());
// TODO: FastAPI의 applications 결과는 아직 저장하지 않는다.
// TODO: applications 저장 후 applicationId를 발급해 /api/meeting-analysis/embeddings로 전달한다.
}

// Decision이 없을 때 새로 생성한다.
private Decision createDecisionIfAbsent(Meeting meeting) {
return decisionRepository.findByMeetingId(meeting.getId())
.orElseGet(() -> {
Decision decision = decisionRepository.save(Decision.create(meeting, true));
log.info("결정사항 저장 완료: meetingId={}, decisionId={}", meeting.getId(), decision.getId());
return decision;
});
}

// 분석 결과의 적용사항 제목 목록을 저장한다.
private void replaceApplications(Long meetingId,
Decision decision,
List<TranscribeApplicationRunResponse.ApplicationResponse> applications) {
List<Application> newApplications = applications.stream()
.map(TranscribeApplicationRunResponse.ApplicationResponse::applicationTitle)
.filter(title -> title != null && !title.isBlank())
.map(title -> Application.create(decision, title.trim()))
.toList();

if (!newApplications.isEmpty()) {
applicationRepository.saveAll(newApplications);
log.info("적용사항 저장 완료: meetingId={}, decisionId={}, applicationCount={}",
meetingId, decision.getId(), newApplications.size());
}
}


// OverallAnalysis를 MeetingAnalysis 저장용 payload로 변환한다.
private MeetingAnalysis.MeetingAnalysisPayload buildMeetingAnalysisPayload(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,14 @@ public class TeamController {
private final TeamQueryService teamQueryService;

@GetMapping("/{teamId}/decisions")
@Operation(summary = "결정사항 목록 조회 API", description = "특정 팀의 결정사항 목록을 조회하는 API입니다.")
@Operation(
summary = "결정사항 목록 조회 API",
description = """
특정 팀의 결정사항 목록을 조회하는 API입니다.
각 결정사항에는 해당 결정사항에 연결된 적용사항 목록도 함께 포함됩니다.
페이징 없습니다.
"""
)
@ApiErrorCodeExamples({
@ApiErrorCodeExample(value = ErrorStatus.class, name = "_UNAUTHORIZED"),
@ApiErrorCodeExample(value = ErrorStatus.class, name = "_BAD_REQUEST")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.whylog.server.domain.team.service;

import com.whylog.server.domain.decision.dto.ApplicationResponse;
import com.whylog.server.domain.decision.dto.DecisionResponse;
import com.whylog.server.domain.decision.entity.Decision;
import com.whylog.server.domain.team.repository.TeamRepository;
Expand All @@ -24,7 +25,14 @@ public List<DecisionResponse.DecisionListDTO> decisions( Long teamId ){
.map(d -> DecisionResponse.DecisionListDTO.builder()
.decisionId(d.getId())
.name(d.getMeeting().getName())
.applicationCount( d.getApplications().size() )
.applications(
d.getApplications().stream()
.map(application -> ApplicationResponse.ApplicationDTO.builder()
.applicationId(application.getId())
.name(application.getName())
.build())
.toList()
)
.build()
).toList();
}
Expand Down
Loading