Skip to content

Commit 9ef56b2

Browse files
committed
feat,refact : 수정 삭제 기능 구현 + 리펙토링
1 parent b4890ef commit 9ef56b2

File tree

5 files changed

+98
-7
lines changed

5 files changed

+98
-7
lines changed

src/main/java/com/back/domain/study/todo/controller/TodoController.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,39 @@ public ResponseEntity<RsData<List<TodoResponseDto>>> getAllTodos(
6060
}
6161

6262
// ==================== 수정 ===================
63+
// 할 일 내용 수정
64+
@PutMapping("/{todoId}")
65+
@Operation(summary = "할 일 수정", description = "할 일의 내용과 날짜를 수정합니다.")
66+
public ResponseEntity<RsData<TodoResponseDto>> updateTodo(
67+
@AuthenticationPrincipal CustomUserDetails userDetails,
68+
@PathVariable Long todoId,
69+
@Valid @RequestBody TodoRequestDto requestDto
70+
) {
71+
TodoResponseDto response = todoService.updateTodo(userDetails.getUserId(), todoId, requestDto);
72+
return ResponseEntity.ok(RsData.success("할 일이 수정되었습니다.", response));
73+
}
74+
75+
// 할 일 완료/미완료 토글
76+
@PutMapping("/{todoId}/complete")
77+
@Operation(summary = "할 일 완료 상태 토글", description = "할 일의 완료 상태를 변경합니다.")
78+
public ResponseEntity<RsData<TodoResponseDto>> toggleTodoComplete(
79+
@AuthenticationPrincipal CustomUserDetails userDetails,
80+
@PathVariable Long todoId
81+
) {
82+
TodoResponseDto response = todoService.toggleTodoComplete(userDetails.getUserId(), todoId);
83+
return ResponseEntity.ok(RsData.success("할 일 상태가 변경되었습니다.", response));
84+
}
6385

6486
// ==================== 삭제 ===================
87+
// 할 일 삭제
88+
@DeleteMapping("/{todoId}")
89+
@Operation(summary = "할 일 삭제", description = "할 일을 삭제합니다.")
90+
public ResponseEntity<RsData<Void>> deleteTodo(
91+
@AuthenticationPrincipal CustomUserDetails userDetails,
92+
@PathVariable Long todoId
93+
) {
94+
todoService.deleteTodo(userDetails.getUserId(), todoId);
95+
return ResponseEntity.ok(RsData.success("할 일이 삭제되었습니다."));
96+
}
6597

6698
}

src/main/java/com/back/domain/study/todo/entity/Todo.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,11 @@ public Todo(User user, String description, LocalDate date) {
3232
this.isComplete = false;
3333
}
3434

35+
public void updateDescription(String description) {
36+
this.description = description;
37+
}
38+
39+
public void toggleComplete() {
40+
this.isComplete = !this.isComplete;
41+
}
3542
}

src/main/java/com/back/domain/study/todo/repository/TodoRepository.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77

88
import java.time.LocalDate;
99
import java.util.List;
10+
import java.util.Optional;
1011

1112
@Repository
1213
public interface TodoRepository extends JpaRepository<Todo, Long> {
1314
List<Todo> findByUserIdAndDate(Long userId, LocalDate date);
1415
List<Todo> findByUserId(Long userId);
16+
Todo findByIdAndUser(Long id, User user);
1517
}

src/main/java/com/back/domain/study/todo/service/TodoService.java

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
import com.back.domain.user.repository.UserRepository;
99
import com.back.global.exception.CustomException;
1010
import com.back.global.exception.ErrorCode;
11-
import com.back.global.security.user.CustomUserDetails;
12-
import jakarta.validation.Valid;
1311
import lombok.RequiredArgsConstructor;
1412
import org.springframework.stereotype.Service;
1513
import org.springframework.transaction.annotation.Transactional;
@@ -26,9 +24,10 @@ public class TodoService {
2624
private final UserRepository userRepository;
2725

2826
// ==================== 생성 ===================
27+
@Transactional
2928
public TodoResponseDto createTodo(Long userId, TodoRequestDto request) {
30-
User user = userRepository.findById(userId)
31-
.orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND));
29+
User user = findUserById(userId);
30+
3231
Todo todo = new Todo(
3332
user,
3433
request.description(),
@@ -40,21 +39,68 @@ public TodoResponseDto createTodo(Long userId, TodoRequestDto request) {
4039
}
4140

4241
// ==================== 조회 ===================
43-
// 유저의 특정 날짜의 모든 할 일 조회
42+
//유저의 특정 날짜의 모든 할 일 조회
4443
public List<TodoResponseDto> getTodosByDate(Long userId, LocalDate date) {
4544
List<Todo> todos = todoRepository.findByUserIdAndDate(userId, date);
4645
return todos.stream()
4746
.map(TodoResponseDto::from)
4847
.collect(Collectors.toList());
4948
}
50-
// 유저의 전체 할 일 조회
49+
50+
//유저의 전체 할 일 조회
5151
public List<TodoResponseDto> getAllTodos(Long userId) {
5252
List<Todo> todos = todoRepository.findByUserId(userId);
5353
return todos.stream()
5454
.map(TodoResponseDto::from)
5555
.collect(Collectors.toList());
5656
}
57+
5758
// ==================== 수정 ===================
59+
// 할 일 내용 수정
60+
@Transactional
61+
public TodoResponseDto updateTodo(Long userId, Long todoId, TodoRequestDto requestDto) {
62+
User user = findUserById(userId);
63+
Todo todo = findTodoByIdAndUser(todoId, user);
64+
65+
todo.updateDescription(requestDto.description());
66+
67+
return TodoResponseDto.from(todo);
68+
}
69+
70+
// 할 일 완료 상태 토글
71+
@Transactional
72+
public TodoResponseDto toggleTodoComplete(Long userId, Long todoId) {
73+
User user = findUserById(userId);
74+
Todo todo = findTodoByIdAndUser(todoId, user);
75+
todo.toggleComplete();
76+
return TodoResponseDto.from(todo);
77+
}
5878

5979
// ==================== 삭제 ===================
60-
}
80+
// 할 일 삭제
81+
@Transactional
82+
public void deleteTodo(Long userId, Long todoId) {
83+
User user = findUserById(userId);
84+
Todo todo = findTodoByIdAndUser(todoId, user);
85+
todoRepository.delete(todo);
86+
}
87+
88+
// ==================== 유틸 ===================
89+
// 유저 조회
90+
private User findUserById(Long userId) {
91+
return userRepository.findById(userId)
92+
.orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND));
93+
}
94+
95+
// 할 일 조회 및 소유권 확인
96+
private Todo findTodoByIdAndUser(Long todoId, User user) {
97+
Todo todo = todoRepository.findById(todoId)
98+
.orElseThrow(() -> new CustomException(ErrorCode.TODO_NOT_FOUND));
99+
100+
if (!todo.getUser().getId().equals(user.getId())) {
101+
throw new CustomException(ErrorCode.TODO_FORBIDDEN);
102+
}
103+
104+
return todo;
105+
}
106+
}

src/main/java/com/back/global/exception/ErrorCode.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ public enum ErrorCode {
4848
REPEAT_INVALID_UNTIL_DATE(HttpStatus.BAD_REQUEST, "REPEAT_001", "반복 계획의 종료 날짜는 시작 날짜 이전일 수 없습니다."),
4949
REPEAT_BYDAY_REQUIRED(HttpStatus.BAD_REQUEST, "REPEAT_002", "주간 반복 계획의 경우 요일(byDay) 정보가 필요합니다."),
5050

51+
// ======================== 투두 관련 ========================
52+
TODO_NOT_FOUND(HttpStatus.NOT_FOUND, "TODO_001", "존재하지 않는 할 일입니다."),
53+
TODO_FORBIDDEN(HttpStatus.FORBIDDEN, "TODO_002", "할 일에 대한 접근 권한이 없습니다."),
54+
5155

5256
// ======================== 메시지 관련 ========================
5357
MESSAGE_NOT_FOUND(HttpStatus.NOT_FOUND, "MESSAGE_001", "존재하지 않는 메시지입니다."),

0 commit comments

Comments
 (0)