Skip to content

Commit a74eaff

Browse files
CLAP-125 1차 카테고리 추가 API 구현 (#94)
* CLAP-104 CI/CD : dev 환경 cd 스크립트 checkout 버전수정 <footer> - 관련: #55 * CLAP-110 Feature : 담당자별 작업 처리량 조회 API 구현 <footer> - 관련: #73 * CLAP-111 Refactor : 통계 조회 API 리팩토링 및 기능 수정 <footer> - 관련: #74 * 내 작업한 내용에 대한 설명 * 내 작업한 내용에 대한 설명 * 담당자 조회 API 구현 * CLAP-111 Refactor : 통계 조회 API 주소 통합, 리팩토링, 예외처리 <footer> - 관련: #74 * CLAP-111 Test : 테스트코드 및 설정 수정 <footer> - 관련: #74 * Bug : 프로퍼티파일 수정 * CLAP-111 refactor : 통계 컨트롤러 스웨거 수정 및 2차 카테고리별 통계 수정 <footer> - 관련: #74 * CLAP-125 Feature : 1차 카테고리 추가 API <footer> - 관련: #90
1 parent 6fb1dad commit a74eaff

File tree

8 files changed

+118
-4
lines changed

8 files changed

+118
-4
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package clap.server.adapter.inbound.web.admin;
2+
3+
import clap.server.adapter.inbound.security.SecurityUserDetails;
4+
import clap.server.adapter.inbound.web.dto.admin.AddMainCategoryRequest;
5+
import clap.server.application.port.inbound.management.AddMainCategoryUsecase;
6+
import clap.server.common.annotation.architecture.WebAdapter;
7+
import io.swagger.v3.oas.annotations.Operation;
8+
import io.swagger.v3.oas.annotations.tags.Tag;
9+
import lombok.RequiredArgsConstructor;
10+
import org.springframework.security.access.annotation.Secured;
11+
import org.springframework.security.core.annotation.AuthenticationPrincipal;
12+
import org.springframework.validation.annotation.Validated;
13+
import org.springframework.web.bind.annotation.PostMapping;
14+
import org.springframework.web.bind.annotation.RequestBody;
15+
16+
@Tag(name = "카테고리 추가")
17+
@WebAdapter
18+
@RequiredArgsConstructor
19+
public class addCategoryController {
20+
private final AddMainCategoryUsecase addMainCategoryUsecase;
21+
22+
@Operation(summary = "1차 카테고리 추가")
23+
@PostMapping("/api/maincategory")
24+
@Secured("ROLE_ADMIN")
25+
public void addMainCategory(@AuthenticationPrincipal SecurityUserDetails userInfo, @Validated @RequestBody AddMainCategoryRequest addMainCategoryRequest) {
26+
addMainCategoryUsecase.addMainCategory(userInfo.getUserId(), addMainCategoryRequest.code(), addMainCategoryRequest.name());
27+
}
28+
29+
// @Operation(summary = "2차 카테고리 추가")
30+
// @PostMapping("/api/subcategory")
31+
// @Secured("ROLE_ADMIN")
32+
// public void addSubCategory(@Validated @RequestBody AddCategoryRequest addCategoryRequest) {
33+
// addMainCategoryUsecase.addSubCategory(addCategoryRequest.code(), addCategoryRequest.name());
34+
// }
35+
36+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package clap.server.adapter.inbound.web.dto.admin;
2+
3+
import jakarta.validation.constraints.NotBlank;
4+
import jakarta.validation.constraints.Pattern;
5+
import org.hibernate.validator.constraints.Length;
6+
7+
public record AddMainCategoryRequest(
8+
@NotBlank @Length(max = 20)
9+
String name,
10+
@NotBlank @Pattern(regexp = "^[A-Z]{1,2}$", message = "올바른 카테고리 코드 형식이 아닙니다.")
11+
String code
12+
) {
13+
}

src/main/java/clap/server/adapter/inbound/web/statistics/FindStatisticsController.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import clap.server.application.port.inbound.statistics.*;
77
import clap.server.common.annotation.architecture.WebAdapter;
88
import clap.server.exception.StatisticsException;
9+
import io.swagger.v3.oas.annotations.Operation;
10+
import io.swagger.v3.oas.annotations.Parameter;
911
import io.swagger.v3.oas.annotations.tags.Tag;
1012
import lombok.RequiredArgsConstructor;
1113
import org.springframework.http.ResponseEntity;
@@ -16,6 +18,7 @@
1618
import java.util.List;
1719

1820
import static clap.server.exception.code.StatisticsErrorCode.STATISTICS_BAD_REQUEST;
21+
import static io.swagger.v3.oas.annotations.enums.ParameterIn.QUERY;
1922

2023
@Tag(name = "작업 관련 통계")
2124
@WebAdapter
@@ -28,6 +31,9 @@ public class FindStatisticsController {
2831
private final FindSubCategoryTaskRequestUsecase findSubCategoryTaskRequestUsecase;
2932
private final FindManagerTaskProcessUsecase findManagerTaskProcessUsecase;
3033

34+
@Operation(summary = "기본 통계 API")
35+
@Parameter(name = "periodType", description = "day, week, month", required = true, in = QUERY)
36+
@Parameter(name = "statisticsType", description = "request-by-period, process-by-period, request-by-category, process-by-manager", required = true, in = QUERY)
3137
@GetMapping
3238
public ResponseEntity<List<StatisticsResponse>> aggregateTaskStatistics(@RequestParam PeriodType periodType, @RequestParam StatisticsType statisticsType) {
3339
switch (statisticsType) {
@@ -62,10 +68,13 @@ public ResponseEntity<List<StatisticsResponse>> aggregateTaskStatistics(@Request
6268
throw new StatisticsException(STATISTICS_BAD_REQUEST);
6369
}
6470

71+
@Operation(summary = "1차 카테고리 하위 2차 카테고리별 통계 API")
72+
@Parameter(name = "periodType", description = "day, week, month", required = true, in = QUERY)
73+
@Parameter(name = "mainCategory", description = "1차 카테고리 이름", required = true, in = QUERY)
6574
@GetMapping("/subcategory")
66-
public ResponseEntity<List<StatisticsResponse>> aggregateSubCategoryTaskRequest(@RequestParam String period, @RequestParam String mainCategory) {
75+
public ResponseEntity<List<StatisticsResponse>> aggregateSubCategoryTaskRequest(@RequestParam PeriodType periodType, @RequestParam String mainCategory) {
6776
return ResponseEntity.ok(findSubCategoryTaskRequestUsecase
68-
.aggregateSubCategoryTaskRequest(period, mainCategory)
77+
.aggregateSubCategoryTaskRequest(periodType.getType(), mainCategory)
6978
.entrySet()
7079
.stream()
7180
.map(result -> new StatisticsResponse(result.getKey(), result.getValue()))

src/main/java/clap/server/adapter/outbound/persistense/CategoryPersistenceAdapter.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import clap.server.adapter.outbound.persistense.entity.task.CategoryEntity;
44
import clap.server.adapter.outbound.persistense.mapper.CategoryPersistenceMapper;
55
import clap.server.adapter.outbound.persistense.repository.task.CategoryRepository;
6+
import clap.server.application.port.outbound.task.CommandCategoryPort;
67
import clap.server.application.port.outbound.task.LoadCategoryPort;
78
import clap.server.common.annotation.architecture.PersistenceAdapter;
89
import clap.server.domain.model.task.Category;
@@ -12,7 +13,7 @@
1213

1314
@PersistenceAdapter
1415
@RequiredArgsConstructor
15-
public class CategoryPersistenceAdapter implements LoadCategoryPort {
16+
public class CategoryPersistenceAdapter implements LoadCategoryPort, CommandCategoryPort {
1617

1718
private final CategoryRepository categoryRepository;
1819
private final CategoryPersistenceMapper categoryPersistenceMapper;
@@ -22,4 +23,9 @@ public Optional<Category> findById(Long id) {
2223
Optional<CategoryEntity> categoryEntity = categoryRepository.findById(id);
2324
return categoryEntity.map(categoryPersistenceMapper::toDomain);
2425
}
25-
}
26+
27+
@Override
28+
public void save(Category category) {
29+
categoryRepository.save(categoryPersistenceMapper.toEntity(category));
30+
}
31+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package clap.server.application.port.inbound.management;
2+
3+
public interface AddMainCategoryUsecase {
4+
void addMainCategory(Long adminId, String code, String name);
5+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package clap.server.application.port.outbound.task;
2+
3+
import clap.server.domain.model.task.Category;
4+
5+
public interface CommandCategoryPort {
6+
void save(Category category);
7+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package clap.server.application.service.admin;
2+
3+
import clap.server.application.port.inbound.management.AddMainCategoryUsecase;
4+
import clap.server.application.port.outbound.member.LoadMemberPort;
5+
import clap.server.application.port.outbound.task.CommandCategoryPort;
6+
import clap.server.common.annotation.architecture.ApplicationService;
7+
import clap.server.domain.model.member.Member;
8+
import clap.server.domain.model.task.Category;
9+
import clap.server.exception.ApplicationException;
10+
import lombok.RequiredArgsConstructor;
11+
12+
import java.util.Optional;
13+
14+
import static clap.server.exception.code.MemberErrorCode.ACTIVE_MEMBER_NOT_FOUND;
15+
16+
@ApplicationService
17+
@RequiredArgsConstructor
18+
public class AddMainCategoryService implements AddMainCategoryUsecase {
19+
private final CommandCategoryPort commandCategoryPort;
20+
private final LoadMemberPort loadMemberPort;
21+
22+
@Override
23+
public void addMainCategory(Long adminId, String code, String name) {
24+
Optional<Member> activeMember = loadMemberPort.findActiveMemberById(adminId);
25+
Category mainCategory = Category.createMainCategory(
26+
activeMember.orElseThrow(() -> new ApplicationException(ACTIVE_MEMBER_NOT_FOUND)),
27+
code, name);
28+
commandCategoryPort.save(mainCategory);
29+
}
30+
}

src/main/java/clap/server/domain/model/task/Category.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,13 @@ public class Category extends BaseTime {
2222
private String descriptionExample;
2323
private LocalDateTime createdAt;
2424
private LocalDateTime updatedAt;
25+
26+
public static Category createMainCategory(Member admin, String code, String name) {
27+
Category category = new Category();
28+
category.admin = admin;
29+
category.code = code;
30+
category.name = name;
31+
return category;
32+
}
2533
}
2634

0 commit comments

Comments
 (0)