diff --git a/src/main/kotlin/org/gitanimals/render/app/UserFacade.kt b/src/main/kotlin/org/gitanimals/render/app/UserFacade.kt index 91d82f1..d61e6da 100644 --- a/src/main/kotlin/org/gitanimals/render/app/UserFacade.kt +++ b/src/main/kotlin/org/gitanimals/render/app/UserFacade.kt @@ -1,5 +1,6 @@ package org.gitanimals.render.app +import org.gitanimals.render.app.request.MergePersonaRequest import org.gitanimals.render.domain.UserService import org.gitanimals.render.domain.request.PersonaChangeRequest import org.gitanimals.render.domain.response.PersonaResponse @@ -40,4 +41,14 @@ class UserFacade( return userService.getPersona(user.username, personaId) } + + fun mergePersona(token: String, request: MergePersonaRequest) { + val user = identityApi.getUserByToken(token) + + return userService.mergePersona( + user.id.toLong(), + request.increasePersonaId, + request.deletePersonaId, + ) + } } diff --git a/src/main/kotlin/org/gitanimals/render/app/request/MergePersonaRequest.kt b/src/main/kotlin/org/gitanimals/render/app/request/MergePersonaRequest.kt new file mode 100644 index 0000000..6bed891 --- /dev/null +++ b/src/main/kotlin/org/gitanimals/render/app/request/MergePersonaRequest.kt @@ -0,0 +1,6 @@ +package org.gitanimals.render.app.request + +data class MergePersonaRequest( + val increasePersonaId: Long, + val deletePersonaId: Long, +) diff --git a/src/main/kotlin/org/gitanimals/render/controller/PersonaController.kt b/src/main/kotlin/org/gitanimals/render/controller/PersonaController.kt index 7652158..f4917e5 100644 --- a/src/main/kotlin/org/gitanimals/render/controller/PersonaController.kt +++ b/src/main/kotlin/org/gitanimals/render/controller/PersonaController.kt @@ -2,6 +2,7 @@ package org.gitanimals.render.controller import org.gitanimals.render.app.AuthorizationException import org.gitanimals.render.app.UserFacade +import org.gitanimals.render.app.request.MergePersonaRequest import org.gitanimals.render.controller.request.AddMultiplyPersonaRequest import org.gitanimals.render.controller.request.AddPersonaRequest import org.gitanimals.render.controller.response.ErrorResponse @@ -72,6 +73,13 @@ class PersonaController( ) } + @PutMapping("/personas/merges") + @ResponseStatus(HttpStatus.OK) + fun mergePersona( + @RequestHeader(HttpHeaders.AUTHORIZATION) token: String, + @RequestBody meregPersonaRequest: MergePersonaRequest, + ) = userFacade.mergePersona(token, meregPersonaRequest) + @ExceptionHandler(IllegalArgumentException::class) @ResponseStatus(HttpStatus.BAD_REQUEST) fun handleIllegalArgumentException(exception: IllegalArgumentException): ErrorResponse = diff --git a/src/main/kotlin/org/gitanimals/render/domain/User.kt b/src/main/kotlin/org/gitanimals/render/domain/User.kt index 338a1a8..a01a128 100644 --- a/src/main/kotlin/org/gitanimals/render/domain/User.kt +++ b/src/main/kotlin/org/gitanimals/render/domain/User.kt @@ -205,6 +205,15 @@ class User( .append("") .toString() + fun mergePersona(increasePersonaId: Long, deletePersonaId: Long) { + val increasePersona = personas.first { it.id == increasePersonaId } + val deletePersona = personas.first { it.id == deletePersonaId } + + increasePersona.level.value += deletePersona.level.value + + personas.remove(deletePersona) + } + companion object { private const val MAX_PERSONA_COUNT = 30L private const val MAX_INIT_PERSONA_COUNT = 10L diff --git a/src/main/kotlin/org/gitanimals/render/domain/UserService.kt b/src/main/kotlin/org/gitanimals/render/domain/UserService.kt index 6e4b7fa..1d9face 100644 --- a/src/main/kotlin/org/gitanimals/render/domain/UserService.kt +++ b/src/main/kotlin/org/gitanimals/render/domain/UserService.kt @@ -104,6 +104,15 @@ class UserService( return user.deletePersona(personaId) } + @Transactional + @Retryable(retryFor = [ObjectOptimisticLockingFailureException::class], maxAttempts = 100) + fun mergePersona(id: Long, increasePersonaId: Long, deletePersonaId: Long) { + val user = userRepository.findByIdOrNull(id) + ?: throw IllegalArgumentException("Cannot find user by id \"$id\"") + + user.mergePersona(increasePersonaId, deletePersonaId) + } + fun getPersona(name: String, personaId: Long): PersonaResponse { return getUserByName(name).personas .find { it.id == personaId } diff --git a/src/test/kotlin/org/gitanimals/render/domain/UserTest.kt b/src/test/kotlin/org/gitanimals/render/domain/UserTest.kt index 373743f..0259184 100644 --- a/src/test/kotlin/org/gitanimals/render/domain/UserTest.kt +++ b/src/test/kotlin/org/gitanimals/render/domain/UserTest.kt @@ -103,6 +103,22 @@ internal class UserTest : DescribeSpec({ } } } + + describe("mergePersona 메소드는") { + context("increasePersonaId와 deletePersonaId를 받아서,") { + val user = User.newUser("devxb", mapOf()) + user.updateContribution(30) + user.giveNewPersona() + + val increasePersonaId = user.personas.minByOrNull { it.level.value }!!.id + val deletePersonaId = user.personas.maxByOrNull { it.level.value }!!.id + it("increasePersonaId에 deletePersonasId의 level을 추가하고, deletePersona를 삭제한다") { + user.mergePersona(increasePersonaId, deletePersonaId) + + user.personas.size shouldBeEqual 1 + } + } + } }) { private companion object { private const val ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"