feat(chat-character): 최근 대화한 캐릭터 조회 구현 및 메인 API 연동
왜: 기존에는 채팅방 미구현으로 최근 대화 리스트를 빈 배열로 응답했음. 채팅방/메시지 기능이 준비됨에 따라 실제 최근 대화 캐릭터를 노출해야 함. 무엇: - repository: findRecentCharactersByMember JPA 쿼리 추가 (채팅방/참여자/메시지 조인, 최신 메시지 기준 정렬) - service: getRecentCharacters(member, limit) 구현 (member null 처리 및 페이징 적용) - controller: /api/chat/character/main에서 인증 사용자 기준 최근 캐릭터 최대 10개 반환
This commit is contained in:
parent
5129400a29
commit
735f1e26df
|
@ -45,8 +45,8 @@ class ChatCharacterController(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 최근 대화한 캐릭터 조회 (현재는 빈 리스트)
|
// 최근 대화한 캐릭터 조회 (회원별 최근 순으로 최대 10개)
|
||||||
val recentCharacters = service.getRecentCharacters()
|
val recentCharacters = service.getRecentCharacters(member, 10)
|
||||||
.map {
|
.map {
|
||||||
RecentCharacter(
|
RecentCharacter(
|
||||||
characterId = it.id!!,
|
characterId = it.id!!,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package kr.co.vividnext.sodalive.chat.character.repository
|
package kr.co.vividnext.sodalive.chat.character.repository
|
||||||
|
|
||||||
import kr.co.vividnext.sodalive.chat.character.ChatCharacter
|
import kr.co.vividnext.sodalive.chat.character.ChatCharacter
|
||||||
|
import kr.co.vividnext.sodalive.member.Member
|
||||||
import org.springframework.data.domain.Page
|
import org.springframework.data.domain.Page
|
||||||
import org.springframework.data.domain.Pageable
|
import org.springframework.data.domain.Pageable
|
||||||
import org.springframework.data.jpa.repository.JpaRepository
|
import org.springframework.data.jpa.repository.JpaRepository
|
||||||
|
@ -40,4 +41,29 @@ interface ChatCharacterRepository : JpaRepository<ChatCharacter, Long> {
|
||||||
@Param("searchTerm") searchTerm: String,
|
@Param("searchTerm") searchTerm: String,
|
||||||
pageable: Pageable
|
pageable: Pageable
|
||||||
): Page<ChatCharacter>
|
): Page<ChatCharacter>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 멤버가 최근에 대화한 캐릭터 목록을 반환 (최신 메시지 시간 기준 내림차순)
|
||||||
|
*/
|
||||||
|
@Query(
|
||||||
|
value = """
|
||||||
|
SELECT c FROM ChatRoom r
|
||||||
|
JOIN r.participants pu
|
||||||
|
JOIN r.participants pc
|
||||||
|
JOIN pc.character c
|
||||||
|
LEFT JOIN r.messages m
|
||||||
|
WHERE pu.member = :member
|
||||||
|
AND pu.participantType = kr.co.vividnext.sodalive.chat.room.ParticipantType.USER
|
||||||
|
AND pu.isActive = true
|
||||||
|
AND pc.participantType = kr.co.vividnext.sodalive.chat.room.ParticipantType.CHARACTER
|
||||||
|
AND pc.isActive = true
|
||||||
|
AND r.isActive = true
|
||||||
|
GROUP BY c.id
|
||||||
|
ORDER BY COALESCE(MAX(m.createdAt), r.createdAt) DESC
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
fun findRecentCharactersByMember(
|
||||||
|
@Param("member") member: Member,
|
||||||
|
pageable: Pageable
|
||||||
|
): List<ChatCharacter>
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterHobbyRepo
|
||||||
import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterRepository
|
import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterRepository
|
||||||
import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterTagRepository
|
import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterTagRepository
|
||||||
import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterValueRepository
|
import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterValueRepository
|
||||||
|
import kr.co.vividnext.sodalive.member.Member
|
||||||
import org.springframework.data.domain.PageRequest
|
import org.springframework.data.domain.PageRequest
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
import org.springframework.transaction.annotation.Transactional
|
import org.springframework.transaction.annotation.Transactional
|
||||||
|
@ -26,12 +27,11 @@ class ChatCharacterService(
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 최근에 대화한 캐릭터 목록 조회
|
* 최근에 대화한 캐릭터 목록 조회
|
||||||
* 현재는 채팅방 구현 전이므로 빈 리스트 반환
|
|
||||||
*/
|
*/
|
||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
fun getRecentCharacters(): List<ChatCharacter> {
|
fun getRecentCharacters(member: Member?, limit: Int = 10): List<ChatCharacter> {
|
||||||
// 채팅방 구현 전이므로 빈 리스트 반환
|
if (member == null) return emptyList()
|
||||||
return emptyList()
|
return chatCharacterRepository.findRecentCharactersByMember(member, PageRequest.of(0, limit))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -94,7 +94,7 @@ class SecurityConfig(
|
||||||
.antMatchers("/ad-tracking/app-launch").permitAll()
|
.antMatchers("/ad-tracking/app-launch").permitAll()
|
||||||
.antMatchers(HttpMethod.GET, "/notice/latest").permitAll()
|
.antMatchers(HttpMethod.GET, "/notice/latest").permitAll()
|
||||||
.antMatchers(HttpMethod.GET, "/api/chat/character/main").permitAll()
|
.antMatchers(HttpMethod.GET, "/api/chat/character/main").permitAll()
|
||||||
.antMatchers(HttpMethod.GET, "/api/chat/list").permitAll()
|
.antMatchers(HttpMethod.GET, "/api/chat/room/list").permitAll()
|
||||||
.anyRequest().authenticated()
|
.anyRequest().authenticated()
|
||||||
.and()
|
.and()
|
||||||
.build()
|
.build()
|
||||||
|
|
Loading…
Reference in New Issue