Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement goal modification #25

Merged
merged 2 commits into from
Aug 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions api-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,39 @@ paths:
title: 5kg 다이어트
streak: 0
status: CLOSED
/v1/goals/{goalId}:
put:
tags:
- goals
summary: 목표 수정(달성 상태 변경 포함)
description: " "
operationId: modifyGoal
parameters:
- name: goalId
in: path
required: true
schema:
type: string
description: 목표 ID
responses:
"200":
description: OK
delete:
tags:
- goals
summary: 목표 삭제
description: " "
operationId: deleteGoal
parameters:
- name: goalId
in: path
required: true
schema:
type: string
description: 목표 ID
responses:
"200":
description: OK

# journals
/v1/goals/{goalId}/journals:
Expand Down
25 changes: 16 additions & 9 deletions src/main/kotlin/com/likelionhgu/stepper/goal/Goal.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ class Goal(
@Column
var title: String,

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id")
val member: Member? = null,

@Column
var startDate: LocalDate? = null,

Expand All @@ -28,18 +32,21 @@ class Goal(
@Column(length = 512)
var thumbnail: String? = null,

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id")
val member: Member
@Column
var status: GoalStatus = GoalStatus.OPEN
) : BaseTime() {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
val goalId = 0L

@Column
var status = GoalStatus.OPEN
val goalId: Long = 0L

@Column
var streak = 0
var streak: Int = 0

fun update(targetGoal: Goal) {
title = targetGoal.title
startDate = targetGoal.startDate
endDate = targetGoal.endDate
thumbnail = targetGoal.thumbnail
status = targetGoal.status
}
}
19 changes: 19 additions & 0 deletions src/main/kotlin/com/likelionhgu/stepper/goal/GoalController.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@ package com.likelionhgu.stepper.goal

import com.likelionhgu.stepper.goal.enums.GoalSortType
import com.likelionhgu.stepper.goal.request.GoalRequest
import com.likelionhgu.stepper.goal.request.GoalUpdateRequest
import com.likelionhgu.stepper.goal.response.GoalResponseWrapper
import com.likelionhgu.stepper.security.oauth2.CommonOAuth2Attribute
import jakarta.validation.Valid
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.security.core.annotation.AuthenticationPrincipal
import org.springframework.web.bind.annotation.DeleteMapping
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.RequestParam
import org.springframework.web.bind.annotation.RestController
Expand Down Expand Up @@ -38,4 +42,19 @@ class GoalController(
val responseBody = GoalResponseWrapper.of(goals)
return ResponseEntity.ok(responseBody)
}

@PutMapping("/v1/goals/{goalId}")
fun updateGoal(
@PathVariable goalId: Long,
@RequestBody goalRequest: GoalUpdateRequest,
) {
goalService.updateGoal(goalId, goalRequest)
}

@DeleteMapping("/v1/goals/{goalId}")
fun deleteGoal(
@PathVariable goalId: Long
) {
goalService.deleteGoal(goalId)
}
}
18 changes: 16 additions & 2 deletions src/main/kotlin/com/likelionhgu/stepper/goal/GoalService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.likelionhgu.stepper.exception.GoalNotFoundException
import com.likelionhgu.stepper.exception.MemberNotFoundException
import com.likelionhgu.stepper.goal.enums.GoalSortType
import com.likelionhgu.stepper.goal.request.GoalRequest
import com.likelionhgu.stepper.goal.request.GoalUpdateRequest
import com.likelionhgu.stepper.member.MemberRepository
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
Expand All @@ -21,15 +22,16 @@ class GoalService(

val goal = Goal(
goalRequest.title!!,
member,
goalRequest.startDate,
goalRequest.endDate,
goalRequest.thumbnail,
member
goalRequest.thumbnail
).let(goalRepository::save)

return goal.goalId
}

@Transactional(readOnly = true)
fun memberGoals(oauth2UserId: String, sortType: GoalSortType): List<Goal> {
val member = memberRepository.findByOauth2Id(oauth2UserId)
?: throw MemberNotFoundException("The member with the oauth2 sub \"$oauth2UserId\" does not exist")
Expand All @@ -44,8 +46,20 @@ class GoalService(
* @return Goal The `Goal` entity corresponding to the provided ID.
* @throws GoalNotFoundException if no goal is found with the provided ID.
*/
@Transactional(readOnly = true)
fun goalInfo(goalId: Long): Goal {
return goalRepository.findById(goalId).getOrNull()
?: throw GoalNotFoundException("The goal with the id \"$goalId\" does not exist")
}

fun updateGoal(goalId: Long, goalRequest: GoalUpdateRequest) {
val sourceGoal = goalRepository.findById(goalId).getOrNull()
?: throw GoalNotFoundException("The goal with the id \"$goalId\" does not exist")

goalRequest.toEntity().also(sourceGoal::update)
}

fun deleteGoal(goalId: Long) {
goalRepository.deleteById(goalId)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.likelionhgu.stepper.goal.request

import com.likelionhgu.stepper.goal.Goal
import com.likelionhgu.stepper.goal.enums.GoalStatus
import jakarta.validation.constraints.NotNull
import org.springframework.format.annotation.DateTimeFormat
import java.time.LocalDate

data class GoalUpdateRequest(

@field:NotNull(message = "The title must not be null")
val title: String?,

@field:NotNull(message = "The status must not be null")
val status: GoalStatus?,

@field:DateTimeFormat(pattern = "yyyy-MM-dd")
val startDate: LocalDate? = null,

@field:DateTimeFormat(pattern = "yyyy-MM-dd")
val endDate: LocalDate? = null,

val thumbnail: String? = null,

) {
fun toEntity() = Goal(
title = title!!,
startDate = startDate,
endDate = endDate,
thumbnail = thumbnail,
status = status!!
)
}
26 changes: 25 additions & 1 deletion src/test/kotlin/com/likelionhgu/stepper/goal/GoalServiceTest.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.likelionhgu.stepper.goal

import com.likelionhgu.stepper.goal.enums.GoalSortType
import com.likelionhgu.stepper.goal.enums.GoalStatus
import com.likelionhgu.stepper.goal.request.GoalRequest
import com.likelionhgu.stepper.goal.request.GoalUpdateRequest
import com.likelionhgu.stepper.member.Member
import com.likelionhgu.stepper.member.MemberRepository
import io.kotest.core.spec.style.BehaviorSpec
Expand Down Expand Up @@ -67,14 +69,36 @@ class GoalServiceTest(
}

`when`("the goals are retrieved with an order of descending") {

then("the goals should be sorted by ascending") {
val goals = goalService.memberGoals(oauth2UserId, GoalSortType.DESC)

goals[0].goalId shouldBe goalId2
goals[1].goalId shouldBe goalId1
}
}

`when`("the goal is updated") {
then("the goal should be updated") {
val request = GoalUpdateRequest(
title = goalTitle,
status = GoalStatus.CLOSED
)
goalService.updateGoal(goalId1, request)

val goal = goalService.goalInfo(goalId1)
goal shouldNotBe null
goal.status shouldBe GoalStatus.CLOSED
}
}

`when`("the goal is deleted") {
then("the goal should be deleted") {
goalService.deleteGoal(goalId1)

val goal = goalRepository.findById(goalId1).getOrNull()
goal shouldBe null
}
}
}
}) {
override fun extensions() = listOf(SpringExtension)
Expand Down
Loading