Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
19bff02
CLAP-104 CI/CD : dev 환경 cd 스크립트 checkout 버전수정
hyoseong-Choi Jan 23, 2025
a3fe141
Merge branch 'develop' of https://github.com/TaskFlow-CLAP/TaskFlow-S…
hyoseong-Choi Jan 23, 2025
87ee143
Merge branch 'develop' of https://github.com/TaskFlow-CLAP/TaskFlow-S…
hyoseong-Choi Jan 23, 2025
0a5bdf1
Merge branch 'develop' of https://github.com/TaskFlow-CLAP/TaskFlow-S…
hyoseong-Choi Jan 23, 2025
c97d37c
CLAP-110 Feature : 담당자별 작업 처리량 조회 API 구현
hyoseong-Choi Jan 23, 2025
73bd762
CLAP-111 Refactor : 통계 조회 API 리팩토링 및 기능 수정
hyoseong-Choi Jan 23, 2025
60ebc4a
내 작업한 내용에 대한 설명
nano-mm Jan 23, 2025
a88a6bf
내 작업한 내용에 대한 설명
nano-mm Jan 23, 2025
1bf4ffb
Resolve merge conflict in application.yml
nano-mm Jan 23, 2025
283e5a5
담당자 조회 API 구현
nano-mm Jan 24, 2025
0ec9b91
Merge branch 'develop' of https://github.com/TaskFlow-CLAP/TaskFlow-S…
hyoseong-Choi Jan 24, 2025
2a9eed4
CLAP-111 Refactor : 통계 조회 API 주소 통합, 리팩토링, 예외처리
hyoseong-Choi Jan 24, 2025
ea99e9f
CLAP-111 Test : 테스트코드 및 설정 수정
hyoseong-Choi Jan 24, 2025
0bf52d6
Merge branch 'develop' of https://github.com/TaskFlow-CLAP/TaskFlow-S…
hyoseong-Choi Jan 24, 2025
0372f2c
Merge branch 'develop' of https://github.com/TaskFlow-CLAP/TaskFlow-S…
hyoseong-Choi Jan 24, 2025
24c582d
Bug : 프로퍼티파일 수정
hyoseong-Choi Jan 24, 2025
269fa7d
Merge branch 'develop' of https://github.com/TaskFlow-CLAP/TaskFlow-S…
hyoseong-Choi Jan 24, 2025
56c005c
CLAP-128 Feature : 2차 카테고리 추가 API
hyoseong-Choi Jan 25, 2025
67d0486
CLAP-128 Feature : 2차 카테고리 추가 API 리뷰 반영
hyoseong-Choi Jan 25, 2025
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
@@ -1,36 +1,39 @@
package clap.server.adapter.inbound.web.admin;

import clap.server.adapter.inbound.security.SecurityUserDetails;
import clap.server.adapter.inbound.web.dto.AddSubCategoryRequest;
import clap.server.adapter.inbound.web.dto.admin.AddMainCategoryRequest;
import clap.server.application.port.inbound.management.AddMainCategoryUsecase;
import clap.server.application.port.inbound.management.AddSubCategoryUsecase;
import clap.server.common.annotation.architecture.WebAdapter;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

@Tag(name = "카테고리 추가")
@WebAdapter
@RequiredArgsConstructor
public class addCategoryController {
public class AddCategoryController {
private final AddMainCategoryUsecase addMainCategoryUsecase;
private final AddSubCategoryUsecase addSubCategoryUsecase;

@Operation(summary = "1차 카테고리 추가")
@PostMapping("/api/maincategory")
@Secured("ROLE_ADMIN")
public void addMainCategory(@AuthenticationPrincipal SecurityUserDetails userInfo, @Validated @RequestBody AddMainCategoryRequest addMainCategoryRequest) {
public void addMainCategory(@AuthenticationPrincipal SecurityUserDetails userInfo, @Valid @RequestBody AddMainCategoryRequest addMainCategoryRequest) {
addMainCategoryUsecase.addMainCategory(userInfo.getUserId(), addMainCategoryRequest.code(), addMainCategoryRequest.name());
}

// @Operation(summary = "2차 카테고리 추가")
// @PostMapping("/api/subcategory")
// @Secured("ROLE_ADMIN")
// public void addSubCategory(@Validated @RequestBody AddCategoryRequest addCategoryRequest) {
// addMainCategoryUsecase.addSubCategory(addCategoryRequest.code(), addCategoryRequest.name());
// }
@Operation(summary = "2차 카테고리 추가")
@PostMapping("/api/subcategory")
@Secured("ROLE_ADMIN")
public void addSubCategory(@AuthenticationPrincipal SecurityUserDetails userInfo, @Valid @RequestBody AddSubCategoryRequest addCategoryRequest) {
addSubCategoryUsecase.addSubCategory(userInfo.getUserId(), addCategoryRequest.mainCategoryId(), addCategoryRequest.code(), addCategoryRequest.name());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package clap.server.adapter.inbound.web.dto;

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

public record AddSubCategoryRequest(
@Min(1)
Long mainCategoryId,
@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
@@ -0,0 +1,6 @@
package clap.server.application.port.inbound.management;


public interface AddSubCategoryUsecase {
void addSubCategory(Long adminId, Long mainCategoryId, String code, String name);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package clap.server.application.service.admin;

import clap.server.application.port.inbound.management.AddSubCategoryUsecase;
import clap.server.application.port.outbound.member.LoadMemberPort;
import clap.server.application.port.outbound.task.CommandCategoryPort;
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.domain.model.task.Category;
import clap.server.exception.ApplicationException;
import lombok.RequiredArgsConstructor;

import java.util.Optional;

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 AddSubCategoryService implements AddSubCategoryUsecase {
private final CommandCategoryPort commandCategoryPort;
private final LoadMemberPort loadMemberPort;
private final LoadCategoryPort loadCategoryPort;

@Override
public void addSubCategory(Long adminId, Long mainCategoryId, String code, String name) {
Optional<Member> activeMember = loadMemberPort.findActiveMemberById(adminId);
Optional<Category> mainCategory = loadCategoryPort.findById(mainCategoryId);

Category subCategory = Category.createSubCategory(
activeMember.orElseThrow(() -> new ApplicationException(ACTIVE_MEMBER_NOT_FOUND)),
mainCategory.orElseThrow(() -> new ApplicationException(CATEGORY_NOT_FOUND)),
code, name);
commandCategoryPort.save(subCategory);
}
}
19 changes: 14 additions & 5 deletions src/main/java/clap/server/domain/model/task/Category.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,20 @@ public class Category extends BaseTime {
private LocalDateTime updatedAt;

public static Category createMainCategory(Member admin, String code, String name) {
Category category = new Category();
category.admin = admin;
category.code = code;
category.name = name;
return category;
return Category.builder()
.admin(admin)
.code(code)
.name(name)
.build();
}

public static Category createSubCategory(Member admin, Category mainCategory, String code, String name) {
return Category.builder()
.mainCategory(mainCategory)
.admin(admin)
.code(code)
.name(name)
.build();
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package clap.server.application.service.admin;

import clap.server.adapter.outbound.persistense.entity.member.MemberEntity;
import clap.server.adapter.outbound.persistense.entity.member.constant.MemberRole;
import clap.server.adapter.outbound.persistense.entity.member.constant.MemberStatus;
import clap.server.adapter.outbound.persistense.entity.task.CategoryEntity;
import jakarta.persistence.EntityManager;
import jakarta.transaction.Transactional;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.elasticsearch.ElasticsearchContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;

import static org.assertj.core.api.Assertions.assertThat;

@SpringBootTest
@Testcontainers
@Transactional
class AddCategoryServiceTest {

@Container
public static ElasticsearchContainer ES_CONTAINER = new ElasticsearchContainer("docker.elastic.co/elasticsearch/elasticsearch:7.17.5")
.withReuse(true);

@DynamicPropertySource
static void elasticProperties(DynamicPropertyRegistry registry) {
// Elasticsearch 설정
registry.add("spring.elasticsearch.uris", ES_CONTAINER::getHttpHostAddress);
}

@Autowired
private AddMainCategoryService addMainCategoryService;
@Autowired
private AddSubCategoryService addsubCategoryService;
@Autowired
private EntityManager entityManager;

@Test
@Transactional
@Rollback(false)
void addMainCategory() {
// 관리자 추가
MemberEntity admin = MemberEntity.builder()
.name("Admin")
.email("admin@example.com")
.nickname("admin.ad")
.isReviewer(false)
.role(MemberRole.ROLE_ADMIN)
.departmentRole("Admin")
.status(MemberStatus.ACTIVE)
.password("admin123")
.build();
entityManager.persist(admin);

admin = entityManager.find(MemberEntity.class, 1);
addMainCategoryService.addMainCategory(admin.getMemberId(), "VM", "가상머신");

CategoryEntity category = entityManager.find(CategoryEntity.class, 1);
assertThat(category.getCategoryId()).isEqualTo(1);
assertThat(category.getName()).isEqualTo("가상머신");
assertThat(category.getCode()).isEqualTo("VM");
assertThat(category.getAdmin().getMemberId()).isEqualTo(1);
}

@Test
void addSubCategory() {
MemberEntity admin = entityManager.find(MemberEntity.class, 1);
addsubCategoryService.addSubCategory(admin.getMemberId(), 1L, "CR", "생성");

CategoryEntity category = entityManager.find(CategoryEntity.class, 2);
assertThat(category.getCategoryId()).isEqualTo(2);
assertThat(category.getMainCategory().getCategoryId()).isEqualTo(1);
assertThat(category.getName()).isEqualTo("생성");
assertThat(category.getCode()).isEqualTo("CR");
assertThat(category.getAdmin().getMemberId()).isEqualTo(1);
}
}
Loading