-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
25 changed files
with
780 additions
and
24 deletions.
There are no files selected for viewing
Submodule CONFIG
updated
from cd8df8 to 0fa42f
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
59 changes: 59 additions & 0 deletions
59
src/main/kotlin/com/ggsdh/backend/photobook/application/NaverGcService.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package com.ggsdh.backend.photobook.application | ||
|
||
import com.fasterxml.jackson.databind.ObjectMapper | ||
import com.fasterxml.jackson.module.kotlin.readValue | ||
import com.ggsdh.backend.photobook.application.dto.ApiResponse | ||
import com.ggsdh.backend.photobook.application.dto.GetLocationInputDto | ||
import com.ggsdh.backend.photobook.domain.Location | ||
import org.asynchttpclient.Dsl.asyncHttpClient | ||
import org.springframework.beans.factory.annotation.Value | ||
import org.springframework.stereotype.Component | ||
import java.util.concurrent.CompletableFuture | ||
|
||
@Component | ||
class NaverGcService( | ||
private val objectMapper: ObjectMapper, | ||
@Value("\${naver.gc.client-id}") | ||
private val clientId: String, | ||
@Value("\${naver.gc.client-secret}") | ||
private val clientSecret: String, | ||
) { | ||
fun getLocation(input: GetLocationInputDto): CompletableFuture<Location?> { | ||
if (input.lat == null || input.lon == null) { | ||
return CompletableFuture.completedFuture(null) | ||
} | ||
|
||
return asyncHttpClient() | ||
.prepareGet( | ||
"https://naveropenapi.apigw.ntruss.com/map-reversegeocode/v2/gc?coords=${input.lon},${input.lat}&output=json&orders=roadaddr", | ||
).setHeader("X-NCP-APIGW-API-KEY", clientSecret) | ||
.setHeader("X-NCP-APIGW-API-KEY-ID", clientId) | ||
.execute() | ||
.toCompletableFuture() | ||
.thenApply { | ||
val body = it.responseBody | ||
val response = objectMapper.readValue<ApiResponse>(body) | ||
|
||
if (response.status.code == 3) { | ||
return@thenApply null | ||
} | ||
|
||
val buildingName = | ||
response.results[0] | ||
.land.addition0.value | ||
|
||
val city = | ||
response.results[0] | ||
.region.area1.name | ||
|
||
if (buildingName == "") { | ||
val roadName = | ||
response.results[0] | ||
.land.name | ||
return@thenApply Location(input.lat, input.lon, "$roadName 근처 어딘가", city) | ||
} else { | ||
return@thenApply Location(input.lat, input.lon, buildingName, city) | ||
} | ||
} | ||
} | ||
} |
88 changes: 88 additions & 0 deletions
88
src/main/kotlin/com/ggsdh/backend/photobook/application/PhotoBookService.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
package com.ggsdh.backend.photobook.application | ||
|
||
import com.ggsdh.backend.global.exception.error.BusinessException | ||
import com.ggsdh.backend.global.exception.error.GlobalError | ||
import com.ggsdh.backend.photobook.domain.Photo | ||
import com.ggsdh.backend.photobook.domain.PhotoBook | ||
import com.ggsdh.backend.photobook.domain.PhotoBookRepository | ||
import com.ggsdh.backend.photobook.presentation.dto.CreatePhotobookRequest | ||
import jakarta.transaction.Transactional | ||
import org.springframework.stereotype.Component | ||
import java.time.LocalDateTime | ||
import java.time.format.DateTimeFormatter | ||
import java.util.concurrent.CompletableFuture | ||
|
||
@Component | ||
class PhotoBookService( | ||
private val naverGcService: NaverGcService, | ||
private val photoBookRepository: PhotoBookRepository, | ||
) { | ||
fun deletePhotoBook( | ||
memberId: Long, | ||
photobookId: Long, | ||
) = photoBookRepository.delete(memberId, photobookId) | ||
|
||
fun getAllPhotoBooks(memberId: Long): List<PhotoBook> = photoBookRepository.getAllByMemberId(memberId) | ||
|
||
fun getPhotoBook( | ||
memberId: Long, | ||
photobookId: Long, | ||
): PhotoBook { | ||
val photoBook = | ||
photoBookRepository.find(memberId, photobookId) ?: throw BusinessException( | ||
GlobalError.PHOTOBOOK_NOT_FOUND, | ||
) | ||
|
||
return photoBook | ||
} | ||
|
||
@Transactional | ||
fun getPhoto( | ||
memberId: Long, | ||
input: CreatePhotobookRequest, | ||
): PhotoBook { | ||
val photos: MutableList<Photo> = mutableListOf() | ||
|
||
CompletableFuture | ||
.allOf( | ||
*input.photos | ||
.map { photo -> | ||
naverGcService.getLocation(photo.toGetLocationInputDto()).thenApply { | ||
photos.add( | ||
Photo( | ||
id = -1, | ||
path = photo.path, | ||
location = it, | ||
dateTime = photo.toGetLocationInputDto().date, | ||
), | ||
) | ||
} | ||
}.toTypedArray(), | ||
).join() | ||
|
||
photos.filter { | ||
it.location?.city == "경기도" | ||
} | ||
|
||
val photoBook = | ||
PhotoBook.create( | ||
id = -1, | ||
input.title, | ||
LocalDateTime.parse(input.startDate, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS")), | ||
LocalDateTime.parse(input.endDate, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS")), | ||
photos, | ||
) | ||
val saved = | ||
photoBookRepository.save( | ||
memberId, | ||
photoBook, | ||
) | ||
|
||
return saved | ||
} | ||
|
||
fun deletePhoto( | ||
memberId: Long, | ||
photoId: List<Long>, | ||
) = photoBookRepository.deletePhotos(memberId, photoId) | ||
} |
10 changes: 10 additions & 0 deletions
10
src/main/kotlin/com/ggsdh/backend/photobook/application/dto/GetLocationInputDto.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package com.ggsdh.backend.photobook.application.dto | ||
|
||
import java.time.LocalDateTime | ||
|
||
class GetLocationInputDto( | ||
val path: String, | ||
val lat: Double?, | ||
val lon: Double?, // 0.0 | ||
val date: LocalDateTime, | ||
) |
72 changes: 72 additions & 0 deletions
72
src/main/kotlin/com/ggsdh/backend/photobook/application/dto/NaverGcResponse.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
package com.ggsdh.backend.photobook.application.dto | ||
|
||
data class ApiResponse( | ||
val status: Status, | ||
val results: List<Result>, | ||
) | ||
|
||
data class Status( | ||
val code: Int, | ||
val name: String, | ||
val message: String, | ||
) | ||
|
||
data class Result( | ||
val name: String, | ||
val code: Code, | ||
val region: Region, | ||
val land: Land, | ||
) | ||
|
||
data class Code( | ||
val id: String, | ||
val type: String, | ||
val mappingId: String, | ||
) | ||
|
||
data class Region( | ||
val area0: Area, | ||
val area1: AreaWithAlias, | ||
val area2: Area, | ||
val area3: Area, | ||
val area4: Area, | ||
) | ||
|
||
data class Area( | ||
val name: String, | ||
val coords: Coords, | ||
) | ||
|
||
data class AreaWithAlias( | ||
val name: String, | ||
val coords: Coords, | ||
val alias: String, | ||
) | ||
|
||
data class Coords( | ||
val center: Center, | ||
) | ||
|
||
data class Center( | ||
val crs: String, | ||
val x: Double, | ||
val y: Double, | ||
) | ||
|
||
data class Land( | ||
val type: String, | ||
val number1: String, | ||
val number2: String, | ||
val addition0: Addition, | ||
val addition1: Addition, | ||
val addition2: Addition, | ||
val addition3: Addition, | ||
val addition4: Addition, | ||
val name: String, | ||
val coords: Coords, | ||
) | ||
|
||
data class Addition( | ||
val type: String, | ||
val value: String, | ||
) |
9 changes: 9 additions & 0 deletions
9
src/main/kotlin/com/ggsdh/backend/photobook/domain/DailyPhotoGroup.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package com.ggsdh.backend.photobook.domain | ||
|
||
import java.time.LocalDate | ||
|
||
class DailyPhotoGroup( | ||
val day: Int, | ||
val dateTime: LocalDate, | ||
val hourlyPhotoGroups: List<HourlyPhotoGroup>, | ||
) |
8 changes: 8 additions & 0 deletions
8
src/main/kotlin/com/ggsdh/backend/photobook/domain/DominantLocation.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package com.ggsdh.backend.photobook.domain | ||
|
||
data class Location( | ||
val lat: Double, | ||
val lon: Double, | ||
val name: String?, | ||
val city: String?, | ||
) |
28 changes: 28 additions & 0 deletions
28
src/main/kotlin/com/ggsdh/backend/photobook/domain/HourlyPhotoGroup.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package com.ggsdh.backend.photobook.domain | ||
|
||
import java.time.LocalDateTime | ||
|
||
// 2024-08-09 23:38:21.000 | ||
class HourlyPhotoGroup( | ||
val dateTime: LocalDateTime, | ||
val photos: List<Photo>, | ||
) { | ||
fun getPhotosCount(): Number = photos.size | ||
|
||
fun getLocalizedTime(): String { | ||
val prefix = if (dateTime.hour < 12) "오전" else "오후" | ||
return "$prefix ${dateTime.hour % 12}시" | ||
} | ||
|
||
fun getDominantLocation(): Location? { | ||
val locationMap = mutableMapOf<Location, Int>() | ||
photos.forEach { photo -> | ||
val location = photo.location | ||
|
||
if (location != null) { | ||
locationMap[location] = (locationMap[location] ?: 0) + 1 | ||
} | ||
} | ||
return locationMap.maxByOrNull { it.value }?.key | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
src/main/kotlin/com/ggsdh/backend/photobook/domain/Photo.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package com.ggsdh.backend.photobook.domain | ||
|
||
import java.time.LocalDateTime | ||
|
||
class Photo( | ||
val id: Long, | ||
val path: String, | ||
val location: Location?, | ||
val dateTime: LocalDateTime, | ||
) { | ||
companion object { | ||
fun create( | ||
path: String, | ||
dateTime: LocalDateTime, | ||
): Photo = Photo(-1, path, null, dateTime) | ||
} | ||
} |
Oops, something went wrong.