Skip to content

Commit fe5be26

Browse files
committed
feat: create weekly/monthly report api
1 parent 8233178 commit fe5be26

File tree

10 files changed

+279
-0
lines changed

10 files changed

+279
-0
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.project.analysis.domain.application.dto.request;
2+
3+
import com.project.analysis.domain.domain.entity.AnalyzedSleepLevel;
4+
import com.project.analysis.domain.domain.entity.AnalyzedSoundEvent;
5+
import com.project.analysis.domain.domain.entity.PeriodicReport;
6+
import lombok.Builder;
7+
8+
import java.util.List;
9+
10+
@Builder
11+
public record CreateWeeklyReportRequest (
12+
PeriodicReport periodicReport,
13+
List<AnalyzedSleepLevel> analyzedSleepLevels,
14+
List<AnalyzedSoundEvent> analyzedSoundEvents
15+
) {}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.project.analysis.domain.application.usecase;
2+
3+
import com.project.analysis.domain.domain.entity.*;
4+
import com.project.analysis.domain.domain.service.AnalyzedSleepLevelService;
5+
import com.project.analysis.domain.domain.service.AnalyzedSoundEventService;
6+
import com.project.analysis.domain.domain.service.PeriodicReportService;
7+
import com.project.analysis.domain.domain.service.SleepSessionService;
8+
import com.project.analysis.domain.infra.client.CreatePeriodicReportClient;
9+
import lombok.RequiredArgsConstructor;
10+
import org.springframework.stereotype.Service;
11+
12+
import java.time.DayOfWeek;
13+
import java.time.LocalDate;
14+
import java.time.temporal.TemporalAdjusters;
15+
import java.util.List;
16+
17+
@Service
18+
@RequiredArgsConstructor
19+
public class CreateMonthlyReportUseCase {
20+
21+
private final PeriodicReportService periodicReportService;
22+
private final SleepSessionService sleepSessionService;
23+
private final AnalyzedSoundEventService analyzedSoundEventService;
24+
private final AnalyzedSleepLevelService analyzedSleepLevelService;
25+
private final CreatePeriodicReportClient createPeriodicReportClient;
26+
27+
public void execute(Long userNo, LocalDate date) {
28+
PeriodicReport periodicReport = periodicReportService.findByUserNoAndStartedAt(userNo, date, DurationType.MONTHLY)
29+
.orElse(
30+
PeriodicReport.builder()
31+
.userNo(userNo)
32+
.periodStartedAt(date.with(TemporalAdjusters.firstDayOfMonth()))
33+
.durationType(DurationType.MONTHLY)
34+
.build()
35+
);
36+
37+
SleepSession sleepSession = sleepSessionService.findByUserNo(userNo, date);
38+
List<AnalyzedSleepLevel> analyzedSleepLevels = analyzedSleepLevelService.findAll(sleepSession);
39+
List<AnalyzedSoundEvent> analyzedSoundEvents = analyzedSoundEventService.findAll(sleepSession);
40+
41+
PeriodicReport request = createPeriodicReportClient.request(periodicReport, analyzedSleepLevels, analyzedSoundEvents);
42+
43+
periodicReportService.save(request);
44+
}
45+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package com.project.analysis.domain.application.usecase;
2+
3+
import com.project.analysis.domain.domain.entity.*;
4+
import com.project.analysis.domain.domain.service.AnalyzedSleepLevelService;
5+
import com.project.analysis.domain.domain.service.AnalyzedSoundEventService;
6+
import com.project.analysis.domain.domain.service.PeriodicReportService;
7+
import com.project.analysis.domain.domain.service.SleepSessionService;
8+
import com.project.analysis.domain.infra.client.CreatePeriodicReportClient;
9+
import lombok.RequiredArgsConstructor;
10+
import org.springframework.stereotype.Service;
11+
12+
import java.time.DayOfWeek;
13+
import java.time.LocalDate;
14+
import java.time.temporal.TemporalAdjusters;
15+
import java.util.List;
16+
17+
import static com.project.analysis.domain.domain.entity.DurationType.WEEKLY;
18+
19+
@Service
20+
@RequiredArgsConstructor
21+
public class CreateWeeklyReportUseCase {
22+
23+
private final PeriodicReportService periodicReportService;
24+
private final SleepSessionService sleepSessionService;
25+
private final AnalyzedSoundEventService analyzedSoundEventService;
26+
private final AnalyzedSleepLevelService analyzedSleepLevelService;
27+
private final CreatePeriodicReportClient createPeriodicReportClient;
28+
29+
public void execute(Long userNo, LocalDate date) {
30+
PeriodicReport periodicReport = periodicReportService.findByUserNoAndStartedAt(userNo, date, WEEKLY)
31+
.orElse(
32+
PeriodicReport.builder()
33+
.userNo(userNo)
34+
.periodStartedAt(date.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY)))
35+
.durationType(WEEKLY)
36+
.build()
37+
);
38+
39+
SleepSession sleepSession = sleepSessionService.findByUserNo(userNo, date);
40+
List<AnalyzedSleepLevel> analyzedSleepLevels = analyzedSleepLevelService.findAll(sleepSession);
41+
List<AnalyzedSoundEvent> analyzedSoundEvents = analyzedSoundEventService.findAll(sleepSession);
42+
43+
PeriodicReport request = createPeriodicReportClient.request(periodicReport, analyzedSleepLevels, analyzedSoundEvents);
44+
45+
periodicReportService.save(request);
46+
}
47+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.project.analysis.domain.domain.repository;
2+
3+
import com.project.analysis.domain.domain.entity.DurationType;
4+
import com.project.analysis.domain.domain.entity.PeriodicReport;
5+
import org.springframework.data.jpa.repository.JpaRepository;
6+
7+
import java.time.LocalDate;
8+
import java.util.Optional;
9+
10+
public interface PeriodicReportRepository extends JpaRepository<PeriodicReport, Long> {
11+
Optional<PeriodicReport> findByUserNoAndPeriodStartedAtAndDurationType(Long userNo, LocalDate periodStartedAt, DurationType durationType);
12+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.project.analysis.domain.domain.service;
2+
3+
import com.project.analysis.domain.domain.entity.DurationType;
4+
import com.project.analysis.domain.domain.entity.PeriodicReport;
5+
import com.project.analysis.domain.domain.repository.PeriodicReportRepository;
6+
import lombok.RequiredArgsConstructor;
7+
import org.springframework.stereotype.Service;
8+
9+
import java.time.LocalDate;
10+
import java.util.Optional;
11+
12+
@Service
13+
@RequiredArgsConstructor
14+
public class PeriodicReportService {
15+
16+
private final PeriodicReportRepository periodicReportRepository;
17+
18+
public Optional<PeriodicReport> findByUserNoAndStartedAt(Long userNo, LocalDate startedAt, DurationType type) {
19+
return periodicReportRepository.findByUserNoAndPeriodStartedAtAndDurationType((userNo, startedAt, type);
20+
}
21+
22+
public void save(PeriodicReport periodicReport) {
23+
periodicReportRepository.save(periodicReport);
24+
}
25+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.project.analysis.domain.infra.client;
2+
3+
import com.project.analysis.domain.application.dto.request.CreateWeeklyReportRequest;
4+
import com.project.analysis.domain.application.dto.request.SleepAnalysisRequest;
5+
import com.project.analysis.domain.application.dto.response.CreateDailyReportResponse;
6+
import com.project.analysis.domain.domain.entity.AnalyzedSleepLevel;
7+
import com.project.analysis.domain.domain.entity.AnalyzedSoundEvent;
8+
import com.project.analysis.domain.domain.entity.PeriodicReport;
9+
import lombok.RequiredArgsConstructor;
10+
import lombok.extern.slf4j.Slf4j;
11+
import org.springframework.http.HttpStatusCode;
12+
import org.springframework.http.MediaType;
13+
import org.springframework.stereotype.Component;
14+
import org.springframework.web.client.RestClient;
15+
import org.springframework.web.client.RestClientException;
16+
17+
import java.util.List;
18+
19+
@Slf4j
20+
@Component
21+
@RequiredArgsConstructor
22+
public class CreatePeriodicReportClient {
23+
24+
private final RestClient aiAnalysisModelRestClient;
25+
26+
public PeriodicReport request(PeriodicReport periodicReport, List<AnalyzedSleepLevel> analyzedSleepLevels, List<AnalyzedSoundEvent> analyzedSoundEvents) {
27+
return aiAnalysisModelRestClient
28+
.post()
29+
.uri("/analyze/periodic_report/json")
30+
.contentType(MediaType.APPLICATION_JSON)
31+
.body(
32+
CreateWeeklyReportRequest.builder()
33+
.periodicReport(periodicReport)
34+
.analyzedSleepLevels(analyzedSleepLevels)
35+
.analyzedSoundEvents(analyzedSoundEvents)
36+
.build()
37+
)
38+
.retrieve()
39+
.onStatus(HttpStatusCode::isError, (req, res) -> {
40+
log.error("AI analysis model returned error: {}", res.getStatusCode());
41+
throw new RestClientException("AI analysis model error: " + res.getStatusCode());
42+
})
43+
.body(PeriodicReport.class);
44+
}
45+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.project.analysis.domain.ui;
2+
3+
import com.project.analysis.domain.application.usecase.CreateMonthlyReportUseCase;
4+
import com.project.analysis.domain.ui.spec.CreateMonthlyReportApiSpec;
5+
import com.project.analysis.global.common.BaseResponse;
6+
import lombok.RequiredArgsConstructor;
7+
import org.springframework.web.bind.annotation.RestController;
8+
9+
import java.time.LocalDate;
10+
11+
@RestController
12+
@RequiredArgsConstructor
13+
public class CreateMonthlyReportController implements CreateMonthlyReportApiSpec {
14+
15+
private final CreateMonthlyReportUseCase createMonthlyReportUseCase;
16+
17+
@Override
18+
public BaseResponse<Void> analyze(Long userNo, LocalDate date) {
19+
createMonthlyReportUseCase.execute(userNo, date);
20+
return BaseResponse.onSuccess();
21+
}
22+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.project.analysis.domain.ui;
2+
3+
import com.project.analysis.domain.application.usecase.CreateWeeklyReportUseCase;
4+
import com.project.analysis.domain.ui.spec.CreateWeeklyReportApiSpec;
5+
import com.project.analysis.global.common.BaseResponse;
6+
import lombok.RequiredArgsConstructor;
7+
import org.springframework.web.bind.annotation.RestController;
8+
9+
import java.time.LocalDate;
10+
11+
@RestController
12+
@RequiredArgsConstructor
13+
public class CreateWeeklyReportController implements CreateWeeklyReportApiSpec {
14+
15+
private final CreateWeeklyReportUseCase createWeeklyReportUseCase;
16+
17+
@Override
18+
public BaseResponse<Void> analyze(Long userNo, LocalDate date) {
19+
createWeeklyReportUseCase.execute(userNo, date);
20+
return BaseResponse.onSuccess();
21+
}
22+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.project.analysis.domain.ui.spec;
2+
3+
import com.project.analysis.global.annotation.CurrentUser;
4+
import com.project.analysis.global.common.BaseResponse;
5+
import io.swagger.v3.oas.annotations.Operation;
6+
import io.swagger.v3.oas.annotations.tags.Tag;
7+
import org.springframework.web.bind.annotation.PostMapping;
8+
import org.springframework.web.bind.annotation.RequestParam;
9+
10+
import java.time.LocalDate;
11+
12+
@Tag(name = "Analysis")
13+
public interface CreateMonthlyReportApiSpec {
14+
15+
@Operation(
16+
summary = "월간 레포트 생성 API"
17+
)
18+
@PostMapping(value = "/api/analysis/reports/monthly")
19+
BaseResponse<Void> analyze(
20+
@CurrentUser Long userNo,
21+
@RequestParam LocalDate date
22+
);
23+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.project.analysis.domain.ui.spec;
2+
3+
import com.project.analysis.global.annotation.CurrentUser;
4+
import com.project.analysis.global.common.BaseResponse;
5+
import io.swagger.v3.oas.annotations.Operation;
6+
import io.swagger.v3.oas.annotations.tags.Tag;
7+
import org.springframework.web.bind.annotation.PostMapping;
8+
import org.springframework.web.bind.annotation.RequestParam;
9+
10+
import java.time.LocalDate;
11+
12+
@Tag(name = "Analysis")
13+
public interface CreateWeeklyReportApiSpec {
14+
15+
@Operation(
16+
summary = "주간 레포트 생성 API"
17+
)
18+
@PostMapping(value = "/api/analysis/reports/weekly")
19+
BaseResponse<Void> analyze(
20+
@CurrentUser Long userNo,
21+
@RequestParam LocalDate date
22+
);
23+
}

0 commit comments

Comments
 (0)