Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,17 @@ public ApiResponse<List<CategoryResponseDTO>> getCategories() {
SuccessStatus.GET_CATEGORIES_SUCCESS.getCode(),
SuccessStatus.GET_CATEGORIES_SUCCESS.getMessage());
}

@Operation(summary = "카테고리 삭제", description = """
카테고리를 삭제합니다.\n
**카테고리 내 할 일도 모두 삭제됩니다.**""")
@DeleteMapping("/{categoryId}")
public ApiResponse<Void> deleteCategory(@PathVariable Long categoryId) {
Long userId = Utils.getUserId();
categoryCommandService.delete(userId, categoryId);
return ApiResponse.onSuccess(
null,
SuccessStatus.DELETE_CATEGORY_SUCCESS.getCode(),
SuccessStatus.DELETE_CATEGORY_SUCCESS.getMessage());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.indayvidual.server.domain.todo.dto.request.*;
import com.indayvidual.server.domain.todo.dto.response.TaskCheckUpdateResponseDTO;
import com.indayvidual.server.domain.todo.dto.response.TaskOrderCategoryUpdateResponseDTO;
import com.indayvidual.server.domain.todo.dto.response.TaskResponseDTO;
import com.indayvidual.server.domain.todo.dto.response.TaskUpdateResponseDTO;
import com.indayvidual.server.domain.todo.service.task.TaskCommandService;
Expand Down Expand Up @@ -110,22 +111,18 @@ public ApiResponse<TaskCheckUpdateResponseDTO> updateTaskStatus(@PathVariable Lo
SuccessStatus.UPDATE_TASK_CHECK_SUCCESS.getMessage());
}

@Operation(summary = "할 일 순서 변경",
@Operation(summary = "할 일 순서 및 카테고리 변경",
description = """
카테고리 내 할 일의 순서를 변경합니다.\n
**해당 카테고리 내 모든 Task ID**를 정렬 순서대로 request body로 전달해야 합니다.\n
해당 순서를 기준으로 `position` 필드를 재정렬합니다.
할 일의 순서 또는 카테고리를 변경합니다.\n
순서/카테고리가 변경되는 모든 `task`의 정보를 포함해야 합니다.
""")
@PatchMapping("/categories/{categoryId}/tasks/order")
public ApiResponse<Void> updateTaskOrder(
@PathVariable Long categoryId,
@RequestBody @Valid TaskOrderUpdateRequestDTO request) {
@PatchMapping("/tasks/order")
public ApiResponse<TaskOrderCategoryUpdateResponseDTO> updateTaskOrder(
@RequestBody @Valid TaskOrderCategoryUpdateBulkRequestDTO request) {

//TODO : 카테고리 변경도 추가하기
Long userId = Utils.getUserId();
taskCommandService.updateTaskOrder(userId, categoryId, request);
return ApiResponse.onSuccess(
null,
taskCommandService.updateTaskOrders(userId, request),
SuccessStatus.UPDATE_TASK_ORDER_SUCCESS.getCode(),
SuccessStatus.UPDATE_TASK_ORDER_SUCCESS.getMessage());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.indayvidual.server.domain.todo.dto.request;

import jakarta.validation.constraints.NotEmpty;
import lombok.Data;

import java.util.List;

@Data
public class TaskOrderCategoryUpdateBulkRequestDTO {

@NotEmpty(message = "tasks 리스트는 비어 있을 수 없습니다.")
private List<TaskOrderCategoryUpdateRequestDTO> tasks;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.indayvidual.server.domain.todo.dto.request;

import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import lombok.Data;

@Data
public class TaskOrderCategoryUpdateRequestDTO {

@NotNull(message = "taskId는 필수입니다.")
private Long taskId;

@NotNull(message = "categoryId는 필수입니다.")
private Long categoryId;

@NotNull(message = "order는 필수입니다.")
@Min(value = 0, message = "order는 0 이상이어야 합니다.")
private Integer order;
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.indayvidual.server.domain.todo.dto.response;

import lombok.Builder;
import lombok.Getter;

import java.util.List;

@Getter
@Builder
public class TaskOrderCategoryUpdateResponseDTO {

private Integer updatedCount;
private List<Long> affectedCategories;

public TaskOrderCategoryUpdateResponseDTO(int updatedCount, List<Long> affectedCategories) {
this.updatedCount = updatedCount;
this.affectedCategories = affectedCategories;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ public void updatePosition(int position) {
this.position = position;
}

public void updateCategory(Category category) {
log.debug("[TASK] 카테고리 변경 - before: {}, after: {}", this.category, category);
this.category = category;
}

public static Task create(User user, Category category, String title, LocalDate dueDate, int position) {
return Task.builder()
.user(user)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;
import java.util.Optional;

public interface CategoryRepository extends JpaRepository<Category, Long> {

List<Category> findAllByUserIdOrderByCreatedAtDesc(Long userId);

Optional<Category> findByIdAndUserId(Long userId, Long categoryId);

boolean existsByIdAndUserId(Long categoryId, Long userId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,8 @@ public interface TaskRepository extends JpaRepository<Task, Long> {
*/
@Query("SELECT MAX(t.position) FROM Task t WHERE t.category.id = :categoryId")
Integer findMaxPositionByCategoryId(@Param("categoryId") Long categoryId);

List<Task> findAllByUserIdAndCategoryId(Long userId, Long categoryId);

List<Task> findAllByCategoryId(Long categoryId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,27 @@
import com.indayvidual.server.domain.todo.dto.request.CategoryCreateRequestDTO;
import com.indayvidual.server.domain.todo.dto.response.CategoryResponseDTO;
import com.indayvidual.server.domain.todo.entity.Category;
import com.indayvidual.server.domain.todo.entity.Task;
import com.indayvidual.server.domain.todo.repository.CategoryRepository;
import com.indayvidual.server.domain.todo.repository.TaskRepository;
import com.indayvidual.server.domain.user.entity.User;
import com.indayvidual.server.domain.user.repository.UserRepository;
import com.indayvidual.server.global.api.code.status.ErrorStatus;
import com.indayvidual.server.global.exception.GeneralException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@Slf4j
@RequiredArgsConstructor
public class CategoryCommandService {

private final CategoryRepository categoryRepository;
private final TaskRepository taskRepository;
private final CategoryConverter categoryConverter;
private final UserRepository userRepository;

Expand All @@ -31,4 +38,18 @@ public CategoryResponseDTO create(CategoryCreateRequestDTO request, Long userId)
Category saved = categoryRepository.save(entity);
return categoryConverter.toResponse(saved);
}

@Transactional
public void delete(Long userId, Long categoryId) {
Category category = categoryRepository.findByIdAndUserId(categoryId, userId)
.orElseThrow(() -> new GeneralException(ErrorStatus.TASK_CATEGORY_NOT_FOUND));

// 연관된 task 먼저 삭제
List<Task> tasks = taskRepository.findAllByCategoryId(categoryId);
taskRepository.deleteAll(tasks);

categoryRepository.delete(category);

log.debug("[CATEGORY] 삭제 완료 - categoryId={}", categoryId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

import com.indayvidual.server.domain.todo.dto.request.TaskCreateRequestDTO;
import com.indayvidual.server.domain.todo.dto.request.TaskDueDateUpdateRequestDTO;
import com.indayvidual.server.domain.todo.dto.request.TaskOrderUpdateRequestDTO;
import com.indayvidual.server.domain.todo.dto.request.TaskOrderCategoryUpdateBulkRequestDTO;
import com.indayvidual.server.domain.todo.dto.request.TaskTitleUpdateRequestDTO;
import com.indayvidual.server.domain.todo.dto.response.TaskCheckUpdateResponseDTO;
import com.indayvidual.server.domain.todo.dto.response.TaskOrderCategoryUpdateResponseDTO;
import com.indayvidual.server.domain.todo.dto.response.TaskResponseDTO;
import com.indayvidual.server.domain.todo.dto.response.TaskUpdateResponseDTO;

Expand Down Expand Up @@ -44,10 +45,9 @@ public interface TaskCommandService {
* 특정 카테고리 내 할 일의 순서를 일괄 변경합니다.
*
* @param userId
* @param categoryId
* @param request 요청 DTO
*/
void updateTaskOrder(Long userId, Long categoryId, TaskOrderUpdateRequestDTO request);
TaskOrderCategoryUpdateResponseDTO updateTaskOrders(Long userId, TaskOrderCategoryUpdateBulkRequestDTO request);

/**
* 할 일의 체크 상태를 토글합니다.
Expand Down
Loading