diff --git a/src/main/generated/com/moplus/moplus_server/domain/problem/service/mapper/ChildProblemMapperImpl.java b/src/main/generated/com/moplus/moplus_server/domain/problem/service/mapper/ChildProblemMapperImpl.java index d528b5c5..7b1bd0c8 100644 --- a/src/main/generated/com/moplus/moplus_server/domain/problem/service/mapper/ChildProblemMapperImpl.java +++ b/src/main/generated/com/moplus/moplus_server/domain/problem/service/mapper/ChildProblemMapperImpl.java @@ -11,7 +11,7 @@ @Generated( value = "org.mapstruct.ap.MappingProcessor", - date = "2025-03-14T20:25:51+0900", + date = "2025-03-24T01:02:22+0900", comments = "version: 1.6.3, compiler: javac, environment: Java 17.0.10 (JetBrains s.r.o.)" ) @Component diff --git a/src/main/generated/com/moplus/moplus_server/domain/problem/service/mapper/ProblemMapperImpl.java b/src/main/generated/com/moplus/moplus_server/domain/problem/service/mapper/ProblemMapperImpl.java index b3e294c2..6992d6a4 100644 --- a/src/main/generated/com/moplus/moplus_server/domain/problem/service/mapper/ProblemMapperImpl.java +++ b/src/main/generated/com/moplus/moplus_server/domain/problem/service/mapper/ProblemMapperImpl.java @@ -15,7 +15,7 @@ @Generated( value = "org.mapstruct.ap.MappingProcessor", - date = "2025-03-15T21:23:23+0900", + date = "2025-03-24T01:02:22+0900", comments = "version: 1.6.3, compiler: javac, environment: Java 17.0.10 (JetBrains s.r.o.)" ) @Component diff --git a/src/main/java/com/moplus/moplus_server/admin/publish/service/PublishGetService.java b/src/main/java/com/moplus/moplus_server/admin/publish/service/PublishGetService.java index d15f2c20..d440d293 100644 --- a/src/main/java/com/moplus/moplus_server/admin/publish/service/PublishGetService.java +++ b/src/main/java/com/moplus/moplus_server/admin/publish/service/PublishGetService.java @@ -1,10 +1,10 @@ package com.moplus.moplus_server.admin.publish.service; -import com.moplus.moplus_server.domain.problemset.domain.ProblemSet; -import com.moplus.moplus_server.domain.problemset.repository.ProblemSetRepository; import com.moplus.moplus_server.admin.publish.domain.Publish; import com.moplus.moplus_server.admin.publish.dto.response.PublishMonthGetResponse; import com.moplus.moplus_server.admin.publish.dto.response.PublishProblemSetResponse; +import com.moplus.moplus_server.domain.problemset.domain.ProblemSet; +import com.moplus.moplus_server.domain.problemset.repository.ProblemSetRepository; import com.moplus.moplus_server.domain.publish.repository.PublishRepository; import com.moplus.moplus_server.global.error.exception.ErrorCode; import com.moplus.moplus_server.global.error.exception.InvalidValueException; @@ -42,6 +42,7 @@ public List getPublishMonth(int year, int month) { .collect(Collectors.toList()); } + private Map getProblemSetMap(List publishes) { List problemSetIds = publishes.stream() .map(Publish::getProblemSetId) @@ -62,4 +63,9 @@ private PublishMonthGetResponse convertToResponse(Publish publish, Map getPublishesBetweenDates(LocalDate startDate, LocalDate endDate) { + return publishRepository.findByPublishedDateBetween(startDate, endDate); + } } diff --git a/src/main/java/com/moplus/moplus_server/client/homefeed/controller/HomeFeedController.java b/src/main/java/com/moplus/moplus_server/client/homefeed/controller/HomeFeedController.java new file mode 100644 index 00000000..2e1bc012 --- /dev/null +++ b/src/main/java/com/moplus/moplus_server/client/homefeed/controller/HomeFeedController.java @@ -0,0 +1,27 @@ +package com.moplus.moplus_server.client.homefeed.controller; + +import com.moplus.moplus_server.client.homefeed.dto.response.HomeFeedResponse; +import com.moplus.moplus_server.client.homefeed.service.HomeFeedFacadeService; +import com.moplus.moplus_server.global.annotation.AuthUser; +import com.moplus.moplus_server.member.domain.Member; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Tag(name = "홈 피드 조회", description = "홈 피드 관련 API") +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1/client/home-feed") +public class HomeFeedController { + + private final HomeFeedFacadeService homeFeedFacadeService; + + @Operation(summary = "홈 피드 조회", description = "회원의 홈 피드 정보를 조회합니다.") + @GetMapping("") + public HomeFeedResponse getHomeFeed(@AuthUser Member member) { + return homeFeedFacadeService.getHomeFeed(member); + } +} diff --git a/src/main/java/com/moplus/moplus_server/client/homefeed/dto/response/HomeFeedResponse.java b/src/main/java/com/moplus/moplus_server/client/homefeed/dto/response/HomeFeedResponse.java new file mode 100644 index 00000000..8ad4c077 --- /dev/null +++ b/src/main/java/com/moplus/moplus_server/client/homefeed/dto/response/HomeFeedResponse.java @@ -0,0 +1,68 @@ +package com.moplus.moplus_server.client.homefeed.dto.response; + +import com.moplus.moplus_server.admin.problemset.dto.response.ProblemSetGetResponse; +import com.moplus.moplus_server.admin.problemset.dto.response.ProblemSummaryResponse; +import java.time.LocalDate; +import java.util.List; + +public record HomeFeedResponse( + List dailyProgresses, + List problemSets +) { + public static HomeFeedResponse of( + List dailyProgresses, + List problemSets + ) { + return new HomeFeedResponse(dailyProgresses, problemSets); + } + + public record DailyProgressResponse( + LocalDate date, + double progressRate + ) { + public static DailyProgressResponse of(LocalDate date, double progressRate) { + return new DailyProgressResponse(date, progressRate); + } + } + + public record ProblemSetHomeFeedResponse( + LocalDate date, + Long problemSetId, + String title, + Long submitCount, + ProblemHomeFeedResponse problemHomeFeedResponse + ) { + public static ProblemSetHomeFeedResponse of(LocalDate date, ProblemSetGetResponse problemSetGetResponse, + Long submitCount) { + return new ProblemSetHomeFeedResponse( + date, + problemSetGetResponse.id(), + problemSetGetResponse.title(), + submitCount, + ProblemHomeFeedResponse.of(problemSetGetResponse.problemSummaries().get(0)) + ); + } + + public static ProblemSetHomeFeedResponse of(LocalDate date) { + return new ProblemSetHomeFeedResponse( + date, + null, + null, + null, + null + ); + } + } + + public record ProblemHomeFeedResponse( + Long problemId, + String mainProblemImageUrl + ) { + public static ProblemHomeFeedResponse of(ProblemSummaryResponse problemSummaryResponse) { + return new ProblemHomeFeedResponse( + problemSummaryResponse.problemId(), + problemSummaryResponse.mainProblemImageUrl() + ); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/moplus/moplus_server/client/homefeed/service/HomeFeedFacadeService.java b/src/main/java/com/moplus/moplus_server/client/homefeed/service/HomeFeedFacadeService.java new file mode 100644 index 00000000..86af53cb --- /dev/null +++ b/src/main/java/com/moplus/moplus_server/client/homefeed/service/HomeFeedFacadeService.java @@ -0,0 +1,75 @@ +package com.moplus.moplus_server.client.homefeed.service; + +import com.moplus.moplus_server.admin.problemset.dto.response.ProblemSetGetResponse; +import com.moplus.moplus_server.admin.publish.domain.Publish; +import com.moplus.moplus_server.admin.publish.service.PublishGetService; +import com.moplus.moplus_server.client.homefeed.dto.response.HomeFeedResponse; +import com.moplus.moplus_server.client.homefeed.dto.response.HomeFeedResponse.DailyProgressResponse; +import com.moplus.moplus_server.client.homefeed.dto.response.HomeFeedResponse.ProblemSetHomeFeedResponse; +import com.moplus.moplus_server.domain.problemset.service.ProblemSetGetService; +import com.moplus.moplus_server.member.domain.Member; +import com.moplus.moplus_server.statistic.Problem.domain.ProblemSetStatistic; +import com.moplus.moplus_server.statistic.Problem.repository.ProblemSetStatisticRepository; +import java.time.DayOfWeek; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +public class HomeFeedFacadeService { + + private final ProblemSetStatisticRepository problemSetStatisticRepository; + private final PublishGetService publishGetService; + private final ProblemSetGetService problemSetGetService; + + @Transactional(readOnly = true) + public HomeFeedResponse getHomeFeed(Member member) { + Long memberId = member.getId(); + + List dailyProgresses = new ArrayList<>(); // 다음 PR에서 구현 + List problemSets = getWeekdayProblemSets(); + + return HomeFeedResponse.of(dailyProgresses, problemSets); + } + + private List getWeekdayProblemSets() { + LocalDate today = LocalDate.now(); + LocalDate monday = today.with(DayOfWeek.MONDAY); + LocalDate friday = today.with(DayOfWeek.FRIDAY); + + // 월요일부터 금요일까지의 발행된 문제 세트 조회 + List publishes = publishGetService.getPublishesBetweenDates(monday, friday); + Map publishByDate = publishes.stream() + .collect(Collectors.toMap(Publish::getPublishedDate, publish -> publish)); + + // 문제 세트 정보 조회 + List problemSetIds = publishes.stream() + .map(Publish::getProblemSetId) + .toList(); + Map problemSetMap = problemSetGetService.getProblemSets(problemSetIds).stream() + .collect(Collectors.toMap(ProblemSetGetResponse::id, response -> response)); + + // 월요일부터 금요일까지의 모든 날짜에 대한 응답 생성 + List responses = new ArrayList<>(); + for (LocalDate date = monday; !date.isAfter(friday); date = date.plusDays(1)) { + Publish publish = publishByDate.get(date); + if (publish != null) { + ProblemSetGetResponse problemSet = problemSetMap.get(publish.getProblemSetId()); + Long submitCount = problemSetStatisticRepository.findById(problemSet.id()) + .map(ProblemSetStatistic::getSubmitCount) + .orElse(0L); + responses.add(ProblemSetHomeFeedResponse.of(date, problemSet, submitCount)); + } else { + responses.add(ProblemSetHomeFeedResponse.of(date)); + } + } + + return responses; + } +} \ No newline at end of file diff --git a/src/main/java/com/moplus/moplus_server/client/submit/repository/ProblemSubmitRepository.java b/src/main/java/com/moplus/moplus_server/client/submit/repository/ProblemSubmitRepository.java index d9ff2554..a78f2f6f 100644 --- a/src/main/java/com/moplus/moplus_server/client/submit/repository/ProblemSubmitRepository.java +++ b/src/main/java/com/moplus/moplus_server/client/submit/repository/ProblemSubmitRepository.java @@ -12,8 +12,9 @@ public interface ProblemSubmitRepository extends JpaRepository findByMemberIdAndPublishIdAndProblemId(Long memberId, Long publishId, Long problemId); - default ProblemSubmit findByMemberIdAndPublishIdAndProblemIdElseThrow(Long memberId, Long publishId, Long problemId) { + default ProblemSubmit findByMemberIdAndPublishIdAndProblemIdElseThrow(Long memberId, Long publishId, + Long problemId) { return findByMemberIdAndPublishIdAndProblemId(memberId, publishId, problemId).orElseThrow( () -> new NotFoundException(ErrorCode.PROBLEM_SUBMIT_NOT_CONFIRMED)); } -} +} \ No newline at end of file diff --git a/src/main/java/com/moplus/moplus_server/domain/problemset/service/ProblemSetGetService.java b/src/main/java/com/moplus/moplus_server/domain/problemset/service/ProblemSetGetService.java index ef66f469..8d7791b3 100644 --- a/src/main/java/com/moplus/moplus_server/domain/problemset/service/ProblemSetGetService.java +++ b/src/main/java/com/moplus/moplus_server/domain/problemset/service/ProblemSetGetService.java @@ -1,14 +1,14 @@ package com.moplus.moplus_server.domain.problemset.service; +import com.moplus.moplus_server.admin.problemset.dto.response.ProblemSetGetResponse; +import com.moplus.moplus_server.admin.problemset.dto.response.ProblemSummaryResponse; +import com.moplus.moplus_server.admin.publish.domain.Publish; import com.moplus.moplus_server.domain.concept.domain.ConceptTag; import com.moplus.moplus_server.domain.concept.repository.ConceptTagRepository; import com.moplus.moplus_server.domain.problem.domain.problem.Problem; import com.moplus.moplus_server.domain.problem.repository.ProblemRepository; import com.moplus.moplus_server.domain.problemset.domain.ProblemSet; -import com.moplus.moplus_server.admin.problemset.dto.response.ProblemSetGetResponse; -import com.moplus.moplus_server.admin.problemset.dto.response.ProblemSummaryResponse; import com.moplus.moplus_server.domain.problemset.repository.ProblemSetRepository; -import com.moplus.moplus_server.admin.publish.domain.Publish; import com.moplus.moplus_server.domain.publish.repository.PublishRepository; import com.moplus.moplus_server.global.error.exception.BusinessException; import com.moplus.moplus_server.global.error.exception.ErrorCode; @@ -55,4 +55,11 @@ public ProblemSetGetResponse getProblemSet(Long problemSetId) { } return ProblemSetGetResponse.of(problemSet, publishedDates, problemSummaries); } + + @Transactional(readOnly = true) + public List getProblemSets(List problemSetIds) { + return problemSetIds.stream() + .map(this::getProblemSet) + .toList(); + } } diff --git a/src/main/java/com/moplus/moplus_server/statistic/Problem/service/CountStatisticsGetService.java b/src/main/java/com/moplus/moplus_server/statistic/Problem/service/CountStatisticsGetService.java new file mode 100644 index 00000000..983a87d6 --- /dev/null +++ b/src/main/java/com/moplus/moplus_server/statistic/Problem/service/CountStatisticsGetService.java @@ -0,0 +1,18 @@ +package com.moplus.moplus_server.statistic.Problem.service; + +import com.moplus.moplus_server.statistic.Problem.repository.ProblemSetStatisticRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +public class CountStatisticsGetService { + + private final ProblemSetStatisticRepository problemSetStatisticRepository; + + @Transactional(readOnly = true) + public Long getProblemSetCount(Long id) { + return problemSetStatisticRepository.findByIdElseThrow(id).getSubmitCount(); + } +}