Skip to content
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] [#58] 관심 부스 로컬 데이터베이스 환경 구축 및 CRUD 연동 #68

Merged
merged 13 commits into from
Apr 13, 2024
Merged
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
4 changes: 2 additions & 2 deletions build-logic/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ gradlePlugin {
"android.feature" to "AndroidFeatureConventionPlugin",
"android.hilt" to "AndroidHiltConventionPlugin",
"android.retrofit" to "AndroidRetrofitConventionPlugin",
"jvm.kotlin" to "JvmKotlinConventionPlugin",
"test.kotest" to "TestKotestConventionPlugin",
"android.room" to "AndroidRoomConventionPlugin",
)

plugins {
Expand Down Expand Up @@ -45,6 +44,7 @@ kotlin {
dependencies {
compileOnly(libs.gradle.android)
compileOnly(libs.gradle.kotlin)
compileOnly(libs.gradle.androidx.room)

compileOnly(files(libs.javaClass.superclass.protectionDomain.codeSource.location))
}
Expand Down
28 changes: 28 additions & 0 deletions build-logic/src/main/kotlin/AndroidRoomConventionPlugin.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import androidx.room.gradle.RoomExtension
import com.unifest.android.Plugins
import com.unifest.android.applyPlugins
import com.unifest.android.implementation
import com.unifest.android.ksp
import com.unifest.android.libs
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.dependencies

class AndroidRoomConventionPlugin : BuildLogicConventionPlugin(
{
applyPlugins(Plugins.AndroidxRoom, Plugins.KotlinxSerialization, Plugins.Ksp)

extensions.configure<RoomExtension> {
// The schemas directory contains a schema file for each version of the Room database.
// This is required to enable Room auto migrations.
// See https://developer.android.com/reference/kotlin/androidx/room/AutoMigration.
schemaDirectory("$projectDir/schemas")
}

dependencies {
implementation(libs.androidx.room.runtime)
implementation(libs.androidx.room.ktx)
ksp(libs.androidx.room.compiler)
implementation(libs.kotlinx.serialization.json)
}
},
)
5 changes: 2 additions & 3 deletions build-logic/src/main/kotlin/com/unifest/android/Plugins.kt
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
package com.unifest.android

internal object Plugins {
const val JavaLibrary = "java-library"

const val KotlinJvm = "org.jetbrains.kotlin.jvm"
const val KotlinAndroid = "org.jetbrains.kotlin.android"

const val KotlinxSerialization = "org.jetbrains.kotlin.plugin.serialization"

const val AndroidApplication = "com.android.application"
const val AndroidLibrary = "com.android.library"

const val AndroidxRoom = "androidx.room"

const val hilt = "dagger.hilt.android.plugin"
const val Ksp = "com.google.devtools.ksp"

Expand Down
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ plugins {
alias(libs.plugins.kotlin.serialization) apply false
alias(libs.plugins.android.application) apply false
alias(libs.plugins.android.library) apply false
alias(libs.plugins.androidx.room) apply false
alias(libs.plugins.hilt) apply false
alias(libs.plugins.google.service) apply false
alias(libs.plugins.firebase.crashlytics) apply false
Expand Down
1 change: 1 addition & 0 deletions core/data/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ dependencies {
implementations(
projects.core.network,
projects.core.datastore,
projects.core.database,

libs.timber,
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.unifest.android.core.data.di

import com.unifest.android.core.data.repository.DefaultLikedBoothRepository
import com.unifest.android.core.data.repository.LikedBoothRepository
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
abstract class RepositoryModule {

@Binds
@Singleton
abstract fun bindLikedBoothRepository(likedBoothRepository: DefaultLikedBoothRepository): LikedBoothRepository
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.unifest.android.core.data.mapper

import com.unifest.android.core.data.response.BoothDetailResponse
import com.unifest.android.core.data.response.MenuResponse
import com.unifest.android.core.database.entity.LikedBoothEntity
import com.unifest.android.core.database.entity.MenuEntity

internal fun LikedBoothEntity.toResponse(): BoothDetailResponse {
return BoothDetailResponse(
id = id,
name = name,
category = category,
description = description,
warning = warning,
location = location,
latitude = latitude,
longitude = longitude,
menus = menus.map { it.toResponse() },
)
}

internal fun MenuEntity.toResponse(): MenuResponse {
return MenuResponse(
id = id,
name = name,
price = price,
imgUrl = imgUrl,
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.unifest.android.core.data.mapper

import com.unifest.android.core.data.response.BoothDetailResponse
import com.unifest.android.core.data.response.MenuResponse
import com.unifest.android.core.database.entity.LikedBoothEntity
import com.unifest.android.core.database.entity.MenuEntity

internal fun BoothDetailResponse.toDBEntity(): LikedBoothEntity {
return LikedBoothEntity(
id = id,
name = name,
category = category,
description = description,
warning = warning,
location = location,
latitude = latitude,
longitude = longitude,
menus = menus.map { it.toDBEntity() },
isLiked = false,
)
}

internal fun MenuResponse.toDBEntity(): MenuEntity {
return MenuEntity(
id = id,
name = name,
price = price,
imgUrl = imgUrl,
)
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.unifest.android.core.data.repository

import com.unifest.android.core.data.mapper.toDBEntity
import com.unifest.android.core.data.mapper.toResponse
import com.unifest.android.core.data.response.BoothDetailResponse
import com.unifest.android.core.database.LikedBoothDao
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import javax.inject.Inject

class DefaultLikedBoothRepository @Inject constructor(
private val likedBoothDao: LikedBoothDao,
) : LikedBoothRepository {
override fun getLikedBoothList(): Flow<List<BoothDetailResponse>> {
return likedBoothDao.getLikedBoothList().map { likedBooths ->
likedBooths.map { likedBooth ->
likedBooth.toResponse()
}
}
}

override suspend fun insertLikedBooth(booth: BoothDetailResponse) {
likedBoothDao.insertLikedBooth(booth.toDBEntity())
}

override suspend fun deleteLikedBooth(booth: BoothDetailResponse) {
likedBoothDao.deleteLikedBooth(booth.toDBEntity())
}

override suspend fun updateLikedBooth(booth: BoothDetailResponse) {
likedBoothDao.updateLikedBooth(booth.id, booth.isLiked)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.unifest.android.core.data.repository

import com.unifest.android.core.data.response.BoothDetailResponse
import kotlinx.coroutines.flow.Flow

interface LikedBoothRepository {
fun getLikedBoothList(): Flow<List<BoothDetailResponse>>
suspend fun insertLikedBooth(booth: BoothDetailResponse)
suspend fun deleteLikedBooth(booth: BoothDetailResponse)
suspend fun updateLikedBooth(booth: BoothDetailResponse)
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ data class BoothDetailResponse(
val longitude: Float,
@SerialName("menus")
val menus: List<MenuResponse>,
val isLiked: Boolean = false,
)

@Serializable
Expand Down
File renamed without changes.
18 changes: 18 additions & 0 deletions core/database/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
@file:Suppress("INLINE_FROM_HIGHER_PLATFORM")

plugins {
alias(libs.plugins.unifest.android.library)
alias(libs.plugins.unifest.android.hilt)
alias(libs.plugins.unifest.android.room)
id("kotlinx-serialization")
}

android {
namespace = "com.unifest.android.core.database"
}

dependencies {
implementations(
libs.timber,
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.unifest.android.core.database

import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.unifest.android.core.database.entity.LikedBoothEntity
import kotlinx.coroutines.flow.Flow

@Dao
interface LikedBoothDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertLikedBooth(userInfo: LikedBoothEntity)

@Delete
suspend fun deleteLikedBooth(userInfo: LikedBoothEntity)

@Query("SELECT * FROM liked_booth")
fun getLikedBoothList(): Flow<List<LikedBoothEntity>>

@Query("UPDATE liked_booth SET is_liked = :isLiked WHERE id = :id")
suspend fun updateLikedBooth(id: Long, isLiked: Boolean)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.unifest.android.core.database

import androidx.room.Database
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import com.unifest.android.core.database.entity.LikedBoothEntity

@Database(
entities = [LikedBoothEntity::class],
version = 1,
exportSchema = true,
)
@TypeConverters(MenuListConverter::class)
abstract class LikedBoothDatabase : RoomDatabase() {
abstract fun likedBoothDao(): LikedBoothDao
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.unifest.android.core.database

import androidx.room.TypeConverter
import com.unifest.android.core.database.entity.MenuEntity
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json

class MenuListConverter {
private val json = Json

@TypeConverter
fun fromMenuList(menuList: List<MenuEntity>): String {
return json.encodeToString(menuList)
}

@TypeConverter
fun toMenuList(menuListString: String): List<MenuEntity> {
return json.decodeFromString(menuListString)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.unifest.android.core.database.di

import com.unifest.android.core.database.LikedBoothDao
import com.unifest.android.core.database.LikedBoothDatabase
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent

@Module
@InstallIn(SingletonComponent::class)
object DaoModule {
@Provides
fun provideLikedBoothDao(
database: LikedBoothDatabase,
): LikedBoothDao = database.likedBoothDao()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.unifest.android.core.database.di

import android.content.Context
import androidx.room.Room
import com.unifest.android.core.database.LikedBoothDatabase
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
object DatabaseModule {

@Singleton
@Provides
fun provideLikedBoothDatabase(@ApplicationContext context: Context): LikedBoothDatabase =
Room.databaseBuilder(
context.applicationContext,
LikedBoothDatabase::class.java,
"liked_booth_database",
).build()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.unifest.android.core.database.entity

import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import kotlinx.serialization.Serializable

@Serializable
@Entity(tableName = "liked_booth")
data class LikedBoothEntity(
@PrimaryKey
@ColumnInfo(name = "id")
val id: Long,
@ColumnInfo(name = "name")
val name: String,
@ColumnInfo(name = "category")
val category: String,
@ColumnInfo(name = "description")
val description: String,
@ColumnInfo(name = "warning")
val warning: String,
@ColumnInfo(name = "location")
val location: String,
@ColumnInfo(name = "latitude")
val latitude: Float,
@ColumnInfo(name = "longitude")
val longitude: Float,
@ColumnInfo(name = "menus")
val menus: List<MenuEntity>,
@ColumnInfo(name = "is_liked")
val isLiked: Boolean,
)

@Serializable
data class MenuEntity(
val id: Long = 0L,
val name: String = "",
val price: Int = 0,
val imgUrl: String = "",
)
Loading
Loading