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

[Feature]: [BE] 카테고리 삭제 기능 #34

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
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 @@ -3,6 +3,8 @@

import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
Expand Down Expand Up @@ -37,7 +39,7 @@ public ApiResponse<CategoryDto> createCategory(

return ApiResponse.of(
true,
"201",
HttpStatus.CREATED,
"%s 카테고리가 생성되었습니다.".formatted(category.getName()),
categoryDto
);
Expand All @@ -51,7 +53,7 @@ public ApiResponse<CategoryPageDto> getCategories(

return ApiResponse.of(
true,
"200",
HttpStatus.OK,
"카테고리 목록 조회",
categoryPageDto
);
Expand All @@ -71,10 +73,23 @@ public ApiResponse<CategoryDto> modifyCategory(

return ApiResponse.of(
true,
"200",
HttpStatus.OK,
"%d번 카테고리가 수정되었습니다.".formatted(category.getId()),
categoryDto
);
}

@DeleteMapping("/{id}")
public ApiResponse<Void> deleteCategory(
@PathVariable Long id
) {
categoryService.softDelete(id);

return ApiResponse.of(
true,
HttpStatus.OK,
"%d번 카테고리가 삭제되었습니다.".formatted(id)
);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,9 @@ public class Category extends BaseEntity {
public void modifyName(String newName) {
this.name = newName; // 이름 변경
}

// soft delete
public void softDelete() {
this.deactivate();
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.app.backend.domain.category.repository;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;

import com.app.backend.domain.category.entity.Category;
Expand All @@ -8,4 +10,6 @@ public interface CategoryRepository extends JpaRepository<Category, Long> {
boolean existsByName(String name);

Category findByName(String name);

Page<Category> findByDisabledFalse(Pageable pageable);
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public Category create(String name) {

// 카테고리 목록 페이지로 조회
public CategoryPageDto getCategories(Pageable pageable) {
Page<Category> categoryPage = categoryRepository.findAll(pageable);
Page<Category> categoryPage = categoryRepository.findByDisabledFalse(pageable);

List<CategoryDto> categories = categoryPage
.getContent()
Expand Down Expand Up @@ -85,4 +85,14 @@ public void modify(Category category, String newName) {

category.modifyName(newName);
}

@Transactional
public void softDelete(Long id) {
Category category = categoryRepository.findById(id)
.orElseThrow(() -> new CategoryException(CategoryErrorCode.CATEGORY_NOT_FOUND));

category.softDelete();

categoryRepository.save(category);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.web.servlet.MockMvc;
Expand Down Expand Up @@ -46,7 +47,7 @@ void t1() throws Exception {
mvc.perform(MockMvcRequestBuilders.post("/api/v1/admin/categories")
.content(requestJson)
.contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.code").value("201"))
.andExpect(jsonPath("$.code").value(HttpStatus.CREATED.value()))
.andExpect(jsonPath("$.message").value("%s 카테고리가 생성되었습니다.".formatted(categoryName)))
.andExpect(jsonPath("$.data.name").value(categoryName));

Expand Down Expand Up @@ -122,7 +123,7 @@ void t5() throws Exception {
ResultActions resultActions = mvc.perform(MockMvcRequestBuilders.get("/api/v1/admin/categories")
.contentType(MediaType.APPLICATION_JSON)
)
.andExpect(jsonPath("$.code").value("200"))
.andExpect(jsonPath("$.code").value(HttpStatus.OK.value()))
.andExpect(jsonPath("$.message").value("카테고리 목록 조회"))
.andExpect(jsonPath("$.data.categories.length()").value(10))
.andExpect(jsonPath("$.data.currentPage").value(1))
Expand All @@ -146,7 +147,7 @@ void t6() throws Exception {
ResultActions resultActions = mvc.perform(MockMvcRequestBuilders.get("/api/v1/admin/categories?page=1")
.contentType(MediaType.APPLICATION_JSON)
)
.andExpect(jsonPath("$.code").value("200"))
.andExpect(jsonPath("$.code").value(HttpStatus.OK.value()))
.andExpect(jsonPath("$.message").value("카테고리 목록 조회"))
.andExpect(jsonPath("$.data.categories.length()").value(1))
.andExpect(jsonPath("$.data.currentPage").value(2))
Expand Down Expand Up @@ -176,12 +177,60 @@ void t7() throws Exception {
mvc.perform(MockMvcRequestBuilders.patch("/api/v1/admin/categories/{id}", category.getId())
.content(requestJson)
.contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.code").value("200"))
.andExpect(jsonPath("$.code").value(HttpStatus.OK.value()))
.andExpect(jsonPath("$.message").value("%d번 카테고리가 수정되었습니다.".formatted(category.getId())))
.andExpect(jsonPath("$.data.name").value(categoryName));

Category updatedCategory = categoryRepository.findById(category.getId()).orElseThrow(() -> new CategoryException(
CategoryErrorCode.CATEGORY_NOT_FOUND));
assertEquals(categoryName, updatedCategory.getName()); // 반영되었는지 확인
}

@Test
@DisplayName("카테고리 삭제")
void t8() throws Exception {
Category category = Category.builder()
.name("카테고리")
.build();
categoryRepository.save(category);

ResultActions resultActions = mvc.perform(MockMvcRequestBuilders.delete("/api/v1/admin/categories/{id}", category.getId())
.contentType(MediaType.APPLICATION_JSON)
)
.andExpect(jsonPath("$.code").value(HttpStatus.OK.value()))
.andExpect(jsonPath("$.message").value("%d번 카테고리가 삭제되었습니다.".formatted(category.getId())));

Category deletedCategory = categoryRepository.findById(category.getId())
.orElseThrow(() -> new CategoryException(
CategoryErrorCode.CATEGORY_NOT_FOUND));
assertTrue(deletedCategory.getDisabled());
}

@Test
@DisplayName("카테고리 삭제 후 카테고리 조회")
void t9() throws Exception {
for (int i = 1; i <= 11; i++) {
Category category = Category.builder()
.name("카테고리" + i)
.build();
categoryRepository.save(category);
}

Category category1 = categoryRepository.findAll().get(0);
category1.softDelete();
categoryRepository.save(category1);

ResultActions resultActions = mvc.perform(MockMvcRequestBuilders.get("/api/v1/admin/categories")
.contentType(MediaType.APPLICATION_JSON)
)
.andExpect(jsonPath("$.code").value(HttpStatus.OK.value()))
.andExpect(jsonPath("$.message").value("카테고리 목록 조회"))
.andExpect(jsonPath("$.data.categories.length()").value(10))
.andExpect(jsonPath("$.data.currentPage").value(1))
.andExpect(jsonPath("$.data.totalPages").value(1))
.andExpect(jsonPath("$.data.totalItems").value(10))
.andExpect(jsonPath("$.data.pageSize").value(10));

assertEquals(11, categoryRepository.count());
}
}
Loading