Skip to content

Commit

Permalink
Merge pull request #442 from Team-Ampersand/440-feat/like-function
Browse files Browse the repository at this point in the history
좋아요 부분 관련 기능
  • Loading branch information
esperar authored Sep 24, 2024
2 parents 3d16cfe + 1dc9585 commit 3a7a636
Show file tree
Hide file tree
Showing 21 changed files with 325 additions and 10 deletions.
13 changes: 11 additions & 2 deletions src/main/kotlin/com/dotori/v2/domain/music/domain/entity/Music.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,18 @@ class Music(
val thumbnail: String,

@Column(name = "like_count", nullable = false, columnDefinition = "INT default 0")
val likeCount: Int = 0,
var likeCount: Int = 0,

@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id", nullable = false)
val member: Member
) : BaseTimeEntity()
) : BaseTimeEntity() {

fun plusLikeCount() {
this.likeCount++
}

fun minusLikeCount() {
this.likeCount--
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.dotori.v2.domain.music.domain.entity

import javax.persistence.Column
import javax.persistence.Entity
import javax.persistence.GeneratedValue
import javax.persistence.GenerationType
import javax.persistence.Id
import javax.persistence.Table

@Entity
@Table(name = "likes")
class MusicLike (
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "like_id")
val id: Long = 0,

@Column(name = "music_id", nullable = false)
val musicId: Long,

@Column(name = "member_id", nullable = false)
val memberId: Long,
) {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.dotori.v2.domain.music.domain.repository

import com.dotori.v2.domain.music.domain.entity.MusicLike
import io.lettuce.core.dynamic.annotation.Param
import javax.persistence.LockModeType
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.data.jpa.repository.Lock
import org.springframework.data.jpa.repository.Query

interface MusicLikeRepository : JpaRepository<MusicLike,Long> {
@Lock(LockModeType.PESSIMISTIC_WRITE)
@Query("select l from MusicLike l where l.memberId = :memberId and l.musicId = :musicId")
fun findByMemberIdAndMusicId(@Param("memberId") memberId: Long,@Param("musicId") musicId: Long): MusicLike?

fun existsByMusicIdAndMemberId(musicId: Long, memberId: Long): Boolean
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,6 @@ interface MusicRepository : JpaRepository<Music, Long> {

fun deleteAllByCreatedDateBefore(date: LocalDateTime)

@Query(value = "select * from music where created_date like :date% order by music.like_count desc", nativeQuery = true)
fun findAllByCreatedDateOrderByLikeCountDESC(@Param("date") date: LocalDate): List<Music>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.dotori.v2.domain.music.exception

import com.dotori.v2.global.error.ErrorCode
import com.dotori.v2.global.error.exception.BasicException

class NotValidMusicLikeException : BasicException(ErrorCode.NOT_VALID_MUSIC_LIKE) {
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package com.dotori.v2.domain.music.presentation.admin

import com.dotori.v2.domain.music.presentation.data.res.MusicLikeCountResDto
import com.dotori.v2.domain.music.presentation.data.res.MusicListResDto
import com.dotori.v2.domain.music.presentation.data.res.MusicRankListResDto
import com.dotori.v2.domain.music.service.DeleteMusicService
import com.dotori.v2.domain.music.service.FindMusicRankService
import com.dotori.v2.domain.music.service.FindMusicsService
import com.dotori.v2.domain.music.service.ToggleMusicLikeService
import org.springframework.format.annotation.DateTimeFormat
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
Expand All @@ -13,7 +17,9 @@ import java.time.LocalDate
@RequestMapping("/v2/admin/music")
class AdminMusicController(
private val findMusicsService: FindMusicsService,
private val deleteMusicService: DeleteMusicService
private val deleteMusicService: DeleteMusicService,
private val toggleMusicLikeService: ToggleMusicLikeService,
private val findMusicRankService: FindMusicRankService
) {
@GetMapping
fun findMusics(
Expand All @@ -29,4 +35,16 @@ class AdminMusicController(
deleteMusicService.execute(musicId)
.run { ResponseEntity.status(HttpStatus.NO_CONTENT).build() }

@PatchMapping("/{music_id}/like")
fun toggleMusicLike(@PathVariable("music_id") musicId: Long): ResponseEntity<MusicLikeCountResDto> =
ResponseEntity.status(HttpStatus.OK).body(toggleMusicLikeService.execute(musicId))

@GetMapping("/like")
fun findMusicRank(
@RequestParam(
value = "date",
required = true
) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) date: LocalDate
): ResponseEntity<MusicRankListResDto> =
ResponseEntity.status(HttpStatus.OK).body(findMusicRankService.execute(date))
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package com.dotori.v2.domain.music.presentation.councillor

import com.dotori.v2.domain.music.presentation.data.req.ApplyMusicReqDto
import com.dotori.v2.domain.music.presentation.data.res.MusicLikeCountResDto
import com.dotori.v2.domain.music.presentation.data.res.MusicListResDto
import com.dotori.v2.domain.music.presentation.data.res.MusicRankListResDto
import com.dotori.v2.domain.music.service.ApplyMusicService
import com.dotori.v2.domain.music.service.DeleteMusicService
import com.dotori.v2.domain.music.service.FindMusicRankService
import com.dotori.v2.domain.music.service.FindMusicsService
import com.dotori.v2.domain.music.service.ToggleMusicLikeService
import org.springframework.format.annotation.DateTimeFormat
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
Expand All @@ -17,7 +21,9 @@ import java.time.LocalDateTime
class CouncillorMusicController(
private val applyMusicService: ApplyMusicService,
private val findMusicsService: FindMusicsService,
private val deleteMusicService: DeleteMusicService
private val deleteMusicService: DeleteMusicService,
private val toggleMusicLikeService: ToggleMusicLikeService,
private val findMusicRankService: FindMusicRankService
) {
@PostMapping
fun applyMusic(@RequestBody applyMusicReqDto: ApplyMusicReqDto): ResponseEntity<Void> =
Expand All @@ -37,4 +43,17 @@ class CouncillorMusicController(
fun deleteMusic(@PathVariable("music_id") musicId: Long): ResponseEntity<Void> =
deleteMusicService.execute(musicId)
.run { ResponseEntity.status(HttpStatus.NO_CONTENT).build() }

@PatchMapping("/{music_id}/like")
fun toggleMusicLike(@PathVariable("music_id") musicId: Long): ResponseEntity<MusicLikeCountResDto> =
ResponseEntity.status(HttpStatus.OK).body(toggleMusicLikeService.execute(musicId))

@GetMapping("/like")
fun findMusicRank(
@RequestParam(
value = "date",
required = true
) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) date: LocalDate
): ResponseEntity<MusicRankListResDto> =
ResponseEntity.status(HttpStatus.OK).body(findMusicRankService.execute(date))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.dotori.v2.domain.music.presentation.data.res

data class MusicLikeCountResDto(
val likeCount: Int
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.dotori.v2.domain.music.presentation.data.res

data class MusicRankListResDto(
val content: List<MusicRankResDto>
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.dotori.v2.domain.music.presentation.data.res

import java.time.LocalDateTime

data class MusicRankResDto(
val id: Long,
val rank: Int,
val url: String,
val title: String,
val thumbnail: String,
val username: String,
val email: String,
val createdTime: LocalDateTime,
val stuNum: String,
val likeCount: Int,
val memberLikeCheck: Boolean
)
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,7 @@ data class MusicResDto(
val username: String,
val email: String,
val createdTime: LocalDateTime,
val stuNum: String
val stuNum: String,
val likeCount: Int,
val memberLikeCheck: Boolean
)
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package com.dotori.v2.domain.music.presentation.developer

import com.dotori.v2.domain.music.presentation.data.req.ApplyMusicReqDto
import com.dotori.v2.domain.music.presentation.data.res.MusicLikeCountResDto
import com.dotori.v2.domain.music.presentation.data.res.MusicListResDto
import com.dotori.v2.domain.music.presentation.data.res.MusicRankListResDto
import com.dotori.v2.domain.music.service.ApplyMusicService
import com.dotori.v2.domain.music.service.DeleteMusicService
import com.dotori.v2.domain.music.service.FindMusicRankService
import com.dotori.v2.domain.music.service.FindMusicsService
import com.dotori.v2.domain.music.service.ToggleMusicLikeService
import org.springframework.format.annotation.DateTimeFormat
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
Expand All @@ -17,7 +21,9 @@ import java.time.LocalDateTime
class DeveloperMusicController(
private val applyMusicService: ApplyMusicService,
private val findMusicsService: FindMusicsService,
private val deleteMusicService: DeleteMusicService
private val deleteMusicService: DeleteMusicService,
private val toggleMusicLikeService: ToggleMusicLikeService,
private val findMusicRankService: FindMusicRankService
) {
@PostMapping
fun applyMusic(@RequestBody applyMusicReqDto: ApplyMusicReqDto): ResponseEntity<Void> =
Expand All @@ -37,4 +43,17 @@ class DeveloperMusicController(
fun deleteMusic(@PathVariable("music_id") musicId: Long): ResponseEntity<Void> =
deleteMusicService.execute(musicId)
.run { ResponseEntity.status(HttpStatus.NO_CONTENT).build() }

@PatchMapping("/{music_id}/like")
fun toggleMusicLike(@PathVariable("music_id") musicId: Long): ResponseEntity<MusicLikeCountResDto> =
ResponseEntity.status(HttpStatus.OK).body(toggleMusicLikeService.execute(musicId))

@GetMapping("/like")
fun findMusicRank(
@RequestParam(
value = "date",
required = true
) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) date: LocalDate
): ResponseEntity<MusicRankListResDto> =
ResponseEntity.status(HttpStatus.OK).body(findMusicRankService.execute(date))
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package com.dotori.v2.domain.music.presentation.member

import com.dotori.v2.domain.music.presentation.data.req.ApplyMusicReqDto
import com.dotori.v2.domain.music.presentation.data.res.MusicLikeCountResDto
import com.dotori.v2.domain.music.presentation.data.res.MusicListResDto
import com.dotori.v2.domain.music.presentation.data.res.MusicRankListResDto
import com.dotori.v2.domain.music.service.ApplyMusicService
import com.dotori.v2.domain.music.service.DeleteMyMusicService
import com.dotori.v2.domain.music.service.FindMusicRankService
import com.dotori.v2.domain.music.service.FindMusicsService
import com.dotori.v2.domain.music.service.ToggleMusicLikeService
import org.springframework.format.annotation.DateTimeFormat
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
Expand All @@ -17,7 +21,9 @@ import java.time.LocalDateTime
class MemberMusicController(
private val applyMusicService: ApplyMusicService,
private val findMusicsService: FindMusicsService,
private val deleteMyMusicService: DeleteMyMusicService
private val deleteMyMusicService: DeleteMyMusicService,
private val toggleMusicLikeService: ToggleMusicLikeService,
private val findMusicRankService: FindMusicRankService
) {
@PostMapping
fun applyMusic(@RequestBody applyMusicReqDto: ApplyMusicReqDto): ResponseEntity<Void> =
Expand All @@ -37,4 +43,17 @@ class MemberMusicController(
fun deleteMusic(@PathVariable("music_id") musicId: Long): ResponseEntity<Void> =
deleteMyMusicService.execute(musicId)
.run { ResponseEntity.status(HttpStatus.NO_CONTENT).build() }

@PatchMapping("/{music_id}/like")
fun toggleMusicLike(@PathVariable("music_id") musicId: Long): ResponseEntity<MusicLikeCountResDto> =
ResponseEntity.status(HttpStatus.OK).body(toggleMusicLikeService.execute(musicId))

@GetMapping("/like")
fun findMusicRank(
@RequestParam(
value = "date",
required = true
) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) date: LocalDate
): ResponseEntity<MusicRankListResDto> =
ResponseEntity.status(HttpStatus.OK).body(findMusicRankService.execute(date))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.dotori.v2.domain.music.service

import com.dotori.v2.domain.music.presentation.data.res.MusicRankListResDto
import java.time.LocalDate

interface FindMusicRankService {
fun execute(date: LocalDate): MusicRankListResDto
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.dotori.v2.domain.music.service

import com.dotori.v2.domain.music.presentation.data.res.MusicLikeCountResDto

interface ToggleMusicLikeService {
fun execute(musicId: Long) : MusicLikeCountResDto
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ class ApplyMusicServiceImpl(
username = music.member.memberName,
email = music.member.email,
createdTime = music.createdDate,
stuNum = music.member.stuNum
stuNum = music.member.stuNum,
likeCount = music.likeCount,
memberLikeCheck = false
)

private fun validDayOfWeek(dayOfWeek: DayOfWeek) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.dotori.v2.domain.music.service.impl

import com.dotori.v2.domain.music.domain.entity.Music
import com.dotori.v2.domain.music.domain.repository.MusicLikeRepository
import com.dotori.v2.domain.music.domain.repository.MusicRepository
import com.dotori.v2.domain.music.presentation.data.res.MusicRankListResDto
import com.dotori.v2.domain.music.presentation.data.res.MusicRankResDto
import com.dotori.v2.domain.music.service.FindMusicRankService
import com.dotori.v2.global.util.UserUtil
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import java.time.LocalDate

@Service
@Transactional
class FindMusicRankServiceImpl(
private val musicRepository: MusicRepository,
private val musicLikeRepository: MusicLikeRepository,
private val userUtil: UserUtil
) : FindMusicRankService {

override fun execute(date: LocalDate): MusicRankListResDto {
val responses = musicRepository.findAllByCreatedDateOrderByLikeCountDESC(date)
.mapIndexed { index, music ->
MusicRankResDto(
id = music.id,
rank = index + 1,
url = music.url,
title = music.title,
thumbnail = music.thumbnail,
username = music.member.memberName,
email = music.member.email,
createdTime = music.createdDate,
stuNum = music.member.stuNum,
likeCount = music.likeCount,
memberLikeCheck = checkLike(music)
)
}

return MusicRankListResDto(
responses
)
}

private fun checkLike(music: Music): Boolean {
val member = userUtil.fetchCurrentUser()

return musicLikeRepository.existsByMusicIdAndMemberId(music.id, member.id)
}

}
Loading

0 comments on commit 3a7a636

Please sign in to comment.