Skip to content

Commit

Permalink
refactor: 도메인명 변경 (memory -> category, moment -> staccato) #594 (#596)
Browse files Browse the repository at this point in the history
* refactor: memory -> category 변경

* refactor: memory -> category 변경

* test: CategoryController 테스트 작성

* refactor: v2를 RequestMapping에서 한번에 처리

* refactor: moment -> staccato 변경

* test: StaccatoController 테스트 작성

* refactor: 주석 삭제

* refactor: 코드 축약

* refactor: v2 삭제

* refactor: 접근제어자 private으로 변경

* refactor: swagger 설명의 추억 -> 스타카토 추가 변경

* refactor: swagger 설명의 추억 -> 스타카토 추가 변경

* fix: 이전 PR 수정사항 반영

* refactor: ControllerTest extend 적용

* refactor: MemoryReadRequest -> CategoryReadRequest 변경 및 적용
  • Loading branch information
BurningFalls authored Jan 19, 2025
1 parent 8361895 commit 7346e49
Show file tree
Hide file tree
Showing 24 changed files with 1,936 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package com.staccato.memory.controller;

import java.net.URI;
import java.time.LocalDate;

import jakarta.validation.Valid;
import jakarta.validation.constraints.Min;

import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.staccato.config.auth.LoginMember;
import com.staccato.config.log.annotation.Trace;
import com.staccato.member.domain.Member;
import com.staccato.memory.controller.docs.CategoryControllerDocs;
import com.staccato.memory.service.MemoryService;
import com.staccato.memory.service.dto.request.CategoryReadRequest;
import com.staccato.memory.service.dto.request.CategoryRequest;
import com.staccato.memory.service.dto.request.MemoryReadRequest;
import com.staccato.memory.service.dto.response.CategoryDetailResponse;
import com.staccato.memory.service.dto.response.CategoryIdResponse;
import com.staccato.memory.service.dto.response.CategoryNameResponses;
import com.staccato.memory.service.dto.response.CategoryResponses;
import com.staccato.memory.service.dto.response.MemoryDetailResponse;
import com.staccato.memory.service.dto.response.MemoryIdResponse;
import com.staccato.memory.service.dto.response.MemoryNameResponses;
import com.staccato.memory.service.dto.response.MemoryResponses;

import lombok.RequiredArgsConstructor;

@Trace
@Validated
@RestController
@RequestMapping("/categories")
@RequiredArgsConstructor
public class CategoryController implements CategoryControllerDocs {
private final MemoryService memoryService;

@PostMapping
public ResponseEntity<CategoryIdResponse> createCategory(
@Valid @RequestBody CategoryRequest categoryRequest,
@LoginMember Member member
) {
MemoryIdResponse memoryIdResponse = memoryService.createMemory(CategoryDtoMapper.toMemoryRequest(categoryRequest), member);
return ResponseEntity.created(URI.create("/categories/" + memoryIdResponse.memoryId())).body(CategoryDtoMapper.toCategoryIdResponse(memoryIdResponse));
}

@GetMapping
public ResponseEntity<CategoryResponses> readAllCategories(
@LoginMember Member member,
@ModelAttribute("CategoryReadRequest") CategoryReadRequest categoryReadRequest
) {
MemoryResponses memoryResponses = memoryService.readAllMemories(member, CategoryDtoMapper.toMemoryReadRequest(categoryReadRequest));
return ResponseEntity.ok(CategoryDtoMapper.toCategoryResponses(memoryResponses));
}

@GetMapping("/candidates")
public ResponseEntity<CategoryNameResponses> readAllCandidateCategories(
@LoginMember Member member,
@RequestParam(value = "currentDate") LocalDate currentDate
) {
MemoryNameResponses memoryNameResponses = memoryService.readAllMemoriesByDate(member, currentDate);
return ResponseEntity.ok(CategoryDtoMapper.toCategoryNameResponses(memoryNameResponses));
}

@GetMapping("/{categoryId}")
public ResponseEntity<CategoryDetailResponse> readCategory(
@LoginMember Member member,
@PathVariable @Min(value = 1L, message = "카테고리 식별자는 양수로 이루어져야 합니다.") long categoryId) {
MemoryDetailResponse memoryDetailResponse = memoryService.readMemoryById(categoryId, member);
return ResponseEntity.ok(CategoryDtoMapper.toCategoryDetailResponse(memoryDetailResponse));
}

@PutMapping(path = "/{categoryId}")
public ResponseEntity<Void> updateCategory(
@PathVariable @Min(value = 1L, message = "카테고리 식별자는 양수로 이루어져야 합니다.") long categoryId,
@Valid @RequestBody CategoryRequest categoryRequest,
@LoginMember Member member) {
memoryService.updateMemory(CategoryDtoMapper.toMemoryRequest(categoryRequest), categoryId, member);
return ResponseEntity.ok().build();
}

@DeleteMapping("/{categoryId}")
public ResponseEntity<Void> deleteCategory(
@PathVariable @Min(value = 1L, message = "카테고리 식별자는 양수로 이루어져야 합니다.") long categoryId,
@LoginMember Member member) {
memoryService.deleteMemory(categoryId, member);
return ResponseEntity.ok().build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package com.staccato.memory.controller;

import java.util.List;

import com.staccato.memory.service.dto.request.CategoryReadRequest;
import com.staccato.memory.service.dto.request.CategoryRequest;
import com.staccato.memory.service.dto.request.MemoryReadRequest;
import com.staccato.memory.service.dto.request.MemoryRequest;
import com.staccato.memory.service.dto.response.CategoryDetailResponse;
import com.staccato.memory.service.dto.response.CategoryIdResponse;
import com.staccato.memory.service.dto.response.CategoryNameResponse;
import com.staccato.memory.service.dto.response.CategoryNameResponses;
import com.staccato.memory.service.dto.response.CategoryResponse;
import com.staccato.memory.service.dto.response.CategoryResponses;
import com.staccato.memory.service.dto.response.MemoryDetailResponse;
import com.staccato.memory.service.dto.response.MemoryIdResponse;
import com.staccato.memory.service.dto.response.MemoryNameResponse;
import com.staccato.memory.service.dto.response.MemoryNameResponses;
import com.staccato.memory.service.dto.response.MemoryResponse;
import com.staccato.memory.service.dto.response.MemoryResponses;
import com.staccato.memory.service.dto.response.MomentResponse;
import com.staccato.memory.service.dto.response.StaccatoResponse;

public class CategoryDtoMapper {
public static MemoryRequest toMemoryRequest(CategoryRequest categoryRequest) {
return new MemoryRequest(
categoryRequest.categoryThumbnailUrl(),
categoryRequest.categoryTitle(),
categoryRequest.description(),
categoryRequest.startAt(),
categoryRequest.endAt()
);
}

public static CategoryIdResponse toCategoryIdResponse(MemoryIdResponse memoryIdResponse) {
return new CategoryIdResponse(memoryIdResponse.memoryId());
}

public static CategoryResponse toCategoryResponse(MemoryResponse memoryResponse) {
return new CategoryResponse(
memoryResponse.memoryId(),
memoryResponse.memoryThumbnailUrl(),
memoryResponse.memoryTitle(),
memoryResponse.startAt(),
memoryResponse.endAt()
);
}

public static CategoryResponses toCategoryResponses(MemoryResponses memoryResponses) {
List<CategoryResponse> categoryResponses = memoryResponses.memories().stream()
.map(CategoryDtoMapper::toCategoryResponse)
.toList();
return new CategoryResponses(categoryResponses);
}

public static CategoryNameResponse toCategoryNameResponse(MemoryNameResponse memoryNameResponse) {
return new CategoryNameResponse(memoryNameResponse.memoryId(), memoryNameResponse.memoryTitle());
}

public static CategoryNameResponses toCategoryNameResponses(MemoryNameResponses memoryNameResponses) {
List<CategoryNameResponse> categoryNameResponses = memoryNameResponses.memories().stream()
.map(CategoryDtoMapper::toCategoryNameResponse)
.toList();
return new CategoryNameResponses(categoryNameResponses);
}

public static CategoryDetailResponse toCategoryDetailResponse(MemoryDetailResponse memoryDetailResponse) {
List<StaccatoResponse> staccatoResponses = memoryDetailResponse.moments().stream()
.map(CategoryDtoMapper::toStaccatoResponse)
.toList();
return new CategoryDetailResponse(
memoryDetailResponse.memoryId(),
memoryDetailResponse.memoryThumbnailUrl(),
memoryDetailResponse.memoryTitle(),
memoryDetailResponse.description(),
memoryDetailResponse.startAt(),
memoryDetailResponse.endAt(),
memoryDetailResponse.mates(),
staccatoResponses
);
}

private static StaccatoResponse toStaccatoResponse(MomentResponse momentResponse) {
return new StaccatoResponse(
momentResponse.momentId(),
momentResponse.staccatoTitle(),
momentResponse.momentImageUrl(),
momentResponse.visitedAt()
);
}

public static MemoryReadRequest toMemoryReadRequest(CategoryReadRequest categoryReadRequest) {
return new MemoryReadRequest(
categoryReadRequest.filters(),
categoryReadRequest.sort()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package com.staccato.memory.controller.docs;

import java.time.LocalDate;

import jakarta.validation.Valid;
import jakarta.validation.constraints.Min;

import org.springframework.http.ResponseEntity;

import com.staccato.member.domain.Member;
import com.staccato.memory.service.dto.request.CategoryReadRequest;
import com.staccato.memory.service.dto.request.CategoryRequest;
import com.staccato.memory.service.dto.request.MemoryReadRequest;
import com.staccato.memory.service.dto.response.CategoryDetailResponse;
import com.staccato.memory.service.dto.response.CategoryIdResponse;
import com.staccato.memory.service.dto.response.CategoryNameResponses;
import com.staccato.memory.service.dto.response.CategoryResponses;
import com.staccato.memory.service.dto.response.MemoryResponses;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;

@Tag(name = "Category", description = "Category API")
public interface CategoryControllerDocs {
@Operation(summary = "카테고리 생성", description = "카테고리(썸네일, 제목, 내용, 기간)을 생성합니다.")
@ApiResponses(value = {
@ApiResponse(description = "카테고리 생성 성공", responseCode = "201"),
@ApiResponse(description = """
<발생 가능한 케이스>
(1) 필수 값(카테고리 제목)이 누락되었을 때
(2) 날짜 형식(yyyy-MM-dd)이 잘못되었을 때
(3) 제목이 공백 포함 30자를 초과했을 때
(4) 내용이 공백 포함 500자를 초과했을 때
(5) 기간 설정이 잘못되었을 때 (시작 날짜와 끝날짜 중 하나만 설정할 수 없음)
(6) 이미 존재하는 카테고리 이름일 때
""",
responseCode = "400")
})
ResponseEntity<CategoryIdResponse> createCategory(
@Parameter(required = true) @Valid CategoryRequest categoryRequest,
@Parameter(hidden = true) Member member);

@Operation(summary = "카테고리 목록 조회", description = "사용자의 모든 카테고리 목록을 조회합니다.")
@ApiResponse(description = "카테고리 목록 조회 성공", responseCode = "200")
ResponseEntity<CategoryResponses> readAllCategories(
@Parameter(hidden = true) Member member,
@Parameter(description = "정렬 기준은 생략하거나 유효하지 않은 값에 대해서는 최근 수정 순(UPDATED)이 기본 정렬로 적용됩니다. 필터링 조건은 생략하거나 유효하지 않은 값이 들어오면 적용되지 않습니다.") CategoryReadRequest categoryReadRequest
);

@Operation(summary = "특정 날짜를 포함하는 사용자의 모든 카테고리 목록 조회", description = "특정 날짜를 포함하는 사용자의 모든 카테고리 목록을 조회합니다.")
@ApiResponses(value = {
@ApiResponse(description = "카테고리 목록 조회 성공", responseCode = "200"),
@ApiResponse(description = "입력받은 현재 날짜가 유효하지 않을 때 발생", responseCode = "400")
})
ResponseEntity<CategoryNameResponses> readAllCandidateCategories(
@Parameter(hidden = true) Member member,
@Parameter(description = "현재 날짜", example = "2024-08-21") LocalDate currentDate);

@Operation(summary = "카테고리 조회", description = "사용자의 카테고리을 조회합니다.")
@ApiResponses(value = {
@ApiResponse(description = "카테고리 조회 성공", responseCode = "200"),
@ApiResponse(description = """
<발생 가능한 케이스>
(1) 존재하지 않는 카테고리을 조회하려고 했을 때
(2) Path Variable 형식이 잘못되었을 때
""",
responseCode = "400")
})
ResponseEntity<CategoryDetailResponse> readCategory(
@Parameter(hidden = true) Member member,
@Parameter(description = "카테고리 ID", example = "1") @Min(value = 1L, message = "카테고리 식별자는 양수로 이루어져야 합니다.") long categoryId);

@Operation(summary = "카테고리 수정", description = "카테고리 정보(썸네일, 제목, 내용, 기간)를 수정합니다.")
@ApiResponses(value = {
@ApiResponse(description = "카테고리 수정 성공", responseCode = "200"),
@ApiResponse(description = """
<발생 가능한 케이스>
(1) 필수 값(카테고리 제목)이 누락되었을 때
(2) 날짜 형식(yyyy-MM-dd)이 잘못되었을 때
(3) 제목이 공백 포함 30자를 초과했을 때
(4) 내용이 공백 포함 500자를 초과했을 때
(5) 기간 설정이 잘못되었을 때
(6) 변경하려는 카테고리 기간이 이미 존재하는 스타카토를 포함하지 않을 때
(7) 수정하려는 카테고리이 존재하지 않을 때
(8) Path Variable 형식이 잘못되었을 때
""",
responseCode = "400")
})
ResponseEntity<Void> updateCategory(
@Parameter(description = "카테고리 ID", example = "1") @Min(value = 1L, message = "카테고리 식별자는 양수로 이루어져야 합니다.") long categoryId,
@Parameter(required = true) @Valid CategoryRequest categoryRequest,
@Parameter(hidden = true) Member member);

@Operation(summary = "카테고리 삭제", description = "사용자의 카테고리을 삭제합니다.")
@ApiResponses(value = {
@ApiResponse(description = "카테고리 삭제 성공", responseCode = "200"),
@ApiResponse(description = "Path Variable 형식이 잘못되었을 때 발생", responseCode = "400")
})
ResponseEntity<Void> deleteCategory(
@Parameter(description = "카테고리 ID", example = "1") @Min(value = 1L, message = "카테고리 식별자는 양수로 이루어져야 합니다.") long categoryId,
@Parameter(hidden = true) Member member);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.staccato.memory.service.dto.request;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;

import com.staccato.memory.service.MemoryFilter;
import com.staccato.memory.service.MemorySort;

import io.swagger.v3.oas.annotations.media.Schema;

@Schema(description = "카테고리 목록 조회시 정렬과 필터링 조건을 위한 요청 형식입니다.")
public record CategoryReadRequest(
@Schema(description = "사용할 필터링을 구분자(,)로 구분하여 나열 (TERM / 대소문자 구분 X)", example = "TERM")
String filters,
@Schema(description = "정렬 기준 (UPDATED, NEWEST, OLDEST / 대소문자 구분 X)", example = "NEWEST")
String sort
) {
private static final String DELIMITER = ",";

public List<MemoryFilter> getFilters() {
List<String> filters = parseFilters().stream()
.map(String::trim)
.toList();
return MemoryFilter.findAllByName(filters);
}

private List<String> parseFilters() {
if (Objects.isNull(filters)) {
return List.of();
}
return Arrays.stream(filters.split(DELIMITER)).toList();
}

public MemorySort getSort() {
return MemorySort.findByName(sort);
}
}
Loading

0 comments on commit 7346e49

Please sign in to comment.