Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions data/domain/src/main/java/com/ku_stacks/ku_ring/domain/Place.kt
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,18 @@ data class PlaceOperationHours(
)

data class PlaceFacility(
val id: Long? = null,
val name: String,
val category: String,
val location: String? = null,
val operationHours: PlaceOperationHours? = null,
val imageUrl: String? = null,
val quantity: Int? = null,
val externalUrl: String? = null,
)

data class PlaceCategory(
val name: String,
val korName: String,
val displayOrder: Int,
)
1 change: 1 addition & 0 deletions data/place/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ android {
dependencies {
implementation(projects.core.util)
implementation(projects.data.domain)
implementation(projects.data.remote)
implementation(projects.domain.place)

testImplementation(libs.kotlinx.coroutines.test)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.ku_stacks.ku_ring.place.mapper

import com.ku_stacks.ku_ring.domain.Place
import com.ku_stacks.ku_ring.domain.PlaceCategory
import com.ku_stacks.ku_ring.domain.PlaceFacility
import com.ku_stacks.ku_ring.domain.PlaceOperationHours
import com.ku_stacks.ku_ring.remote.place.response.PlaceBuildingDetailResponse
import com.ku_stacks.ku_ring.remote.place.response.PlaceBuildingResponse
import com.ku_stacks.ku_ring.remote.place.response.PlaceCampusPlaceResponse
import com.ku_stacks.ku_ring.remote.place.response.PlaceCategoryResponse
import com.ku_stacks.ku_ring.remote.place.response.PlaceOperatingHoursResponse

internal fun PlaceBuildingResponse.toDomain() = Place(
id = id.toString(),
name = name,
category = "",
address = address,
latitude = latitude,
longitude = longitude,
priority = Place.Priority.MIDDLE,
)

internal fun PlaceBuildingDetailResponse.toDomain() = Place(
id = id.toString(),
name = name,
category = "",
address = address,
latitude = latitude,
longitude = longitude,
priority = Place.Priority.MIDDLE,
imageUrl = imageUrl,
operationHours = currentOperatingHours?.toDomain(),
facilities = campusPlaces.map { it.toDomain() },
)

internal fun PlaceCampusPlaceResponse.toDomain() = PlaceFacility(
name = name,
category = categoryKorName,
location = listOfNotNull(floor, locationDetail).joinToString(" ").ifBlank { null },
operationHours = currentOperatingHours?.toDomain(),
id = id,
imageUrl = imageUrl,
quantity = quantity,
externalUrl = externalUrl,
)

internal fun PlaceOperatingHoursResponse.toDomain() = PlaceOperationHours(
current = toDisplayText(),
)

private fun PlaceOperatingHoursResponse.toDisplayText(): String = when (status) {
"OPEN_24_HOURS" -> "24시간 운영"
"CLOSED" -> "휴무"
else -> if (opensAt != null && closesAt != null) "$opensAt - $closesAt" else "-"
}

internal fun PlaceCategoryResponse.toDomain() = PlaceCategory(
name = name,
korName = korName,
displayOrder = displayOrder,
)
Original file line number Diff line number Diff line change
@@ -1,15 +1,63 @@
package com.ku_stacks.ku_ring.place.repository

import com.ku_stacks.ku_ring.domain.Place
import com.ku_stacks.ku_ring.domain.PlaceCategory
import com.ku_stacks.ku_ring.domain.PlaceFacility
import com.ku_stacks.ku_ring.domain.place.repository.PlaceRepository
import com.ku_stacks.ku_ring.place.datasource.PlaceDataSource
import com.ku_stacks.ku_ring.place.mapper.toDomain
import com.ku_stacks.ku_ring.remote.place.PlaceClient
import com.ku_stacks.ku_ring.util.suspendRunCatching
import javax.inject.Inject

class PlaceRepositoryImpl @Inject constructor(
private val placeDataSource: PlaceDataSource,
): PlaceRepository {
private val placeClient: PlaceClient,
) : PlaceRepository {
override suspend fun getPlaces(): List<Place> {
return placeDataSource.getJsonPlaces().map { it.toDomain() }
}

override suspend fun getPlaceBuildingDetail(buildingId: Long): Result<Place> =
suspendRunCatching {
val response = placeClient.fetchBuildingDetail(buildingId)
when {
response.isSuccessAndDataExists -> response.data!!.toDomain()
else -> throw IllegalStateException(response.resultMsg)
}
}

override suspend fun searchPlaceBuildings(keyword: String): Result<List<Place>> =
suspendRunCatching {
val response = placeClient.searchBuildings(keyword)
when {
response.isSuccessAndDataExists -> response.data!!.buildings.map { it.toDomain() }
else -> throw IllegalStateException(response.resultMsg)
}
}

override suspend fun getPlaceBuildings(): Result<List<Place>> = suspendRunCatching {
val response = placeClient.fetchBuildings()
when {
response.isSuccessAndDataExists -> response.data!!.buildings.map { it.toDomain() }
else -> throw IllegalStateException(response.resultMsg)
}
}

override suspend fun getPlaceCampusPlaces(category: String): Result<List<PlaceFacility>> =
suspendRunCatching {
val response = placeClient.fetchCampusPlaces(category)
when {
response.isSuccessAndDataExists -> response.data!!.campusPlaces.map { it.toDomain() }
else -> throw IllegalStateException(response.resultMsg)
}
}

override suspend fun getPlaceCategories(): Result<List<PlaceCategory>> = suspendRunCatching {
val response = placeClient.fetchCategories()
when {
response.isSuccessAndDataExists -> response.data!!.categories.map { it.toDomain() }
else -> throw IllegalStateException(response.resultMsg)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import com.ku_stacks.ku_ring.domain.Place
import com.ku_stacks.ku_ring.domain.place.repository.PlaceRepository
import com.ku_stacks.ku_ring.place.datasource.PlaceDataSource
import com.ku_stacks.ku_ring.place.repository.PlaceRepositoryImpl
import com.ku_stacks.ku_ring.remote.place.PlaceClient
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestCoroutineScheduler
import kotlinx.coroutines.test.TestDispatcher
Expand All @@ -14,13 +15,15 @@ import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito
import org.robolectric.RobolectricTestRunner

@RunWith(RobolectricTestRunner::class)
class PlaceRepositoryTest {
private lateinit var dataSource: PlaceDataSource
private lateinit var repository: PlaceRepository
private lateinit var testDispatcher: TestDispatcher
private val placeClient = Mockito.mock(PlaceClient::class.java)
Comment thread
boiledeggg marked this conversation as resolved.

@Before
fun setUp() {
Expand All @@ -29,7 +32,7 @@ class PlaceRepositoryTest {
testDispatcher = StandardTestDispatcher(testScheduler)

dataSource = PlaceDataSource(context, testDispatcher)
repository = PlaceRepositoryImpl(dataSource)
repository = PlaceRepositoryImpl(dataSource, placeClient)
}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.ku_stacks.ku_ring.remote.place

import com.ku_stacks.ku_ring.remote.place.response.PlaceBuildingDetailResponse
import com.ku_stacks.ku_ring.remote.place.response.PlaceBuildingListResponse
import com.ku_stacks.ku_ring.remote.place.response.PlaceCampusPlaceListResponse
import com.ku_stacks.ku_ring.remote.place.response.PlaceCategoryListResponse
import com.ku_stacks.ku_ring.remote.util.DefaultResponse
import javax.inject.Inject

class PlaceClient @Inject constructor(
private val placeService: PlaceService,
) {
suspend fun fetchBuildingDetail(buildingId: Long): DefaultResponse<PlaceBuildingDetailResponse> =
placeService.fetchBuildingDetail(buildingId)

suspend fun searchBuildings(keyword: String): DefaultResponse<PlaceBuildingListResponse> =
placeService.searchBuildings(keyword)

suspend fun fetchBuildings(): DefaultResponse<PlaceBuildingListResponse> =
placeService.fetchBuildings()

suspend fun fetchCampusPlaces(category: String): DefaultResponse<PlaceCampusPlaceListResponse> =
placeService.fetchCampusPlaces(category)

suspend fun fetchCategories(): DefaultResponse<PlaceCategoryListResponse> =
placeService.fetchCategories()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.ku_stacks.ku_ring.remote.place

import com.ku_stacks.ku_ring.remote.place.response.PlaceBuildingDetailResponse
import com.ku_stacks.ku_ring.remote.place.response.PlaceBuildingListResponse
import com.ku_stacks.ku_ring.remote.place.response.PlaceCampusPlaceListResponse
import com.ku_stacks.ku_ring.remote.place.response.PlaceCategoryListResponse
import com.ku_stacks.ku_ring.remote.util.DefaultResponse
import retrofit2.http.GET
import retrofit2.http.Path
import retrofit2.http.Query

interface PlaceService {
@GET("v2/maps/buildings/{buildingId}")
suspend fun fetchBuildingDetail(
@Path("buildingId") buildingId: Long,
): DefaultResponse<PlaceBuildingDetailResponse>

@GET("v2/maps/buildings/search")
suspend fun searchBuildings(
@Query("keyword") keyword: String,
): DefaultResponse<PlaceBuildingListResponse>

@GET("v2/maps/buildings")
suspend fun fetchBuildings(): DefaultResponse<PlaceBuildingListResponse>

@GET("v2/maps/campus-places")
suspend fun fetchCampusPlaces(
@Query("category") category: String,
): DefaultResponse<PlaceCampusPlaceListResponse>

@GET("v2/maps/categories")
suspend fun fetchCategories(): DefaultResponse<PlaceCategoryListResponse>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.ku_stacks.ku_ring.remote.place.di

import com.ku_stacks.ku_ring.remote.place.PlaceClient
import com.ku_stacks.ku_ring.remote.place.PlaceService
import com.ku_stacks.ku_ring.remote.util.Default
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import retrofit2.Retrofit
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
object PlaceModule {
@Provides
@Singleton
fun providePlaceService(@Default retrofit: Retrofit): PlaceService =
retrofit.create(PlaceService::class.java)

@Provides
@Singleton
fun providePlaceClient(placeService: PlaceService): PlaceClient =
PlaceClient(placeService)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.ku_stacks.ku_ring.remote.place.response

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class PlaceBuildingDetailResponse(
@SerialName("id") val id: Long,
@SerialName("name") val name: String,
@SerialName("address") val address: String,
@SerialName("latitude") val latitude: Double,
@SerialName("longitude") val longitude: Double,
@SerialName("imageUrl") val imageUrl: String? = null,
@SerialName("currentOperatingHours") val currentOperatingHours: PlaceOperatingHoursResponse? = null,
@SerialName("campusPlaces") val campusPlaces: List<PlaceCampusPlaceResponse> = emptyList(),
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.ku_stacks.ku_ring.remote.place.response

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class PlaceBuildingListResponse(
@SerialName("buildings") val buildings: List<PlaceBuildingResponse>,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.ku_stacks.ku_ring.remote.place.response

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class PlaceBuildingResponse(
@SerialName("id") val id: Long,
@SerialName("name") val name: String,
@SerialName("address") val address: String,
@SerialName("latitude") val latitude: Double,
@SerialName("longitude") val longitude: Double,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.ku_stacks.ku_ring.remote.place.response

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class PlaceCampusPlaceListResponse(
@SerialName("campusPlaces") val campusPlaces: List<PlaceCampusPlaceResponse>,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.ku_stacks.ku_ring.remote.place.response

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class PlaceCampusPlaceResponse(
@SerialName("id") val id: Long,
@SerialName("name") val name: String,
@SerialName("category") val category: String,
@SerialName("categoryKorName") val categoryKorName: String,
@SerialName("imageUrl") val imageUrl: String? = null,
@SerialName("locationType") val locationType: String,
@SerialName("floor") val floor: String? = null,
@SerialName("locationDetail") val locationDetail: String? = null,
@SerialName("quantity") val quantity: Int? = null,
@SerialName("currentOperatingHours") val currentOperatingHours: PlaceOperatingHoursResponse? = null,
@SerialName("externalUrl") val externalUrl: String? = null,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.ku_stacks.ku_ring.remote.place.response

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class PlaceCategoryListResponse(
@SerialName("categories") val categories: List<PlaceCategoryResponse>,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.ku_stacks.ku_ring.remote.place.response

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class PlaceCategoryResponse(
@SerialName("name") val name: String,
@SerialName("korName") val korName: String,
@SerialName("displayOrder") val displayOrder: Int,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.ku_stacks.ku_ring.remote.place.response

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class PlaceOperatingHoursResponse(
@SerialName("period") val period: String,
@SerialName("dayGroup") val dayGroup: String,
@SerialName("status") val status: String,
@SerialName("opensAt") val opensAt: String? = null,
@SerialName("closesAt") val closesAt: String? = null,
)
Loading