Skip to content

Commit b30159b

Browse files
CLAP-111 통계 조회 API 리팩토링 및 기능 수정 (#81)
CLAP-111 Refactor : 통계 조회 API 주소 통합, 리팩토링, 예외처리 <footer> - 관련: #74
1 parent 472ec03 commit b30159b

41 files changed

Lines changed: 861 additions & 121 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package clap.server.adapter.inbound.web.auth;
2+
3+
import clap.server.adapter.inbound.web.dto.auth.ReissueTokenResponse;
4+
import clap.server.application.port.inbound.auth.ReissueTokenUsecase;
5+
import clap.server.common.annotation.architecture.WebAdapter;
6+
import io.swagger.v3.oas.annotations.Operation;
7+
import io.swagger.v3.oas.annotations.tags.Tag;
8+
import lombok.RequiredArgsConstructor;
9+
import org.springframework.http.ResponseEntity;
10+
import org.springframework.web.bind.annotation.PostMapping;
11+
import org.springframework.web.bind.annotation.RequestHeader;
12+
import org.springframework.web.bind.annotation.RequestMapping;
13+
14+
@Tag(name = "토큰 재발급")
15+
@WebAdapter
16+
@RequiredArgsConstructor
17+
@RequestMapping("/api/auths")
18+
public class ReissueTokenController {
19+
private final ReissueTokenUsecase reissueTokenUsecase;
20+
21+
@Operation(summary = "토큰 재발급 API")
22+
@PostMapping("/reissuance")
23+
public ResponseEntity<ReissueTokenResponse> login(@RequestHeader String refreshToken) {
24+
return ResponseEntity.ok(reissueTokenUsecase.reissueToken(refreshToken));
25+
}
26+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package clap.server.adapter.inbound.web.dto.admin;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Getter;
5+
6+
import java.util.List;
7+
8+
@Getter
9+
@AllArgsConstructor
10+
public class FindManagersResponse {
11+
12+
private Long memberId;
13+
private String nickname;
14+
private String imageUrl;
15+
private int remainingTasks;
16+
17+
public static List<FindManagersResponse> emptyListResponse() {
18+
return List.of();
19+
}
20+
21+
}
22+
23+
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package clap.server.adapter.inbound.web.dto.auth;
2+
3+
public record ReissueTokenResponse(
4+
String accessToken,
5+
String refreshToken
6+
) {
7+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package clap.server.adapter.inbound.web.dto.statistics;
2+
3+
import clap.server.exception.StatisticsException;
4+
import com.fasterxml.jackson.annotation.JsonCreator;
5+
import lombok.Getter;
6+
import lombok.RequiredArgsConstructor;
7+
8+
import static clap.server.exception.code.StatisticsErrorCode.STATISTICS_BAD_REQUEST;
9+
10+
@Getter
11+
@RequiredArgsConstructor
12+
public enum PeriodType {
13+
DAY("day"),
14+
WEEK("week"),
15+
MONTH("month");
16+
17+
private final String type;
18+
19+
@JsonCreator
20+
public static PeriodType from(String input) {
21+
for (PeriodType periodType : PeriodType.values()) {
22+
if (periodType.getType().equals(input)) {
23+
return periodType;
24+
}
25+
}
26+
throw new StatisticsException(STATISTICS_BAD_REQUEST);
27+
}
28+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package clap.server.adapter.inbound.web.dto.statistics;
2+
3+
public record StatisticsResponse(String key, long count) {
4+
5+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package clap.server.adapter.inbound.web.dto.statistics;
2+
3+
import com.fasterxml.jackson.annotation.JsonCreator;
4+
import lombok.Getter;
5+
import lombok.RequiredArgsConstructor;
6+
7+
8+
@Getter
9+
@RequiredArgsConstructor
10+
public enum StatisticsType {
11+
REQUEST_BY_PERIOD("request-by-period"),
12+
PROCESS_BY_PERIOD("process-by-period"),
13+
REQUEST_BY_CATEGORY("request-by-category"),
14+
PROCESS_BY_MANAGER("process-by-manager");
15+
16+
private final String type;
17+
18+
@JsonCreator
19+
public static StatisticsType from(String input) {
20+
for (StatisticsType statisticsType : StatisticsType.values()) {
21+
if (statisticsType.getType().equals(input)) {
22+
return statisticsType;
23+
}
24+
}
25+
return null;
26+
}
27+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package clap.server.adapter.inbound.web.member;
2+
3+
import clap.server.application.port.inbound.domain.FindManagersUsecase;
4+
import clap.server.adapter.inbound.web.dto.admin.FindManagersResponse;
5+
import lombok.RequiredArgsConstructor;
6+
import org.springframework.web.bind.annotation.GetMapping;
7+
import org.springframework.web.bind.annotation.RequestMapping;
8+
import org.springframework.web.bind.annotation.RestController;
9+
10+
import java.util.List;
11+
12+
@RestController
13+
@RequestMapping("/manager")
14+
@RequiredArgsConstructor
15+
public class ManagerController {
16+
17+
private final FindManagersUsecase findManagersUsecase;
18+
19+
@GetMapping
20+
public List<FindManagersResponse> findManagers() {
21+
22+
List<FindManagersResponse> managers = findManagersUsecase.execute();
23+
24+
if (managers.isEmpty()) {
25+
return FindManagersResponse.emptyListResponse();
26+
}
27+
28+
return managers;
29+
}
30+
}
Lines changed: 48 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
package clap.server.adapter.inbound.web.statistics;
22

3+
import clap.server.adapter.inbound.web.dto.statistics.PeriodType;
4+
import clap.server.adapter.inbound.web.dto.statistics.StatisticsResponse;
5+
import clap.server.adapter.inbound.web.dto.statistics.StatisticsType;
36
import clap.server.application.port.inbound.statistics.*;
47
import clap.server.common.annotation.architecture.WebAdapter;
8+
import clap.server.exception.StatisticsException;
59
import io.swagger.v3.oas.annotations.tags.Tag;
610
import lombok.RequiredArgsConstructor;
711
import org.springframework.http.ResponseEntity;
812
import org.springframework.web.bind.annotation.GetMapping;
913
import org.springframework.web.bind.annotation.RequestMapping;
1014
import org.springframework.web.bind.annotation.RequestParam;
1115

12-
import java.util.Map;
16+
import java.util.List;
17+
18+
import static clap.server.exception.code.StatisticsErrorCode.STATISTICS_BAD_REQUEST;
1319

1420
@Tag(name = "작업 관련 통계")
1521
@WebAdapter
@@ -20,30 +26,49 @@ public class FindStatisticsController {
2026
private final FindPeriodTaskProcessUsecase findPeriodTaskProcessUsecase;
2127
private final FindCategoryTaskRequestUsecase findCategoryTaskRequestUsecase;
2228
private final FindSubCategoryTaskRequestUsecase findSubCategoryTaskRequestUsecase;
23-
private final ManagerTaskProcessUsecase managerTaskProcessUsecase;
24-
25-
@GetMapping(value = "/task-requests-by-period")
26-
public ResponseEntity<Map<String, Long>> aggregatePeriodTaskRequest(@RequestParam String period) {
27-
return ResponseEntity.ok(findPeriodTaskRequestUsecase.aggregatePeriodTaskRequest(period));
28-
}
29-
30-
@GetMapping("/task-processed-by-period")
31-
public ResponseEntity<Map<String, Long>> aggregatePeriodTaskProcess(@RequestParam String period) {
32-
return ResponseEntity.ok(findPeriodTaskProcessUsecase.aggregatePeriodTaskProcess(period));
33-
}
34-
35-
@GetMapping("/task-requests-by-category")
36-
public ResponseEntity<Map<String, Long>> aggregateCategoryTaskRequest(@RequestParam String period) {
37-
return ResponseEntity.ok(findCategoryTaskRequestUsecase.aggregateCategoryTaskRequest(period));
38-
}
29+
private final FindManagerTaskProcessUsecase findManagerTaskProcessUsecase;
3930

40-
@GetMapping("/task-requests-by-subcategory")
41-
public ResponseEntity<Map<String, Long>> aggregateSubCategoryTaskRequest(@RequestParam String period, @RequestParam String mainCategory) {
42-
return ResponseEntity.ok(findSubCategoryTaskRequestUsecase.aggregateSubCategoryTaskRequest(period, mainCategory));
31+
@GetMapping
32+
public ResponseEntity<List<StatisticsResponse>> aggregateTaskStatistics(@RequestParam PeriodType periodType, @RequestParam StatisticsType statisticsType) {
33+
switch (statisticsType) {
34+
case REQUEST_BY_PERIOD ->
35+
ResponseEntity.ok(findPeriodTaskRequestUsecase
36+
.aggregatePeriodTaskRequest(periodType.getType())
37+
.entrySet()
38+
.stream()
39+
.map(result -> new StatisticsResponse(result.getKey(), result.getValue()))
40+
.toList());
41+
case PROCESS_BY_PERIOD ->
42+
ResponseEntity.ok(findPeriodTaskProcessUsecase
43+
.aggregatePeriodTaskProcess(periodType.getType())
44+
.entrySet()
45+
.stream()
46+
.map(result -> new StatisticsResponse(result.getKey(), result.getValue()))
47+
.toList());
48+
case REQUEST_BY_CATEGORY ->
49+
ResponseEntity.ok(findCategoryTaskRequestUsecase.aggregateCategoryTaskRequest(periodType.getType())
50+
.entrySet()
51+
.stream()
52+
.map(result -> new StatisticsResponse(result.getKey(), result.getValue()))
53+
.toList());
54+
case PROCESS_BY_MANAGER ->
55+
ResponseEntity.ok(findManagerTaskProcessUsecase
56+
.aggregateManagerTaskProcess(periodType.getType())
57+
.entrySet()
58+
.stream()
59+
.map(result -> new StatisticsResponse(result.getKey(), result.getValue()))
60+
.toList());
61+
}
62+
throw new StatisticsException(STATISTICS_BAD_REQUEST);
4363
}
4464

45-
@GetMapping("/tasks-processed-by-manager")
46-
public ResponseEntity<Map<String, Long>> aggregateSubCategoryTaskRequest(@RequestParam String period) {
47-
return ResponseEntity.ok(managerTaskProcessUsecase.aggregateManagerTaskProcess(period));
65+
@GetMapping("/subcategory")
66+
public ResponseEntity<List<StatisticsResponse>> aggregateSubCategoryTaskRequest(@RequestParam String period, @RequestParam String mainCategory) {
67+
return ResponseEntity.ok(findSubCategoryTaskRequestUsecase
68+
.aggregateSubCategoryTaskRequest(period, mainCategory)
69+
.entrySet()
70+
.stream()
71+
.map(result -> new StatisticsResponse(result.getKey(), result.getValue()))
72+
.toList());
4873
}
4974
}

src/main/java/clap/server/adapter/outbound/infrastructure/elastic/PeriodConfig.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,27 @@
44
import lombok.Getter;
55
import lombok.RequiredArgsConstructor;
66

7+
import java.time.LocalDate;
8+
import java.time.temporal.ChronoUnit;
9+
710
@Getter
811
@RequiredArgsConstructor
912
public enum PeriodConfig {
10-
DAY(1, CalendarInterval.Hour, 11, 19),
11-
WEEK(14, CalendarInterval.Day, 0, 10);
13+
DAY(1, CalendarInterval.Hour, 11, 16),
14+
WEEK(7, CalendarInterval.Day, 0, 10),
15+
MONTH(-1, CalendarInterval.Day, 0, 10);
1216

1317
private final long daysToSubtract;
1418
private final CalendarInterval calendarInterval;
1519
private final int substringStart;
1620
private final int substringEnd;
1721

18-
}
22+
// MONTH에 대해 동적으로 daysToSubtract를 계산하는 메서드
23+
public long getDaysToSubtract() {
24+
if (this == MONTH) {
25+
return ChronoUnit.DAYS.between(LocalDate.now().minusMonths(1), LocalDate.now());
26+
}
27+
return daysToSubtract;
28+
}
29+
30+
}

src/main/java/clap/server/adapter/outbound/infrastructure/elastic/TaskDocumentAdapter.java

Lines changed: 5 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -50,23 +50,23 @@ public Map<String, Long> findCategoryTaskRequestByPeriod(String period) {
5050
PeriodConfig periodConfig = PeriodConfig.valueOf(period.toUpperCase());
5151

5252
NativeQuery query = buildCategoryTaskRequestQuery(periodConfig);
53-
return getCategoryTaskResults(executeQuery(query));
53+
return getNonPeriodTaskResults(executeQuery(query), "category_task");
5454
}
5555

5656
@Override
5757
public Map<String, Long> findSubCategoryTaskRequestByPeriod(String period, String mainCategory) {
5858
PeriodConfig periodConfig = PeriodConfig.valueOf(period.toUpperCase());
5959

6060
NativeQuery query = buildSubCategoryTaskRequestQuery(periodConfig, mainCategory);
61-
return getCategoryTaskResults(executeQuery(query));
61+
return getNonPeriodTaskResults(executeQuery(query), "category_task");
6262
}
6363

6464
@Override
6565
public Map<String, Long> findManagerTaskProcessByPeriod(String period) {
6666
PeriodConfig periodConfig = PeriodConfig.valueOf(period.toUpperCase());
6767

6868
NativeQuery query = buildManagerTaskProcessQuery(periodConfig);
69-
return getManagerTaskResults(executeQuery(query));
69+
return getNonPeriodTaskResults(executeQuery(query), "manager_task");
7070
}
7171

7272
private NativeQuery buildPeriodTaskRequestQuery(PeriodConfig config) {
@@ -188,25 +188,9 @@ private Map<String, Long> getPeriodTaskResults(ElasticsearchAggregations aggrega
188188
);
189189
}
190190

191-
private Map<String, Long> getCategoryTaskResults(ElasticsearchAggregations aggregations) {
191+
private Map<String, Long> getNonPeriodTaskResults(ElasticsearchAggregations aggregations, String name) {
192192
return new TreeMap<>(
193-
aggregations.get("category_task")
194-
.aggregation()
195-
.getAggregate()
196-
.sterms()
197-
.buckets()
198-
.array()
199-
.stream()
200-
.collect(Collectors.toMap(
201-
bucket -> bucket.key().stringValue(),
202-
MultiBucketBase::docCount
203-
))
204-
);
205-
}
206-
207-
private Map<String, Long> getManagerTaskResults(ElasticsearchAggregations aggregations) {
208-
return new TreeMap<>(
209-
aggregations.get("manager_task")
193+
aggregations.get(name)
210194
.aggregation()
211195
.getAggregate()
212196
.sterms()

0 commit comments

Comments
 (0)