test #340
| @@ -69,10 +69,10 @@ class ChatCharacterController( | ||||
|         val popularCharacters = service.getPopularCharacters() | ||||
|  | ||||
|         // 최근 등록된 캐릭터 리스트 조회 | ||||
|         val newCharacters = service.getRecentCharacters( | ||||
|         val newCharacters = service.getRecentCharactersPage( | ||||
|             page = 0, | ||||
|             size = 50 | ||||
|         ) | ||||
|         ).content | ||||
|  | ||||
|         // 큐레이션 섹션 (활성화된 큐레이션 + 캐릭터) | ||||
|         val curationSections = curationQueryService.getActiveCurationsWithCharacters() | ||||
| @@ -187,7 +187,7 @@ class ChatCharacterController( | ||||
|     @GetMapping("/recent") | ||||
|     fun getRecentCharacters(@RequestParam("page", required = false) page: Int?) = run { | ||||
|         ApiResponse.ok( | ||||
|             service.getRecentCharacters( | ||||
|             service.getRecentCharactersPage( | ||||
|                 page = page ?: 0, | ||||
|                 size = 20 | ||||
|             ) | ||||
|   | ||||
| @@ -0,0 +1,9 @@ | ||||
| package kr.co.vividnext.sodalive.chat.character.dto | ||||
|  | ||||
| /** | ||||
|  * 최근 등록된 캐릭터 전체보기 페이지 응답 DTO | ||||
|  */ | ||||
| data class RecentCharactersResponse( | ||||
|     val totalCount: Long, | ||||
|     val content: List<Character> | ||||
| ) | ||||
| @@ -12,6 +12,7 @@ import kr.co.vividnext.sodalive.chat.character.ChatCharacterHobby | ||||
| import kr.co.vividnext.sodalive.chat.character.ChatCharacterTag | ||||
| import kr.co.vividnext.sodalive.chat.character.ChatCharacterValue | ||||
| import kr.co.vividnext.sodalive.chat.character.dto.Character | ||||
| import kr.co.vividnext.sodalive.chat.character.dto.RecentCharactersResponse | ||||
| import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterGoalRepository | ||||
| import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterHobbyRepository | ||||
| import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterRepository | ||||
| @@ -68,12 +69,12 @@ class ChatCharacterService( | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 최근 등록된 캐릭터 전체보기 (페이징) | ||||
|      * 최근 등록된 캐릭터 전체보기 (페이징) - 전체 개수 포함 | ||||
|      * - 기준: 현재 시각 기준 2주 이내 생성된 활성 캐릭터 | ||||
|      * - 2주 이내 캐릭터가 0개라면: 최근 등록한 캐릭터 20개 반환(페이지 무시) | ||||
|      * - 2주 이내 캐릭터가 0개라면: totalCount=20, 첫 페이지는 최근 등록 활성 캐릭터 20개, 그 외 페이지는 빈 리스트 | ||||
|      */ | ||||
|     @Transactional(readOnly = true) | ||||
|     fun getRecentCharacters(page: Int = 0, size: Int = 20): List<Character> { | ||||
|     fun getRecentCharactersPage(page: Int = 0, size: Int = 20): RecentCharactersResponse { | ||||
|         val safePage = if (page < 0) 0 else page | ||||
|         val safeSize = when { | ||||
|             size <= 0 -> 20 | ||||
| @@ -85,13 +86,15 @@ class ChatCharacterService( | ||||
|         val totalRecent = chatCharacterRepository.countByIsActiveTrueAndCreatedAtGreaterThanEqual(since) | ||||
|         if (totalRecent == 0L) { | ||||
|             if (safePage > 0) { | ||||
|                 return emptyList() | ||||
|                 return RecentCharactersResponse( | ||||
|                     totalCount = 20, | ||||
|                     content = emptyList() | ||||
|                 ) | ||||
|             } | ||||
|  | ||||
|             val fallback = chatCharacterRepository.findByIsActiveTrue( | ||||
|                 PageRequest.of(0, 20, Sort.by("createdAt").descending()) | ||||
|             ) | ||||
|             return fallback.content.map { | ||||
|             val content = fallback.content.map { | ||||
|                 Character( | ||||
|                     characterId = it.id!!, | ||||
|                     name = it.name, | ||||
| @@ -99,13 +102,17 @@ class ChatCharacterService( | ||||
|                     imageUrl = "$imageHost/${it.imagePath ?: "profile/default-profile.png"}" | ||||
|                 ) | ||||
|             } | ||||
|             return RecentCharactersResponse( | ||||
|                 totalCount = 20, | ||||
|                 content = content | ||||
|             ) | ||||
|         } | ||||
|  | ||||
|         val pageResult = chatCharacterRepository.findRecentSince( | ||||
|             since, | ||||
|             PageRequest.of(safePage, safeSize) | ||||
|         ) | ||||
|         return pageResult.content.map { | ||||
|         val content = pageResult.content.map { | ||||
|             Character( | ||||
|                 characterId = it.id!!, | ||||
|                 name = it.name, | ||||
| @@ -113,6 +120,11 @@ class ChatCharacterService( | ||||
|                 imageUrl = "$imageHost/${it.imagePath ?: "profile/default-profile.png"}" | ||||
|             ) | ||||
|         } | ||||
|  | ||||
|         return RecentCharactersResponse( | ||||
|             totalCount = totalRecent, | ||||
|             content = content | ||||
|         ) | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|   | ||||
		Reference in New Issue
	
	Block a user