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 @@ -46,6 +46,19 @@ public ApiResponse<List<CategoryResponseDTO>> getCategories() {
SuccessStatus.GET_CATEGORIES_SUCCESS.getMessage());
}

@Operation(summary = "카테고리 수정", description = "카테고리 제목과 색상을 수정합니다.")
@PatchMapping("/{categoryId}")
public ApiResponse<CategoryResponseDTO> updateCategoryTitleAndColor(
@PathVariable Long categoryId,
@RequestBody @Valid CategoryCreateRequestDTO request
) {
Long userId = Utils.getUserId();
return ApiResponse.onSuccess(
categoryCommandService.updateCategoryTitleAndColor(request, userId, categoryId),
SuccessStatus.UPDATE_CATEGORY_SUCCESS.getCode(),
SuccessStatus.UPDATE_CATEGORY_SUCCESS.getMessage());
}

@Operation(summary = "카테고리 삭제", description = """
카테고리를 삭제합니다.\n
**카테고리 내 할 일도 모두 삭제됩니다.**""")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package com.indayvidual.server.domain.todo.dto.request;

import jakarta.validation.constraints.NotBlank;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
public class CategoryCreateRequestDTO {

@NotBlank(message = "title 은 비어 있을 수 없습니다.")
@NotBlank(message = "name 은 비어 있을 수 없습니다.")
private String name;

@NotBlank(message = "color 은 비어 있을 수 없습니다.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import com.indayvidual.server.common.BaseEntity;
import com.indayvidual.server.domain.user.entity.User;
import com.indayvidual.server.global.api.code.status.ErrorStatus;
import com.indayvidual.server.global.exception.GeneralException;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
Expand All @@ -14,8 +16,10 @@
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Entity
@Slf4j
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Category extends BaseEntity {
Expand All @@ -35,12 +39,16 @@ public class Category extends BaseEntity {
private String color;

// --- 도메인 로직 ---
public static Category create(User user, String title, String color) {
return Category.builder()
.user(user)
.title(title)
.color(color)
.build();
public void updateTitle(String title) {
if (title == null || title.isBlank()) throw new GeneralException(ErrorStatus.TASK_CATEGORY_TITLE_EMPTY);
log.debug("[CATEGORY] 제목 변경 - before: {}, after: {}", this.title, title);
this.title = title;
}

public void updateColor(String color) {
log.debug("[CATEGORY] 색상 변경 - before: {}, after: {}", this.color, color);
if (color == null || !color.startsWith("#")) throw new GeneralException(ErrorStatus.COLOR_INVALID);
this.color = color;
}

@Builder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,20 @@ public CategoryResponseDTO create(CategoryCreateRequestDTO request, Long userId)
return categoryConverter.toResponse(saved);
}

@Transactional
public CategoryResponseDTO updateCategoryTitleAndColor(CategoryCreateRequestDTO request, Long userId, Long categoryId) {

User user = userRepository.findById(userId)
.orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND));

Category category = categoryRepository.findByIdAndUserId(categoryId, userId)
.orElseThrow(() -> new GeneralException(ErrorStatus.TASK_CATEGORY_NOT_FOUND));

category.updateTitle(request.getName());
category.updateColor(request.getColor());
return categoryConverter.toResponse(category);
}

@Transactional
public void delete(Long userId, Long categoryId) {
Category category = categoryRepository.findByIdAndUserId(categoryId, userId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,9 +286,15 @@ public enum ErrorStatus implements BaseErrorCode {
// ===== 할 일 관련 에러 (TASK) =====
// 할 일 카테고리
TASK_CATEGORY_NOT_FOUND(HttpStatus.NOT_FOUND, "TASK4041", "카테고리를 찾을 수 없습니다."),
TASK_CATEGORY_TITLE_EMPTY(HttpStatus.BAD_REQUEST, "TASK4001", "카테고리 이름이 비어있습니다."),

// 할 일
TASK_NOT_FOUND(HttpStatus.NOT_FOUND, "TASK4042", "할 일을 찾을 수 없습니다."),
TASK_FORBIDDEN(HttpStatus.FORBIDDEN, "TASK4031", "해당 할 일에 대한 권한이 없습니다."),
TASK_INVALID_ORDER(HttpStatus.BAD_REQUEST, "TASK4001", "유효하지 않은 할 일 순서 요청입니다.");
TASK_INVALID_ORDER(HttpStatus.BAD_REQUEST, "TASK4002", "유효하지 않은 할 일 순서 요청입니다."),

// ===== 색상 관련 에러 (COLOR) =====
COLOR_INVALID(HttpStatus.BAD_REQUEST, "COLOR4001", "유효하지 않은 색상 코드 형식입니다.");

private final HttpStatus httpStatus;
private final String code;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public enum SuccessStatus implements BaseCode {

// 할 일 관련 응답
CREATE_CATEGORY_SUCCESS(HttpStatus.CREATED, "CREATE_CATEGORY_SUCCESS", "카테고리 등록 성공"),
UPDATE_CATEGORY_SUCCESS(HttpStatus.CREATED, "UPDATE_CATEGORY_SUCCESS", "카테고리 수정 성공"),
GET_CATEGORIES_SUCCESS(HttpStatus.OK, "GET_CATEGORIES_SUCCESS", "카테고리 목록 조회 성공"),
DELETE_CATEGORY_SUCCESS(HttpStatus.OK, "DELETE_CATEGORY_SUCCESS", "카테고리 삭제 성공"),
CREATE_TASK_SUCCESS(HttpStatus.CREATED, "CREATE_TASK_SUCCESS", "할일 등록 성공"),
Expand Down