Skip to content

Commit

Permalink
handle detail data
Browse files Browse the repository at this point in the history
  • Loading branch information
sanggggg committed Jul 6, 2024
1 parent 6ab4d2a commit 8dd931b
Show file tree
Hide file tree
Showing 16 changed files with 149 additions and 17 deletions.
3 changes: 3 additions & 0 deletions app-server/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import io.gitlab.arturbosch.detekt.Detekt
import org.jetbrains.kotlin.gradle.plugin.ide.kotlinExtrasSerialization
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.springframework.boot.gradle.tasks.bundling.BootJar

Expand Down Expand Up @@ -44,7 +45,9 @@ subprojects {
implementation(rootProject.projects.crossCuttingConcern.infra.springWeb)
}
val kotlinLoggingVersion: String by project
val kotlinSerialization: String by project
implementation("io.github.microutils:kotlin-logging-jvm:$kotlinLoggingVersion")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlinSerialization")
}

tasks.test {
Expand Down
1 change: 1 addition & 0 deletions app-server/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ kotlin.code.style=official
kotlinVersion=1.8.20
kotlinxSerializationVersion=1.5.0
kotlinLoggingVersion=3.0.5
kotlinSerialization=1.5.1
jakartaInjectVersion=2.0.1
springBootVersion=3.0.5
springDependencyManagementVersion=1.1.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -627,10 +627,15 @@ paths:
$ref: '#/components/schemas/Location'
distanceMetersLimit:
type: integer
categories:
type: array
items:
type: string
required:
- distanceMetersLimit
responses:
'200':
description: 응답 리스트
content:
application/json:
schema:
Expand Down Expand Up @@ -1442,7 +1447,28 @@ components:
description: 장소의 human-readable한 주소.
location:
$ref: '#/components/schemas/Location'
description: 장소의 위경도.
details:
$ref: '#/components/schemas/ExternalAccessibilityDetails'

ExternalAccessibilityDetails:
type: object
properties:
gender:
type: boolean
accessDesc:
type: string
availableDesc:
type: string
entranceDesc:
type: string
stallDesc:
type: string
doorDesc:
type: string
washStandDesc:
type: string
extra:
type: string

PlaceListItem:
type: object
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package club.staircrusher.external_accessibility.application.port.`in`
import club.staircrusher.external_accessibility.application.port.out.persistence.ExternalAccessibilityRepository
import club.staircrusher.external_accessibility.domain.model.ExternalAccessibility
import club.staircrusher.stdlib.di.annotation.Component
import club.staircrusher.stdlib.external_accessibility.ExternalAccessibilityCategory
import club.staircrusher.stdlib.geography.Length
import club.staircrusher.stdlib.geography.Location
import club.staircrusher.stdlib.util.string.isSimilarWith
Expand All @@ -15,13 +16,16 @@ class ExternalAccessibilitySearchService(
searchText: String?,
currentLocation: Location?,
distanceMetersLimit: Length,
categories: List<ExternalAccessibilityCategory> = emptyList(),
): List<ExternalAccessibility> {
return externalAccessibilityRepository
.findAll()
return (
if (categories.isEmpty()) externalAccessibilityRepository.findAll()
else externalAccessibilityRepository.findByCategoryIn(categories.toSet())
)
// FIXME: 현재 fullscan 후 필터링 중, 나중에 spatial index 걸어주기
.filter {
currentLocation ?: return@filter true
val distance = currentLocation.distanceMeter(Location(it.longitude, it.latitude))
val distance = currentLocation.distanceMeter(it.location)
distance <= distanceMetersLimit
}
.filter {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ package club.staircrusher.external_accessibility.application.port.out.persistenc

import club.staircrusher.external_accessibility.domain.model.ExternalAccessibility
import club.staircrusher.stdlib.domain.repository.EntityRepository
import club.staircrusher.stdlib.external_accessibility.ExternalAccessibilityCategory

@Suppress("TooManyFunctions")
interface ExternalAccessibilityRepository : EntityRepository<ExternalAccessibility, String> {
fun findAll(): List<ExternalAccessibility>
fun findByCategoryIn(categories: Set<ExternalAccessibilityCategory>): List<ExternalAccessibility>
}
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
plugins {
kotlin("plugin.serialization")
}

dependencies {
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package club.staircrusher.external_accessibility.domain.model

import club.staircrusher.stdlib.external_accessibility.ExternalAccessibilityCategory
import club.staircrusher.stdlib.geography.Location
import java.time.Instant

data class ExternalAccessibility(
val id: String,
val name: String,
val latitude: Double,
val longitude: Double,
val location: Location,
val address: String,
val createdAt: Instant,
val updatedAt: Instant,
val category: ExternalAccessibilityCategory,
val toiletDetails: ToiletAccessibilityDetails?,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package club.staircrusher.external_accessibility.domain.model

import kotlinx.serialization.Serializable

@Serializable
data class ToiletAccessibilityDetails(
val gender: Boolean? = null,
val accessDesc: String? = null,
val availableDesc: String? = null,
val entranceDesc: String? = null,
val stallDesc: String? = null,
val doorDesc: String? = null,
val washStandDesc: String? = null,
val extra: String? = null,
)
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package club.staircrusher.external_accessibility.infra.adapter.`in`.controller

import club.staircrusher.api.spec.dto.ExternalAccessibilityDetails
import club.staircrusher.api.spec.dto.ExternalAccessibilityListItem
import club.staircrusher.api.spec.dto.SearchExternalAccessibilitiesPostRequest
import club.staircrusher.api.spec.dto.SearchExternalAccessibilitiesPost200Response
import club.staircrusher.external_accessibility.application.port.`in`.ExternalAccessibilitySearchService
import club.staircrusher.stdlib.external_accessibility.ExternalAccessibilityCategory
import club.staircrusher.stdlib.geography.Length
import club.staircrusher.stdlib.geography.Location
import org.springframework.web.bind.annotation.PostMapping
Expand All @@ -20,9 +22,12 @@ class SearchExternalAccessibilitiesController(
): SearchExternalAccessibilitiesPost200Response {
return SearchExternalAccessibilitiesPost200Response(
externalAccessibilitySearchService.searchExternalAccessibilities(
request.searchText,
request.currentLocation?.let { Location(lng = it.lng, lat = it.lat) },
Length.ofMeters(request.distanceMetersLimit),
searchText = request.searchText,
currentLocation = request.currentLocation?.let { Location(lng = it.lng, lat = it.lat) },
distanceMetersLimit = Length.ofMeters(request.distanceMetersLimit),
categories = request.categories?.mapNotNull {
runCatching { ExternalAccessibilityCategory.valueOf(it) }.getOrNull()
} ?: emptyList()
)
.map {
ExternalAccessibilityListItem(
Expand All @@ -31,9 +36,21 @@ class SearchExternalAccessibilitiesController(
address = it.address,
location =
club.staircrusher.api.spec.dto.Location(
lng = it.longitude,
lat = it.latitude
lng = it.location.lng,
lat = it.location.lat,
),
details = it.toiletDetails?.run {
ExternalAccessibilityDetails(
gender = gender,
accessDesc = accessDesc,
availableDesc = availableDesc,
entranceDesc = entranceDesc,
stallDesc = stallDesc,
doorDesc = doorDesc,
washStandDesc = washStandDesc,
extra = extra
)
}
)
}
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import club.staircrusher.external_accessibility.infra.adapter.out.persistence.sq
import club.staircrusher.external_accessibility.infra.adapter.out.persistence.sqldelight.toPersistenceModel
import club.staircrusher.infra.persistence.sqldelight.DB
import club.staircrusher.stdlib.di.annotation.Component
import club.staircrusher.stdlib.external_accessibility.ExternalAccessibilityCategory

@Suppress("TooManyFunctions")
@Component
Expand Down Expand Up @@ -42,4 +43,10 @@ class ExternalAccessibilityRepository(
.executeAsList()
.map { it.toDomainModel() }
}

override fun findByCategoryIn(categories: Set<ExternalAccessibilityCategory>): List<ExternalAccessibility> {
return queries.findByCategoryIn(categories)
.executeAsList()
.map { it.toDomainModel() }
}
}
Original file line number Diff line number Diff line change
@@ -1,27 +1,44 @@
package club.staircrusher.external_accessibility.infra.adapter.out.persistence.sqldelight

import club.staircrusher.external_accessibility.domain.model.ExternalAccessibility
import club.staircrusher.external_accessibility.domain.model.ToiletAccessibilityDetails
import club.staircrusher.infra.persistence.sqldelight.migration.External_accessibility
import club.staircrusher.stdlib.geography.Location
import club.staircrusher.stdlib.time.toOffsetDateTime
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.Json.Default.decodeFromString
import java.time.Instant


fun External_accessibility.toDomainModel(): ExternalAccessibility = ExternalAccessibility(
id = id,
name = name,
latitude = location_x,
longitude = location_y,
location = Location(
lat = location_x,
lng = location_y,
),
address = address,
createdAt = created_at.toInstant(),
updatedAt = updated_at.toInstant(),
category = category,
toiletDetails = details?.let {
// TODO: 새로운 카테고리가 생기면 대응하기
runCatching { decodeFromString<ToiletAccessibilityDetails>(it) }.getOrNull()
}
)

fun ExternalAccessibility.toPersistenceModel(): External_accessibility = External_accessibility(
id = id,
name = name,
location_x = latitude,
location_y = longitude,
location_x = location.lat,
location_y = location.lng,
address = address,
created_at = Instant.now().toOffsetDateTime(),
updated_at = Instant.now().toOffsetDateTime(),
category = category,
details = toiletDetails?.let {
// TODO: 새로운 카테고리가 생기면 대응하기
runCatching { Json.encodeToString(it) }.getOrNull()
},
)
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package club.staircrusher.infra.persistence.sqldelight

import app.cash.sqldelight.ColumnAdapter
import club.staircrusher.challenge.domain.model.ChallengeCondition
import club.staircrusher.infra.persistence.sqldelight.column_adapter.AccessibilityImageListStringColumnAdapter
import club.staircrusher.infra.persistence.sqldelight.column_adapter.EntranceDoorTypeListStringColumnAdapter
Expand All @@ -14,11 +15,13 @@ import club.staircrusher.infra.persistence.sqldelight.column_adapter.UserMobilit
import club.staircrusher.infra.persistence.sqldelight.migration.Accessibility_allowed_region
import club.staircrusher.infra.persistence.sqldelight.migration.Building_accessibility
import club.staircrusher.infra.persistence.sqldelight.migration.Challenge
import club.staircrusher.infra.persistence.sqldelight.migration.External_accessibility
import club.staircrusher.infra.persistence.sqldelight.migration.Place
import club.staircrusher.infra.persistence.sqldelight.migration.Place_accessibility
import club.staircrusher.infra.persistence.sqldelight.migration.Scc_user
import club.staircrusher.infra.persistence.sqldelight.migration.User_auth_info
import club.staircrusher.stdlib.di.annotation.Component
import club.staircrusher.stdlib.external_accessibility.ExternalAccessibilityCategory
import club.staircrusher.stdlib.persistence.Transaction
import club.staircrusher.stdlib.persistence.TransactionIsolationLevel
import club.staircrusher.stdlib.persistence.TransactionManager
Expand Down Expand Up @@ -74,6 +77,16 @@ class DB(dataSource: DataSource) : TransactionManager {
}

}
),
external_accessibilityAdapter = External_accessibility.Adapter(
categoryAdapter = object : ColumnAdapter<ExternalAccessibilityCategory, String> {
override fun decode(databaseValue: String): ExternalAccessibilityCategory {
return ExternalAccessibilityCategory.valueOf(databaseValue)
}

override fun encode(value: ExternalAccessibilityCategory): String = value.name
}

)
)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import club.staircrusher.stdlib.external_accessibility.ExternalAccessibilityCategory;

CREATE TABLE IF NOT EXISTS external_accessibility (
id VARCHAR(36) NOT NULL,
name VARCHAR(64) NOT NULL,
Expand All @@ -7,5 +9,7 @@ CREATE TABLE IF NOT EXISTS external_accessibility (
address VARCHAR(64) NOT NULL,
created_at TIMESTAMP(6) WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP(6) WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
category VARCHAR(32) AS ExternalAccessibilityCategory NOT NULL,
details TEXT,
PRIMARY KEY (id)
);
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ ON CONFLICT(id) DO UPDATE SET
location_x = EXCLUDED.location_x,
location_y = EXCLUDED.location_y,
address = EXCLUDED.address,
category = EXCLUDED.category,
details = EXCLUDED.details,
created_at = EXCLUDED.created_at,
updated_at = NULL;

Expand All @@ -17,6 +19,11 @@ SELECT *
FROM external_accessibility
WHERE external_accessibility.id = :id;

findByCategoryIn:
SELECT *
FROM external_accessibility
WHERE external_accessibility.category IN :categories;

findAll:
SELECT *
FROM external_accessibility;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package club.staircrusher.stdlib.external_accessibility

enum class ExternalAccessibilityCategory(val humanReadableName: String) {
TOILET(humanReadableName = "화장실"),
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@ import club.staircrusher.challenge.domain.model.ChallengeContribution
import club.staircrusher.challenge.domain.model.ChallengeParticipation
import club.staircrusher.external_accessibility.application.port.out.persistence.ExternalAccessibilityRepository
import club.staircrusher.external_accessibility.domain.model.ExternalAccessibility
import club.staircrusher.external_accessibility.domain.model.ToiletAccessibilityDetails
import club.staircrusher.place.application.port.out.persistence.BuildingRepository
import club.staircrusher.place.application.port.out.persistence.PlaceRepository
import club.staircrusher.place.domain.model.Building
import club.staircrusher.place.domain.model.BuildingAddress
import club.staircrusher.place.domain.model.Place
import club.staircrusher.stdlib.di.annotation.Component
import club.staircrusher.stdlib.domain.entity.EntityIdGenerator
import club.staircrusher.stdlib.external_accessibility.ExternalAccessibilityCategory
import club.staircrusher.stdlib.geography.Location
import club.staircrusher.stdlib.geography.eupMyeonDongById
import club.staircrusher.stdlib.geography.siGunGuById
Expand Down Expand Up @@ -156,16 +158,18 @@ class ITDataGenerator {
name: String = "공공화장실",
location: Location = Location(127.5, 37.5),
address: String = "임의주소",
category: ExternalAccessibilityCategory = ExternalAccessibilityCategory.TOILET,
): ExternalAccessibility {
return externalAccessibilityRepository.save(
ExternalAccessibility(
id = EntityIdGenerator.generateRandom(),
name = name,
latitude = location.lat,
longitude = location.lng,
location = location,
address = address,
createdAt = Instant.now(),
updatedAt = Instant.now(),
category = category,
toiletDetails = ToiletAccessibilityDetails(gender = true, availableDesc = "asdf"),
)
)
}
Expand Down

0 comments on commit 8dd931b

Please sign in to comment.