Skip to content
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package clap.server.adapter.inbound.web.admin;

import clap.server.adapter.inbound.security.SecurityUserDetails;
import clap.server.adapter.inbound.web.dto.admin.AddSubCategoryRequest;
import clap.server.adapter.inbound.web.dto.admin.AddMainCategoryRequest;
import clap.server.adapter.inbound.web.dto.admin.AddSubCategoryRequest;
import clap.server.application.port.inbound.admin.AddCategoryUsecase;
import clap.server.common.annotation.architecture.WebAdapter;
import io.swagger.v3.oas.annotations.Operation;
Expand All @@ -18,7 +18,7 @@
@Tag(name = "카테고리 추가")
@WebAdapter
@RequiredArgsConstructor
@RequestMapping("/api/managements")
@RequestMapping("/api/management")
public class AddCategoryController {
private final AddCategoryUsecase addCategoryUsecase;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package clap.server.adapter.inbound.web.admin;

import clap.server.adapter.inbound.web.dto.admin.FindAllCategoryResponse;
import clap.server.adapter.inbound.web.dto.admin.FindMainCategoryResponse;
import clap.server.adapter.inbound.web.dto.admin.FindSubCategoryResponse;
import clap.server.application.port.inbound.admin.FindAllCategoryUsecase;
import clap.server.application.port.inbound.admin.FindMainCategoryUsecase;
import clap.server.application.port.inbound.admin.FindSubCategoryUsecase;
import clap.server.common.annotation.architecture.WebAdapter;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.List;

@Tag(name = "카테고리 조회")
@WebAdapter
@RequiredArgsConstructor
@RequestMapping("/api")
public class FindCategoryController {
private final FindAllCategoryUsecase findAllCategoryUsecase;
private final FindMainCategoryUsecase findmainCategoryUsecase;
private final FindSubCategoryUsecase findsubCategoryUsecase;

@Operation(summary = "모든 카테고리 조회")
@GetMapping("/category")
public ResponseEntity<FindAllCategoryResponse> findAllCategory() {
return ResponseEntity.ok(findAllCategoryUsecase.findAllCategory());
}

@Operation(summary = "1차 카테고리 조회")
@GetMapping("/main-category")
public ResponseEntity<List<FindMainCategoryResponse>> findMainCategory() {
return ResponseEntity.ok(findmainCategoryUsecase.findMainCategory());
}

@Operation(summary = "2차 카테고리 조회")
@GetMapping("/sub-category")
public ResponseEntity<List<FindSubCategoryResponse>> findSubCategory() {
return ResponseEntity.ok(findsubCategoryUsecase.findSubCategory());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package clap.server.adapter.inbound.web.admin;

import clap.server.adapter.inbound.security.SecurityUserDetails;
import clap.server.adapter.inbound.web.dto.admin.UpdateCategoryRequest;
import clap.server.application.port.inbound.admin.UpdateCategoryUsecase;
import clap.server.common.annotation.architecture.WebAdapter;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;

@Tag(name = "카테고리 수정")
@WebAdapter
@RequiredArgsConstructor
@RequestMapping("/api/management")
public class UpdateCategoryController {
private final UpdateCategoryUsecase updateCategoryUsecase;

@Operation(summary = "카테고리 수정")
@PatchMapping("/categories/categoryId")
@Secured("ROLE_ADMIN")
public void updateCategory(@AuthenticationPrincipal SecurityUserDetails userInfo, Long categoryId,
@RequestBody UpdateCategoryRequest updateCategoryRequest) {
updateCategoryUsecase.updateCategory(userInfo.getUserId(), categoryId, updateCategoryRequest.name(), updateCategoryRequest.code());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package clap.server.adapter.inbound.web.dto.admin;

import java.util.List;

public record FindAllCategoryResponse(
List<FindMainCategoryResponse> mainCategory,
List<FindSubCategoryResponse> subCategory
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package clap.server.adapter.inbound.web.dto.admin;

public record FindMainCategoryResponse(
Long id,
String name,
String code
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package clap.server.adapter.inbound.web.dto.admin;

public record FindSubCategoryResponse(
Long id,
Long mainCategoryId,
String name,
String code
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package clap.server.adapter.inbound.web.dto.admin;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import org.hibernate.validator.constraints.Length;

public record UpdateCategoryRequest(
@NotBlank @Length(max = 20)
String name,
@NotBlank @Pattern(regexp = "^[A-Z]{1,2}$", message = "올바른 카테고리 코드 형식이 아닙니다.")
String code
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import clap.server.domain.model.task.Category;
import lombok.RequiredArgsConstructor;

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

@PersistenceAdapter
Expand All @@ -24,6 +25,30 @@ public Optional<Category> findById(Long id) {
return categoryEntity.map(categoryPersistenceMapper::toDomain);
}

@Override
public List<Category> findAll() {
return categoryRepository.findByIsDeletedFalse()
.stream()
.map(categoryPersistenceMapper::toDomain)
.toList();
}

@Override
public List<Category> findMainCategory() {
return categoryRepository.findByIsDeletedFalseAndMainCategoryIsNull()
.stream()
.map(categoryPersistenceMapper::toDomain)
.toList();
}

@Override
public List<Category> findSubCategory() {
return categoryRepository.findByIsDeletedFalseAndMainCategoryIsNotNull()
.stream()
.map(categoryPersistenceMapper::toDomain)
.toList();
}

@Override
public void save(Category category) {
categoryRepository.save(categoryPersistenceMapper.toEntity(category));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface CategoryRepository extends JpaRepository<CategoryEntity, Long> {

List<CategoryEntity> findByIsDeletedFalse();
List<CategoryEntity> findByIsDeletedFalseAndMainCategoryIsNull();
List<CategoryEntity> findByIsDeletedFalseAndMainCategoryIsNotNull();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package clap.server.application.mapper.response;

import clap.server.adapter.inbound.web.dto.admin.FindAllCategoryResponse;
import clap.server.adapter.inbound.web.dto.admin.FindMainCategoryResponse;
import clap.server.adapter.inbound.web.dto.admin.FindSubCategoryResponse;
import clap.server.domain.model.task.Category;

import java.util.List;

public class CategoryResponseMapper {

public static FindAllCategoryResponse toFindAllCategoryResponse(
List<FindMainCategoryResponse> mainCategoryResponses,
List<FindSubCategoryResponse> subCategoryResponses) {
return new FindAllCategoryResponse(mainCategoryResponses, subCategoryResponses);
}

public static FindMainCategoryResponse toFindMainCategoryResponse(Category category) {
return new FindMainCategoryResponse(category.getCategoryId(), category.getName(), category.getCode());
}

public static FindSubCategoryResponse toFindSubCategoryResponse(Category category) {
return new FindSubCategoryResponse(category.getCategoryId(), category.getMainCategory().getCategoryId(), category.getName(), category.getCode());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package clap.server.application.port.inbound.admin;

import clap.server.adapter.inbound.web.dto.admin.FindAllCategoryResponse;

public interface FindAllCategoryUsecase {
FindAllCategoryResponse findAllCategory();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package clap.server.application.port.inbound.admin;

import clap.server.adapter.inbound.web.dto.admin.FindMainCategoryResponse;

import java.util.List;

public interface FindMainCategoryUsecase {
List<FindMainCategoryResponse> findMainCategory();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package clap.server.application.port.inbound.admin;

import clap.server.adapter.inbound.web.dto.admin.FindSubCategoryResponse;

import java.util.List;

public interface FindSubCategoryUsecase {
List<FindSubCategoryResponse> findSubCategory();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package clap.server.application.port.inbound.admin;

public interface UpdateCategoryUsecase {
void updateCategory(Long adminId, Long categoryId, String name, String code);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@

import clap.server.domain.model.task.Category;

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

public interface LoadCategoryPort {
Optional<Category> findById(Long id);

List<Category> findAll();
List<Category> findMainCategory();
List<Category> findSubCategory();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package clap.server.application.service.admin;

import clap.server.adapter.inbound.web.dto.admin.FindAllCategoryResponse;
import clap.server.adapter.inbound.web.dto.admin.FindMainCategoryResponse;
import clap.server.adapter.inbound.web.dto.admin.FindSubCategoryResponse;
import clap.server.application.mapper.response.CategoryResponseMapper;
import clap.server.application.port.inbound.admin.FindAllCategoryUsecase;
import clap.server.application.port.outbound.task.LoadCategoryPort;
import clap.server.common.annotation.architecture.ApplicationService;
import lombok.RequiredArgsConstructor;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

@ApplicationService
@RequiredArgsConstructor
public class FindAllCategoryService implements FindAllCategoryUsecase {
private final LoadCategoryPort loadCategoryPort;

@Override
@Transactional(readOnly = true)
public FindAllCategoryResponse findAllCategory() {
List<FindMainCategoryResponse> mainCategoryResponses = new ArrayList<>();
List<FindSubCategoryResponse> subCategoryResponses = new ArrayList<>();
loadCategoryPort.findAll().forEach(category -> {
if (category.getMainCategory() == null) {
mainCategoryResponses.add(CategoryResponseMapper.toFindMainCategoryResponse(category));
} else {
subCategoryResponses.add(CategoryResponseMapper.toFindSubCategoryResponse(category));
}
});
return CategoryResponseMapper.toFindAllCategoryResponse(mainCategoryResponses, subCategoryResponses);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package clap.server.application.service.admin;

import clap.server.adapter.inbound.web.dto.admin.FindMainCategoryResponse;
import clap.server.application.mapper.response.CategoryResponseMapper;
import clap.server.application.port.inbound.admin.FindMainCategoryUsecase;
import clap.server.application.port.outbound.task.LoadCategoryPort;
import clap.server.common.annotation.architecture.ApplicationService;
import lombok.RequiredArgsConstructor;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@ApplicationService
@RequiredArgsConstructor
public class FindMainCategoryService implements FindMainCategoryUsecase {
private final LoadCategoryPort loadCategoryPort;

@Override
@Transactional
public List<FindMainCategoryResponse> findMainCategory() {
return loadCategoryPort.findMainCategory()
.stream()
.map(CategoryResponseMapper::toFindMainCategoryResponse)
.toList();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package clap.server.application.service.admin;

import clap.server.adapter.inbound.web.dto.admin.FindSubCategoryResponse;
import clap.server.application.mapper.response.CategoryResponseMapper;
import clap.server.application.port.inbound.admin.FindSubCategoryUsecase;
import clap.server.application.port.outbound.task.LoadCategoryPort;
import clap.server.common.annotation.architecture.ApplicationService;
import lombok.RequiredArgsConstructor;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@ApplicationService
@RequiredArgsConstructor
public class FindSubCategoryService implements FindSubCategoryUsecase {
private final LoadCategoryPort loadCategoryPort;

@Override
@Transactional
public List<FindSubCategoryResponse> findSubCategory() {
return loadCategoryPort.findSubCategory()
.stream()
.map(CategoryResponseMapper::toFindSubCategoryResponse)
.toList();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package clap.server.application.service.admin;

import clap.server.application.port.inbound.admin.UpdateCategoryUsecase;
import clap.server.application.port.outbound.member.LoadMemberPort;
import clap.server.application.port.outbound.task.LoadCategoryPort;
import clap.server.common.annotation.architecture.ApplicationService;
import clap.server.domain.model.member.Member;
import clap.server.exception.ApplicationException;
import lombok.RequiredArgsConstructor;
import org.springframework.transaction.annotation.Transactional;

import static clap.server.exception.code.MemberErrorCode.ACTIVE_MEMBER_NOT_FOUND;
import static clap.server.exception.code.TaskErrorCode.CATEGORY_NOT_FOUND;

@ApplicationService
@RequiredArgsConstructor
public class UpdateCategoryService implements UpdateCategoryUsecase {
private final LoadCategoryPort loadCategoryPort;
private final LoadMemberPort loadMemberPort;

@Override
@Transactional
public void updateCategory(Long adminId, Long categoryId, String name, String code) {
Member admin = loadMemberPort.findActiveMemberById(adminId).orElseThrow(() -> new ApplicationException(ACTIVE_MEMBER_NOT_FOUND));
loadCategoryPort.findById(categoryId)
.orElseThrow(() -> new ApplicationException(CATEGORY_NOT_FOUND))
.updateCategory(admin, name, code);
}
}
Loading
Loading