Skip to content
Merged
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,4 @@ out/

## Agents
AGENTS.md
CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,11 +190,13 @@ public ApiResponse<MeetingResponse.MeetingDetailDTO> getMeetingDetail(
@ApiErrorCodeExamples({
@ApiErrorCodeExample(value = ErrorStatus.class, name = "_UNAUTHORIZED"),
@ApiErrorCodeExample(value = ErrorStatus.class, name = "_BAD_REQUEST"),
@ApiErrorCodeExample(value = MeetingErrorCode.class, name = "MEETING_NOT_FOUND")
@ApiErrorCodeExample(value = MeetingErrorCode.class, name = "MEETING_NOT_FOUND"),
@ApiErrorCodeExample(value = MeetingErrorCode.class, name = "MEETING_NOT_END"),
@ApiErrorCodeExample(value = MeetingErrorCode.class, name = "MEETING_UNNORMAL_END")
})
public ApiResponse<MeetingResponse.HistoryListDTO> getHistory(
@PathVariable Long meetingId) {
return ApiResponse.onSuccess(null);
return ApiResponse.onSuccess(meetingQueryService.getDialogueHistory(meetingId));
}

@GetMapping("/meetings/{meetingId}/analysis")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
package com.whylog.server.domain.meeting.dto;

import com.whylog.server.domain.meeting.entity.Dialogue;
import com.whylog.server.domain.meeting.entity.Meeting;
import com.whylog.server.domain.meeting.entity.MeetingAnalysis;
import com.whylog.server.domain.meeting.enums.MeetingStatus;
import com.whylog.server.domain.meeting.socket.MeetingParticipant;
import com.whylog.server.domain.user.entity.Member;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;

Expand Down Expand Up @@ -191,6 +195,16 @@ public static class ParticipantDTO {

@Schema(description = "참여자 프로필 사진 URL", example = "https://example.com/profile/user-1.jpg")
private String profileImage;

public static List<ParticipantDTO> create(List<Member> members) {
return members.stream().map(member -> ParticipantDTO.builder()
.memberId(member.getId())
.name(member.getName())
.profileImage(member.getProfileImage())
.build()
).toList();
}

}

@Getter
Expand All @@ -208,7 +222,47 @@ public static class DialogueDTO {

@Schema(description = "말한 시간", example = "00:22")
private String timestamp;

public static List<DialogueDTO> create(Meeting meeting, List<Dialogue> dialogues) {
LocalDateTime startDateTime = meeting.getStartDateTime();

return dialogues.stream().map(dialogue -> DialogueDTO.builder()
.memberId(dialogue.getMember().getId())
.content(dialogue.getContent())
.timestamp(formatElapsed(startDateTime, dialogue.getSpeechDateTime()))
.build()
).toList();
}

private static String formatElapsed(LocalDateTime startDateTime, LocalDateTime speechDateTime) {
if (startDateTime == null || speechDateTime == null) {
return null;
}

Duration elapsed = Duration.between(startDateTime, speechDateTime);
if (elapsed.isNegative()) {
return "00:00";
}

long totalSeconds = elapsed.getSeconds();
long minutes = totalSeconds / 60;
long seconds = totalSeconds % 60;
return String.format("%02d:%02d", minutes, seconds);
}

}

public static HistoryListDTO create(Meeting meeting, List<Dialogue> dialogues, List<Member> participants ) {

List<ParticipantDTO> participantDtoList = ParticipantDTO.create(participants);
List<DialogueDTO> dialogueDtoList = DialogueDTO.create(meeting, dialogues);
return HistoryListDTO.builder()
.participants(participantDtoList)
.dialogues(dialogueDtoList)
.build();

}

}

@Getter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ public enum MeetingErrorCode implements BaseErrorCode {
MEETING_NOT_OWNER(HttpStatus.FORBIDDEN, "MEETING_403", "회의 삭제 권한이 없습니다."),
MEETING_AUDIO_NOT_READY(HttpStatus.CONFLICT, "MEETING_411", "회의 녹음본이 아직 생성되지 않았거나 업로드가 완료되지 않았습니다."),
MEETING_ALREADY_PARTICIPATING(HttpStatus.CONFLICT, "MEETING_412", "이미 실시간으로 참여 중인 회의입니다."),
MEETING_NOT_END(HttpStatus.CONFLICT, "MEETING413", "아직 종료되지 않은 회의입니다."),
MEETING_UNNORMAL_END(HttpStatus.CONFLICT, "MEETING414", "비정상 종료된 회의입니다."),
;

private final HttpStatus httpStatus;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.whylog.server.domain.meeting.repository;

import com.whylog.server.domain.meeting.entity.MeetingAnalysis;
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;
Expand All @@ -15,4 +16,7 @@ public interface MeetingAnalysisRepository extends JpaRepository<MeetingAnalysis
@Modifying
@Query("DELETE FROM MeetingAnalysis ma WHERE ma.meeting.id = :meetingId")
void deleteByMeetingId(@Param("meetingId") Long meetingId);

@Query("SELECT ma FROM MeetingAnalysis ma WHERE ma.meeting.id = :meetingId")
Optional<MeetingAnalysis> findByMeetingId(@Param("meetingId") Long meetingId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,13 @@ public interface MeetingRepository extends JpaRepository<Meeting, Long> {
""")
int markAllOngoingMeetingsAsEnded(@Param("endedAt") LocalDateTime endedAt);

@Query("""
SELECT m FROM Meeting m
LEFT JOIN FETCH m.dialogues d
LEFT JOIN FETCH m.meetingMembers mm
JOIN FETCH d.member dm
WHERE m.id = :meetingId
""")
Optional<Meeting> findWithDialogue(@Param("meetingId") Long meetingId);

}
Loading
Loading