-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: 도서관 남은 좌석 API 구현 #387
base: develop
Are you sure you want to change the base?
Changes from all commits
875f775
38e4866
3eb841d
c0a455f
ab4ada9
6e5ab88
421b6a3
435b015
6b2dad6
f0f9525
7a0e0b3
8257079
bd1beba
ff2768c
b6eecb8
cdbb761
4db7c8b
80eec3b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package com.ku_stacks.ku_ring.domain | ||
|
||
data class LibraryRoom( | ||
val name: String, | ||
val totalSeats: Int, | ||
val occupiedSeats: Int, | ||
val availableSeats: Int, | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/build |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import com.ku_stacks.ku_ring.buildlogic.dsl.setNameSpace | ||
|
||
plugins { | ||
kuring("feature") | ||
kuringPrimitive("retrofit") | ||
kuringPrimitive("test") | ||
} | ||
|
||
android { | ||
setNameSpace("library") | ||
l2hyunwoo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
compileSdk = 34 | ||
|
||
testOptions { | ||
unitTests { | ||
isIncludeAndroidResources = true | ||
} | ||
} | ||
} | ||
|
||
dependencies { | ||
implementation(projects.core.util) | ||
implementation(projects.data.domain) | ||
implementation(projects.data.remote) | ||
|
||
testImplementation(libs.kotlinx.coroutines.test) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# Add project specific ProGuard rules here. | ||
# You can control the set of applied configuration files using the | ||
# proguardFiles setting in build.gradle. | ||
# | ||
# For more details, see | ||
# http://developer.android.com/guide/developing/tools/proguard.html | ||
|
||
# If your project uses WebView with JS, uncomment the following | ||
# and specify the fully qualified class name to the JavaScript interface | ||
# class: | ||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview { | ||
# public *; | ||
#} | ||
|
||
# Uncomment this to preserve the line number information for | ||
# debugging stack traces. | ||
#-keepattributes SourceFile,LineNumberTable | ||
|
||
# If you keep the line number information, uncomment this to | ||
# hide the original source file name. | ||
#-renamesourcefileattribute SourceFile |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> | ||
|
||
</manifest> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package com.ku_stacks.ku_ring.library.di | ||
|
||
import com.ku_stacks.ku_ring.library.repository.LibraryRepository | ||
import com.ku_stacks.ku_ring.library.repository.LibraryRepositoryImpl | ||
import dagger.Binds | ||
import dagger.Module | ||
import dagger.hilt.InstallIn | ||
import dagger.hilt.components.SingletonComponent | ||
import javax.inject.Singleton | ||
|
||
@InstallIn(SingletonComponent::class) | ||
@Module | ||
abstract class RepositoryModule { | ||
@Binds | ||
@Singleton | ||
abstract fun provideLibraryRepository(repositoryImpl: LibraryRepositoryImpl): LibraryRepository | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package com.ku_stacks.ku_ring.library.mapper | ||
|
||
import com.ku_stacks.ku_ring.domain.LibraryRoom | ||
import com.ku_stacks.ku_ring.remote.library.response.LibrarySeatResponse | ||
|
||
fun LibrarySeatResponse.toLibraryAreaList(): List<LibraryRoom> { | ||
return data.libraryRooms.map { | ||
LibraryRoom( | ||
name = it.roomName, | ||
totalSeats = it.seats.total, | ||
availableSeats = it.seats.available, | ||
occupiedSeats = it.seats.occupied | ||
) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.ku_stacks.ku_ring.library.repository | ||
|
||
import com.ku_stacks.ku_ring.domain.LibraryRoom | ||
|
||
interface LibraryRepository { | ||
suspend fun getRemainingSeats(): Result<List<LibraryRoom>> | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package com.ku_stacks.ku_ring.library.repository | ||
|
||
import com.ku_stacks.ku_ring.domain.LibraryRoom | ||
import com.ku_stacks.ku_ring.library.mapper.toLibraryAreaList | ||
import com.ku_stacks.ku_ring.remote.library.LibraryClient | ||
import javax.inject.Inject | ||
|
||
class LibraryRepositoryImpl @Inject constructor( | ||
private val libraryClient: LibraryClient | ||
) : LibraryRepository { | ||
override suspend fun getRemainingSeats(): Result<List<LibraryRoom>> = runCatching { | ||
libraryClient.fetchRoomSeatStatus().toLibraryAreaList() | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package com.ku_stacks.ku_ring.library | ||
|
||
import com.ku_stacks.ku_ring.library.repository.LibraryRepository | ||
import com.ku_stacks.ku_ring.library.repository.LibraryRepositoryImpl | ||
import com.ku_stacks.ku_ring.remote.library.LibraryClient | ||
import junit.framework.TestCase.assertEquals | ||
import kotlinx.coroutines.test.runTest | ||
import org.junit.Before | ||
import org.junit.Test | ||
import org.mockito.Mockito | ||
import org.mockito.kotlin.times | ||
|
||
class LibraryRepositoryTest { | ||
private lateinit var libraryRepository: LibraryRepository | ||
private val client: LibraryClient = Mockito.mock(LibraryClient::class.java) | ||
|
||
@Before | ||
fun setup() { | ||
libraryRepository = LibraryRepositoryImpl(client) | ||
} | ||
|
||
@Test | ||
fun `get Library Seat Status From Remote Test`() = runTest { | ||
val mockLibraryStatus = LibraryTestUtil.mockLibrarySeatResponse() | ||
|
||
Mockito.`when`(client.fetchRoomSeatStatus()).thenReturn(mockLibraryStatus) | ||
Comment on lines
+15
to
+26
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 굳이 Mock을 사용할 필요가 있을까요? 인터페이스 다형성을 활용해보면 좋을 것 같아요 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 제가 테스트 코드 작성이 아직 미흡해서 기존 테스트 코드를 좀 차용했습니다.. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 넵 좋습니다. |
||
|
||
libraryRepository.getRemainingSeats().onSuccess { mockResult -> | ||
val expectedResult = LibraryTestUtil.mockLibraryRoomList() | ||
|
||
Mockito.verify( | ||
client, | ||
times(1) | ||
).fetchRoomSeatStatus() | ||
|
||
assertEquals(mockResult, expectedResult) | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package com.ku_stacks.ku_ring.library | ||
|
||
import com.ku_stacks.ku_ring.domain.LibraryRoom | ||
import com.ku_stacks.ku_ring.remote.library.response.LibraryRoomBranchResponse | ||
import com.ku_stacks.ku_ring.remote.library.response.LibraryRoomListResponse | ||
import com.ku_stacks.ku_ring.remote.library.response.LibraryRoomResponse | ||
import com.ku_stacks.ku_ring.remote.library.response.LibraryRoomSeatResponse | ||
import com.ku_stacks.ku_ring.remote.library.response.LibraryRoomTypeResponse | ||
import com.ku_stacks.ku_ring.remote.library.response.LibrarySeatResponse | ||
|
||
object LibraryTestUtil { | ||
fun mockLibrarySeatResponse() = LibrarySeatResponse( | ||
success = true, | ||
code = "success.retrieved", | ||
message = "조회되었습니다.", | ||
data = LibraryRoomListResponse( | ||
resultCount = 1, | ||
libraryRooms = listOf( | ||
LibraryRoomResponse( | ||
id = 102, | ||
roomName = "제 1 열람실 (A구역)", | ||
roomType = LibraryRoomTypeResponse( | ||
id = 1, | ||
roomName = "열람실", | ||
sortOrder = 1 | ||
), | ||
awaitable = true, | ||
isChargeable = true, | ||
branch = LibraryRoomBranchResponse( | ||
id = 1, | ||
roomBranchName = "상허기념도서관", | ||
alias = "상허", | ||
libraryCode = "211004", | ||
sortOrder = 1 | ||
), | ||
unableMessage = null, | ||
seats = LibraryRoomSeatResponse( | ||
total = 219, | ||
occupied = 82, | ||
waiting = 0, | ||
available = 137 | ||
) | ||
) | ||
) | ||
) | ||
) | ||
|
||
|
||
fun mockLibraryRoomList() = listOf( | ||
LibraryRoom( | ||
name = "제 1 열람실 (A구역)", | ||
totalSeats = 219, | ||
occupiedSeats = 82, | ||
availableSeats = 137 | ||
) | ||
) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package com.ku_stacks.ku_ring.remote.library | ||
|
||
import com.ku_stacks.ku_ring.remote.library.request.LibrarySeatRequest | ||
import com.ku_stacks.ku_ring.remote.library.response.LibrarySeatResponse | ||
import javax.inject.Inject | ||
|
||
class LibraryClient @Inject constructor(private val libraryService: LibraryService) { | ||
|
||
suspend fun fetchRoomSeatStatus(): LibrarySeatResponse = libraryService.fetchLibrarySeatStatus( | ||
methodCode = LibrarySeatRequest.METHOD_CODE, | ||
roomTypeId = LibrarySeatRequest.ROOM_TYPE_ID, | ||
branchTypeId = LibrarySeatRequest.BRANCH_TYPE_ID, | ||
) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package com.ku_stacks.ku_ring.remote.library | ||
|
||
import com.ku_stacks.ku_ring.remote.library.response.LibrarySeatResponse | ||
import retrofit2.http.GET | ||
import retrofit2.http.Query | ||
|
||
interface LibraryService { | ||
@GET("1/seat-rooms") | ||
suspend fun fetchLibrarySeatStatus( | ||
@Query("smufMethodCode") methodCode: String, | ||
@Query("roomTypeId") roomTypeId: Int, | ||
@Query("branchTypeId") branchTypeId: Int, | ||
): LibrarySeatResponse | ||
mwy3055 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package com.ku_stacks.ku_ring.remote.library.di | ||
|
||
import com.ku_stacks.ku_ring.remote.library.LibraryClient | ||
import com.ku_stacks.ku_ring.remote.library.LibraryService | ||
import dagger.Module | ||
import dagger.Provides | ||
import dagger.hilt.InstallIn | ||
import dagger.hilt.components.SingletonComponent | ||
import retrofit2.Retrofit | ||
import javax.inject.Named | ||
import javax.inject.Singleton | ||
|
||
@Module | ||
@InstallIn(SingletonComponent::class) | ||
object LibraryModule { | ||
@Provides | ||
@Singleton | ||
fun provideLibraryService(@Named("Library") retrofit: Retrofit): LibraryService | ||
= retrofit.create(LibraryService::class.java) | ||
|
||
@Provides | ||
@Singleton | ||
fun provideLibraryClient(libraryService: LibraryService): LibraryClient | ||
= LibraryClient(libraryService) | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.ku_stacks.ku_ring.remote.library.request | ||
|
||
object LibrarySeatRequest { | ||
const val METHOD_CODE: String = "PC" | ||
const val ROOM_TYPE_ID = 4 | ||
const val BRANCH_TYPE_ID: Int = 1 | ||
} | ||
mwy3055 marked this conversation as resolved.
Show resolved
Hide resolved
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package com.ku_stacks.ku_ring.remote.library.response | ||
|
||
import com.google.gson.annotations.SerializedName | ||
|
||
data class LibraryRoomBranchResponse ( | ||
@SerializedName("id") | ||
val id: Int, | ||
@SerializedName("name") | ||
val roomBranchName: String, | ||
@SerializedName("alias") | ||
val alias: String, | ||
@SerializedName("libraryCode") | ||
val libraryCode: String, | ||
@SerializedName("sortOrder") | ||
val sortOrder: Int, | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package com.ku_stacks.ku_ring.remote.library.response | ||
|
||
import com.google.gson.annotations.SerializedName | ||
|
||
data class LibraryRoomListResponse( | ||
@SerializedName(value = "totalCount") | ||
val resultCount: Int, | ||
@SerializedName(value = "list") | ||
val libraryRooms: List<LibraryRoomResponse>, | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package com.ku_stacks.ku_ring.remote.library.response | ||
|
||
import com.google.gson.annotations.SerializedName | ||
|
||
data class LibraryRoomResponse( | ||
@SerializedName("id") | ||
val id: Int, | ||
@SerializedName("name") | ||
val roomName: String, | ||
@SerializedName("roomType") | ||
val roomType: LibraryRoomTypeResponse, | ||
@SerializedName("awaitable") | ||
val awaitable: Boolean, | ||
@SerializedName("isChargeable") | ||
val isChargeable: Boolean, | ||
@SerializedName("branch") | ||
val branch: LibraryRoomBranchResponse, | ||
@SerializedName("unableMessage") | ||
val unableMessage: String?, | ||
@SerializedName("seats") | ||
val seats: LibraryRoomSeatResponse, | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package com.ku_stacks.ku_ring.remote.library.response | ||
|
||
import com.google.gson.annotations.SerializedName | ||
|
||
data class LibraryRoomSeatResponse( | ||
@SerializedName("total") | ||
val total: Int, | ||
@SerializedName("occupied") | ||
val occupied: Int, | ||
@SerializedName("waiting") | ||
val waiting: Int, | ||
@SerializedName("available") | ||
val available: Int, | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package com.ku_stacks.ku_ring.remote.library.response | ||
|
||
import com.google.gson.annotations.SerializedName | ||
|
||
data class LibraryRoomTypeResponse( | ||
@SerializedName("id") | ||
val id: Int, | ||
@SerializedName("name") | ||
val roomName: String, | ||
@SerializedName("sortOrder") | ||
val sortOrder: Int, | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package com.ku_stacks.ku_ring.remote.library.response | ||
|
||
import com.google.gson.annotations.SerializedName | ||
|
||
data class LibrarySeatResponse( | ||
@SerializedName("success") | ||
val success: Boolean, | ||
@SerializedName("code") | ||
val code: String, | ||
@SerializedName("message") | ||
val message: String, | ||
@SerializedName("data") | ||
val data: LibraryRoomListResponse, | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이거 이해하기 어렵지 않았나요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
사실 아직 제대로 이해하진 못했어요,,
저 플러그인들에 필요한 라이브러리들이 있겠거니 해서 일단 넣었습니다😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ㅋㅋㅋㅋㅋ이것도 강의 해줄게요