Skip to content

Commit

Permalink
feat: 도서관 남은 좌석 API 구현 (#387)
Browse files Browse the repository at this point in the history
* [추가] LibraryArea 도메인 엔티티 추가

* [추가] 도서관용 레트로핏 모듈 추가

* [추가] 응답 dto 추가

* [추가] LibraryService 및 힐트 모듈 추가

* [추가] LibraryClient 및 모듈 추가

* [수정] LibraryService 미사용 라이브러리 제거

* [추가] data:library 모듈 추가

* [수정] 도메인 엔티티 이름 수정

* [추가] Library Repository 구현

* [추가] LibraryRepository DI 모듈 구현

* [추가] 레포지토리 테스트 코드 작성

* [추가] 서비스 테스트 코드 구현

* [추가] DTO SerializedName 추가

* [수정] Repository 예외처리 수정

* [추가] dto trailing comma 추가

* [추가] 엔티티 trailing comma 추가

* [수정] 레포지토리 테스트 수정
  • Loading branch information
boiledEgg-s authored Nov 28, 2024
1 parent 7656d6e commit 4a567d0
Show file tree
Hide file tree
Showing 26 changed files with 603 additions and 0 deletions.
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,
)
1 change: 1 addition & 0 deletions data/library/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
26 changes: 26 additions & 0 deletions data/library/build.gradle.kts
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")
compileSdk = 34

testOptions {
unitTests {
isIncludeAndroidResources = true
}
}
}

dependencies {
implementation(projects.core.util)
implementation(projects.data.domain)
implementation(projects.data.remote)

testImplementation(libs.kotlinx.coroutines.test)
}
Empty file added data/library/consumer-rules.pro
Empty file.
21 changes: 21 additions & 0 deletions data/library/proguard-rules.pro
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
4 changes: 4 additions & 0 deletions data/library/src/main/AndroidManifest.xml
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)

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
}
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
}
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,
)
Loading

0 comments on commit 4a567d0

Please sign in to comment.