Skip to content
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
package com.haru.api.domain.lastOpened.service;

import com.haru.api.domain.lastOpened.entity.Documentable;
import com.haru.api.domain.lastOpened.entity.enums.DocumentType;
import com.haru.api.domain.lastOpened.entity.UserDocumentId;
import com.haru.api.domain.user.entity.User;
import com.haru.api.global.common.entity.TitleHolder;

import java.util.List;

public interface UserDocumentLastOpenedService {

void updateLastOpened(Long userId, DocumentType documentType, Long documentId, Long workspaceId, String title);
void updateLastOpened(UserDocumentId userDocumentId, Long workspaceId, String title);

void createInitialRecordsForWorkspaceUsers(List<User> usersInWorkspace, Documentable document);

void deleteRecordsForWorkspaceUsers(Documentable document);

void updateRecordsForWorkspaceUsers(Documentable document);

void updateRecordsForWorkspaceUsers(Documentable document, TitleHolder titleHolder);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
import com.haru.api.domain.lastOpened.entity.Documentable;
import com.haru.api.domain.lastOpened.entity.UserDocumentId;
import com.haru.api.domain.lastOpened.entity.UserDocumentLastOpened;
import com.haru.api.domain.lastOpened.entity.enums.DocumentType;
import com.haru.api.domain.lastOpened.repository.UserDocumentLastOpenedRepository;
import com.haru.api.domain.user.entity.User;
import com.haru.api.domain.user.repository.UserRepository;
import com.haru.api.global.apiPayload.code.status.ErrorStatus;
import com.haru.api.global.apiPayload.exception.handler.MemberHandler;
import com.haru.api.global.common.entity.TitleHolder;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
Expand All @@ -28,15 +28,14 @@ public class UserDocumentLastOpenedServiceImpl implements UserDocumentLastOpened

@Override
@Transactional
public void updateLastOpened(Long userId, DocumentType documentType, Long documentId, Long workspaceId, String title) {
UserDocumentId id = new UserDocumentId(userId, documentId, documentType);
public void updateLastOpened(UserDocumentId userDocumentId, Long workspaceId, String title) {

UserDocumentLastOpened record = userDocumentLastOpenedRepository.findById(id)
UserDocumentLastOpened record = userDocumentLastOpenedRepository.findById(userDocumentId)
.orElseGet(() -> {
User foundUser = userRepository.findById(userId)
User foundUser = userRepository.findById(userDocumentId.getUserId())
.orElseThrow(() -> new MemberHandler(ErrorStatus.MEMBER_NOT_FOUND));
return UserDocumentLastOpened.builder()
.id(id)
.id(userDocumentId)
.user(foundUser)
.workspaceId(workspaceId)
.title(title)
Expand Down Expand Up @@ -86,6 +85,20 @@ public void updateRecordsForWorkspaceUsers(Documentable documentable) {
}
}

@Override
@Transactional
public void updateRecordsForWorkspaceUsers(Documentable documentable, TitleHolder titleHolder) {

// 해당 문서 id, 문서 타입에 해당하는 last opened 튜플 검색
List<UserDocumentLastOpened> recordsToUpdate = userDocumentLastOpenedRepository.findByDocumentIdAndDocumentType(documentable.getId(), documentable.getDocumentType());

if (!recordsToUpdate.isEmpty()) {
for (UserDocumentLastOpened record : recordsToUpdate) {
record.updateTitle(titleHolder.getTitle());
}
}
}

private List<UserDocumentLastOpened> recordsToProcess(List<User> usersInWorkspace, Documentable document) {
// 처리할 엔티티들을 담을 리스트 생성
List<UserDocumentLastOpened> recordsToProcess = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@

import com.haru.api.domain.meeting.dto.MeetingRequestDTO;
import com.haru.api.domain.meeting.dto.MeetingResponseDTO;
import com.haru.api.domain.meeting.entity.Meeting;
import com.haru.api.domain.meeting.service.MeetingCommandService;
import com.haru.api.domain.meeting.service.MeetingQueryService;
import com.haru.api.domain.user.security.jwt.SecurityUtil;
import com.haru.api.domain.user.entity.User;
import com.haru.api.global.annotation.AuthMeeting;
import com.haru.api.global.annotation.AuthUser;
import com.haru.api.global.apiPayload.ApiResponse;
import com.haru.api.global.apiPayload.code.status.ErrorStatus;
import com.haru.api.global.apiPayload.exception.GeneralException;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Encoding;
import lombok.RequiredArgsConstructor;
Expand Down Expand Up @@ -45,15 +49,16 @@ public class MeetingController {
)
public ApiResponse<MeetingResponseDTO.createMeetingResponse> createMeeting(
@RequestPart("agendaFile") MultipartFile agendaFile,
@RequestPart("request") MeetingRequestDTO.createMeetingRequest request) {
@RequestPart("request") MeetingRequestDTO.createMeetingRequest request,
@Parameter(hidden = true) @AuthUser User user
) {

// file업로드가 되지 않는 경우 controller단에서 요청 처리
if (agendaFile == null || agendaFile.isEmpty()) {
throw new GeneralException(ErrorStatus.MEETING_AGENDAFILE_NOT_FOUND);
}
Long userId = SecurityUtil.getCurrentUserId();

MeetingResponseDTO.createMeetingResponse response = meetingCommandService.createMeeting(userId, agendaFile, request);
MeetingResponseDTO.createMeetingResponse response = meetingCommandService.createMeeting(user, agendaFile, request);

return ApiResponse.onSuccess(response);
}
Expand All @@ -64,11 +69,12 @@ public ApiResponse<MeetingResponseDTO.createMeetingResponse> createMeeting(
)
@GetMapping("/workspaces/{workspaceId}")
public ApiResponse<List<MeetingResponseDTO.getMeetingResponse>> getMeetings(
@PathVariable("workspaceId") String workspaceId){

Long userId = SecurityUtil.getCurrentUserId();
@PathVariable("workspaceId") String workspaceId,
@Parameter(hidden = true) @AuthUser User user,
@Parameter(hidden = true) @AuthMeeting Meeting meeting
) {

List<MeetingResponseDTO.getMeetingResponse> response = meetingQueryService.getMeetings(userId, Long.parseLong(workspaceId));
List<MeetingResponseDTO.getMeetingResponse> response = meetingQueryService.getMeetings(user, meeting);

return ApiResponse.onSuccess(response);
}
Expand All @@ -79,11 +85,12 @@ public ApiResponse<List<MeetingResponseDTO.getMeetingResponse>> getMeetings(
@PatchMapping("/{meetingId}/title")
public ApiResponse<String> updateMeetingTitle(
@PathVariable("meetingId")String meetingId,
@RequestBody MeetingRequestDTO.updateTitle request) {

Long userId = SecurityUtil.getCurrentUserId();
@RequestBody MeetingRequestDTO.updateTitle request,
@Parameter(hidden = true) @AuthUser User user,
@Parameter(hidden = true) @AuthMeeting Meeting meeting
) {

meetingCommandService.updateMeetingTitle(userId, Long.parseLong(meetingId), request.getTitle());
meetingCommandService.updateMeetingTitle(user, meeting, request);

return ApiResponse.onSuccess("제목수정이 완료되었습니다.");
}
Expand All @@ -93,11 +100,12 @@ public ApiResponse<String> updateMeetingTitle(
)
@DeleteMapping("/{meetingId}")
public ApiResponse<String> deleteMeeting(
@PathVariable("meetingId") String meetingId) {

Long userId = SecurityUtil.getCurrentUserId();
@PathVariable("meetingId") String meetingId,
@Parameter(hidden = true) @AuthUser User user,
@Parameter(hidden = true) @AuthMeeting Meeting meeting
) {

meetingCommandService.deleteMeeting(userId, Long.parseLong(meetingId));
meetingCommandService.deleteMeeting(user, meeting);

return ApiResponse.onSuccess("회의가 삭제되었습니다.");
}
Expand All @@ -107,12 +115,15 @@ public ApiResponse<String> deleteMeeting(
)
@GetMapping("/{meetingId}/ai-proceeding")
public ApiResponse<MeetingResponseDTO.getMeetingProceeding> getMeetingProceeding(
@PathVariable("meetingId")String meetingId) {
@PathVariable("meetingId")String meetingId,
@Parameter(hidden = true) @AuthUser User user,
@Parameter(hidden = true) @AuthMeeting Meeting meeting
) {

Long userId = SecurityUtil.getCurrentUserId();
MeetingResponseDTO.getMeetingProceeding response = meetingQueryService.getMeetingProceeding(userId, Long.parseLong(meetingId));
MeetingResponseDTO.getMeetingProceeding response = meetingQueryService.getMeetingProceeding(user, meeting);

return ApiResponse.onSuccess(response);

}


Expand All @@ -122,13 +133,15 @@ public ApiResponse<MeetingResponseDTO.getMeetingProceeding> getMeetingProceeding
@PatchMapping("/{meetingId}")
public ApiResponse<String> adjustProceeding(
@PathVariable("meetingId") String meetingId,
@RequestBody MeetingRequestDTO.meetingProceedingRequest request) {

Long userId = SecurityUtil.getCurrentUserId();
@RequestBody MeetingRequestDTO.meetingProceedingRequest request,
@Parameter(hidden = true) @AuthUser User user,
@Parameter(hidden = true) @AuthMeeting Meeting meeting
) {

meetingCommandService.adjustProceeding(userId, Long.parseLong(meetingId), request);
meetingCommandService.adjustProceeding(user, meeting, request);

return ApiResponse.onSuccess("회의가 수정되었습니다.");

}

@Operation(summary = "회의 종료", description =
Expand All @@ -137,13 +150,15 @@ public ApiResponse<String> adjustProceeding(
)
@PostMapping("/{meetingId}/end")
public ApiResponse<String> endMeeting(
@PathVariable("meetindId") String meetingId
@PathVariable("meetingId") String meetingId,
@Parameter(hidden = true) @AuthUser User user,
@Parameter(hidden = true) @AuthMeeting Meeting meeting
) {
Long userId = SecurityUtil.getCurrentUserId();

meetingCommandService.endMeeting(userId, Long.parseLong(meetingId));
meetingCommandService.endMeeting(user, meeting);

return ApiResponse.onSuccess("회의가 종료되었습니다");

}

@Operation(summary = "회의록 다운로드", description =
Expand All @@ -152,13 +167,15 @@ public ApiResponse<String> endMeeting(
)
@GetMapping("{meetingId}/ai-proceeding/download")
public ApiResponse<MeetingResponseDTO.proceedingDownLoadLinkResponse> downloadMeeting(
@PathVariable("meetingId") String meetingId
@PathVariable("meetingId") String meetingId,
@Parameter(hidden = true) @AuthUser User user,
@Parameter(hidden = true) @AuthMeeting Meeting meeting
){
Long userId = SecurityUtil.getCurrentUserId();

MeetingResponseDTO.proceedingDownLoadLinkResponse response = meetingQueryService.downloadMeeting(userId, Long.parseLong(meetingId));
MeetingResponseDTO.proceedingDownLoadLinkResponse response = meetingQueryService.downloadMeeting(user, meeting);

return ApiResponse.onSuccess(response);

}


Expand All @@ -168,15 +185,16 @@ public ApiResponse<MeetingResponseDTO.proceedingDownLoadLinkResponse> downloadMe
)
@GetMapping("/{meetingId}/transcript")
public ApiResponse<MeetingResponseDTO.TranscriptResponse> getMeetingTranscript(
@PathVariable("meetingId") String meetingId
@PathVariable("meetingId") String meetingId,
@Parameter(hidden = true) @AuthUser User user,
@Parameter(hidden = true) @AuthMeeting Meeting meeting
) {
Long userId = SecurityUtil.getCurrentUserId();

MeetingResponseDTO.TranscriptResponse transcriptResponse = meetingQueryService.getTranscript(userId, Long.parseLong(meetingId));
MeetingResponseDTO.TranscriptResponse transcriptResponse = meetingQueryService.getTranscript(user, meeting);

return ApiResponse.onSuccess(transcriptResponse);
}

}


@Operation(summary = "회의록 음성파일 조회API", description =
Expand All @@ -185,12 +203,14 @@ public ApiResponse<MeetingResponseDTO.TranscriptResponse> getMeetingTranscript(
)
@GetMapping("{meetingId}/ai-proceeding/voice")
public ApiResponse<MeetingResponseDTO.proceedingVoiceLinkResponse> MeetingvoiceFile(
@PathVariable("meetingId") String meetingId
@PathVariable("meetingId") String meetingId,
@Parameter(hidden = true) @AuthUser User user,
@Parameter(hidden = true) @AuthMeeting Meeting meeting
){
Long userId = SecurityUtil.getCurrentUserId();

MeetingResponseDTO.proceedingVoiceLinkResponse response = meetingQueryService.MeetingVoiceFile(userId, Long.parseLong(meetingId));
MeetingResponseDTO.proceedingVoiceLinkResponse response = meetingQueryService.getMeetingVoiceFile(user, meeting);

return ApiResponse.onSuccess(response);

}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.haru.api.domain.meeting.dto;

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.haru.api.global.common.entity.TitleHolder;
import com.haru.api.global.util.json.ToLongDeserializer;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
Expand All @@ -21,7 +22,7 @@ public static class createMeetingRequest{
private String title;
}
@Getter
public static class updateTitle {
public static class updateTitle implements TitleHolder {
private String title;
}

Expand Down
11 changes: 4 additions & 7 deletions src/main/java/com/haru/api/domain/meeting/entity/Meeting.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public class Meeting extends BaseEntity implements Documentable {
@Column(columnDefinition="TEXT")
private String proceeding;

@ManyToOne(fetch = FetchType.LAZY)
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "user_id")
private User creator;

Expand All @@ -49,7 +49,7 @@ public class Meeting extends BaseEntity implements Documentable {
private String proceedingKeyName;

@Column(columnDefinition = "TEXT")
private String thumbnailKey;
private String thumbnailKeyName;

@OneToMany(mappedBy = "meeting", cascade = CascadeType.ALL, orphanRemoval = true)
private List<MeetingKeyword> meetingKeywords = new ArrayList<>();
Expand All @@ -61,9 +61,6 @@ public class Meeting extends BaseEntity implements Documentable {
@Setter
private String audioFileKey;

@Column(columnDefinition = "TEXT")
private String thumbnailKeyName;

private Meeting(String title, String agendaResult, User user, Workspace workspace) {
this.title = title;
this.agendaResult = agendaResult;
Expand All @@ -80,8 +77,8 @@ public void updateTitle(String title) {
public void updateProceeding(String proceeding) {
this.proceeding = proceeding;
}
public void initProceedingKeyName(String proceedingKeyName) {this.proceedingKeyName = proceedingKeyName;}
public void initThumbnailKey(String thumbnailKey) {this.thumbnailKey = thumbnailKey;}
public void initProceedingKeyName(String proceedingKeyName) { this.proceedingKeyName = proceedingKeyName; }
public void initThumbnailKeyName(String thumbnailKeyName) { this.thumbnailKeyName = thumbnailKeyName; }
public void initStartTime(LocalDateTime startTime) {
this.startTime = startTime;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,10 @@ public interface MeetingRepository extends JpaRepository<Meeting, Long> {
"AND mt.createdAt BETWEEN :startDate AND :endDate")
List<Meeting> findAllDocumentForCalendars(Long workspaceId, LocalDateTime startDate, LocalDateTime endDate);

@Query("SELECT m FROM Meeting m " +
"WHERE m.id = :meetingId AND EXISTS (" +
" SELECT 1 FROM UserWorkspace uw " +
" WHERE uw.user.id = :userId AND uw.workspace.id = m.workspace.id" +
")")
Optional<Meeting> findMeetingByIdIfUserHasAccess(Long userId, Long meetingId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,24 @@

import com.haru.api.domain.meeting.dto.MeetingRequestDTO;
import com.haru.api.domain.meeting.dto.MeetingResponseDTO;
import com.haru.api.domain.meeting.entity.Meeting;
import com.haru.api.domain.user.entity.User;
import com.haru.api.infra.websocket.AudioSessionBuffer;
import org.springframework.web.multipart.MultipartFile;

public interface MeetingCommandService {

MeetingResponseDTO.createMeetingResponse createMeeting(Long userId, MultipartFile agendaFile, MeetingRequestDTO.createMeetingRequest request);
void updateMeetingTitle(Long userId, Long meetingId, String newTitle);
void deleteMeeting(Long userId, Long meetingId);
void adjustProceeding(Long userId, Long meetingId, MeetingRequestDTO.meetingProceedingRequest newProceeding);
void endMeeting(Long userId, Long meetingId);
MeetingResponseDTO.createMeetingResponse createMeeting(User user, MultipartFile agendaFile, MeetingRequestDTO.createMeetingRequest request);

void updateMeetingTitle(User user, Meeting meeting, MeetingRequestDTO.updateTitle request);

void deleteMeeting(User user, Meeting meeting);

void adjustProceeding(User user, Meeting meeting, MeetingRequestDTO.meetingProceedingRequest newProceeding);

void endMeeting(User user, Meeting meeting);

void processAfterMeeting(AudioSessionBuffer audioSessionBuffer);


}
Loading