From 5b0a774439dc7185f224914a88a8e667c26aa591 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Mon, 22 Jul 2024 15:36:22 +0900 Subject: [PATCH 01/23] =?UTF-8?q?refactor:=20VoteUseCase=20=EB=84=A4?= =?UTF-8?q?=EC=9D=B4=EB=B0=8D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/kotlin/com/wespot/vote/VoteController.kt | 8 ++++---- .../kotlin/com/wespot/vote/service/VoteServiceTest.kt | 2 +- .../vote/port/in/{VoteUseCase.kt => SaveVoteUseCase.kt} | 2 +- .../vote/service/{VoteService.kt => SaveVoteService.kt} | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) rename core/src/main/kotlin/com/wespot/vote/port/in/{VoteUseCase.kt => SaveVoteUseCase.kt} (91%) rename core/src/main/kotlin/com/wespot/vote/service/{VoteService.kt => SaveVoteService.kt} (97%) diff --git a/app/src/main/kotlin/com/wespot/vote/VoteController.kt b/app/src/main/kotlin/com/wespot/vote/VoteController.kt index 9237dba6..eca436fa 100644 --- a/app/src/main/kotlin/com/wespot/vote/VoteController.kt +++ b/app/src/main/kotlin/com/wespot/vote/VoteController.kt @@ -3,7 +3,7 @@ package com.wespot.vote import com.wespot.vote.dto.request.VoteRequests import com.wespot.vote.dto.response.SaveVoteResponse import com.wespot.vote.dto.response.VoteItems -import com.wespot.vote.port.`in`.VoteUseCase +import com.wespot.vote.port.`in`.SaveVoteUseCase import org.springframework.http.HttpStatus import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.GetMapping @@ -15,12 +15,12 @@ import org.springframework.web.bind.annotation.RestController @RestController @RequestMapping("/v1/votes") class VoteController( - private val voteUseCase: VoteUseCase + private val saveVoteUseCase: SaveVoteUseCase ) { @GetMapping("/options") fun getVoteOptions(userId: Long): ResponseEntity { - val responses = voteUseCase.getVoteOptions(userId) + val responses = saveVoteUseCase.getVoteOptions(userId) return ResponseEntity.ok(responses) } @@ -29,7 +29,7 @@ class VoteController( userId: Long, @RequestBody requests: VoteRequests ): ResponseEntity { - val savedId: SaveVoteResponse = voteUseCase.saveVote(userId, requests) + val savedId: SaveVoteResponse = saveVoteUseCase.saveVote(userId, requests) return ResponseEntity.status(HttpStatus.CREATED) .body(savedId) } diff --git a/app/src/test/kotlin/com/wespot/vote/service/VoteServiceTest.kt b/app/src/test/kotlin/com/wespot/vote/service/VoteServiceTest.kt index b769f1ef..7f74e885 100644 --- a/app/src/test/kotlin/com/wespot/vote/service/VoteServiceTest.kt +++ b/app/src/test/kotlin/com/wespot/vote/service/VoteServiceTest.kt @@ -29,7 +29,7 @@ import kotlin.test.Test @SpringBootTest class VoteServiceTest( @Autowired - private var voteService: VoteService, + private var voteService: SaveVoteService, @Autowired private var databaseCleanup: DatabaseCleanup, @Autowired diff --git a/core/src/main/kotlin/com/wespot/vote/port/in/VoteUseCase.kt b/core/src/main/kotlin/com/wespot/vote/port/in/SaveVoteUseCase.kt similarity index 91% rename from core/src/main/kotlin/com/wespot/vote/port/in/VoteUseCase.kt rename to core/src/main/kotlin/com/wespot/vote/port/in/SaveVoteUseCase.kt index ae5b562f..8338c13b 100644 --- a/core/src/main/kotlin/com/wespot/vote/port/in/VoteUseCase.kt +++ b/core/src/main/kotlin/com/wespot/vote/port/in/SaveVoteUseCase.kt @@ -4,7 +4,7 @@ import com.wespot.vote.dto.request.VoteRequests import com.wespot.vote.dto.response.SaveVoteResponse import com.wespot.vote.dto.response.VoteItems -interface VoteUseCase { +interface SaveVoteUseCase { fun getVoteOptions(userId: Long): VoteItems diff --git a/core/src/main/kotlin/com/wespot/vote/service/VoteService.kt b/core/src/main/kotlin/com/wespot/vote/service/SaveVoteService.kt similarity index 97% rename from core/src/main/kotlin/com/wespot/vote/service/VoteService.kt rename to core/src/main/kotlin/com/wespot/vote/service/SaveVoteService.kt index 55b0aea0..1078f15a 100644 --- a/core/src/main/kotlin/com/wespot/vote/service/VoteService.kt +++ b/core/src/main/kotlin/com/wespot/vote/service/SaveVoteService.kt @@ -7,7 +7,7 @@ import com.wespot.vote.dto.request.VoteRequest import com.wespot.vote.dto.request.VoteRequests import com.wespot.vote.dto.response.SaveVoteResponse import com.wespot.vote.dto.response.VoteItems -import com.wespot.vote.port.`in`.VoteUseCase +import com.wespot.vote.port.`in`.SaveVoteUseCase import com.wespot.vote.port.out.VoteOptionPort import com.wespot.vote.port.out.VotePort import com.wespot.voteoption.VoteOption @@ -16,11 +16,11 @@ import org.springframework.stereotype.Service import java.time.LocalDate @Service -class VoteService( +class SaveVoteService( private val votePort: VotePort, private val voteOptionPort: VoteOptionPort, private val userPort: UserPort, -) : VoteUseCase { +) : SaveVoteUseCase { @Transactional override fun getVoteOptions(userId: Long): VoteItems { From 3bd48f5a9a65e0338723a07737b841faedcc5c2a Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Mon, 22 Jul 2024 15:47:49 +0900 Subject: [PATCH 02/23] =?UTF-8?q?feat:=20VoteRank=20Service=20=EC=A0=95?= =?UTF-8?q?=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...SaveVoteUseCase.kt => SavedVoteUseCase.kt} | 2 +- .../wespot/vote/port/in/VoteRankUseCase.kt | 13 +++++++++ ...SaveVoteService.kt => SavedVoteService.kt} | 6 ++--- .../wespot/vote/service/VoteRankService.kt | 27 +++++++++++++++++++ 4 files changed, 44 insertions(+), 4 deletions(-) rename core/src/main/kotlin/com/wespot/vote/port/in/{SaveVoteUseCase.kt => SavedVoteUseCase.kt} (91%) create mode 100644 core/src/main/kotlin/com/wespot/vote/port/in/VoteRankUseCase.kt rename core/src/main/kotlin/com/wespot/vote/service/{SaveVoteService.kt => SavedVoteService.kt} (97%) create mode 100644 core/src/main/kotlin/com/wespot/vote/service/VoteRankService.kt diff --git a/core/src/main/kotlin/com/wespot/vote/port/in/SaveVoteUseCase.kt b/core/src/main/kotlin/com/wespot/vote/port/in/SavedVoteUseCase.kt similarity index 91% rename from core/src/main/kotlin/com/wespot/vote/port/in/SaveVoteUseCase.kt rename to core/src/main/kotlin/com/wespot/vote/port/in/SavedVoteUseCase.kt index 8338c13b..94b45714 100644 --- a/core/src/main/kotlin/com/wespot/vote/port/in/SaveVoteUseCase.kt +++ b/core/src/main/kotlin/com/wespot/vote/port/in/SavedVoteUseCase.kt @@ -4,7 +4,7 @@ import com.wespot.vote.dto.request.VoteRequests import com.wespot.vote.dto.response.SaveVoteResponse import com.wespot.vote.dto.response.VoteItems -interface SaveVoteUseCase { +interface SavedVoteUseCase { fun getVoteOptions(userId: Long): VoteItems diff --git a/core/src/main/kotlin/com/wespot/vote/port/in/VoteRankUseCase.kt b/core/src/main/kotlin/com/wespot/vote/port/in/VoteRankUseCase.kt new file mode 100644 index 00000000..6a65fa3a --- /dev/null +++ b/core/src/main/kotlin/com/wespot/vote/port/in/VoteRankUseCase.kt @@ -0,0 +1,13 @@ +package com.wespot.vote.port.`in` + +import com.wespot.vote.dto.response.top1.VoteResultResponsesOfTop1 +import com.wespot.vote.dto.response.top5.VoteResultResponsesOfTop5 +import java.time.LocalDate + +interface VoteRankUseCase { + + fun getVoteResultsOfTop5(userId: Long, date: LocalDate): VoteResultResponsesOfTop5 + + fun getVoteResultsOfTop1(userId: Long, date: LocalDate): VoteResultResponsesOfTop1 + +} diff --git a/core/src/main/kotlin/com/wespot/vote/service/SaveVoteService.kt b/core/src/main/kotlin/com/wespot/vote/service/SavedVoteService.kt similarity index 97% rename from core/src/main/kotlin/com/wespot/vote/service/SaveVoteService.kt rename to core/src/main/kotlin/com/wespot/vote/service/SavedVoteService.kt index 1078f15a..04bc199c 100644 --- a/core/src/main/kotlin/com/wespot/vote/service/SaveVoteService.kt +++ b/core/src/main/kotlin/com/wespot/vote/service/SavedVoteService.kt @@ -7,7 +7,7 @@ import com.wespot.vote.dto.request.VoteRequest import com.wespot.vote.dto.request.VoteRequests import com.wespot.vote.dto.response.SaveVoteResponse import com.wespot.vote.dto.response.VoteItems -import com.wespot.vote.port.`in`.SaveVoteUseCase +import com.wespot.vote.port.`in`.SavedVoteUseCase import com.wespot.vote.port.out.VoteOptionPort import com.wespot.vote.port.out.VotePort import com.wespot.voteoption.VoteOption @@ -16,11 +16,11 @@ import org.springframework.stereotype.Service import java.time.LocalDate @Service -class SaveVoteService( +class SavedVoteService( private val votePort: VotePort, private val voteOptionPort: VoteOptionPort, private val userPort: UserPort, -) : SaveVoteUseCase { +) : SavedVoteUseCase { @Transactional override fun getVoteOptions(userId: Long): VoteItems { diff --git a/core/src/main/kotlin/com/wespot/vote/service/VoteRankService.kt b/core/src/main/kotlin/com/wespot/vote/service/VoteRankService.kt new file mode 100644 index 00000000..7f2b660e --- /dev/null +++ b/core/src/main/kotlin/com/wespot/vote/service/VoteRankService.kt @@ -0,0 +1,27 @@ +package com.wespot.vote.service + +import com.wespot.user.port.out.UserPort +import com.wespot.vote.dto.response.top1.VoteResultResponsesOfTop1 +import com.wespot.vote.dto.response.top5.VoteResultResponsesOfTop5 +import com.wespot.vote.port.`in`.VoteRankUseCase +import com.wespot.vote.port.out.VoteOptionPort +import com.wespot.vote.port.out.VotePort +import org.springframework.stereotype.Service +import java.time.LocalDate + +@Service +class VoteRankService( + private val votePort: VotePort, + private val voteOptionPort: VoteOptionPort, + private val userPort: UserPort, +) : VoteRankUseCase { + + override fun getVoteResultsOfTop5(userId: Long, date: LocalDate): VoteResultResponsesOfTop5 { + TODO("Not yet implemented") + } + + override fun getVoteResultsOfTop1(userId: Long, date: LocalDate): VoteResultResponsesOfTop1 { + TODO("Not yet implemented") + } + +} From 9b108116fab43e71e7bbd1a31897f971c198cb1d Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Mon, 22 Jul 2024 15:48:00 +0900 Subject: [PATCH 03/23] =?UTF-8?q?feat:=20API=20=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/com/wespot/vote/VoteController.kt | 34 ++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/app/src/main/kotlin/com/wespot/vote/VoteController.kt b/app/src/main/kotlin/com/wespot/vote/VoteController.kt index eca436fa..092bee94 100644 --- a/app/src/main/kotlin/com/wespot/vote/VoteController.kt +++ b/app/src/main/kotlin/com/wespot/vote/VoteController.kt @@ -3,24 +3,30 @@ package com.wespot.vote import com.wespot.vote.dto.request.VoteRequests import com.wespot.vote.dto.response.SaveVoteResponse import com.wespot.vote.dto.response.VoteItems -import com.wespot.vote.port.`in`.SaveVoteUseCase +import com.wespot.vote.dto.response.top1.VoteResultResponsesOfTop1 +import com.wespot.vote.dto.response.top5.VoteResultResponsesOfTop5 +import com.wespot.vote.port.`in`.SavedVoteUseCase +import com.wespot.vote.port.`in`.VoteRankUseCase import org.springframework.http.HttpStatus import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.PostMapping import org.springframework.web.bind.annotation.RequestBody import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RequestParam import org.springframework.web.bind.annotation.RestController +import java.time.LocalDate @RestController @RequestMapping("/v1/votes") class VoteController( - private val saveVoteUseCase: SaveVoteUseCase + private val savedVoteUseCase: SavedVoteUseCase, + private val voteRankUseCase: VoteRankUseCase ) { @GetMapping("/options") fun getVoteOptions(userId: Long): ResponseEntity { - val responses = saveVoteUseCase.getVoteOptions(userId) + val responses = savedVoteUseCase.getVoteOptions(userId) return ResponseEntity.ok(responses) } @@ -29,9 +35,29 @@ class VoteController( userId: Long, @RequestBody requests: VoteRequests ): ResponseEntity { - val savedId: SaveVoteResponse = saveVoteUseCase.saveVote(userId, requests) + val savedId: SaveVoteResponse = savedVoteUseCase.saveVote(userId, requests) return ResponseEntity.status(HttpStatus.CREATED) .body(savedId) } + @GetMapping + fun getTop5VoteResults( + userId: Long, + @RequestParam date: LocalDate + ): ResponseEntity { + val responses: VoteResultResponsesOfTop5 = voteRankUseCase.getVoteResultsOfTop5(userId, date) + + return ResponseEntity.ok(responses) + } + + @GetMapping("/tops") + fun getTop1VoteResults( + userId: Long, + @RequestParam date: LocalDate + ): ResponseEntity { + val responses: VoteResultResponsesOfTop1 = voteRankUseCase.getVoteResultsOfTop1(userId, date) + + return ResponseEntity.ok(responses) + } + } From bb765fa02215a7d0839a20d01f72fcd9c287c045 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Mon, 22 Jul 2024 15:48:20 +0900 Subject: [PATCH 04/23] =?UTF-8?q?feat:=20DTO=20=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wespot/vote/service/VoteServiceTest.kt | 2 +- .../dto/response/top1/UserResponseOfTop1.kt | 25 +++++++++++++++ .../top1/VoteDetailResultResponseOfTop1.kt | 21 +++++++++++++ .../response/top1/VoteResultResponseOfTop1.kt | 31 +++++++++++++++++++ .../top1/VoteResultResponsesOfTop1.kt | 20 ++++++++++++ .../dto/response/top5/UserResponseOfTop5.kt | 26 ++++++++++++++++ .../top5/VoteDetailResultResponseOfTop5.kt | 21 +++++++++++++ .../response/top5/VoteResultResponseOfTop5.kt | 25 +++++++++++++++ .../top5/VoteResultResponsesOfTop5.kt | 19 ++++++++++++ 9 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 core/src/main/kotlin/com/wespot/vote/dto/response/top1/UserResponseOfTop1.kt create mode 100644 core/src/main/kotlin/com/wespot/vote/dto/response/top1/VoteDetailResultResponseOfTop1.kt create mode 100644 core/src/main/kotlin/com/wespot/vote/dto/response/top1/VoteResultResponseOfTop1.kt create mode 100644 core/src/main/kotlin/com/wespot/vote/dto/response/top1/VoteResultResponsesOfTop1.kt create mode 100644 core/src/main/kotlin/com/wespot/vote/dto/response/top5/UserResponseOfTop5.kt create mode 100644 core/src/main/kotlin/com/wespot/vote/dto/response/top5/VoteDetailResultResponseOfTop5.kt create mode 100644 core/src/main/kotlin/com/wespot/vote/dto/response/top5/VoteResultResponseOfTop5.kt create mode 100644 core/src/main/kotlin/com/wespot/vote/dto/response/top5/VoteResultResponsesOfTop5.kt diff --git a/app/src/test/kotlin/com/wespot/vote/service/VoteServiceTest.kt b/app/src/test/kotlin/com/wespot/vote/service/VoteServiceTest.kt index 7f74e885..d18d4da8 100644 --- a/app/src/test/kotlin/com/wespot/vote/service/VoteServiceTest.kt +++ b/app/src/test/kotlin/com/wespot/vote/service/VoteServiceTest.kt @@ -29,7 +29,7 @@ import kotlin.test.Test @SpringBootTest class VoteServiceTest( @Autowired - private var voteService: SaveVoteService, + private var voteService: SavedVoteService, @Autowired private var databaseCleanup: DatabaseCleanup, @Autowired diff --git a/core/src/main/kotlin/com/wespot/vote/dto/response/top1/UserResponseOfTop1.kt b/core/src/main/kotlin/com/wespot/vote/dto/response/top1/UserResponseOfTop1.kt new file mode 100644 index 00000000..cbf9f0c9 --- /dev/null +++ b/core/src/main/kotlin/com/wespot/vote/dto/response/top1/UserResponseOfTop1.kt @@ -0,0 +1,25 @@ +package com.wespot.vote.dto.response.top1 + +import com.wespot.user.User + +data class UserResponseOfTop1( + val id: Long, + val name: String, + val introduction: String, + val iconUrl: String, +) { + + companion object { + + fun from(user: User): UserResponseOfTop1 { + return UserResponseOfTop1( + user.id, + user.name, + user.introduction, + user.profile.iconUrl + ) + } + + } + +} diff --git a/core/src/main/kotlin/com/wespot/vote/dto/response/top1/VoteDetailResultResponseOfTop1.kt b/core/src/main/kotlin/com/wespot/vote/dto/response/top1/VoteDetailResultResponseOfTop1.kt new file mode 100644 index 00000000..1e87afdd --- /dev/null +++ b/core/src/main/kotlin/com/wespot/vote/dto/response/top1/VoteDetailResultResponseOfTop1.kt @@ -0,0 +1,21 @@ +package com.wespot.vote.dto.response.top1 + +import com.wespot.vote.VoteRecord + +data class VoteDetailResultResponseOfTop1( + val user: UserResponseOfTop1, + val voteCount: Int +) { + + companion object { + + fun from(voteRecords: VoteRecord): VoteDetailResultResponseOfTop1 { + return VoteDetailResultResponseOfTop1( + UserResponseOfTop1.from(voteRecords.user), + voteRecords.voteCount + ) + } + + } + +} diff --git a/core/src/main/kotlin/com/wespot/vote/dto/response/top1/VoteResultResponseOfTop1.kt b/core/src/main/kotlin/com/wespot/vote/dto/response/top1/VoteResultResponseOfTop1.kt new file mode 100644 index 00000000..8058d6f6 --- /dev/null +++ b/core/src/main/kotlin/com/wespot/vote/dto/response/top1/VoteResultResponseOfTop1.kt @@ -0,0 +1,31 @@ +package com.wespot.vote.dto.response.top1 + +import com.wespot.vote.VoteRecord +import com.wespot.vote.dto.response.VoteOptionResponse +import com.wespot.voteoption.VoteOption + +data class VoteResultResponseOfTop1( + val voteOption: VoteOptionResponse, + val voteResult: VoteDetailResultResponseOfTop1? +) { + + companion object { + + fun of(voteOption: VoteOption, voteResults: List): VoteResultResponseOfTop1 { + return VoteResultResponseOfTop1( + VoteOptionResponse.from(voteOption), + getVoteDetailResultResponseOfTop1(voteResults) + ) + } + + private fun getVoteDetailResultResponseOfTop1(voteResults: List): VoteDetailResultResponseOfTop1? { + if (voteResults.isEmpty()) { + return null + } + + return VoteDetailResultResponseOfTop1.from(voteResults[0]) + } + + } + +} diff --git a/core/src/main/kotlin/com/wespot/vote/dto/response/top1/VoteResultResponsesOfTop1.kt b/core/src/main/kotlin/com/wespot/vote/dto/response/top1/VoteResultResponsesOfTop1.kt new file mode 100644 index 00000000..3fde1a6e --- /dev/null +++ b/core/src/main/kotlin/com/wespot/vote/dto/response/top1/VoteResultResponsesOfTop1.kt @@ -0,0 +1,20 @@ +package com.wespot.vote.dto.response.top1 + +import com.wespot.vote.VoteRecord +import com.wespot.voteoption.VoteOption + +data class VoteResultResponsesOfTop1( + val voteResults: List +) { + + companion object { + + fun from(voteResults: Map>): VoteResultResponsesOfTop1 { + val results = voteResults.map { VoteResultResponseOfTop1.of(it.key, it.value) } + .toList() + return VoteResultResponsesOfTop1(results) + } + + } + +} diff --git a/core/src/main/kotlin/com/wespot/vote/dto/response/top5/UserResponseOfTop5.kt b/core/src/main/kotlin/com/wespot/vote/dto/response/top5/UserResponseOfTop5.kt new file mode 100644 index 00000000..f2dba8b4 --- /dev/null +++ b/core/src/main/kotlin/com/wespot/vote/dto/response/top5/UserResponseOfTop5.kt @@ -0,0 +1,26 @@ +package com.wespot.vote.dto.response.top5 + +import com.wespot.user.User +import com.wespot.user.dto.response.ProfileResponse + +data class UserResponseOfTop5( + val id: Long, + val name: String, + val introduction: String, + val profile: ProfileResponse +) { + + companion object { + + fun from(user: User): UserResponseOfTop5 { + return UserResponseOfTop5( + user.id, + user.name, + user.introduction, + ProfileResponse.from(user.profile) + ) + } + + } + +} diff --git a/core/src/main/kotlin/com/wespot/vote/dto/response/top5/VoteDetailResultResponseOfTop5.kt b/core/src/main/kotlin/com/wespot/vote/dto/response/top5/VoteDetailResultResponseOfTop5.kt new file mode 100644 index 00000000..fd1d99ca --- /dev/null +++ b/core/src/main/kotlin/com/wespot/vote/dto/response/top5/VoteDetailResultResponseOfTop5.kt @@ -0,0 +1,21 @@ +package com.wespot.vote.dto.response.top5 + +import com.wespot.vote.VoteRecord + +data class VoteDetailResultResponseOfTop5( + val user: UserResponseOfTop5, + val voteCount: Int +) { + + companion object { + + fun from(voteRecords: VoteRecord): VoteDetailResultResponseOfTop5 { + return VoteDetailResultResponseOfTop5( + UserResponseOfTop5.from(voteRecords.user), + voteRecords.voteCount + ) + } + + } + +} diff --git a/core/src/main/kotlin/com/wespot/vote/dto/response/top5/VoteResultResponseOfTop5.kt b/core/src/main/kotlin/com/wespot/vote/dto/response/top5/VoteResultResponseOfTop5.kt new file mode 100644 index 00000000..de1ca50e --- /dev/null +++ b/core/src/main/kotlin/com/wespot/vote/dto/response/top5/VoteResultResponseOfTop5.kt @@ -0,0 +1,25 @@ +package com.wespot.vote.dto.response.top5 + +import com.wespot.vote.VoteRecord +import com.wespot.vote.dto.response.VoteOptionResponse +import com.wespot.voteoption.VoteOption + +data class VoteResultResponseOfTop5( + val voteOption: VoteOptionResponse, + val voteResults: List +) { + + companion object { + + fun of(voteOption: VoteOption, voteResults: List): VoteResultResponseOfTop5 { + return VoteResultResponseOfTop5( + VoteOptionResponse.from(voteOption), + voteResults.stream() + .map { VoteDetailResultResponseOfTop5.from(it) } + .toList() + ) + } + + } + +} diff --git a/core/src/main/kotlin/com/wespot/vote/dto/response/top5/VoteResultResponsesOfTop5.kt b/core/src/main/kotlin/com/wespot/vote/dto/response/top5/VoteResultResponsesOfTop5.kt new file mode 100644 index 00000000..0d89becb --- /dev/null +++ b/core/src/main/kotlin/com/wespot/vote/dto/response/top5/VoteResultResponsesOfTop5.kt @@ -0,0 +1,19 @@ +package com.wespot.vote.dto.response.top5 + +import com.wespot.voteoption.VoteOption + +data class VoteResultResponsesOfTop5( + val voteResults: List +) { + + companion object { + + fun from(voteResults: Map>): VoteResultResponsesOfTop5 { + val results = voteResults.map { VoteResultResponseOfTop5.of(it.key, it.value) } + .toList() + return VoteResultResponsesOfTop5(results) + } + + } + +} From a501dcf5c51425099252a6b38f1dc952d98b2ce5 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Mon, 22 Jul 2024 15:49:37 +0900 Subject: [PATCH 05/23] =?UTF-8?q?feat:=20=EC=98=A4=EB=8A=98=EC=9D=98=20?= =?UTF-8?q?=EC=A7=88=EB=AC=B8=EC=A7=80=EB=A5=BC=20=EA=B0=90=EC=8B=B8?= =?UTF-8?q?=EB=8A=94=20=EA=B0=9D=EC=B2=B4=20=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/wespot/vote/VoteOptionsByVoteDate.kt | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 domain/src/main/kotlin/com/wespot/vote/VoteOptionsByVoteDate.kt diff --git a/domain/src/main/kotlin/com/wespot/vote/VoteOptionsByVoteDate.kt b/domain/src/main/kotlin/com/wespot/vote/VoteOptionsByVoteDate.kt new file mode 100644 index 00000000..73faf467 --- /dev/null +++ b/domain/src/main/kotlin/com/wespot/vote/VoteOptionsByVoteDate.kt @@ -0,0 +1,30 @@ +package com.wespot.vote + +import com.wespot.voteoption.VoteOption +import java.time.LocalDate + +data class VoteOptionsByVoteDate( + val voteDate: LocalDate, + val voteOptions: List +) { + + companion object { + fun of(date: LocalDate, voteOptions: List): VoteOptionsByVoteDate { + if (voteOptions.size != 5) { + throw IllegalArgumentException("선택지는 5개가 주어져야 합니다.") + } + + return VoteOptionsByVoteDate(date, voteOptions) + } + } + + fun validateVoteOption( + voteOptionId: Long + ) { + if (voteOptions.find { it.id == voteOptionId } != null) { + return + } + throw IllegalArgumentException("오늘 제공된 질문지만 선택해 투표할 수 있습니다.") + } + +} From 853840eea9fdb6ff05ebc7a0affea8a461977440 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Mon, 22 Jul 2024 15:50:20 +0900 Subject: [PATCH 06/23] =?UTF-8?q?feat:=20VoteMetrics,=20VoteRecord=20?= =?UTF-8?q?=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/com/wespot/vote/VoteMetrics.kt | 29 +++++++++++ .../main/kotlin/com/wespot/vote/VoteRecord.kt | 51 +++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 domain/src/main/kotlin/com/wespot/vote/VoteMetrics.kt create mode 100644 domain/src/main/kotlin/com/wespot/vote/VoteRecord.kt diff --git a/domain/src/main/kotlin/com/wespot/vote/VoteMetrics.kt b/domain/src/main/kotlin/com/wespot/vote/VoteMetrics.kt new file mode 100644 index 00000000..2d242a7c --- /dev/null +++ b/domain/src/main/kotlin/com/wespot/vote/VoteMetrics.kt @@ -0,0 +1,29 @@ +package com.wespot.vote + +import java.time.LocalDateTime + +data class VoteMetrics( + val userId: Long, + val lastVotedDateTime: LocalDateTime, + val voteCount: Int, + val isReceiverRead: Boolean +) { + + companion object { + + fun createInitialState(userId: Long): VoteMetrics { + return VoteMetrics(userId, LocalDateTime.MIN, 0, false) + } + + } + + fun recordVote(ballot: Ballot): VoteMetrics { + return VoteMetrics( + userId = userId, + lastVotedDateTime = maxOf(lastVotedDateTime, ballot.createdAt), + voteCount = voteCount + 1, + isReceiverRead = isReceiverRead || ballot.isReceiverRead + ) + } + +} diff --git a/domain/src/main/kotlin/com/wespot/vote/VoteRecord.kt b/domain/src/main/kotlin/com/wespot/vote/VoteRecord.kt new file mode 100644 index 00000000..dd09e70e --- /dev/null +++ b/domain/src/main/kotlin/com/wespot/vote/VoteRecord.kt @@ -0,0 +1,51 @@ +package com.wespot.vote + +import com.wespot.user.User +import java.time.LocalDateTime +import java.util.* + +data class VoteRecord( + val user: User, + val rate: Int, + val lastVotedDateTime: LocalDateTime, + val voteCount: Int, + val isReceiverRead: Boolean +) { + + companion object { + fun of( + user: User, + voteMetrics: VoteMetrics + ): VoteRecord { + validateInvalidUser(user) + return VoteRecord( + user, + rate = Int.MAX_VALUE, + voteMetrics.lastVotedDateTime, + voteMetrics.voteCount, + voteMetrics.isReceiverRead + ) + } + + private fun validateInvalidUser(user: User) { + if (Objects.isNull(user)) { + throw IllegalArgumentException("존재하지 않는 사용자에 대한 투표가 존재합니다.") + } + } + + fun ofWithRate( + user: User, + rate: Int, + voteMetrics: VoteMetrics + ): VoteRecord { + return VoteRecord( + user, + rate, + voteMetrics.lastVotedDateTime, + voteMetrics.voteCount, + voteMetrics.isReceiverRead + ) + } + } + +} From d7b1317e0d5a6c49b762b1b58e1c372eba01caf3 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Mon, 22 Jul 2024 15:58:32 +0900 Subject: [PATCH 07/23] =?UTF-8?q?feat:=20Domain=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/com/wespot/vote/domain/VoteTest.kt | 21 ++----- .../top5/VoteResultResponsesOfTop5.kt | 1 + .../wespot/vote/service/SavedVoteService.kt | 17 ++---- .../com/wespot/vote/BallotsAggregator.kt | 40 +++++++++++++ .../src/main/kotlin/com/wespot/vote/Vote.kt | 56 +++++++++++-------- 5 files changed, 86 insertions(+), 49 deletions(-) create mode 100644 domain/src/main/kotlin/com/wespot/vote/BallotsAggregator.kt diff --git a/app/src/test/kotlin/com/wespot/vote/domain/VoteTest.kt b/app/src/test/kotlin/com/wespot/vote/domain/VoteTest.kt index 1b404818..a52faa5d 100644 --- a/app/src/test/kotlin/com/wespot/vote/domain/VoteTest.kt +++ b/app/src/test/kotlin/com/wespot/vote/domain/VoteTest.kt @@ -20,7 +20,7 @@ class VoteTest() : BehaviorSpec({ `when`("voteNumber가 0일 때의 오늘의 질문지를") { val vote = VoteFixture.createWithVoteNumberAndBallots(0, Collections.emptyList()) - val todayVoteOptions = vote.findTodayVoteOptions(voteOptions) + val todayVoteOptions = vote.findVoteOptionsByVoteDate(voteOptions).voteOptions then("정상적으로 반환한다.") { todayVoteOptions[0].id shouldBe 1 @@ -33,7 +33,7 @@ class VoteTest() : BehaviorSpec({ `when`("voteNumber가 1일 때의 오늘의 질문지를") { val vote = VoteFixture.createWithVoteNumberAndBallots(1, Collections.emptyList()) - val todayVoteOptions = vote.findTodayVoteOptions(voteOptions) + val todayVoteOptions = vote.findVoteOptionsByVoteDate(voteOptions).voteOptions then("정상적으로 반환한다.") { todayVoteOptions[0].id shouldBe 6 @@ -50,7 +50,7 @@ class VoteTest() : BehaviorSpec({ `when`("5개 미만인 경우") { val vote = VoteFixture.createWithVoteNumberAndBallots(0, Collections.emptyList()) - val throwingCallable = { vote.findTodayVoteOptions(voteOptions) } + val throwingCallable = { vote.findVoteOptionsByVoteDate(voteOptions) } then("예외를 발생시킨다.") { val shouldThrow = shouldThrow(throwingCallable) @@ -66,10 +66,7 @@ class VoteTest() : BehaviorSpec({ val voteOptions = createVoteOptionByCount(10) `when`("중복된 투표를 하는 경우") { val vote = VoteFixture.createWithVoteNumberAndBallots(0, ballots) - val todayVoteOptions = vote.findTodayVoteOptions(voteOptions) - .stream() - .map { it.id } - .toList() + val todayVoteOptions = vote.findVoteOptionsByVoteDate(voteOptions) then("예외가 발생한다.") { val shouldThrow = shouldThrow { @@ -86,10 +83,7 @@ class VoteTest() : BehaviorSpec({ `when`("중복되지 않은 투표를 하는 경우") { val vote = VoteFixture.createWithVoteNumberAndBallots(0, ballots) - val todayVoteOptions = vote.findTodayVoteOptions(voteOptions) - .stream() - .map { it.id } - .toList() + val todayVoteOptions = vote.findVoteOptionsByVoteDate(voteOptions) then("정상적으로 투표가 진행된다.") { shouldNotThrow { @@ -105,10 +99,7 @@ class VoteTest() : BehaviorSpec({ `when`("오늘의 질문지가 아닌 질문지를 선택한 경우") { val vote = VoteFixture.createWithVoteNumberAndBallots(0, ballots) - val todayVoteOptions = vote.findTodayVoteOptions(voteOptions) - .stream() - .map { it.id } - .toList() + val todayVoteOptions = vote.findVoteOptionsByVoteDate(voteOptions) then("예외가 발생한다.") { val shouldThrow = shouldThrow { diff --git a/core/src/main/kotlin/com/wespot/vote/dto/response/top5/VoteResultResponsesOfTop5.kt b/core/src/main/kotlin/com/wespot/vote/dto/response/top5/VoteResultResponsesOfTop5.kt index 0d89becb..6fe3f2c2 100644 --- a/core/src/main/kotlin/com/wespot/vote/dto/response/top5/VoteResultResponsesOfTop5.kt +++ b/core/src/main/kotlin/com/wespot/vote/dto/response/top5/VoteResultResponsesOfTop5.kt @@ -1,5 +1,6 @@ package com.wespot.vote.dto.response.top5 +import com.wespot.vote.VoteRecord import com.wespot.voteoption.VoteOption data class VoteResultResponsesOfTop5( diff --git a/core/src/main/kotlin/com/wespot/vote/service/SavedVoteService.kt b/core/src/main/kotlin/com/wespot/vote/service/SavedVoteService.kt index 04bc199c..b02fea09 100644 --- a/core/src/main/kotlin/com/wespot/vote/service/SavedVoteService.kt +++ b/core/src/main/kotlin/com/wespot/vote/service/SavedVoteService.kt @@ -3,6 +3,7 @@ package com.wespot.vote.service import com.wespot.user.User import com.wespot.user.port.out.UserPort import com.wespot.vote.Vote +import com.wespot.vote.VoteOptionsByVoteDate import com.wespot.vote.dto.request.VoteRequest import com.wespot.vote.dto.request.VoteRequests import com.wespot.vote.dto.response.SaveVoteResponse @@ -28,12 +29,12 @@ class SavedVoteService( val classmates = findClassmatesByUser(user) val today = LocalDate.now() val vote: Vote = findVoteByUser(user, today) - val todayVoteOptions: List = findTodayVoteOptions(vote) + val todayVoteOptions: VoteOptionsByVoteDate = findVoteOptionsByVoteDate(vote) val usersForVote: List = vote.findUsersForVote(classmates = classmates, user = user) return VoteItems.of( classmates = usersForVote, - voteOptions = todayVoteOptions + voteOptions = todayVoteOptions.voteOptions ) } @@ -59,10 +60,10 @@ class SavedVoteService( ) ?: throw IllegalArgumentException("해당 투표가 존재하지 않습니다.") } - private fun findTodayVoteOptions(vote: Vote): List { + private fun findVoteOptionsByVoteDate(vote: Vote): VoteOptionsByVoteDate { val voteOptions: List = voteOptionPort.findAllVoteOption() - return vote.findTodayVoteOptions(voteOptions) + return vote.findVoteOptionsByVoteDate(voteOptions) } @Transactional @@ -78,7 +79,7 @@ class SavedVoteService( requests.voteRequests.stream() .forEach { request -> vote.addBallot( - todayVoteOptionsIds = findTodayVoteOptionIds(vote), + voteOptionsByVoteDate = findVoteOptionsByVoteDate(vote), voteOptionId = request.voteOptionId, senderId = userId, receiverId = request.userId @@ -109,10 +110,4 @@ class SavedVoteService( throw IllegalArgumentException("투표하고자 하는 회원이 존재하지 않습니다.") } - private fun findTodayVoteOptionIds(vote: Vote): List { - return findTodayVoteOptions(vote).stream() - .map { it.id } - .toList() - } - } diff --git a/domain/src/main/kotlin/com/wespot/vote/BallotsAggregator.kt b/domain/src/main/kotlin/com/wespot/vote/BallotsAggregator.kt new file mode 100644 index 00000000..eb486f12 --- /dev/null +++ b/domain/src/main/kotlin/com/wespot/vote/BallotsAggregator.kt @@ -0,0 +1,40 @@ +package com.wespot.vote + +class BallotsAggregator( + val ballots: List +) { + + companion object { + + fun of(voteOptionId: Long, ballots: List): BallotsAggregator { + if (isBallotsForVoteOption(ballots, voteOptionId)) { + throw IllegalArgumentException("서로 다른 질문지에 대한 결과가 섞였습니다.") + } + return BallotsAggregator(ballots) + } + + private fun isBallotsForVoteOption( + ballots: List, + voteOptionId: Long + ) = ballots.stream() + .anyMatch { it.voteOptionId != voteOptionId } + + } + + fun getRankedResults(): List { + val ranked: MutableMap = LinkedHashMap() + ballots.forEach { + val voteMetrics = + ranked.getOrDefault(it.receiverId, VoteMetrics.createInitialState(it.receiverId)) + ranked[it.receiverId] = voteMetrics.recordVote(it) + } + + return calculatedRanked(ranked.map { it.value }) + } + + private fun calculatedRanked( + ranked: List + ) = ranked.sortedByDescending { it.lastVotedDateTime } + .sortedByDescending { it.voteCount } + +} diff --git a/domain/src/main/kotlin/com/wespot/vote/Vote.kt b/domain/src/main/kotlin/com/wespot/vote/Vote.kt index 883640a8..8f27d22a 100644 --- a/domain/src/main/kotlin/com/wespot/vote/Vote.kt +++ b/domain/src/main/kotlin/com/wespot/vote/Vote.kt @@ -20,26 +20,26 @@ data class Vote( private val MOVE_TO_NEXT_VOTE_OPTION = 1 } - fun findTodayVoteOptions(voteOptions: List): List { - validateVoteOptionsSize(voteOptions) - val todayVoteOptions: MutableList = mutableListOf() - var voteOptionIndex: Int = (voteNumber * NUMBER_OF_VOTE_OPTIONS) % voteOptions.size - while (todayVoteOptions.size < NUMBER_OF_VOTE_OPTIONS) { - todayVoteOptions.add(voteOptions[voteOptionIndex]) - voteOptionIndex = (voteOptionIndex + MOVE_TO_NEXT_VOTE_OPTION) % voteOptions.size + fun findVoteOptionsByVoteDate(allVoteOptions: List): VoteOptionsByVoteDate { + validateVoteOptionsSize(allVoteOptions) + val voteOptionsByDate: MutableList = mutableListOf() + var voteOptionIndex: Int = (voteNumber * NUMBER_OF_VOTE_OPTIONS) % allVoteOptions.size + while (voteOptionsByDate.size < NUMBER_OF_VOTE_OPTIONS) { + voteOptionsByDate.add(allVoteOptions[voteOptionIndex]) + voteOptionIndex = (voteOptionIndex + MOVE_TO_NEXT_VOTE_OPTION) % allVoteOptions.size } - return todayVoteOptions.toList() + return VoteOptionsByVoteDate(date, voteOptionsByDate.toList()) } - private fun validateVoteOptionsSize(voteOptions: List) { - if (voteOptions.size < 5) { + private fun validateVoteOptionsSize(allVoteOptions: List) { + if (allVoteOptions.size < 5) { throw IllegalArgumentException("선택지는 최소 5개 이상이어야 합니다.") } } fun findUsersForVote(classmates: List, user: User): List { - val alreadyVotedByUser: List = ballots.findUserIdsVotedByUser(user.id) + val alreadyVotedByUser: List = ballots.findUserIdsVotedByUser(user.id!!) return classmates.stream() .filter { !alreadyVotedByUser.contains(it.id) && isNotMe(it, user) } .toList() @@ -49,12 +49,12 @@ data class Vote( private fun isNotMe(classmate: User, user: User) = classmate != user fun addBallot( - todayVoteOptionsIds: List, + voteOptionsByVoteDate: VoteOptionsByVoteDate, voteOptionId: Long, senderId: Long, receiverId: Long ) { - validateVoteOption(todayVoteOptionsIds, voteOptionId) + voteOptionsByVoteDate.validateVoteOption(voteOptionId) ballots.add( Ballot.of( voteId = id, @@ -65,16 +65,6 @@ data class Vote( ) } - private fun validateVoteOption( - todayVoteOptionsIds: List, - voteOptionId: Long - ) { - if (todayVoteOptionsIds.contains(voteOptionId)) { - return - } - throw IllegalArgumentException("오늘 제공된 질문지만 선택해 투표할 수 있습니다.") - } - fun getBallots(): List { return ballots.ballots .map { it.value } @@ -82,4 +72,24 @@ data class Vote( .toList() } + fun getRankedVoteResults( + voteOptionsByVoteDate: VoteOptionsByVoteDate, + users: List + ): Map> { + val usersAssociateBy = users.associateBy { it.id } + val rankedVoteResults: Map> = + getBallots().groupBy { it.voteOptionId } + .mapValues { BallotsAggregator.of(it.key, it.value) } + .mapValues { + it.value.getRankedResults() + .filter { usersAssociateBy.containsKey(it.userId) } + .map { VoteRecord.of(usersAssociateBy[it.userId]!!, it) } + } + .toMap(LinkedHashMap()) + + return voteOptionsByVoteDate.voteOptions + .associateWith { rankedVoteResults[it.id] ?: emptyList() } + .toMap(LinkedHashMap()) + } + } From 058a95c98e570907d0509474550da025a678ad8b Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Mon, 22 Jul 2024 16:00:22 +0900 Subject: [PATCH 08/23] =?UTF-8?q?refactor:=20=EC=A1=B0=ED=9A=8C=EC=97=90?= =?UTF-8?q?=EB=8A=94=20Transactional=20=EC=96=B4=EB=85=B8=ED=85=8C?= =?UTF-8?q?=EC=9D=B4=EC=85=98=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/{VoteServiceTest.kt => SavedVoteServiceTest.kt} | 2 +- .../src/main/kotlin/com/wespot/vote/service/SavedVoteService.kt | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) rename app/src/test/kotlin/com/wespot/vote/service/{VoteServiceTest.kt => SavedVoteServiceTest.kt} (99%) diff --git a/app/src/test/kotlin/com/wespot/vote/service/VoteServiceTest.kt b/app/src/test/kotlin/com/wespot/vote/service/SavedVoteServiceTest.kt similarity index 99% rename from app/src/test/kotlin/com/wespot/vote/service/VoteServiceTest.kt rename to app/src/test/kotlin/com/wespot/vote/service/SavedVoteServiceTest.kt index d18d4da8..7753c7c8 100644 --- a/app/src/test/kotlin/com/wespot/vote/service/VoteServiceTest.kt +++ b/app/src/test/kotlin/com/wespot/vote/service/SavedVoteServiceTest.kt @@ -27,7 +27,7 @@ import java.util.* import kotlin.test.Test @SpringBootTest -class VoteServiceTest( +class SavedVoteServiceTest( @Autowired private var voteService: SavedVoteService, @Autowired diff --git a/core/src/main/kotlin/com/wespot/vote/service/SavedVoteService.kt b/core/src/main/kotlin/com/wespot/vote/service/SavedVoteService.kt index b02fea09..822d0fac 100644 --- a/core/src/main/kotlin/com/wespot/vote/service/SavedVoteService.kt +++ b/core/src/main/kotlin/com/wespot/vote/service/SavedVoteService.kt @@ -23,7 +23,6 @@ class SavedVoteService( private val userPort: UserPort, ) : SavedVoteUseCase { - @Transactional override fun getVoteOptions(userId: Long): VoteItems { val user: User = findUser(userId) val classmates = findClassmatesByUser(user) From 0d70fa18339d18934a50382600447a6e65985f81 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Mon, 22 Jul 2024 16:05:27 +0900 Subject: [PATCH 09/23] =?UTF-8?q?feat:=20=EC=88=9C=EC=9C=84=20=EB=B0=98?= =?UTF-8?q?=ED=99=98=20=EC=84=9C=EB=B9=84=EC=8A=A4=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wespot/vote/service/VoteRankService.kt | 19 ++++++++- .../vote/service/helper/VoteServiceHelper.kt | 42 +++++++++++++++++++ 2 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 core/src/main/kotlin/com/wespot/vote/service/helper/VoteServiceHelper.kt diff --git a/core/src/main/kotlin/com/wespot/vote/service/VoteRankService.kt b/core/src/main/kotlin/com/wespot/vote/service/VoteRankService.kt index 7f2b660e..3e8f9686 100644 --- a/core/src/main/kotlin/com/wespot/vote/service/VoteRankService.kt +++ b/core/src/main/kotlin/com/wespot/vote/service/VoteRankService.kt @@ -1,11 +1,14 @@ package com.wespot.vote.service import com.wespot.user.port.out.UserPort +import com.wespot.vote.VoteRecord import com.wespot.vote.dto.response.top1.VoteResultResponsesOfTop1 import com.wespot.vote.dto.response.top5.VoteResultResponsesOfTop5 import com.wespot.vote.port.`in`.VoteRankUseCase import com.wespot.vote.port.out.VoteOptionPort import com.wespot.vote.port.out.VotePort +import com.wespot.vote.service.helper.VoteServiceHelper +import com.wespot.voteoption.VoteOption import org.springframework.stereotype.Service import java.time.LocalDate @@ -17,11 +20,23 @@ class VoteRankService( ) : VoteRankUseCase { override fun getVoteResultsOfTop5(userId: Long, date: LocalDate): VoteResultResponsesOfTop5 { - TODO("Not yet implemented") + return VoteResultResponsesOfTop5.from(getRankedVoteResults(userId, date)) + } + + private fun getRankedVoteResults( + userId: Long, + date: LocalDate + ): Map> { + val user = VoteServiceHelper.findUser(userPort, userId) + val classmates = VoteServiceHelper.findClassmatesByUser(userPort, user) + val vote = VoteServiceHelper.findVoteByUser(votePort, user, date) + val voteOptions = VoteServiceHelper.findVoteOptionsByVoteDate(voteOptionPort, vote) + val rankedVoteResults = vote.getRankedVoteResults(voteOptions, classmates) + return rankedVoteResults } override fun getVoteResultsOfTop1(userId: Long, date: LocalDate): VoteResultResponsesOfTop1 { - TODO("Not yet implemented") + return VoteResultResponsesOfTop1.from(getRankedVoteResults(userId, date)) } } diff --git a/core/src/main/kotlin/com/wespot/vote/service/helper/VoteServiceHelper.kt b/core/src/main/kotlin/com/wespot/vote/service/helper/VoteServiceHelper.kt new file mode 100644 index 00000000..25d2469e --- /dev/null +++ b/core/src/main/kotlin/com/wespot/vote/service/helper/VoteServiceHelper.kt @@ -0,0 +1,42 @@ +package com.wespot.vote.service.helper + +import com.wespot.user.User +import com.wespot.user.port.out.UserPort +import com.wespot.vote.Vote +import com.wespot.vote.VoteOptionsByVoteDate +import com.wespot.vote.port.out.VoteOptionPort +import com.wespot.vote.port.out.VotePort +import com.wespot.voteoption.VoteOption +import java.time.LocalDate + +object VoteServiceHelper { + + fun findUser(userPort: UserPort, userId: Long): User { + return userPort.findById(userId) + ?: throw IllegalArgumentException("ID에 해당하는 사용자가 존재하지 않습니다.") + } + + fun findClassmatesByUser(userPort: UserPort, user: User): List { + return userPort.findAllBySchoolIdAndGradeAndClassNumber( + schoolId = user.schoolId, + grade = user.grade, + groupNumber = user.classNumber + ) + } + + fun findVoteByUser(votePort: VotePort, user: User, date: LocalDate): Vote { + return votePort.findBySchoolIdAndGradeAndClassNumberAndDate( + schoolId = user.schoolId, + grade = user.grade, + groupNumber = user.classNumber, + date = date + ) ?: throw IllegalArgumentException("해당 투표가 존재하지 않습니다.") + } + + fun findVoteOptionsByVoteDate(voteOptionPort: VoteOptionPort, vote: Vote): VoteOptionsByVoteDate { + val voteOptions: List = voteOptionPort.findAllVoteOption() + + return vote.findVoteOptionsByVoteDate(voteOptions) + } + +} From 84175b5cde63f0f06030d12c047f0e82ceb56f12 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Mon, 22 Jul 2024 16:09:25 +0900 Subject: [PATCH 10/23] =?UTF-8?q?refactor:=20SavedVoteService=EC=97=90?= =?UTF-8?q?=EC=84=9C=20Helper=EB=A5=BC=20=EC=82=AC=EC=9A=A9=ED=95=A0=20?= =?UTF-8?q?=EC=88=98=20=EC=9E=88=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wespot/vote/service/SavedVoteService.kt | 51 ++++--------------- .../wespot/vote/service/VoteRankService.kt | 1 + 2 files changed, 11 insertions(+), 41 deletions(-) diff --git a/core/src/main/kotlin/com/wespot/vote/service/SavedVoteService.kt b/core/src/main/kotlin/com/wespot/vote/service/SavedVoteService.kt index 822d0fac..54a547d0 100644 --- a/core/src/main/kotlin/com/wespot/vote/service/SavedVoteService.kt +++ b/core/src/main/kotlin/com/wespot/vote/service/SavedVoteService.kt @@ -11,7 +11,7 @@ import com.wespot.vote.dto.response.VoteItems import com.wespot.vote.port.`in`.SavedVoteUseCase import com.wespot.vote.port.out.VoteOptionPort import com.wespot.vote.port.out.VotePort -import com.wespot.voteoption.VoteOption +import com.wespot.vote.service.helper.VoteServiceHelper import jakarta.transaction.Transactional import org.springframework.stereotype.Service import java.time.LocalDate @@ -24,12 +24,12 @@ class SavedVoteService( ) : SavedVoteUseCase { override fun getVoteOptions(userId: Long): VoteItems { - val user: User = findUser(userId) - val classmates = findClassmatesByUser(user) + val user: User = VoteServiceHelper.findUser(userPort, userId) + val classmates = VoteServiceHelper.findClassmatesByUser(userPort, user) val today = LocalDate.now() - val vote: Vote = findVoteByUser(user, today) - val todayVoteOptions: VoteOptionsByVoteDate = findVoteOptionsByVoteDate(vote) - val usersForVote: List = vote.findUsersForVote(classmates = classmates, user = user) + val vote: Vote = VoteServiceHelper.findVoteByUser(votePort, user, today) + val todayVoteOptions: VoteOptionsByVoteDate = VoteServiceHelper.findVoteOptionsByVoteDate(voteOptionPort, vote) + val usersForVote: List = vote.findUsersForVote(classmates, user) return VoteItems.of( classmates = usersForVote, @@ -37,34 +37,6 @@ class SavedVoteService( ) } - private fun findUser(userId: Long): User { - return userPort.findById(userId) - ?: throw IllegalArgumentException("ID에 해당하는 사용자가 존재하지 않습니다.") - } - - private fun findClassmatesByUser(user: User): List { - return userPort.findAllBySchoolIdAndGradeAndClassNumber( - schoolId = user.schoolId, - grade = user.grade, - groupNumber = user.classNumber - ) - } - - private fun findVoteByUser(user: User, date: LocalDate): Vote { - return votePort.findBySchoolIdAndGradeAndClassNumberAndDate( - schoolId = user.schoolId, - grade = user.grade, - groupNumber = user.classNumber, - date = date - ) ?: throw IllegalArgumentException("해당 투표가 존재하지 않습니다.") - } - - private fun findVoteOptionsByVoteDate(vote: Vote): VoteOptionsByVoteDate { - val voteOptions: List = voteOptionPort.findAllVoteOption() - - return vote.findVoteOptionsByVoteDate(voteOptions) - } - @Transactional override fun saveVote( userId: Long, @@ -72,13 +44,13 @@ class SavedVoteService( ): SaveVoteResponse { validateRequestsSize(requests.voteRequests.size) validateUserIdsInRequests(requests.voteRequests) - val user: User = findUser(userId) + val user: User = VoteServiceHelper.findUser(userPort, userId) val today = LocalDate.now() - val vote: Vote = findVoteByUser(user = user, date = today) + val vote: Vote = VoteServiceHelper.findVoteByUser(votePort, user, today) requests.voteRequests.stream() .forEach { request -> vote.addBallot( - voteOptionsByVoteDate = findVoteOptionsByVoteDate(vote), + voteOptionsByVoteDate = VoteServiceHelper.findVoteOptionsByVoteDate(voteOptionPort, vote), voteOptionId = request.voteOptionId, senderId = userId, receiverId = request.userId @@ -98,11 +70,8 @@ class SavedVoteService( val userIds: List = requests.stream() .map { it.userId } .toList() - validateUserIds(userIds) - } - - private fun validateUserIds(userIds: List) { val foundUserIds = userPort.findIdsByIdIn(userIds) + if (foundUserIds.size == userIds.size) { return } diff --git a/core/src/main/kotlin/com/wespot/vote/service/VoteRankService.kt b/core/src/main/kotlin/com/wespot/vote/service/VoteRankService.kt index 3e8f9686..2123a761 100644 --- a/core/src/main/kotlin/com/wespot/vote/service/VoteRankService.kt +++ b/core/src/main/kotlin/com/wespot/vote/service/VoteRankService.kt @@ -32,6 +32,7 @@ class VoteRankService( val vote = VoteServiceHelper.findVoteByUser(votePort, user, date) val voteOptions = VoteServiceHelper.findVoteOptionsByVoteDate(voteOptionPort, vote) val rankedVoteResults = vote.getRankedVoteResults(voteOptions, classmates) + return rankedVoteResults } From 3735400904d33923f31af5433a996c5416f4cb40 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Mon, 22 Jul 2024 16:18:59 +0900 Subject: [PATCH 11/23] =?UTF-8?q?refactor:=20Response=20=EB=AA=85=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/wespot/vote/dto/response/VoteItem.kt | 4 ++-- .../vote/dto/response/VoteProfileResponse.kt | 21 +++++++++++++++++++ .../{UserResponse.kt => VoteUserResponse.kt} | 8 +++---- .../top1/VoteDetailResultResponseOfTop1.kt | 4 ++-- ...nseOfTop1.kt => VoteUserResponseOfTop1.kt} | 6 +++--- .../top5/VoteDetailResultResponseOfTop5.kt | 4 ++-- ...nseOfTop5.kt => VoteUserResponseOfTop5.kt} | 12 +++++------ 7 files changed, 40 insertions(+), 19 deletions(-) create mode 100644 core/src/main/kotlin/com/wespot/vote/dto/response/VoteProfileResponse.kt rename core/src/main/kotlin/com/wespot/vote/dto/response/{UserResponse.kt => VoteUserResponse.kt} (70%) rename core/src/main/kotlin/com/wespot/vote/dto/response/top1/{UserResponseOfTop1.kt => VoteUserResponseOfTop1.kt} (72%) rename core/src/main/kotlin/com/wespot/vote/dto/response/top5/{UserResponseOfTop5.kt => VoteUserResponseOfTop5.kt} (50%) diff --git a/core/src/main/kotlin/com/wespot/vote/dto/response/VoteItem.kt b/core/src/main/kotlin/com/wespot/vote/dto/response/VoteItem.kt index 8534a093..b5406ef0 100644 --- a/core/src/main/kotlin/com/wespot/vote/dto/response/VoteItem.kt +++ b/core/src/main/kotlin/com/wespot/vote/dto/response/VoteItem.kt @@ -4,7 +4,7 @@ import com.wespot.user.User import com.wespot.voteoption.VoteOption data class VoteItem( - val user: UserResponse, + val user: VoteUserResponse, val voteOptions: List ) { @@ -12,7 +12,7 @@ data class VoteItem( fun of(classmate: User, voteOptions: List): VoteItem { return VoteItem( - user = UserResponse.from(classmate), + user = VoteUserResponse.from(classmate), voteOptions = voteOptions.stream() .map { voteOption -> VoteOptionResponse.from(voteOption) } .toList() diff --git a/core/src/main/kotlin/com/wespot/vote/dto/response/VoteProfileResponse.kt b/core/src/main/kotlin/com/wespot/vote/dto/response/VoteProfileResponse.kt new file mode 100644 index 00000000..2f6e5fb6 --- /dev/null +++ b/core/src/main/kotlin/com/wespot/vote/dto/response/VoteProfileResponse.kt @@ -0,0 +1,21 @@ +package com.wespot.vote.dto.response + +import com.wespot.user.Profile + +data class VoteProfileResponse( + val backgroundColor: String, + val iconUrl: String +) { + + companion object { + + fun from(profile: Profile): VoteProfileResponse { + return VoteProfileResponse( + backgroundColor = profile.backgroundColor, + iconUrl = profile.iconUrl + ) + } + + } + +} diff --git a/core/src/main/kotlin/com/wespot/vote/dto/response/UserResponse.kt b/core/src/main/kotlin/com/wespot/vote/dto/response/VoteUserResponse.kt similarity index 70% rename from core/src/main/kotlin/com/wespot/vote/dto/response/UserResponse.kt rename to core/src/main/kotlin/com/wespot/vote/dto/response/VoteUserResponse.kt index aceb96c4..5a0f412b 100644 --- a/core/src/main/kotlin/com/wespot/vote/dto/response/UserResponse.kt +++ b/core/src/main/kotlin/com/wespot/vote/dto/response/VoteUserResponse.kt @@ -3,16 +3,16 @@ package com.wespot.vote.dto.response import com.wespot.user.User import com.wespot.user.dto.response.ProfileResponse -data class UserResponse( +data class VoteUserResponse( val id: Long, val name: String, - val profile: ProfileResponse? + val profile: ProfileResponse ) { companion object { - fun from(user: User): UserResponse { - return UserResponse( + fun from(user: User): VoteUserResponse { + return VoteUserResponse( id = user.id, name = user.name, profile = user.profile.let { ProfileResponse.from(it) } diff --git a/core/src/main/kotlin/com/wespot/vote/dto/response/top1/VoteDetailResultResponseOfTop1.kt b/core/src/main/kotlin/com/wespot/vote/dto/response/top1/VoteDetailResultResponseOfTop1.kt index 1e87afdd..74a02243 100644 --- a/core/src/main/kotlin/com/wespot/vote/dto/response/top1/VoteDetailResultResponseOfTop1.kt +++ b/core/src/main/kotlin/com/wespot/vote/dto/response/top1/VoteDetailResultResponseOfTop1.kt @@ -3,7 +3,7 @@ package com.wespot.vote.dto.response.top1 import com.wespot.vote.VoteRecord data class VoteDetailResultResponseOfTop1( - val user: UserResponseOfTop1, + val user: VoteUserResponseOfTop1, val voteCount: Int ) { @@ -11,7 +11,7 @@ data class VoteDetailResultResponseOfTop1( fun from(voteRecords: VoteRecord): VoteDetailResultResponseOfTop1 { return VoteDetailResultResponseOfTop1( - UserResponseOfTop1.from(voteRecords.user), + VoteUserResponseOfTop1.from(voteRecords.user), voteRecords.voteCount ) } diff --git a/core/src/main/kotlin/com/wespot/vote/dto/response/top1/UserResponseOfTop1.kt b/core/src/main/kotlin/com/wespot/vote/dto/response/top1/VoteUserResponseOfTop1.kt similarity index 72% rename from core/src/main/kotlin/com/wespot/vote/dto/response/top1/UserResponseOfTop1.kt rename to core/src/main/kotlin/com/wespot/vote/dto/response/top1/VoteUserResponseOfTop1.kt index cbf9f0c9..db02d018 100644 --- a/core/src/main/kotlin/com/wespot/vote/dto/response/top1/UserResponseOfTop1.kt +++ b/core/src/main/kotlin/com/wespot/vote/dto/response/top1/VoteUserResponseOfTop1.kt @@ -2,7 +2,7 @@ package com.wespot.vote.dto.response.top1 import com.wespot.user.User -data class UserResponseOfTop1( +data class VoteUserResponseOfTop1( val id: Long, val name: String, val introduction: String, @@ -11,8 +11,8 @@ data class UserResponseOfTop1( companion object { - fun from(user: User): UserResponseOfTop1 { - return UserResponseOfTop1( + fun from(user: User): VoteUserResponseOfTop1 { + return VoteUserResponseOfTop1( user.id, user.name, user.introduction, diff --git a/core/src/main/kotlin/com/wespot/vote/dto/response/top5/VoteDetailResultResponseOfTop5.kt b/core/src/main/kotlin/com/wespot/vote/dto/response/top5/VoteDetailResultResponseOfTop5.kt index fd1d99ca..525ef613 100644 --- a/core/src/main/kotlin/com/wespot/vote/dto/response/top5/VoteDetailResultResponseOfTop5.kt +++ b/core/src/main/kotlin/com/wespot/vote/dto/response/top5/VoteDetailResultResponseOfTop5.kt @@ -3,7 +3,7 @@ package com.wespot.vote.dto.response.top5 import com.wespot.vote.VoteRecord data class VoteDetailResultResponseOfTop5( - val user: UserResponseOfTop5, + val user: VoteUserResponseOfTop5, val voteCount: Int ) { @@ -11,7 +11,7 @@ data class VoteDetailResultResponseOfTop5( fun from(voteRecords: VoteRecord): VoteDetailResultResponseOfTop5 { return VoteDetailResultResponseOfTop5( - UserResponseOfTop5.from(voteRecords.user), + VoteUserResponseOfTop5.from(voteRecords.user), voteRecords.voteCount ) } diff --git a/core/src/main/kotlin/com/wespot/vote/dto/response/top5/UserResponseOfTop5.kt b/core/src/main/kotlin/com/wespot/vote/dto/response/top5/VoteUserResponseOfTop5.kt similarity index 50% rename from core/src/main/kotlin/com/wespot/vote/dto/response/top5/UserResponseOfTop5.kt rename to core/src/main/kotlin/com/wespot/vote/dto/response/top5/VoteUserResponseOfTop5.kt index f2dba8b4..e92e17eb 100644 --- a/core/src/main/kotlin/com/wespot/vote/dto/response/top5/UserResponseOfTop5.kt +++ b/core/src/main/kotlin/com/wespot/vote/dto/response/top5/VoteUserResponseOfTop5.kt @@ -1,23 +1,23 @@ package com.wespot.vote.dto.response.top5 import com.wespot.user.User -import com.wespot.user.dto.response.ProfileResponse +import com.wespot.vote.dto.response.VoteProfileResponse -data class UserResponseOfTop5( +data class VoteUserResponseOfTop5( val id: Long, val name: String, val introduction: String, - val profile: ProfileResponse + val profile: VoteProfileResponse ) { companion object { - fun from(user: User): UserResponseOfTop5 { - return UserResponseOfTop5( + fun from(user: User): VoteUserResponseOfTop5 { + return VoteUserResponseOfTop5( user.id, user.name, user.introduction, - ProfileResponse.from(user.profile) + VoteProfileResponse.from(user.profile) ) } From 033fb6d79662de9782dc5e0793b75a29d3b46c78 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Mon, 22 Jul 2024 16:51:12 +0900 Subject: [PATCH 12/23] =?UTF-8?q?refactor:=20Security=20Context=EC=97=90?= =?UTF-8?q?=EC=84=9C=20UserId=EB=A5=BC=20=EB=BD=91=EC=95=84=EB=82=BC=20?= =?UTF-8?q?=EC=88=98=20=EC=9E=88=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/com/wespot/vote/VoteController.kt | 13 ++---- .../com/wespot/user/fixture/UserFixture.kt | 46 ++++++++++++++++++- .../vote/service/SavedVoteServiceTest.kt | 26 ++++++++--- .../wespot/vote/port/in/SavedVoteUseCase.kt | 4 +- .../wespot/vote/port/in/VoteRankUseCase.kt | 4 +- .../wespot/vote/service/SavedVoteService.kt | 6 ++- .../wespot/vote/service/VoteRankService.kt | 10 ++-- .../vote/service/helper/VoteServiceHelper.kt | 5 ++ 8 files changed, 86 insertions(+), 28 deletions(-) diff --git a/app/src/main/kotlin/com/wespot/vote/VoteController.kt b/app/src/main/kotlin/com/wespot/vote/VoteController.kt index 092bee94..f4d0c33d 100644 --- a/app/src/main/kotlin/com/wespot/vote/VoteController.kt +++ b/app/src/main/kotlin/com/wespot/vote/VoteController.kt @@ -25,37 +25,34 @@ class VoteController( ) { @GetMapping("/options") - fun getVoteOptions(userId: Long): ResponseEntity { - val responses = savedVoteUseCase.getVoteOptions(userId) + fun getVoteOptions(): ResponseEntity { + val responses = savedVoteUseCase.getVoteOptions() return ResponseEntity.ok(responses) } @PostMapping fun createVote( - userId: Long, @RequestBody requests: VoteRequests ): ResponseEntity { - val savedId: SaveVoteResponse = savedVoteUseCase.saveVote(userId, requests) + val savedId: SaveVoteResponse = savedVoteUseCase.saveVote(requests) return ResponseEntity.status(HttpStatus.CREATED) .body(savedId) } @GetMapping fun getTop5VoteResults( - userId: Long, @RequestParam date: LocalDate ): ResponseEntity { - val responses: VoteResultResponsesOfTop5 = voteRankUseCase.getVoteResultsOfTop5(userId, date) + val responses: VoteResultResponsesOfTop5 = voteRankUseCase.getVoteResultsOfTop5(date) return ResponseEntity.ok(responses) } @GetMapping("/tops") fun getTop1VoteResults( - userId: Long, @RequestParam date: LocalDate ): ResponseEntity { - val responses: VoteResultResponsesOfTop1 = voteRankUseCase.getVoteResultsOfTop1(userId, date) + val responses: VoteResultResponsesOfTop1 = voteRankUseCase.getVoteResultsOfTop1(date) return ResponseEntity.ok(responses) } diff --git a/app/src/test/kotlin/com/wespot/user/fixture/UserFixture.kt b/app/src/test/kotlin/com/wespot/user/fixture/UserFixture.kt index 90f90046..da207f4d 100644 --- a/app/src/test/kotlin/com/wespot/user/fixture/UserFixture.kt +++ b/app/src/test/kotlin/com/wespot/user/fixture/UserFixture.kt @@ -2,7 +2,15 @@ package com.wespot.user.fixture import com.wespot.auth.PrincipalDetails import com.wespot.auth.dto.request.ProfileRequest -import com.wespot.user.* +import com.wespot.user.ConsentType +import com.wespot.user.FCM +import com.wespot.user.Profile +import com.wespot.user.Role +import com.wespot.user.Setting +import com.wespot.user.Social +import com.wespot.user.SocialType +import com.wespot.user.User +import com.wespot.user.UserConsent import com.wespot.user.dto.request.UpdateProfileRequest import org.springframework.security.authentication.TestingAuthenticationToken import org.springframework.security.core.context.SecurityContextHolder @@ -43,8 +51,42 @@ object UserFixture { withdrawAt = LocalDateTime.now(), ) + fun createWithIdAndEmail( + id: Long, + email: String, + ) = User( + id = id, + email = email, + password = "TestPassword", + role = Role.USER, + name = "TestUser", + introduction = "hello", + gender = "male", + schoolId = 1L, + grade = 1, + classNumber = 1, + setting = Setting(), + profile = Profile(0, "black", "image.png"), + fcm = FCM(0, "token", LocalDateTime.now()), + social = Social( + socialType = SocialType.KAKAO, + socialId = "1123123", + socialEmail = null, + socialRefreshToken = "refreshToken" + ), + userConsent = UserConsent( + id = 0, + consentType = ConsentType.MARKETING, + consentValue = true, + consentedAt = LocalDateTime.now() + ), + createdAt = LocalDateTime.now(), + updatedAt = null, + withdrawAt = LocalDateTime.now(), + ) + // SecurityContextHolder를 사용하여 테스트를 위한 User를 설정 - fun setSecurityContextUser(user : User){ + fun setSecurityContextUser(user: User) { val mockUserDetail = PrincipalDetails(user) val authentication = TestingAuthenticationToken(mockUserDetail, null) diff --git a/app/src/test/kotlin/com/wespot/vote/service/SavedVoteServiceTest.kt b/app/src/test/kotlin/com/wespot/vote/service/SavedVoteServiceTest.kt index 7753c7c8..436a8bb9 100644 --- a/app/src/test/kotlin/com/wespot/vote/service/SavedVoteServiceTest.kt +++ b/app/src/test/kotlin/com/wespot/vote/service/SavedVoteServiceTest.kt @@ -50,7 +50,7 @@ class SavedVoteServiceTest( voteOptions.clear() users.clear() for (i in 0 until 8) { - val userJpaEntity = UserMapper.mapToJpaEntity(UserFixture.createWithId(0)) + val userJpaEntity = UserMapper.mapToJpaEntity(UserFixture.createWithIdAndEmail(0, "TestEmail${i}@Kakako")) users.add(userJpaRepository.save(userJpaEntity)) val voteOptionJpaEntity = VoteOptionMapper.mapToJpaEntity(VoteOptionFixture.createWithId(0)) @@ -68,8 +68,12 @@ class SavedVoteServiceTest( @Test fun `투표에 지정된 질문지를 반환받는다`() { - // given when - val voteOptions = voteService.getVoteOptions(users[0].id) + // given + val loginUser = UserMapper.mapToDomainEntity(users[users.size - 1]) + UserFixture.setSecurityContextUser(loginUser) + + // when + val voteOptions = voteService.getVoteOptions() // then voteOptions.voteItems.size shouldBe 5 @@ -89,7 +93,9 @@ class SavedVoteServiceTest( ) // when - val throwingCallable = { voteService.saveVote(users[users.size - 1].id, requests) } + val loginUser = UserMapper.mapToDomainEntity(users[users.size - 1]) + UserFixture.setSecurityContextUser(loginUser) + val throwingCallable = { voteService.saveVote(requests) } // then val shouldThrow = shouldThrow(throwingCallable) @@ -129,7 +135,9 @@ class SavedVoteServiceTest( ) // when - val throwingCallable = { voteService.saveVote(users[users.size - 1].id, requests) } + val loginUser = UserMapper.mapToDomainEntity(users[users.size - 1]) + UserFixture.setSecurityContextUser(loginUser) + val throwingCallable = { voteService.saveVote(requests) } // then val shouldThrow = shouldThrow(throwingCallable) @@ -149,7 +157,9 @@ class SavedVoteServiceTest( ) // when - val throwingCallable = { voteService.saveVote(users[users.size - 1].id, requests) } + val loginUser = UserMapper.mapToDomainEntity(users[users.size - 1]) + UserFixture.setSecurityContextUser(loginUser) + val throwingCallable = { voteService.saveVote(requests) } // then val shouldThrow = shouldThrow(throwingCallable) @@ -185,7 +195,9 @@ class SavedVoteServiceTest( ) // when - voteService.saveVote(users[users.size - 1].id, requests) + val loginUser = UserMapper.mapToDomainEntity(users[users.size - 1]) + UserFixture.setSecurityContextUser(loginUser) + voteService.saveVote(requests) // then val ballots = ballotJpaRepository.findAll() diff --git a/core/src/main/kotlin/com/wespot/vote/port/in/SavedVoteUseCase.kt b/core/src/main/kotlin/com/wespot/vote/port/in/SavedVoteUseCase.kt index 94b45714..341ca830 100644 --- a/core/src/main/kotlin/com/wespot/vote/port/in/SavedVoteUseCase.kt +++ b/core/src/main/kotlin/com/wespot/vote/port/in/SavedVoteUseCase.kt @@ -6,8 +6,8 @@ import com.wespot.vote.dto.response.VoteItems interface SavedVoteUseCase { - fun getVoteOptions(userId: Long): VoteItems + fun getVoteOptions(): VoteItems - fun saveVote(userId: Long, requests: VoteRequests): SaveVoteResponse + fun saveVote(requests: VoteRequests): SaveVoteResponse } diff --git a/core/src/main/kotlin/com/wespot/vote/port/in/VoteRankUseCase.kt b/core/src/main/kotlin/com/wespot/vote/port/in/VoteRankUseCase.kt index 6a65fa3a..551475ca 100644 --- a/core/src/main/kotlin/com/wespot/vote/port/in/VoteRankUseCase.kt +++ b/core/src/main/kotlin/com/wespot/vote/port/in/VoteRankUseCase.kt @@ -6,8 +6,8 @@ import java.time.LocalDate interface VoteRankUseCase { - fun getVoteResultsOfTop5(userId: Long, date: LocalDate): VoteResultResponsesOfTop5 + fun getVoteResultsOfTop5(date: LocalDate): VoteResultResponsesOfTop5 - fun getVoteResultsOfTop1(userId: Long, date: LocalDate): VoteResultResponsesOfTop1 + fun getVoteResultsOfTop1(date: LocalDate): VoteResultResponsesOfTop1 } diff --git a/core/src/main/kotlin/com/wespot/vote/service/SavedVoteService.kt b/core/src/main/kotlin/com/wespot/vote/service/SavedVoteService.kt index 54a547d0..612043a8 100644 --- a/core/src/main/kotlin/com/wespot/vote/service/SavedVoteService.kt +++ b/core/src/main/kotlin/com/wespot/vote/service/SavedVoteService.kt @@ -23,10 +23,12 @@ class SavedVoteService( private val userPort: UserPort, ) : SavedVoteUseCase { - override fun getVoteOptions(userId: Long): VoteItems { + override fun getVoteOptions(): VoteItems { + val userId = VoteServiceHelper.findLoginUserId(userPort) val user: User = VoteServiceHelper.findUser(userPort, userId) val classmates = VoteServiceHelper.findClassmatesByUser(userPort, user) val today = LocalDate.now() + val vote: Vote = VoteServiceHelper.findVoteByUser(votePort, user, today) val todayVoteOptions: VoteOptionsByVoteDate = VoteServiceHelper.findVoteOptionsByVoteDate(voteOptionPort, vote) val usersForVote: List = vote.findUsersForVote(classmates, user) @@ -39,11 +41,11 @@ class SavedVoteService( @Transactional override fun saveVote( - userId: Long, requests: VoteRequests ): SaveVoteResponse { validateRequestsSize(requests.voteRequests.size) validateUserIdsInRequests(requests.voteRequests) + val userId = VoteServiceHelper.findLoginUserId(userPort) val user: User = VoteServiceHelper.findUser(userPort, userId) val today = LocalDate.now() val vote: Vote = VoteServiceHelper.findVoteByUser(votePort, user, today) diff --git a/core/src/main/kotlin/com/wespot/vote/service/VoteRankService.kt b/core/src/main/kotlin/com/wespot/vote/service/VoteRankService.kt index 2123a761..21043177 100644 --- a/core/src/main/kotlin/com/wespot/vote/service/VoteRankService.kt +++ b/core/src/main/kotlin/com/wespot/vote/service/VoteRankService.kt @@ -19,14 +19,14 @@ class VoteRankService( private val userPort: UserPort, ) : VoteRankUseCase { - override fun getVoteResultsOfTop5(userId: Long, date: LocalDate): VoteResultResponsesOfTop5 { - return VoteResultResponsesOfTop5.from(getRankedVoteResults(userId, date)) + override fun getVoteResultsOfTop5(date: LocalDate): VoteResultResponsesOfTop5 { + return VoteResultResponsesOfTop5.from(getRankedVoteResults(date)) } private fun getRankedVoteResults( - userId: Long, date: LocalDate ): Map> { + val userId=VoteServiceHelper.findLoginUserId(userPort) val user = VoteServiceHelper.findUser(userPort, userId) val classmates = VoteServiceHelper.findClassmatesByUser(userPort, user) val vote = VoteServiceHelper.findVoteByUser(votePort, user, date) @@ -36,8 +36,8 @@ class VoteRankService( return rankedVoteResults } - override fun getVoteResultsOfTop1(userId: Long, date: LocalDate): VoteResultResponsesOfTop1 { - return VoteResultResponsesOfTop1.from(getRankedVoteResults(userId, date)) + override fun getVoteResultsOfTop1(date: LocalDate): VoteResultResponsesOfTop1 { + return VoteResultResponsesOfTop1.from(getRankedVoteResults(date)) } } diff --git a/core/src/main/kotlin/com/wespot/vote/service/helper/VoteServiceHelper.kt b/core/src/main/kotlin/com/wespot/vote/service/helper/VoteServiceHelper.kt index 25d2469e..23c4b3f5 100644 --- a/core/src/main/kotlin/com/wespot/vote/service/helper/VoteServiceHelper.kt +++ b/core/src/main/kotlin/com/wespot/vote/service/helper/VoteServiceHelper.kt @@ -1,5 +1,6 @@ package com.wespot.vote.service.helper +import com.wespot.auth.service.SecurityUtils import com.wespot.user.User import com.wespot.user.port.out.UserPort import com.wespot.vote.Vote @@ -11,6 +12,10 @@ import java.time.LocalDate object VoteServiceHelper { + fun findLoginUserId(userPort: UserPort): Long { + return SecurityUtils.getLoginUserId(userPort) + } + fun findUser(userPort: UserPort, userId: Long): User { return userPort.findById(userId) ?: throw IllegalArgumentException("ID에 해당하는 사용자가 존재하지 않습니다.") From 0bd40f49e6211f7a6adf196f448a1f896c200354 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Mon, 22 Jul 2024 16:54:48 +0900 Subject: [PATCH 13/23] =?UTF-8?q?refactor:=20=EC=88=9C=ED=99=98=ED=95=B4?= =?UTF-8?q?=EC=84=9C=20=EC=A7=88=EB=AC=B8=EC=A7=80=EB=A5=BC=20=EA=B0=80?= =?UTF-8?q?=EC=A0=B8=EC=98=A4=EC=A7=80=20=EC=95=8A=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/com/wespot/vote/domain/VoteTest.kt | 13 ++++------ .../src/main/kotlin/com/wespot/vote/Vote.kt | 26 +++++++++++-------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/app/src/test/kotlin/com/wespot/vote/domain/VoteTest.kt b/app/src/test/kotlin/com/wespot/vote/domain/VoteTest.kt index a52faa5d..ea9135c3 100644 --- a/app/src/test/kotlin/com/wespot/vote/domain/VoteTest.kt +++ b/app/src/test/kotlin/com/wespot/vote/domain/VoteTest.kt @@ -31,16 +31,13 @@ class VoteTest() : BehaviorSpec({ } } - `when`("voteNumber가 1일 때의 오늘의 질문지를") { + `when`("오늘의 질문지를 뽑아낼 때, 범위를 벗어나는 경우") { val vote = VoteFixture.createWithVoteNumberAndBallots(1, Collections.emptyList()) - val todayVoteOptions = vote.findVoteOptionsByVoteDate(voteOptions).voteOptions + val throwingCallable = { vote.findVoteOptionsByVoteDate(voteOptions) } - then("정상적으로 반환한다.") { - todayVoteOptions[0].id shouldBe 6 - todayVoteOptions[1].id shouldBe 7 - todayVoteOptions[2].id shouldBe 8 - todayVoteOptions[3].id shouldBe 9 - todayVoteOptions[4].id shouldBe 1 + then("예외가 발생한다.") { + val shouldThrow = shouldThrow(throwingCallable) + shouldThrow shouldHaveMessage "선택지의 개수가 5의 배수가 아닙니다." } } } diff --git a/domain/src/main/kotlin/com/wespot/vote/Vote.kt b/domain/src/main/kotlin/com/wespot/vote/Vote.kt index 8f27d22a..eea6139d 100644 --- a/domain/src/main/kotlin/com/wespot/vote/Vote.kt +++ b/domain/src/main/kotlin/com/wespot/vote/Vote.kt @@ -17,19 +17,23 @@ data class Vote( companion object { private val NUMBER_OF_VOTE_USERS = 5 private val NUMBER_OF_VOTE_OPTIONS = 5 - private val MOVE_TO_NEXT_VOTE_OPTION = 1 } fun findVoteOptionsByVoteDate(allVoteOptions: List): VoteOptionsByVoteDate { validateVoteOptionsSize(allVoteOptions) - val voteOptionsByDate: MutableList = mutableListOf() - var voteOptionIndex: Int = (voteNumber * NUMBER_OF_VOTE_OPTIONS) % allVoteOptions.size - while (voteOptionsByDate.size < NUMBER_OF_VOTE_OPTIONS) { - voteOptionsByDate.add(allVoteOptions[voteOptionIndex]) - voteOptionIndex = (voteOptionIndex + MOVE_TO_NEXT_VOTE_OPTION) % allVoteOptions.size - } + val voteOptionIndex: Int = (voteNumber * NUMBER_OF_VOTE_OPTIONS) % allVoteOptions.size + validateVoteOptionsSizeMultipleOf5(allVoteOptions.size, voteOptionIndex) + val voteOptionsByVoteDate = allVoteOptions.subList(voteOptionIndex, voteOptionIndex + NUMBER_OF_VOTE_OPTIONS) + return VoteOptionsByVoteDate.of(date, voteOptionsByVoteDate) + } - return VoteOptionsByVoteDate(date, voteOptionsByDate.toList()) + private fun validateVoteOptionsSizeMultipleOf5( + allVoteOptionsSize: Int, + voteOptionIndex: Int + ) { + if (allVoteOptionsSize <= voteOptionIndex + NUMBER_OF_VOTE_OPTIONS) { + throw IllegalArgumentException("선택지의 개수가 5의 배수가 아닙니다.") + } } private fun validateVoteOptionsSize(allVoteOptions: List) { @@ -39,7 +43,7 @@ data class Vote( } fun findUsersForVote(classmates: List, user: User): List { - val alreadyVotedByUser: List = ballots.findUserIdsVotedByUser(user.id!!) + val alreadyVotedByUser: List = ballots.findUserIdsVotedByUser(user.id) return classmates.stream() .filter { !alreadyVotedByUser.contains(it.id) && isNotMe(it, user) } .toList() @@ -80,8 +84,8 @@ data class Vote( val rankedVoteResults: Map> = getBallots().groupBy { it.voteOptionId } .mapValues { BallotsAggregator.of(it.key, it.value) } - .mapValues { - it.value.getRankedResults() + .mapValues { entry -> + entry.value.getRankedResults() .filter { usersAssociateBy.containsKey(it.userId) } .map { VoteRecord.of(usersAssociateBy[it.userId]!!, it) } } From a924c935563d4d12738be4b7e77e8e2a1537e69c Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Mon, 22 Jul 2024 17:12:44 +0900 Subject: [PATCH 14/23] =?UTF-8?q?chore:=20submodule=20=EA=B0=80=EC=A0=B8?= =?UTF-8?q?=EC=98=A4=EB=8A=94=20=EA=B3=BC=EC=A0=95=20ci=EC=97=90=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/opened-pr-notification.yml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/opened-pr-notification.yml b/.github/workflows/opened-pr-notification.yml index c8b8c404..d7fe6637 100644 --- a/.github/workflows/opened-pr-notification.yml +++ b/.github/workflows/opened-pr-notification.yml @@ -13,6 +13,10 @@ jobs: runs-on: ubuntu-latest steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + token: ${{ secrets.SUBMODULE_ACCESS_TOKEN }} - uses: actions/checkout@v3 - name: set up JDK 17 uses: actions/setup-java@v3 @@ -36,7 +40,7 @@ jobs: DISCORD_AVATAR: https://www.notion.so/image/https%3A%2F%2Fi.imgur.com%2FqIqJ0GA.png?table=block&id=232c40c1-598a-4163-bb8d-acf1151cd026&spaceId=4263d120-003b-49f8-8cb5-37585d6fb45d&width=2000&userId=c0125a99-ca81-4e9f-9c32-096f12a6698c&cache=v2 DISCORD_EMBEDS: | [ - { + { "author": { "name": "${{ github.event.pull_request.user.login }}", "url": "https://github.com/pknu-wap/WAPP/blob/main/image/icon.png?raw=true", @@ -69,7 +73,7 @@ jobs: DISCORD_AVATAR: https://www.notion.so/image/https%3A%2F%2Fi.imgur.com%2FqIqJ0GA.png?table=block&id=232c40c1-598a-4163-bb8d-acf1151cd026&spaceId=4263d120-003b-49f8-8cb5-37585d6fb45d&width=2000&userId=c0125a99-ca81-4e9f-9c32-096f12a6698c&cache=v2 DISCORD_EMBEDS: | [ - { + { "author": { "name": "${{ github.event.pull_request.user.login }}", "url": "https://github.com/pknu-wap/WAPP/blob/main/image/icon.png?raw=true", @@ -91,4 +95,4 @@ jobs: } ] } - ] \ No newline at end of file + ] From 0a206fd65b75b33a1d3a182dd81ea669bdb18650 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Mon, 22 Jul 2024 18:11:47 +0900 Subject: [PATCH 15/23] =?UTF-8?q?test:=20=EC=98=A4=EB=8A=98=EC=9D=98=20?= =?UTF-8?q?=EC=A7=88=EB=AC=B8=EC=A7=80=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vote/domain/VoteOptionsByVoteDateTest.kt | 81 +++++++++++++++++++ .../com/wespot/vote/VoteOptionsByVoteDate.kt | 3 + 2 files changed, 84 insertions(+) create mode 100644 app/src/test/kotlin/com/wespot/vote/domain/VoteOptionsByVoteDateTest.kt diff --git a/app/src/test/kotlin/com/wespot/vote/domain/VoteOptionsByVoteDateTest.kt b/app/src/test/kotlin/com/wespot/vote/domain/VoteOptionsByVoteDateTest.kt new file mode 100644 index 00000000..547f547c --- /dev/null +++ b/app/src/test/kotlin/com/wespot/vote/domain/VoteOptionsByVoteDateTest.kt @@ -0,0 +1,81 @@ +package com.wespot.vote.domain + +import com.wespot.vote.VoteOptionsByVoteDate +import com.wespot.voteoption.fixture.VoteOptionFixture +import io.kotest.assertions.throwables.shouldNotThrow +import io.kotest.assertions.throwables.shouldThrow +import io.kotest.core.spec.style.BehaviorSpec +import io.kotest.matchers.shouldBe +import io.kotest.matchers.throwable.shouldHaveMessage +import java.time.LocalDate + +class VoteOptionsByVoteDateTest : BehaviorSpec({ + + given("오늘의 선택지가") { + val voteOption1 = VoteOptionFixture.create() + val voteOption2 = VoteOptionFixture.create() + val voteOption3 = VoteOptionFixture.create() + val voteOption4 = VoteOptionFixture.create() + val voteOption5 = VoteOptionFixture.create() + + `when`("5개가 아닌 경우") { + val throwingCallable = { + VoteOptionsByVoteDate.of( + LocalDate.now(), + listOf(voteOption1, voteOption2, voteOption3, voteOption4) + ) + } + then("예외가 발생한다.") { + val shouldThrow = shouldThrow(throwingCallable) + shouldThrow shouldHaveMessage "선택지는 5개가 주어져야 합니다." + } + } + `when`("미래의 선택지인 경우") { + val throwingCallable = { + VoteOptionsByVoteDate.of( + LocalDate.now().plusDays(1L), + listOf(voteOption1, voteOption2, voteOption3, voteOption4, voteOption5) + ) + } + then("예외가 발생한다.") { + val shouldThrow = shouldThrow(throwingCallable) + shouldThrow shouldHaveMessage "미래의 선택지는 정할 수 없습니다." + } + } + `when`("정상적으로 주어진 경우") { + val voteOptionsByVoteDate = VoteOptionsByVoteDate.of( + LocalDate.now(), + listOf(voteOption1, voteOption2, voteOption3, voteOption4, voteOption5) + ) + then("정상적으로 생성된다.") { + voteOptionsByVoteDate.voteDate shouldBe LocalDate.now() + voteOptionsByVoteDate.voteOptions.size shouldBe 5 + } + } + } + + given("주어진 선택지가") { + val voteOptions = VoteOptionsByVoteDate.of( + LocalDate.now(), + listOf( + VoteOptionFixture.createWithId(1L), + VoteOptionFixture.createWithId(2L), + VoteOptionFixture.createWithId(3L), + VoteOptionFixture.createWithId(4L), + VoteOptionFixture.createWithId(5L), + ) + ) + `when`("오늘의 선택지에 포함되어 있지 않은 경우") { + val shouldThrow = shouldThrow { voteOptions.validateVoteOption(6L) } + then("예외가 발생한다.") { + shouldThrow shouldHaveMessage "오늘 제공된 질문지만 선택해 투표할 수 있습니다." + } + } + `when`("오늘의 선택지에 포함되어 있는 경우") { + then("예외가 발생하지 않는다.") { + shouldNotThrow { voteOptions.validateVoteOption(5L) } + } + } + } + +}) diff --git a/domain/src/main/kotlin/com/wespot/vote/VoteOptionsByVoteDate.kt b/domain/src/main/kotlin/com/wespot/vote/VoteOptionsByVoteDate.kt index 73faf467..8c8239af 100644 --- a/domain/src/main/kotlin/com/wespot/vote/VoteOptionsByVoteDate.kt +++ b/domain/src/main/kotlin/com/wespot/vote/VoteOptionsByVoteDate.kt @@ -13,6 +13,9 @@ data class VoteOptionsByVoteDate( if (voteOptions.size != 5) { throw IllegalArgumentException("선택지는 5개가 주어져야 합니다.") } + if (LocalDate.now() < date) { + throw IllegalArgumentException("미래의 선택지는 정할 수 없습니다.") + } return VoteOptionsByVoteDate(date, voteOptions) } From 2393cd7225eb4fb60134b471cfc0208c39b9b3f1 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Mon, 22 Jul 2024 18:31:08 +0900 Subject: [PATCH 16/23] =?UTF-8?q?test:=20VoteMetrics=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/wespot/vote/domain/VoteMetricsTest.kt | 50 +++++++++++++++++++ .../com/wespot/vote/fixture/BallotFixture.kt | 4 +- .../src/main/kotlin/com/wespot/vote/Ballot.kt | 6 ++- 3 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 app/src/test/kotlin/com/wespot/vote/domain/VoteMetricsTest.kt diff --git a/app/src/test/kotlin/com/wespot/vote/domain/VoteMetricsTest.kt b/app/src/test/kotlin/com/wespot/vote/domain/VoteMetricsTest.kt new file mode 100644 index 00000000..1cf50a08 --- /dev/null +++ b/app/src/test/kotlin/com/wespot/vote/domain/VoteMetricsTest.kt @@ -0,0 +1,50 @@ +package com.wespot.vote.domain + +import com.wespot.vote.VoteMetrics +import com.wespot.vote.fixture.BallotFixture +import io.kotest.core.spec.style.BehaviorSpec +import io.kotest.matchers.shouldBe +import java.time.LocalDateTime + +class VoteMetricsTest : BehaviorSpec({ + + given("초기의 VoteMetrics를") { + val userId = 1L + `when`("생성하면") { + val voteMetrics = VoteMetrics.createInitialState(userId) + then("정상적으로 생성된다.") { + voteMetrics.userId shouldBe userId + voteMetrics.lastVotedDateTime shouldBe LocalDateTime.MIN + voteMetrics.voteCount shouldBe 0 + voteMetrics.isReceiverRead shouldBe true + } + } + } + + given("기존의 VoteMetrics에") { + val userId = 1L + val voteMetrics = VoteMetrics.createInitialState(userId) + val ballot = BallotFixture.create() + `when`("최근의 Ballot을 추가하면") { + ballot.receiverRead() + val resultVoteMetrics = voteMetrics.recordBallot(ballot) + then("최근으로 갱신된다.") { + resultVoteMetrics.userId shouldBe userId + resultVoteMetrics.lastVotedDateTime shouldBe ballot.createdAt + resultVoteMetrics.voteCount shouldBe 1 + resultVoteMetrics.isReceiverRead shouldBe true + } + } + `when`("수신자가 읽지 않은 Ballot을 추가하면") { + val noReceiverReadBallot = BallotFixture.create() + val resultVoteMetrics = voteMetrics.recordBallot(noReceiverReadBallot) + then("읽지 않음으로 갱신된다.") { + resultVoteMetrics.userId shouldBe userId + resultVoteMetrics.lastVotedDateTime shouldBe noReceiverReadBallot.createdAt + resultVoteMetrics.voteCount shouldBe 1 + resultVoteMetrics.isReceiverRead shouldBe false + } + } + } + +}) diff --git a/app/src/test/kotlin/com/wespot/vote/fixture/BallotFixture.kt b/app/src/test/kotlin/com/wespot/vote/fixture/BallotFixture.kt index 69adf727..23bb4851 100644 --- a/app/src/test/kotlin/com/wespot/vote/fixture/BallotFixture.kt +++ b/app/src/test/kotlin/com/wespot/vote/fixture/BallotFixture.kt @@ -12,7 +12,7 @@ object BallotFixture { senderId = 1L, receiverId = 1L, createdAt = LocalDateTime.now(), - isReceiverRead = true + isReceiverRead = false ) fun createByVoteAndVoteOptionAndSenderAndReceiver( @@ -27,7 +27,7 @@ object BallotFixture { senderId = senderId, receiverId = receiverId, createdAt = LocalDateTime.now(), - isReceiverRead = true + isReceiverRead = false ) } diff --git a/domain/src/main/kotlin/com/wespot/vote/Ballot.kt b/domain/src/main/kotlin/com/wespot/vote/Ballot.kt index 091335c4..d4cf331a 100644 --- a/domain/src/main/kotlin/com/wespot/vote/Ballot.kt +++ b/domain/src/main/kotlin/com/wespot/vote/Ballot.kt @@ -10,7 +10,7 @@ data class Ballot( val senderId: Long, val receiverId: Long, val createdAt: LocalDateTime, - val isReceiverRead: Boolean, + var isReceiverRead: Boolean, ) { companion object { @@ -49,4 +49,8 @@ data class Ballot( } + fun receiverRead() { + isReceiverRead = true + } + } From 9faf8c03fbb78b249d0b4d3a9999d3d31fe46052 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Mon, 22 Jul 2024 19:10:21 +0900 Subject: [PATCH 17/23] =?UTF-8?q?test:=20VoteRecord=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/com/wespot/vote/domain/RateTest.kt | 36 +++++++++++++ .../com/wespot/vote/domain/VoteRecordTest.kt | 54 +++++++++++++++++++ .../src/main/kotlin/com/wespot/vote/Rate.kt | 27 ++++++++++ .../kotlin/com/wespot/vote/VoteMetrics.kt | 6 +-- .../main/kotlin/com/wespot/vote/VoteRecord.kt | 15 ++++-- 5 files changed, 130 insertions(+), 8 deletions(-) create mode 100644 app/src/test/kotlin/com/wespot/vote/domain/RateTest.kt create mode 100644 app/src/test/kotlin/com/wespot/vote/domain/VoteRecordTest.kt create mode 100644 domain/src/main/kotlin/com/wespot/vote/Rate.kt diff --git a/app/src/test/kotlin/com/wespot/vote/domain/RateTest.kt b/app/src/test/kotlin/com/wespot/vote/domain/RateTest.kt new file mode 100644 index 00000000..bb10a0c1 --- /dev/null +++ b/app/src/test/kotlin/com/wespot/vote/domain/RateTest.kt @@ -0,0 +1,36 @@ +package com.wespot.vote.domain + +import com.wespot.vote.Rate +import io.kotest.assertions.throwables.shouldThrow +import io.kotest.core.spec.style.BehaviorSpec +import io.kotest.matchers.shouldBe +import io.kotest.matchers.throwable.shouldHaveMessage + +class RateTest : BehaviorSpec({ + + given("Rate를 만들 때") { + val validRate = 1 + `when`("0 이하의 등수가 입력되면") { + then("예외가 발생한다.") { + val shouldThrow = shouldThrow { Rate.from(0) } + shouldThrow shouldHaveMessage "등수는 0 이하일 수 없습니다." + } + } + `when`("정상적인 값이 입력되면") { + val rate = Rate.from(validRate) + then("정상적으로 생성된다.") { + rate.value shouldBe validRate + } + } + } + + given("의미없는") { + `when`("Rate를 만들면") { + val Rate = Rate.createMeaningLessRate() + then("등수가 Int MAX VALUE로 설정되게 된다.") { + Rate.value shouldBe Int.MAX_VALUE + } + } + } + +}) diff --git a/app/src/test/kotlin/com/wespot/vote/domain/VoteRecordTest.kt b/app/src/test/kotlin/com/wespot/vote/domain/VoteRecordTest.kt new file mode 100644 index 00000000..c1f0d754 --- /dev/null +++ b/app/src/test/kotlin/com/wespot/vote/domain/VoteRecordTest.kt @@ -0,0 +1,54 @@ +package com.wespot.vote.domain + +import com.wespot.user.fixture.UserFixture +import com.wespot.vote.VoteMetrics +import com.wespot.vote.VoteRecord +import io.kotest.assertions.throwables.shouldThrow +import io.kotest.core.spec.style.BehaviorSpec +import io.kotest.matchers.shouldBe +import io.kotest.matchers.throwable.shouldHaveMessage + +class VoteRecordTest : BehaviorSpec({ + + given("VoteMetrics와 User를 활용해") { + val voteMetrics = VoteMetrics.createInitialState(1L) + val user = UserFixture.createWithId(1L) + `when`("VoteRecord를") { + val actual = VoteRecord.of(user, voteMetrics) + then("정상적으로 생성한다.") { + actual.user shouldBe user + actual.voteCount shouldBe voteMetrics.voteCount + actual.lastVotedDateTime shouldBe voteMetrics.lastVotedDateTime + actual.isReceiverRead shouldBe voteMetrics.isReceiverRead + } + } + + `when`("VoteRecord를 생성할 때, VoteMetrics내의 userId와 입력된 userId가 일치하지 않으면") { + val invalidUser = UserFixture.createWithId(2L) + then("예외가 발생한다.") { + val shouldThrow = shouldThrow { VoteRecord.of(invalidUser, voteMetrics) } + shouldThrow shouldHaveMessage "userId가 일치하지 않습니다." + } + } + + `when`("VoteRecord를 생성할 때, 등수가 0 이하이면") { + then("예외가 발생한다.") { + val shouldThrow = + shouldThrow { VoteRecord.ofWithRate(user, 0, voteMetrics) } + shouldThrow shouldHaveMessage "등수는 0 이하일 수 없습니다." + } + } + + `when`("VoteRecord를 생성할 때, 등수도 같이 입력해") { + val actual = VoteRecord.ofWithRate(user, 1, voteMetrics) + then("정상적으로 생성한다.") { + actual.user shouldBe user + actual.rate.value shouldBe 1 + actual.voteCount shouldBe voteMetrics.voteCount + actual.lastVotedDateTime shouldBe voteMetrics.lastVotedDateTime + actual.isReceiverRead shouldBe voteMetrics.isReceiverRead + } + } + } + +}) diff --git a/domain/src/main/kotlin/com/wespot/vote/Rate.kt b/domain/src/main/kotlin/com/wespot/vote/Rate.kt new file mode 100644 index 00000000..11b602f7 --- /dev/null +++ b/domain/src/main/kotlin/com/wespot/vote/Rate.kt @@ -0,0 +1,27 @@ +package com.wespot.vote + +data class Rate( + val value: Int +) { + + companion object { + + fun from(value: Int): Rate { + validate(value) + return Rate(value) + } + + private fun validate(value: Int) { + if (0 < value) { + return + } + throw IllegalArgumentException("등수는 0 이하일 수 없습니다.") + } + + fun createMeaningLessRate(): Rate { + return Rate(Int.MAX_VALUE) + } + + } + +} diff --git a/domain/src/main/kotlin/com/wespot/vote/VoteMetrics.kt b/domain/src/main/kotlin/com/wespot/vote/VoteMetrics.kt index 2d242a7c..375579f7 100644 --- a/domain/src/main/kotlin/com/wespot/vote/VoteMetrics.kt +++ b/domain/src/main/kotlin/com/wespot/vote/VoteMetrics.kt @@ -12,17 +12,17 @@ data class VoteMetrics( companion object { fun createInitialState(userId: Long): VoteMetrics { - return VoteMetrics(userId, LocalDateTime.MIN, 0, false) + return VoteMetrics(userId, LocalDateTime.MIN, 0, true) } } - fun recordVote(ballot: Ballot): VoteMetrics { + fun recordBallot(ballot: Ballot): VoteMetrics { return VoteMetrics( userId = userId, lastVotedDateTime = maxOf(lastVotedDateTime, ballot.createdAt), voteCount = voteCount + 1, - isReceiverRead = isReceiverRead || ballot.isReceiverRead + isReceiverRead = isReceiverRead && ballot.isReceiverRead ) } diff --git a/domain/src/main/kotlin/com/wespot/vote/VoteRecord.kt b/domain/src/main/kotlin/com/wespot/vote/VoteRecord.kt index dd09e70e..53ffa474 100644 --- a/domain/src/main/kotlin/com/wespot/vote/VoteRecord.kt +++ b/domain/src/main/kotlin/com/wespot/vote/VoteRecord.kt @@ -6,31 +6,35 @@ import java.util.* data class VoteRecord( val user: User, - val rate: Int, + val rate: Rate, val lastVotedDateTime: LocalDateTime, val voteCount: Int, val isReceiverRead: Boolean ) { companion object { + fun of( user: User, voteMetrics: VoteMetrics ): VoteRecord { - validateInvalidUser(user) + validateInvalidUser(user, voteMetrics) return VoteRecord( user, - rate = Int.MAX_VALUE, + rate = Rate.createMeaningLessRate(), voteMetrics.lastVotedDateTime, voteMetrics.voteCount, voteMetrics.isReceiverRead ) } - private fun validateInvalidUser(user: User) { + private fun validateInvalidUser(user: User, voteMetrics: VoteMetrics) { if (Objects.isNull(user)) { throw IllegalArgumentException("존재하지 않는 사용자에 대한 투표가 존재합니다.") } + if (user.id != voteMetrics.userId) { + throw IllegalArgumentException("userId가 일치하지 않습니다.") + } } fun ofWithRate( @@ -38,9 +42,10 @@ data class VoteRecord( rate: Int, voteMetrics: VoteMetrics ): VoteRecord { + validateInvalidUser(user, voteMetrics) return VoteRecord( user, - rate, + Rate.from(rate), voteMetrics.lastVotedDateTime, voteMetrics.voteCount, voteMetrics.isReceiverRead From b20251cf7ca1a48165dee9825914b790a7c27cf5 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Mon, 22 Jul 2024 19:30:40 +0900 Subject: [PATCH 18/23] =?UTF-8?q?test:=20BallotsAggregator=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vote/domain/BallotsAggregatorTest.kt | 113 ++++++++++++++++++ .../com/wespot/vote/fixture/BallotFixture.kt | 16 +++ .../com/wespot/vote/BallotsAggregator.kt | 8 +- .../src/main/kotlin/com/wespot/vote/Vote.kt | 2 +- 4 files changed, 134 insertions(+), 5 deletions(-) create mode 100644 app/src/test/kotlin/com/wespot/vote/domain/BallotsAggregatorTest.kt diff --git a/app/src/test/kotlin/com/wespot/vote/domain/BallotsAggregatorTest.kt b/app/src/test/kotlin/com/wespot/vote/domain/BallotsAggregatorTest.kt new file mode 100644 index 00000000..7e1c5385 --- /dev/null +++ b/app/src/test/kotlin/com/wespot/vote/domain/BallotsAggregatorTest.kt @@ -0,0 +1,113 @@ +package com.wespot.vote.domain + +import com.wespot.vote.BallotsAggregator +import com.wespot.vote.fixture.BallotFixture +import io.kotest.assertions.throwables.shouldThrow +import io.kotest.core.spec.style.BehaviorSpec +import io.kotest.matchers.shouldBe +import io.kotest.matchers.throwable.shouldHaveMessage +import java.time.LocalDateTime + +class BallotsAggregatorTest : BehaviorSpec({ + + given("투표지 집계기를 생성할 때") { + `when`("서로 다른 선택지에 대한 결과가 섞여 있으면") { + then("예외가 발생한다.") { + val shouldThrow = shouldThrow { + BallotsAggregator.of( + 1L, + listOf(BallotFixture.createByVoteAndVoteOptionAndSenderAndReceiver(1L, 2L, 1L, 2L)) + ) + } + shouldThrow shouldHaveMessage "서로 다른 질문지에 대한 결과가 섞였습니다." + } + } + } + + given("투표지 집계기를 통해") { + val calculateRankByBallotSize = listOf( + BallotFixture.createByVoteAndVoteOptionAndSenderAndReceiver(1L, 1L, 1L, 2L), + BallotFixture.createByVoteAndVoteOptionAndSenderAndReceiver(1L, 1L, 2L, 3L), + BallotFixture.createByVoteAndVoteOptionAndSenderAndReceiver(1L, 1L, 3L, 2L), + BallotFixture.createByVoteAndVoteOptionAndSenderAndReceiver(1L, 1L, 4L, 3L), + BallotFixture.createByVoteAndVoteOptionAndSenderAndReceiver(1L, 1L, 5L, 2L), + BallotFixture.createByVoteAndVoteOptionAndSenderAndReceiver(1L, 1L, 6L, 4L), + ) + `when`("득표수를 토대로") { + val ballotsAggregator = BallotsAggregator.of(1L, calculateRankByBallotSize) + val rankedResults = ballotsAggregator.getRankResults() + then("정렬된 순서를 반환받는다.") { + rankedResults[0].userId shouldBe 2 + rankedResults[0].voteCount shouldBe 3 + rankedResults[1].userId shouldBe 3 + rankedResults[1].voteCount shouldBe 2 + rankedResults[2].userId shouldBe 4 + rankedResults[2].voteCount shouldBe 1 + } + } + val calculateRankByBallotSizeAndReceivedAt = listOf( + BallotFixture.createByVoteAndVoteOptionAndSenderAndReceiverAndCreatedAt( + 1L, + 1L, + 1L, + 2L, + LocalDateTime.now().minusHours(10) + ), + BallotFixture.createByVoteAndVoteOptionAndSenderAndReceiverAndCreatedAt( + 1L, + 1L, + 3L, + 2L, + LocalDateTime.now().minusHours(10) + ), + BallotFixture.createByVoteAndVoteOptionAndSenderAndReceiverAndCreatedAt( + 1L, + 1L, + 5L, + 2L, + LocalDateTime.now().minusHours(10) + ), + BallotFixture.createByVoteAndVoteOptionAndSenderAndReceiverAndCreatedAt( + 1L, + 1L, + 2L, + 3L, + LocalDateTime.now().minusHours(10) + ), + BallotFixture.createByVoteAndVoteOptionAndSenderAndReceiverAndCreatedAt( + 1L, + 1L, + 4L, + 3L, + LocalDateTime.now().minusHours(1) + ), + BallotFixture.createByVoteAndVoteOptionAndSenderAndReceiverAndCreatedAt( + 1L, + 1L, + 6L, + 4L, + LocalDateTime.now().minusHours(2) + ), + BallotFixture.createByVoteAndVoteOptionAndSenderAndReceiverAndCreatedAt( + 1L, + 1L, + 7L, + 4L, + LocalDateTime.now().minusHours(2) + ), + ) + `when`("득표수가 같다면, 가장 최근에 받은 투푠을 기준으로") { + val ballotsAggregator = BallotsAggregator.of(1L, calculateRankByBallotSizeAndReceivedAt) + val rankedResults = ballotsAggregator.getRankResults() + then("정렬된 순서를 반환받는다.") { + rankedResults[0].userId shouldBe 2 + rankedResults[0].voteCount shouldBe 3 + rankedResults[1].userId shouldBe 3 + rankedResults[1].voteCount shouldBe 2 + rankedResults[2].userId shouldBe 4 + rankedResults[2].voteCount shouldBe 2 + } + } + } + +}) diff --git a/app/src/test/kotlin/com/wespot/vote/fixture/BallotFixture.kt b/app/src/test/kotlin/com/wespot/vote/fixture/BallotFixture.kt index 23bb4851..759027c4 100644 --- a/app/src/test/kotlin/com/wespot/vote/fixture/BallotFixture.kt +++ b/app/src/test/kotlin/com/wespot/vote/fixture/BallotFixture.kt @@ -30,4 +30,20 @@ object BallotFixture { isReceiverRead = false ) + fun createByVoteAndVoteOptionAndSenderAndReceiverAndCreatedAt( + voteId: Long, + voteOptionId: Long, + senderId: Long, + receiverId: Long, + createdAt:LocalDateTime + ) = Ballot( + id = 0L, + voteId = voteId, + voteOptionId = voteOptionId, + senderId = senderId, + receiverId = receiverId, + createdAt = createdAt, + isReceiverRead = false + ) + } diff --git a/domain/src/main/kotlin/com/wespot/vote/BallotsAggregator.kt b/domain/src/main/kotlin/com/wespot/vote/BallotsAggregator.kt index eb486f12..397065a9 100644 --- a/domain/src/main/kotlin/com/wespot/vote/BallotsAggregator.kt +++ b/domain/src/main/kotlin/com/wespot/vote/BallotsAggregator.kt @@ -7,13 +7,13 @@ class BallotsAggregator( companion object { fun of(voteOptionId: Long, ballots: List): BallotsAggregator { - if (isBallotsForVoteOption(ballots, voteOptionId)) { + if (validateBallotsForVoteOption(ballots, voteOptionId)) { throw IllegalArgumentException("서로 다른 질문지에 대한 결과가 섞였습니다.") } return BallotsAggregator(ballots) } - private fun isBallotsForVoteOption( + private fun validateBallotsForVoteOption( ballots: List, voteOptionId: Long ) = ballots.stream() @@ -21,12 +21,12 @@ class BallotsAggregator( } - fun getRankedResults(): List { + fun getRankResults(): List { val ranked: MutableMap = LinkedHashMap() ballots.forEach { val voteMetrics = ranked.getOrDefault(it.receiverId, VoteMetrics.createInitialState(it.receiverId)) - ranked[it.receiverId] = voteMetrics.recordVote(it) + ranked[it.receiverId] = voteMetrics.recordBallot(it) } return calculatedRanked(ranked.map { it.value }) diff --git a/domain/src/main/kotlin/com/wespot/vote/Vote.kt b/domain/src/main/kotlin/com/wespot/vote/Vote.kt index eea6139d..ffee8a17 100644 --- a/domain/src/main/kotlin/com/wespot/vote/Vote.kt +++ b/domain/src/main/kotlin/com/wespot/vote/Vote.kt @@ -85,7 +85,7 @@ data class Vote( getBallots().groupBy { it.voteOptionId } .mapValues { BallotsAggregator.of(it.key, it.value) } .mapValues { entry -> - entry.value.getRankedResults() + entry.value.getRankResults() .filter { usersAssociateBy.containsKey(it.userId) } .map { VoteRecord.of(usersAssociateBy[it.userId]!!, it) } } From 1a175af96a3cb41b2d852ce60daf8422ff4f0332 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Mon, 22 Jul 2024 20:44:52 +0900 Subject: [PATCH 19/23] =?UTF-8?q?test:=20Vote=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/com/wespot/vote/domain/VoteTest.kt | 129 ++++++++++++++++++ 1 file changed, 129 insertions(+) diff --git a/app/src/test/kotlin/com/wespot/vote/domain/VoteTest.kt b/app/src/test/kotlin/com/wespot/vote/domain/VoteTest.kt index ea9135c3..4f5fdc81 100644 --- a/app/src/test/kotlin/com/wespot/vote/domain/VoteTest.kt +++ b/app/src/test/kotlin/com/wespot/vote/domain/VoteTest.kt @@ -11,6 +11,7 @@ import io.kotest.assertions.throwables.shouldThrow import io.kotest.core.spec.style.BehaviorSpec import io.kotest.matchers.shouldBe import io.kotest.matchers.throwable.shouldHaveMessage +import java.time.LocalDateTime import java.util.* class VoteTest() : BehaviorSpec({ @@ -146,6 +147,134 @@ class VoteTest() : BehaviorSpec({ } + given("투표 결과를 통해") { + val ballots = listOf( + BallotFixture.createByVoteAndVoteOptionAndSenderAndReceiverAndCreatedAt( + 1L, + 1L, + 2L, + 1L, + LocalDateTime.now().minusHours(10) + ), + BallotFixture.createByVoteAndVoteOptionAndSenderAndReceiverAndCreatedAt( + 1L, + 1L, + 3L, + 2L, + LocalDateTime.now().minusHours(8) + ), + BallotFixture.createByVoteAndVoteOptionAndSenderAndReceiver(1L, 2L, 1L, 3L), + BallotFixture.createByVoteAndVoteOptionAndSenderAndReceiver(1L, 3L, 5L, 4L), + BallotFixture.createByVoteAndVoteOptionAndSenderAndReceiver(1L, 4L, 4L, 6L), + BallotFixture.createByVoteAndVoteOptionAndSenderAndReceiver(1L, 6L, 4L, 5L), + ) + + `when`("등수를 집계할 때, 존재하지 않는 유저의 통계는") { + val users = createUserOptionByCount(5) + val voteOptions = createVoteOptionByCount(10) + val vote = VoteFixture.createWithVoteNumberAndBallots(0, ballots) + val voteOptionsByVoteDate = vote.findVoteOptionsByVoteDate(voteOptions) + val rankedVoteResults = vote.getRankedVoteResults(voteOptionsByVoteDate, users) + + then("집계하지 않는다.") { + val forthVoteOption = voteOptions[3] + rankedVoteResults[forthVoteOption]!!.size shouldBe 0 + } + } + + `when`("등수를 집계할 때, 존재하지 않는 VoteOption에 대해") { + val users = createUserOptionByCount(5) + val voteOptions = createVoteOptionByCount(10) + val vote = VoteFixture.createWithVoteNumberAndBallots(0, ballots) + val voteOptionsByVoteDate = vote.findVoteOptionsByVoteDate(voteOptions) + val rankedVoteResults = vote.getRankedVoteResults(voteOptionsByVoteDate, users) + + then("집계하지 않는다.") { + rankedVoteResults.containsKey(voteOptions[5]) shouldBe false + } + } + + `when`("등수를 집계할 때, VoteOption의 Id로") { + val users = createUserOptionByCount(5) + val voteOptions = createVoteOptionByCount(10) + val vote = VoteFixture.createWithVoteNumberAndBallots(0, ballots) + val voteOptionsByVoteDate = vote.findVoteOptionsByVoteDate(voteOptions) + val rankedVoteResults = vote.getRankedVoteResults(voteOptionsByVoteDate, users) + + then("정렬되어 집계한다.") { + val entries = rankedVoteResults.toList() + entries[0].first.id shouldBe 1 + entries[1].first.id shouldBe 2 + entries[2].first.id shouldBe 3 + entries[3].first.id shouldBe 4 + entries[4].first.id shouldBe 5 + } + } + + `when`("등수를 집계할 때, 주어진 User를 매핑해서") { + val users = createUserOptionByCount(5) + val voteOptions = createVoteOptionByCount(10) + val vote = VoteFixture.createWithVoteNumberAndBallots(0, ballots) + val voteOptionsByVoteDate = vote.findVoteOptionsByVoteDate(voteOptions) + val rankedVoteResults = vote.getRankedVoteResults(voteOptionsByVoteDate, users) + + then("결과를 반환한다.") { + val entries = rankedVoteResults.toList() + entries[0].second.size shouldBe 2 + entries[0].second[0].user.id shouldBe 2 + entries[0].second[1].user.id shouldBe 1 + entries[1].second.size shouldBe 1 + entries[1].second[0].user.id shouldBe 3 + entries[2].second.size shouldBe 1 + entries[2].second[0].user.id shouldBe 4 + entries[3].second.size shouldBe 0 + entries[4].second.size shouldBe 0 + } + } + + `when`("등수를 집계할 때, 주어진 VoteOption을 매핑해서") { + val users = createUserOptionByCount(5) + val voteOptions = createVoteOptionByCount(10) + val vote = VoteFixture.createWithVoteNumberAndBallots(0, ballots) + val voteOptionsByVoteDate = vote.findVoteOptionsByVoteDate(voteOptions) + val rankedVoteResults = vote.getRankedVoteResults(voteOptionsByVoteDate, users) + + then("결과를 반환한다.") { + val entries = rankedVoteResults.toList() + entries[0].first shouldBe voteOptionsByVoteDate.voteOptions[0] + entries[1].first shouldBe voteOptionsByVoteDate.voteOptions[1] + entries[2].first shouldBe voteOptionsByVoteDate.voteOptions[2] + entries[3].first shouldBe voteOptionsByVoteDate.voteOptions[3] + entries[4].first shouldBe voteOptionsByVoteDate.voteOptions[4] + } + } + + `when`("등수를 집계할 때, 등수도 함께 포함해서") { + val users = createUserOptionByCount(5) + val voteOptions = createVoteOptionByCount(10) + val vote = VoteFixture.createWithVoteNumberAndBallots(0, ballots) + val voteOptionsByVoteDate = vote.findVoteOptionsByVoteDate(voteOptions) + val rankedVoteResults = vote.getRankedVoteResults(voteOptionsByVoteDate, users) + + then("결과를 반환한다.") { + val entries = rankedVoteResults.toList() + entries[0].second.size shouldBe 2 + entries[0].second[0].user.id shouldBe 2 + entries[0].second[0].rate.value shouldBe Int.MAX_VALUE + entries[0].second[1].user.id shouldBe 1 + entries[0].second[1].rate.value shouldBe Int.MAX_VALUE + entries[1].second.size shouldBe 1 + entries[1].second[0].user.id shouldBe 3 + entries[1].second[0].rate.value shouldBe Int.MAX_VALUE + entries[2].second.size shouldBe 1 + entries[2].second[0].user.id shouldBe 4 + entries[2].second[0].rate.value shouldBe Int.MAX_VALUE + entries[3].second.size shouldBe 0 + entries[4].second.size shouldBe 0 + } + } + } + }) private fun createVoteOptionByCount(voteOptionCount: Long): List { From dec455bc52874438a878e8d24cc1d4ca00a23bb9 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Mon, 22 Jul 2024 21:13:15 +0900 Subject: [PATCH 20/23] =?UTF-8?q?test:=20VoteRankServiceTest=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vote/service/VoteRankServiceTest.kt | 170 ++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 app/src/test/kotlin/com/wespot/vote/service/VoteRankServiceTest.kt diff --git a/app/src/test/kotlin/com/wespot/vote/service/VoteRankServiceTest.kt b/app/src/test/kotlin/com/wespot/vote/service/VoteRankServiceTest.kt new file mode 100644 index 00000000..a0d16850 --- /dev/null +++ b/app/src/test/kotlin/com/wespot/vote/service/VoteRankServiceTest.kt @@ -0,0 +1,170 @@ +package com.wespot.vote.service + +import com.wespot.DatabaseCleanup +import com.wespot.user.entity.UserJpaEntity +import com.wespot.user.fixture.UserFixture +import com.wespot.user.mapper.UserMapper +import com.wespot.user.repository.UserJpaRepository +import com.wespot.vote.Ballot +import com.wespot.vote.BallotJpaRepository +import com.wespot.vote.BallotMapper +import com.wespot.vote.VoteJpaEntity +import com.wespot.vote.VoteJpaRepository +import com.wespot.vote.VoteMapper +import com.wespot.vote.fixture.VoteFixture +import com.wespot.voteoption.VoteOptionJpaEntity +import com.wespot.voteoption.VoteOptionJpaRepository +import com.wespot.voteoption.VoteOptionMapper +import com.wespot.voteoption.fixture.VoteOptionFixture +import io.kotest.matchers.shouldBe +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest +import java.time.LocalDate +import java.util.* + +@SpringBootTest +class VoteRankServiceTest( + @Autowired + private var voteRankService: VoteRankService, + @Autowired + private var databaseCleanup: DatabaseCleanup, + @Autowired + private var userJpaRepository: UserJpaRepository, + @Autowired + private var voteOptionJpaRepository: VoteOptionJpaRepository, + @Autowired + private var voteJpaRepository: VoteJpaRepository, + @Autowired + private var ballotJpaRepository: BallotJpaRepository, +) { + + private var users: MutableList = mutableListOf() + private var voteOptions: MutableList = mutableListOf() + private var savedVote: VoteJpaEntity? = null + + @BeforeEach + fun setUp() { + voteOptions.clear() + users.clear() + for (i in 0 until 8) { + val userJpaEntity = UserMapper.mapToJpaEntity(UserFixture.createWithIdAndEmail(0, "TestEmail${i}@Kakako")) + users.add(userJpaRepository.save(userJpaEntity)) + val voteOptionJpaEntity = + VoteOptionMapper.mapToJpaEntity(VoteOptionFixture.createWithId(0)) + voteOptions.add(voteOptionJpaRepository.save(voteOptionJpaEntity)) + } + val vote = + VoteFixture.createWithIdAndVoteNumberAndBallots(0, 0, Collections.emptyList()) + savedVote = voteJpaRepository.save(VoteMapper.mapToJpaEntity(vote)) + } + + @AfterEach + fun tearDown() { + databaseCleanup.execute() + } + + @Test + fun `투표 결과 1~5등을 조회한다`() { + // given + val loginUser = UserMapper.mapToDomainEntity(users[0]) + UserFixture.setSecurityContextUser(loginUser) + ballotJpaRepository.save( + BallotMapper.mapToJpaEntity( + Ballot.of( + savedVote!!.id, + voteOptions[0].id, + users[0].id, + users[1].id + ) + ) + ) + Thread.sleep(1) + ballotJpaRepository.save( + BallotMapper.mapToJpaEntity( + Ballot.of( + savedVote!!.id, + voteOptions[0].id, + users[1].id, + users[0].id + ) + ) + ) + ballotJpaRepository.save( + BallotMapper.mapToJpaEntity( + Ballot.of( + savedVote!!.id, + voteOptions[1].id, + users[0].id, + users[2].id + ) + ) + ) + + // when + val voteResultsOfTop5 = voteRankService.getVoteResultsOfTop5(LocalDate.now()) + + // then + voteResultsOfTop5.voteResults.size shouldBe 5 + voteResultsOfTop5.voteResults[0].voteResults.size shouldBe 2 + voteResultsOfTop5.voteResults[0].voteResults[0].voteCount shouldBe 1 + voteResultsOfTop5.voteResults[0].voteResults[0].user.id shouldBe users[1].id + voteResultsOfTop5.voteResults[0].voteResults[1].voteCount shouldBe 1 + voteResultsOfTop5.voteResults[0].voteResults[1].user.id shouldBe users[0].id + voteResultsOfTop5.voteResults[1].voteResults.size shouldBe 1 + voteResultsOfTop5.voteResults[1].voteResults[0].voteCount shouldBe 1 + voteResultsOfTop5.voteResults[1].voteResults[0].user.id shouldBe users[2].id + } + + @Test + fun `투표 결과 1등을 조회한다`() { + // given + val loginUser = UserMapper.mapToDomainEntity(users[0]) + UserFixture.setSecurityContextUser(loginUser) + ballotJpaRepository.save( + BallotMapper.mapToJpaEntity( + Ballot.of( + savedVote!!.id, + voteOptions[0].id, + users[0].id, + users[1].id + ) + ) + ) + Thread.sleep(1) + ballotJpaRepository.save( + BallotMapper.mapToJpaEntity( + Ballot.of( + savedVote!!.id, + voteOptions[0].id, + users[1].id, + users[0].id + ) + ) + ) + ballotJpaRepository.save( + BallotMapper.mapToJpaEntity( + Ballot.of( + savedVote!!.id, + voteOptions[1].id, + users[0].id, + users[2].id + ) + ) + ) + + // when + val voteResultsOfTop1 = voteRankService.getVoteResultsOfTop1(LocalDate.now()) + + // then + voteResultsOfTop1.voteResults.size shouldBe 5 + voteResultsOfTop1.voteResults[0].voteResult!!.user.id shouldBe users[1].id + voteResultsOfTop1.voteResults[1].voteResult!!.user.id shouldBe users[2].id + voteResultsOfTop1.voteResults[2].voteResult shouldBe null + voteResultsOfTop1.voteResults[3].voteResult shouldBe null + voteResultsOfTop1.voteResults[4].voteResult shouldBe null + } + +} From 43e18410f518993177f698cedad503b926eb17ca Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Mon, 22 Jul 2024 21:48:44 +0900 Subject: [PATCH 21/23] =?UTF-8?q?chore:=20CustomUrlFilter=EC=97=90=20valid?= =?UTF-8?q?=20url=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/kotlin/com/wespot/config/security/CustomUrlFilter.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/kotlin/com/wespot/config/security/CustomUrlFilter.kt b/app/src/main/kotlin/com/wespot/config/security/CustomUrlFilter.kt index dd419396..d365f9c9 100644 --- a/app/src/main/kotlin/com/wespot/config/security/CustomUrlFilter.kt +++ b/app/src/main/kotlin/com/wespot/config/security/CustomUrlFilter.kt @@ -30,6 +30,9 @@ class CustomUrlFilter( "/api/v1/users/me", "/api/v1/users/backgrounds", "/api/v1/users/characters", + "/v1/votes/options", + "/v1/votes", + "/v1/votes/tops", ) override fun doFilterInternal( From 36ad53716a655873be733c2384fef0721b1be677 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Mon, 22 Jul 2024 21:57:01 +0900 Subject: [PATCH 22/23] =?UTF-8?q?refactor:=20groupNumber->classNumber?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/wespot/vote/fixture/VoteFixture.kt | 6 +- .../vote/fixture/VoteJpaEntityFixture.kt | 2 +- .../com/wespot/vote/mapper/VoteMapperTest.kt | 4 +- .../vote/presentation/VoteControllerTest.kt | 60 ++++++++++++++++++- .../wespot/user/dto/response/UserResponse.kt | 4 +- .../com/wespot/user/port/out/UserPort.kt | 2 +- .../com/wespot/vote/port/out/VotePort.kt | 2 +- .../vote/service/helper/VoteServiceHelper.kt | 4 +- .../src/main/kotlin/com/wespot/vote/Vote.kt | 2 +- .../kotlin/com/wespot/vote/VoteJpaEntity.kt | 2 +- .../com/wespot/vote/VoteJpaRepository.kt | 4 +- .../main/kotlin/com/wespot/vote/VoteMapper.kt | 4 +- .../com/wespot/vote/VotePersistenceAdapter.kt | 6 +- 13 files changed, 80 insertions(+), 22 deletions(-) diff --git a/app/src/test/kotlin/com/wespot/vote/fixture/VoteFixture.kt b/app/src/test/kotlin/com/wespot/vote/fixture/VoteFixture.kt index d1320578..c63a9ee0 100644 --- a/app/src/test/kotlin/com/wespot/vote/fixture/VoteFixture.kt +++ b/app/src/test/kotlin/com/wespot/vote/fixture/VoteFixture.kt @@ -12,7 +12,7 @@ object VoteFixture { id = 1L, schoolId = 1L, grade = 1, - groupNumber = 1, + classNumber = 1, voteNumber = 0, date = LocalDate.now(), ballots = Ballots.from(Collections.emptyList()) @@ -22,7 +22,7 @@ object VoteFixture { id = 1L, schoolId = 1L, grade = 1, - groupNumber = 1, + classNumber = 1, voteNumber = voteNumber, date = LocalDate.now(), ballots = Ballots.from(ballots) @@ -33,7 +33,7 @@ object VoteFixture { id = id, schoolId = 1L, grade = 1, - groupNumber = 1, + classNumber = 1, voteNumber = voteNumber, date = LocalDate.now(), ballots = Ballots.from(ballots) diff --git a/app/src/test/kotlin/com/wespot/vote/fixture/VoteJpaEntityFixture.kt b/app/src/test/kotlin/com/wespot/vote/fixture/VoteJpaEntityFixture.kt index 0b478c1a..629af5c9 100644 --- a/app/src/test/kotlin/com/wespot/vote/fixture/VoteJpaEntityFixture.kt +++ b/app/src/test/kotlin/com/wespot/vote/fixture/VoteJpaEntityFixture.kt @@ -9,7 +9,7 @@ object VoteJpaEntityFixture { id = 1L, schoolId = 1L, grade = 1, - groupNumber = 1, + classNumber = 1, voteNumber = 0, date = LocalDate.now(), ) diff --git a/app/src/test/kotlin/com/wespot/vote/mapper/VoteMapperTest.kt b/app/src/test/kotlin/com/wespot/vote/mapper/VoteMapperTest.kt index 5273c535..e98baf8b 100644 --- a/app/src/test/kotlin/com/wespot/vote/mapper/VoteMapperTest.kt +++ b/app/src/test/kotlin/com/wespot/vote/mapper/VoteMapperTest.kt @@ -23,7 +23,7 @@ class VoteMapperTest : BehaviorSpec({ voteDomainEntity.id shouldBe voteJpaEntity.id voteDomainEntity.schoolId shouldBe voteJpaEntity.schoolId voteDomainEntity.grade shouldBe voteJpaEntity.grade - voteDomainEntity.groupNumber shouldBe voteJpaEntity.groupNumber + voteDomainEntity.classNumber shouldBe voteJpaEntity.classNumber voteDomainEntity.voteNumber shouldBe voteJpaEntity.voteNumber voteDomainEntity.date shouldBe voteJpaEntity.date voteDomainEntity.ballots::class shouldBe Ballots::class @@ -39,7 +39,7 @@ class VoteMapperTest : BehaviorSpec({ jpaEntity.id shouldBe domainEntity.id jpaEntity.schoolId shouldBe domainEntity.schoolId jpaEntity.grade shouldBe domainEntity.grade - jpaEntity.groupNumber shouldBe domainEntity.groupNumber + jpaEntity.classNumber shouldBe domainEntity.classNumber jpaEntity.voteNumber shouldBe domainEntity.voteNumber jpaEntity.date shouldBe domainEntity.date } diff --git a/app/src/test/kotlin/com/wespot/vote/presentation/VoteControllerTest.kt b/app/src/test/kotlin/com/wespot/vote/presentation/VoteControllerTest.kt index 54c51f00..964f8796 100644 --- a/app/src/test/kotlin/com/wespot/vote/presentation/VoteControllerTest.kt +++ b/app/src/test/kotlin/com/wespot/vote/presentation/VoteControllerTest.kt @@ -1,6 +1,64 @@ package com.wespot.vote.presentation import com.wespot.common.presentation.IntegrationTest +import com.wespot.user.fixture.UserFixture +import com.wespot.user.mapper.UserMapper +import com.wespot.user.repository.UserJpaRepository +import com.wespot.vote.BallotJpaRepository +import com.wespot.vote.VoteJpaRepository +import com.wespot.vote.VoteMapper +import com.wespot.vote.fixture.VoteFixture +import com.wespot.voteoption.VoteOptionJpaEntity +import com.wespot.voteoption.VoteOptionJpaRepository +import com.wespot.voteoption.VoteOptionMapper +import com.wespot.voteoption.fixture.VoteOptionFixture +import io.kotest.matchers.shouldBe +import io.restassured.RestAssured +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.http.MediaType +import java.util.* + +class VoteControllerTest( + @Autowired + private var userJpaRepository: UserJpaRepository, + @Autowired + private var voteOptionJpaRepository: VoteOptionJpaRepository, + @Autowired + private var voteJpaRepository: VoteJpaRepository, + @Autowired + private var ballotJpaRepository: BallotJpaRepository, +) : IntegrationTest() { // TODO : 회원가입 구현하신 거 보고 바로 인수테스트 구현할게요 + +// @Test +// fun `질문지를 반환한다`() { +// val voteOptions = mutableListOf() +// val userJpaEntity = userJpaRepository.save( +// UserMapper.mapToJpaEntity( +// UserFixture.createWithIdAndEmail( +// 0, +// "TestEmail@Kakako" +// ) +// ) +// ) +// val loginUser = UserMapper.mapToDomainEntity(userJpaEntity) +// UserFixture.setSecurityContextUser(loginUser) +// for (i in 0 until 5) { +// val voteOptionJpaEntity = +// VoteOptionMapper.mapToJpaEntity(VoteOptionFixture.createWithId(0)) +// voteOptions.add(voteOptionJpaRepository.save(voteOptionJpaEntity)) +// } +// val vote = +// VoteFixture.createWithIdAndVoteNumberAndBallots(0, 0, Collections.emptyList()) +// voteJpaRepository.save(VoteMapper.mapToJpaEntity(vote)) +// +// val response = RestAssured.given().log().all() +// .accept(MediaType.APPLICATION_JSON_VALUE) +// .`when`().get("/v1/votes/options") +// .then().log().all() +// .extract() +// +// response.statusCode() shouldBe 200 +// } -class VoteControllerTest : IntegrationTest() { // TODO : 회원가입 구현하신 거 보고 바로 인수테스트 구현할게요 } diff --git a/core/src/main/kotlin/com/wespot/user/dto/response/UserResponse.kt b/core/src/main/kotlin/com/wespot/user/dto/response/UserResponse.kt index 7a86f65c..469645d1 100644 --- a/core/src/main/kotlin/com/wespot/user/dto/response/UserResponse.kt +++ b/core/src/main/kotlin/com/wespot/user/dto/response/UserResponse.kt @@ -9,7 +9,7 @@ data class UserResponse( val introduction : String, val schoolName : String, val grade : Int, - val groupNumber : Int, + val classNumber : Int, val profile: ProfileResponse? ) { @@ -23,7 +23,7 @@ data class UserResponse( introduction = user.introduction, schoolName = school, grade = user.grade, - groupNumber = user.classNumber, + classNumber = user.classNumber, profile = user.profile.let { ProfileResponse.from(it) } ) } diff --git a/core/src/main/kotlin/com/wespot/user/port/out/UserPort.kt b/core/src/main/kotlin/com/wespot/user/port/out/UserPort.kt index 95dc2118..9e900bd0 100644 --- a/core/src/main/kotlin/com/wespot/user/port/out/UserPort.kt +++ b/core/src/main/kotlin/com/wespot/user/port/out/UserPort.kt @@ -9,7 +9,7 @@ interface UserPort { fun findAllBySchoolIdAndGradeAndClassNumber( schoolId: Long, grade: Int, - groupNumber: Int + classNumber: Int ): List fun findIdsByIdIn(ids: List): List diff --git a/core/src/main/kotlin/com/wespot/vote/port/out/VotePort.kt b/core/src/main/kotlin/com/wespot/vote/port/out/VotePort.kt index d298d8b7..14fc83fa 100644 --- a/core/src/main/kotlin/com/wespot/vote/port/out/VotePort.kt +++ b/core/src/main/kotlin/com/wespot/vote/port/out/VotePort.kt @@ -8,7 +8,7 @@ interface VotePort { fun findBySchoolIdAndGradeAndClassNumberAndDate( schoolId: Long, grade: Int, - groupNumber: Int, + classNumber: Int, date: LocalDate ): Vote? diff --git a/core/src/main/kotlin/com/wespot/vote/service/helper/VoteServiceHelper.kt b/core/src/main/kotlin/com/wespot/vote/service/helper/VoteServiceHelper.kt index 23c4b3f5..fd22f754 100644 --- a/core/src/main/kotlin/com/wespot/vote/service/helper/VoteServiceHelper.kt +++ b/core/src/main/kotlin/com/wespot/vote/service/helper/VoteServiceHelper.kt @@ -25,7 +25,7 @@ object VoteServiceHelper { return userPort.findAllBySchoolIdAndGradeAndClassNumber( schoolId = user.schoolId, grade = user.grade, - groupNumber = user.classNumber + classNumber = user.classNumber ) } @@ -33,7 +33,7 @@ object VoteServiceHelper { return votePort.findBySchoolIdAndGradeAndClassNumberAndDate( schoolId = user.schoolId, grade = user.grade, - groupNumber = user.classNumber, + classNumber = user.classNumber, date = date ) ?: throw IllegalArgumentException("해당 투표가 존재하지 않습니다.") } diff --git a/domain/src/main/kotlin/com/wespot/vote/Vote.kt b/domain/src/main/kotlin/com/wespot/vote/Vote.kt index ffee8a17..9bd679f0 100644 --- a/domain/src/main/kotlin/com/wespot/vote/Vote.kt +++ b/domain/src/main/kotlin/com/wespot/vote/Vote.kt @@ -8,7 +8,7 @@ data class Vote( val id: Long, val schoolId: Long, val grade: Int, - val groupNumber: Int, + val classNumber: Int, val voteNumber: Int, val date: LocalDate, val ballots: Ballots, diff --git a/infrastructure/mysql/src/main/kotlin/com/wespot/vote/VoteJpaEntity.kt b/infrastructure/mysql/src/main/kotlin/com/wespot/vote/VoteJpaEntity.kt index b87258cb..5598b29a 100644 --- a/infrastructure/mysql/src/main/kotlin/com/wespot/vote/VoteJpaEntity.kt +++ b/infrastructure/mysql/src/main/kotlin/com/wespot/vote/VoteJpaEntity.kt @@ -19,7 +19,7 @@ class VoteJpaEntity( val grade: Int, @field: NotNull - val groupNumber: Int, + val classNumber: Int, @field: NotNull val voteNumber: Int, diff --git a/infrastructure/mysql/src/main/kotlin/com/wespot/vote/VoteJpaRepository.kt b/infrastructure/mysql/src/main/kotlin/com/wespot/vote/VoteJpaRepository.kt index 093816cc..1e34cf63 100644 --- a/infrastructure/mysql/src/main/kotlin/com/wespot/vote/VoteJpaRepository.kt +++ b/infrastructure/mysql/src/main/kotlin/com/wespot/vote/VoteJpaRepository.kt @@ -5,10 +5,10 @@ import java.time.LocalDate interface VoteJpaRepository : JpaRepository { - fun findBySchoolIdAndGradeAndGroupNumberAndDate( + fun findBySchoolIdAndGradeAndClassNumberAndDate( schoolId: Long, grade: Int, - groupNumber: Int, + classNumber: Int, date: LocalDate ): VoteJpaEntity? diff --git a/infrastructure/mysql/src/main/kotlin/com/wespot/vote/VoteMapper.kt b/infrastructure/mysql/src/main/kotlin/com/wespot/vote/VoteMapper.kt index 0eff4c6e..87cd689e 100644 --- a/infrastructure/mysql/src/main/kotlin/com/wespot/vote/VoteMapper.kt +++ b/infrastructure/mysql/src/main/kotlin/com/wespot/vote/VoteMapper.kt @@ -7,7 +7,7 @@ object VoteMapper { id = voteJpaEntity.id, schoolId = voteJpaEntity.schoolId, grade = voteJpaEntity.grade, - groupNumber = voteJpaEntity.groupNumber, + classNumber = voteJpaEntity.classNumber, voteNumber = voteJpaEntity.voteNumber, date = voteJpaEntity.date, ballots = Ballots.from(ballots) @@ -18,7 +18,7 @@ object VoteMapper { id = vote.id, schoolId = vote.schoolId, grade = vote.grade, - groupNumber = vote.groupNumber, + classNumber = vote.classNumber, voteNumber = vote.voteNumber, date = vote.date, ) diff --git a/infrastructure/mysql/src/main/kotlin/com/wespot/vote/VotePersistenceAdapter.kt b/infrastructure/mysql/src/main/kotlin/com/wespot/vote/VotePersistenceAdapter.kt index bf24fdc2..865d4c99 100644 --- a/infrastructure/mysql/src/main/kotlin/com/wespot/vote/VotePersistenceAdapter.kt +++ b/infrastructure/mysql/src/main/kotlin/com/wespot/vote/VotePersistenceAdapter.kt @@ -13,13 +13,13 @@ class VotePersistenceAdapter( override fun findBySchoolIdAndGradeAndClassNumberAndDate( schoolId: Long, grade: Int, - groupNumber: Int, + classNumber: Int, date: LocalDate ): Vote? { - return voteJpaRepository.findBySchoolIdAndGradeAndGroupNumberAndDate( + return voteJpaRepository.findBySchoolIdAndGradeAndClassNumberAndDate( schoolId, grade, - groupNumber, + classNumber, date )?.let { voteJpaEntity -> VoteMapper.mapToDomainEntity( From 0f571bbf97f372f8ca8b6a9bb5aa639dac73a6ea Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Mon, 22 Jul 2024 21:58:07 +0900 Subject: [PATCH 23/23] =?UTF-8?q?refactor:=20groupNumber->classNumber?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wespot/vote/presentation/VoteControllerTest.kt | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/app/src/test/kotlin/com/wespot/vote/presentation/VoteControllerTest.kt b/app/src/test/kotlin/com/wespot/vote/presentation/VoteControllerTest.kt index 964f8796..9b5e86fe 100644 --- a/app/src/test/kotlin/com/wespot/vote/presentation/VoteControllerTest.kt +++ b/app/src/test/kotlin/com/wespot/vote/presentation/VoteControllerTest.kt @@ -1,23 +1,11 @@ package com.wespot.vote.presentation import com.wespot.common.presentation.IntegrationTest -import com.wespot.user.fixture.UserFixture -import com.wespot.user.mapper.UserMapper import com.wespot.user.repository.UserJpaRepository import com.wespot.vote.BallotJpaRepository import com.wespot.vote.VoteJpaRepository -import com.wespot.vote.VoteMapper -import com.wespot.vote.fixture.VoteFixture -import com.wespot.voteoption.VoteOptionJpaEntity import com.wespot.voteoption.VoteOptionJpaRepository -import com.wespot.voteoption.VoteOptionMapper -import com.wespot.voteoption.fixture.VoteOptionFixture -import io.kotest.matchers.shouldBe -import io.restassured.RestAssured -import org.junit.jupiter.api.Test import org.springframework.beans.factory.annotation.Autowired -import org.springframework.http.MediaType -import java.util.* class VoteControllerTest( @Autowired