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

#332 [feat] 메트릭 API 기간 입력 요구사항 반영 #333

Merged
merged 8 commits into from
Sep 1, 2024
6 changes: 6 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ bootJar {
enabled = true;
}

tasks.test {
testLogging {
exceptionFormat = 'full'
}
}

configurations {
compileOnly {
extendsFrom annotationProcessor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import static com.asap.server.persistence.domain.QMeeting.meeting;
import static com.asap.server.persistence.domain.user.QUser.user;

import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.core.types.dsl.DateTimePath;
import com.querydsl.jpa.impl.JPAQueryFactory;
import java.time.LocalDateTime;
import lombok.RequiredArgsConstructor;
Expand All @@ -17,7 +19,7 @@ public Long countTotalMeetingCount(final LocalDateTime from, final LocalDateTime
return jpaQueryFactory
.select(meeting.count())
.from(meeting)
.where(meeting.createdAt.between(from, to))
.where(generateDateFilter(meeting.createdAt, from, to))
.fetchOne();
}

Expand All @@ -27,7 +29,7 @@ public Long countTotalConfirmedMeetingCount(final LocalDateTime from, final Loca
.from(meeting)
.where(
meeting.confirmedDateTime.confirmedStartTime.isNotNull()
.and(meeting.createdAt.between(from, to))
.and(generateDateFilter(meeting.createdAt, from, to))
)
.fetchOne();
}
Expand All @@ -36,7 +38,24 @@ public Long countTotalUserCount(final LocalDateTime from, final LocalDateTime to
return jpaQueryFactory
.select(user.count())
.from(user)
.where(user.createdAt.between(from, to))
.where(generateDateFilter(user.createdAt, from, to))
.fetchOne();
}

private BooleanExpression generateDateFilter(
final DateTimePath<LocalDateTime> createdAt,
final LocalDateTime from,
final LocalDateTime to
) {
if (from != null && to != null) {
return createdAt.between(from, to);
}
if (from != null) {
return createdAt.after(from);
}
if (to != null) {
return createdAt.before(to);
}
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ public class MetricsController implements MetricsControllerDocs {

@GetMapping("/metrics")
public SuccessResponse sendMetrics(
@RequestParam("from") final String from,
@RequestParam("to") final String to
@RequestParam(value = "from", required = false) final String from,
@RequestParam(value = "to", required = false) final String to
) {
metricsService.sendMetrics(from.trim(), to.trim());
metricsService.sendMetrics(from, to);
return SuccessResponse.success(Success.GET_METRICS_SUCCESS);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public interface MetricsControllerDocs {
@ApiResponse(responseCode = "500", description = "서버 내부 오류", content = @Content(schema = @Schema(implementation = ErrorResponse.class)))
})
SuccessResponse sendMetrics(
@Parameter(example = "2024-08-12", required = true) final String from,
@Parameter(example = "2024-08-15", required = true) final String to
@Parameter(example = "2024-08-12") final String from,
@Parameter(example = "2024-08-15") final String to
);
}
15 changes: 12 additions & 3 deletions src/main/java/com/asap/server/service/internal/MetricsService.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import com.asap.server.common.exception.model.BadRequestException;
import com.asap.server.infra.slack.MetricsEvent;
import com.asap.server.persistence.repository.internal.MetricsRepository;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
Expand All @@ -27,8 +26,14 @@ public void sendMetrics(final String fromStr, final String toStr) {
throw new BadRequestException(INVALID_DATE_FORMAT_EXCEPTION);
}

LocalDateTime from = LocalDate.parse(fromStr, DateTimeFormatter.ISO_LOCAL_DATE).atStartOfDay();
LocalDateTime to = LocalDate.parse(toStr, DateTimeFormatter.ISO_LOCAL_DATE).atStartOfDay();
LocalDateTime from = null;
LocalDateTime to = null;
if (fromStr != null) {
from = LocalDate.parse(fromStr, DateTimeFormatter.ISO_LOCAL_DATE).atStartOfDay();
}
if (toStr != null) {
to = LocalDate.parse(toStr, DateTimeFormatter.ISO_LOCAL_DATE).atStartOfDay();
}

Map<String, String> metrics = new HashMap<>();
metrics.put("개설된 총 회의 수", String.valueOf(metricsRepository.countTotalMeetingCount(from, to)));
Expand All @@ -39,6 +44,10 @@ public void sendMetrics(final String fromStr, final String toStr) {
}

private boolean isValidDate(final String dateStr) {
if (dateStr == null) {
return true;
}

try {
LocalDate.parse(dateStr, DateTimeFormatter.ISO_LOCAL_DATE);
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.springframework.transaction.annotation.Transactional;

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;


@SpringBootTest
@AutoConfigureMockMvc
@Transactional
public class DuplicatedInterceptorTest {
@Autowired
private MockMvc mockMvc;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package com.asap.server.persistence.repository.internal;

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

import jakarta.persistence.EntityManager;
import java.time.LocalDateTime;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Transactional;

@Transactional
@SpringBootTest
class MetricsRepositoryGenerateDateFilterTest {
private static final String INSERT_QUERY_TEMPLATE = "INSERT INTO meeting (title, password, duration, place_type, additional_info, created_at) VALUES ('title', '1234', 'HALF','ONLINE', '', ?)";

@Autowired
private MetricsRepository metricsRepository;

@Autowired
private EntityManager em;

@DisplayName(
"""
1. 2022년 5월 20일 데이터
2. 2023년 1월 1일 데이터
3. 2023년 6월 15일 데이터
4. 2023년 12월 31일 데이터
"""
)
@BeforeEach
public void setUp() {
em.createNativeQuery(INSERT_QUERY_TEMPLATE)
.setParameter(1, "2022-05-20T10:00:00")
.executeUpdate();

em.createNativeQuery(INSERT_QUERY_TEMPLATE)
.setParameter(1, "2023-01-01T12:00:00")
.executeUpdate();

em.createNativeQuery(INSERT_QUERY_TEMPLATE)
.setParameter(1, "2023-06-15T15:30:00")
.executeUpdate();

em.createNativeQuery(INSERT_QUERY_TEMPLATE)
.setParameter(1, "2023-12-31T23:59:59")
.executeUpdate();
}

@DisplayName("시작 날짜와 종료 날짜 모두가 주어졌을 때, 주어진 범위 내의 결과를 반환한다.")
@Test
public void test() {
// given
LocalDateTime from = LocalDateTime.of(2023, 1, 1, 0, 0);
LocalDateTime to = LocalDateTime.of(2023, 12, 31, 0, 0);

// when
Long count = metricsRepository.countTotalMeetingCount(from, to);

// then
assertThat(count).isEqualTo(2);
}

@DisplayName("시작 날짜가 주어지고 종료 날짜가 주어지지 않았을 때, 시작 날짜 이후의 결과를 반환한다.")
@Test
public void test2() {
// given
LocalDateTime from = LocalDateTime.of(2023, 6, 1, 0, 0);
LocalDateTime to = null;

// when
Long count = metricsRepository.countTotalMeetingCount(from, to);

// then
assertThat(count).isEqualTo(2);
}

@DisplayName("종료 날짜가 주어지고 시작 날짜가 주어지지 않았을 때, 종료 날짜 이전의 결과를 반환한다.")
@Test
public void test3() {
// given
LocalDateTime from = null;
LocalDateTime to = LocalDateTime.of(2023, 1, 1, 0, 0);

// when
Long count = metricsRepository.countTotalMeetingCount(from, to);

// then
assertThat(count).isEqualTo(1);
}

@DisplayName("날짜 범위가 주어지지 않았을 때, 전범위를 반환한다.")
@Test
public void test4() {
// given
LocalDateTime from = null;
LocalDateTime to = null;

// when
Long count = metricsRepository.countTotalMeetingCount(from, to);

// then
assertThat(count).isEqualTo(4);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
import org.springframework.test.web.servlet.setup.MockMvcBuilders;

import java.nio.charset.Charset;
import org.springframework.transaction.annotation.Transactional;

@Transactional
@ExtendWith(MockitoExtension.class)
public class MeetingRetrieveControllerTest {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import com.asap.server.common.exception.model.BadRequestException;
import com.asap.server.infra.slack.MetricsEvent;
import com.asap.server.persistence.repository.internal.MetricsRepository;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
Expand Down Expand Up @@ -71,4 +70,77 @@ void test2(String fromStr) {
.isInstanceOf(BadRequestException.class)
.hasMessage("유효하지 않은 날짜를 입력했습니다.");
}

@DisplayName("시작, 종료 날짜 모두 들어오지 않을 수 있다.")
@Test
void test3() {
// given
String fromStr = null;
String toStr = null;

when(metricsRepository.countTotalMeetingCount(null, null)).thenReturn(1L);
when(metricsRepository.countTotalUserCount(null, null)).thenReturn(1L);
when(metricsRepository.countTotalConfirmedMeetingCount(null, null)).thenReturn(1L);
Map<String, String> metrics = Map.of(
"개설된 총 회의 수", "1",
"사용한 총 사용자 수", "1",
"확정된 총 회의 수", "1"
);

// when
metricsService.sendMetrics(fromStr, toStr);

// then
verify(publisher, times(1)).publishEvent(new MetricsEvent(metrics));
}

@DisplayName("시작 날짜는 들어오지 않고, 종료 날짜만 들어올 수 있다.")
@Test
void test4() {
// given
String fromStr = null;
String toStr = "2024-08-26";

LocalDateTime to = LocalDate.parse(toStr, DateTimeFormatter.ISO_LOCAL_DATE).atStartOfDay();

when(metricsRepository.countTotalMeetingCount(null, to)).thenReturn(1L);
when(metricsRepository.countTotalUserCount(null, to)).thenReturn(1L);
when(metricsRepository.countTotalConfirmedMeetingCount(null, to)).thenReturn(1L);
Map<String, String> metrics = Map.of(
"개설된 총 회의 수", "1",
"사용한 총 사용자 수", "1",
"확정된 총 회의 수", "1"
);

// when
metricsService.sendMetrics(fromStr, toStr);

// then
verify(publisher, times(1)).publishEvent(new MetricsEvent(metrics));
}

@DisplayName("시작 날짜는 들어오고, 종료 날짜는 들어오지 않을 수 있다.")
@Test
void test5() {
// given
String fromStr = "2024-08-26";
String toStr = null;

LocalDateTime from = LocalDate.parse(fromStr, DateTimeFormatter.ISO_LOCAL_DATE).atStartOfDay();

when(metricsRepository.countTotalMeetingCount(from, null)).thenReturn(1L);
when(metricsRepository.countTotalUserCount(from, null)).thenReturn(1L);
when(metricsRepository.countTotalConfirmedMeetingCount(from, null)).thenReturn(1L);
Map<String, String> metrics = Map.of(
"개설된 총 회의 수", "1",
"사용한 총 사용자 수", "1",
"확정된 총 회의 수", "1"
);

// when
metricsService.sendMetrics(fromStr, toStr);

// then
verify(publisher, times(1)).publishEvent(new MetricsEvent(metrics));
}
}
Loading