유저 행동 데이터, 포인트 추가 #309

Merged
klaus merged 25 commits from test into main 2025-04-24 02:44:58 +00:00
6 changed files with 200 additions and 0 deletions
Showing only changes of commit d94418067f - Show all commits

View File

@ -0,0 +1,37 @@
package kr.co.vividnext.sodalive.admin.point
import kr.co.vividnext.sodalive.point.PointRewardPolicy
import kr.co.vividnext.sodalive.useraction.ActionType
import java.time.LocalDateTime
import java.time.ZoneId
import java.time.format.DateTimeFormatter
data class CreatePointRewardPolicyRequest(
val title: String,
val actionType: ActionType,
val threshold: Int,
val pointAmount: Int,
val startDate: String,
val endDate: String,
val isActive: Boolean
) {
fun toEntity(): PointRewardPolicy {
val dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")
return PointRewardPolicy(
title = title,
actionType = actionType,
threshold = threshold,
pointAmount = pointAmount,
startDate = LocalDateTime.parse(startDate, dateTimeFormatter)
.atZone(ZoneId.of("Asia/Seoul"))
.withZoneSameInstant(ZoneId.of("UTC"))
.toLocalDateTime(),
endDate = LocalDateTime.parse(endDate, dateTimeFormatter).withSecond(59)
.atZone(ZoneId.of("Asia/Seoul"))
.withZoneSameInstant(ZoneId.of("UTC"))
.toLocalDateTime(),
isActive = isActive
)
}
}

View File

@ -0,0 +1,15 @@
package kr.co.vividnext.sodalive.admin.point
import com.querydsl.core.annotations.QueryProjection
import kr.co.vividnext.sodalive.useraction.ActionType
data class GetPointRewardPolicyResponse @QueryProjection constructor(
val id: Long,
val title: String,
val actionType: ActionType,
val threshold: Int,
val pointAmount: Int,
val startDate: String,
val endDate: String,
val isActive: Boolean
)

View File

@ -0,0 +1,8 @@
package kr.co.vividnext.sodalive.admin.point
data class ModifyPointRewardPolicyRequest(
val title: String?,
val startDate: String?,
val endDate: String?,
val isActive: Boolean?
)

View File

@ -0,0 +1,36 @@
package kr.co.vividnext.sodalive.admin.point
import kr.co.vividnext.sodalive.common.ApiResponse
import org.springframework.data.domain.Pageable
import org.springframework.security.access.prepost.PreAuthorize
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.PutMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
@RestController
@RequestMapping("/admin/point-policies")
@PreAuthorize("hasRole('ADMIN')")
class PointPolicyController(private val service: PointPolicyService) {
@GetMapping
fun getAll(pageable: Pageable) = ApiResponse.ok(
service.getAll(
offset = pageable.offset,
limit = pageable.pageSize.toLong()
)
)
@PostMapping
fun create(
@RequestBody request: CreatePointRewardPolicyRequest
) = ApiResponse.ok(service.create(request))
@PutMapping("/{id}")
fun update(
@PathVariable id: Long,
@RequestBody request: ModifyPointRewardPolicyRequest
) = ApiResponse.ok(service.update(id, request))
}

View File

@ -0,0 +1,55 @@
package kr.co.vividnext.sodalive.admin.point
import com.querydsl.core.types.dsl.DateTimePath
import com.querydsl.core.types.dsl.Expressions
import com.querydsl.core.types.dsl.StringTemplate
import com.querydsl.jpa.impl.JPAQueryFactory
import kr.co.vividnext.sodalive.point.PointRewardPolicy
import kr.co.vividnext.sodalive.point.QPointRewardPolicy.pointRewardPolicy
import org.springframework.data.jpa.repository.JpaRepository
import java.time.LocalDateTime
interface PointPolicyRepository : JpaRepository<PointRewardPolicy, Long>, PointPolicyQueryRepository
interface PointPolicyQueryRepository {
fun getAll(offset: Long, limit: Long): List<GetPointRewardPolicyResponse>
}
class PointPolicyQueryRepositoryImpl(
private val queryFactory: JPAQueryFactory
) : PointPolicyQueryRepository {
override fun getAll(offset: Long, limit: Long): List<GetPointRewardPolicyResponse> {
return queryFactory
.select(
QGetPointRewardPolicyResponse(
pointRewardPolicy.id,
pointRewardPolicy.title,
pointRewardPolicy.actionType,
pointRewardPolicy.threshold,
pointRewardPolicy.pointAmount,
getFormattedDate(pointRewardPolicy.startDate),
getFormattedDate(pointRewardPolicy.endDate),
pointRewardPolicy.isActive
)
)
.from(pointRewardPolicy)
.orderBy(pointRewardPolicy.isActive.desc(), pointRewardPolicy.startDate.desc())
.offset(offset)
.limit(limit)
.fetch()
}
private fun getFormattedDate(dateTimePath: DateTimePath<LocalDateTime>): StringTemplate {
return Expressions.stringTemplate(
"DATE_FORMAT({0}, {1})",
Expressions.dateTimeTemplate(
LocalDateTime::class.java,
"CONVERT_TZ({0},{1},{2})",
dateTimePath,
"UTC",
"Asia/Seoul"
),
"%Y-%m-%d %H:%i"
)
}
}

View File

@ -0,0 +1,49 @@
package kr.co.vividnext.sodalive.admin.point
import kr.co.vividnext.sodalive.common.SodaException
import org.springframework.data.repository.findByIdOrNull
import org.springframework.stereotype.Service
import java.time.LocalDateTime
import java.time.ZoneId
import java.time.format.DateTimeFormatter
@Service
class PointPolicyService(private val repository: PointPolicyRepository) {
fun getAll(offset: Long, limit: Long): List<GetPointRewardPolicyResponse> {
return repository.getAll(offset, limit)
}
fun create(request: CreatePointRewardPolicyRequest) {
val pointPolicy = request.toEntity()
repository.save(pointPolicy)
}
fun update(id: Long, request: ModifyPointRewardPolicyRequest) {
val pointPolicy = repository.findByIdOrNull(id)
?: throw SodaException("잘못된 접근입니다.")
val dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")
if (request.title != null) {
pointPolicy.title = request.title
}
if (request.startDate != null) {
pointPolicy.startDate = LocalDateTime.parse(request.startDate, dateTimeFormatter)
.atZone(ZoneId.of("Asia/Seoul"))
.withZoneSameInstant(ZoneId.of("UTC"))
.toLocalDateTime()
}
if (request.endDate != null) {
pointPolicy.endDate = LocalDateTime.parse(request.endDate, dateTimeFormatter).withSecond(59)
.atZone(ZoneId.of("Asia/Seoul"))
.withZoneSameInstant(ZoneId.of("UTC"))
.toLocalDateTime()
}
if (request.isActive != null) {
pointPolicy.isActive = request.isActive
}
}
}