Skip to content

Commit 98922e1

Browse files
committed
feat: 7일간 회원 평균 다운 횟수 통계 API 추가
1 parent d8c7ec1 commit 98922e1

File tree

6 files changed

+75
-0
lines changed

6 files changed

+75
-0
lines changed

src/main/java/com/appcenter/marketplace/domain/member_payback/controller/MemberPaybackAdminController.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.appcenter.marketplace.domain.member_coupon.dto.res.CouponHandleRes;
55
import com.appcenter.marketplace.domain.member_payback.dto.res.AdminReceiptRes;
66
import com.appcenter.marketplace.domain.member_payback.dto.res.CouponPaybackStatsRes;
7+
import com.appcenter.marketplace.domain.member_payback.dto.res.RecentMemberPaybackStatsRes;
78
import com.appcenter.marketplace.domain.member_payback.service.MemberPaybackAdminService;
89
import com.appcenter.marketplace.global.common.CommonResponse;
910
import io.swagger.v3.oas.annotations.Operation;
@@ -71,4 +72,14 @@ public ResponseEntity<CommonResponse<CouponPaybackStatsRes>> getCouponPaybackSta
7172
.ok(CommonResponse.from(STATS_FOUND.getMessage(),
7273
memberPaybackAdminService.getCouponPaybackStats()));
7374
}
75+
76+
@Operation(summary = "최근 7일 가입 회원 환급 쿠폰 통계 조회",
77+
description = "관리자가 최근 7일간 가입한 회원들의 환급 쿠폰 통계를 조회합니다. <br>" +
78+
"최근 7일 가입 회원 수와 회원당 평균 환급 쿠폰 다운로드 수를 제공합니다.")
79+
@GetMapping("/stats/recent")
80+
public ResponseEntity<CommonResponse<RecentMemberPaybackStatsRes>> getRecentMemberPaybackStats() {
81+
return ResponseEntity
82+
.ok(CommonResponse.from(STATS_FOUND.getMessage(),
83+
memberPaybackAdminService.getRecentMemberPaybackStats()));
84+
}
7485
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.appcenter.marketplace.domain.member_payback.dto.res;
2+
3+
import lombok.Builder;
4+
import lombok.Getter;
5+
6+
@Getter
7+
public class RecentMemberPaybackStatsRes {
8+
private final Long recentSevenDaysMemberCount;
9+
private final Double avgPaybackCouponDownloadPerMember;
10+
11+
@Builder
12+
public RecentMemberPaybackStatsRes(Long recentSevenDaysMemberCount, Double avgPaybackCouponDownloadPerMember) {
13+
this.recentSevenDaysMemberCount = recentSevenDaysMemberCount;
14+
this.avgPaybackCouponDownloadPerMember = avgPaybackCouponDownloadPerMember;
15+
}
16+
17+
public static RecentMemberPaybackStatsRes of(Long recentSevenDaysMemberCount, Double avgPaybackCouponDownloadPerMember) {
18+
return RecentMemberPaybackStatsRes.builder()
19+
.recentSevenDaysMemberCount(recentSevenDaysMemberCount)
20+
.avgPaybackCouponDownloadPerMember(avgPaybackCouponDownloadPerMember)
21+
.build();
22+
}
23+
}

src/main/java/com/appcenter/marketplace/domain/member_payback/repository/MemberPaybackRepositoryCustom.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.appcenter.marketplace.domain.member_payback.dto.res.AdminReceiptRes;
66
import com.appcenter.marketplace.domain.member_payback.dto.res.ReceiptRes;
77

8+
import java.time.LocalDateTime;
89
import java.util.List;
910
import java.util.Optional;
1011

@@ -18,4 +19,5 @@ public interface MemberPaybackRepositoryCustom {
1819
List<MemberPayback> findMemberPaybacksByMarketId(Long marketId);
1920
List<AdminReceiptRes> findReceiptsForAdmin(Long memberPaybackId, Long marketId, Integer size);
2021
AdminReceiptRes findReceiptDetailForAdmin(Long memberPaybackId);
22+
long countByMemberCreatedAtBetween(LocalDateTime startDateTime, LocalDateTime endDateTime);
2123
}

src/main/java/com/appcenter/marketplace/domain/member_payback/repository/MemberPaybackRepositoryCustomImpl.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,4 +199,16 @@ public AdminReceiptRes findReceiptDetailForAdmin(Long memberPaybackId) {
199199
.fetchOne();
200200
}
201201

202+
// 특정 기간에 가입한 회원들의 MemberPayback 개수 조회
203+
@Override
204+
public long countByMemberCreatedAtBetween(LocalDateTime startDateTime, LocalDateTime endDateTime) {
205+
Long count = jpaQueryFactory
206+
.select(memberPayback.count())
207+
.from(memberPayback)
208+
.innerJoin(memberPayback.member, member)
209+
.where(member.createdAt.between(startDateTime, endDateTime))
210+
.fetchOne();
211+
return count != null ? count : 0L;
212+
}
213+
202214
}

src/main/java/com/appcenter/marketplace/domain/member_payback/service/MemberPaybackAdminService.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.appcenter.marketplace.domain.member_coupon.dto.res.CouponHandleRes;
55
import com.appcenter.marketplace.domain.member_payback.dto.res.AdminReceiptRes;
66
import com.appcenter.marketplace.domain.member_payback.dto.res.CouponPaybackStatsRes;
7+
import com.appcenter.marketplace.domain.member_payback.dto.res.RecentMemberPaybackStatsRes;
78

89
public interface MemberPaybackAdminService {
910

@@ -15,4 +16,6 @@ public interface MemberPaybackAdminService {
1516

1617
CouponPaybackStatsRes getCouponPaybackStats();
1718

19+
RecentMemberPaybackStatsRes getRecentMemberPaybackStats();
20+
1821
}

src/main/java/com/appcenter/marketplace/domain/member_payback/service/impl/MemberPaybackAdminServiceImpl.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,17 @@
77
import com.appcenter.marketplace.domain.member_payback.MemberPayback;
88
import com.appcenter.marketplace.domain.member_payback.dto.res.AdminReceiptRes;
99
import com.appcenter.marketplace.domain.member_payback.dto.res.CouponPaybackStatsRes;
10+
import com.appcenter.marketplace.domain.member_payback.dto.res.RecentMemberPaybackStatsRes;
1011
import com.appcenter.marketplace.domain.member_payback.repository.MemberPaybackRepository;
1112
import com.appcenter.marketplace.domain.member_payback.service.MemberPaybackAdminService;
1213
import com.appcenter.marketplace.global.exception.CustomException;
1314
import lombok.RequiredArgsConstructor;
1415
import org.springframework.stereotype.Service;
1516
import org.springframework.transaction.annotation.Transactional;
1617

18+
import java.time.LocalDate;
19+
import java.time.LocalDateTime;
20+
import java.time.LocalTime;
1721
import java.util.List;
1822

1923
import static com.appcenter.marketplace.global.common.StatusCode.COUPON_NOT_EXIST;
@@ -81,6 +85,26 @@ public CouponPaybackStatsRes getCouponPaybackStats() {
8185
return CouponPaybackStatsRes.of(avgCouponDownloadPerMember, paybackRate);
8286
}
8387

88+
@Override
89+
public RecentMemberPaybackStatsRes getRecentMemberPaybackStats() {
90+
LocalDate today = LocalDate.now();
91+
LocalDateTime sevenDaysAgoStart = LocalDateTime.of(today.minusDays(7), LocalTime.MIN);
92+
LocalDateTime todayEnd = LocalDateTime.of(today, LocalTime.MAX);
93+
94+
// 최근 7일간 가입한 회원 수
95+
long recentMemberCount = memberRepository.countByCreatedAtBetween(sevenDaysAgoStart, todayEnd);
96+
97+
// 최근 7일간 가입한 회원들의 환급 쿠폰 다운로드 수
98+
long recentMemberPaybackCount = memberPaybackRepository.countByMemberCreatedAtBetween(sevenDaysAgoStart, todayEnd);
99+
100+
// 회원당 평균 환급 쿠폰 다운로드 수
101+
double avgPaybackCouponDownloadPerMember = recentMemberCount > 0
102+
? (double) recentMemberPaybackCount / recentMemberCount
103+
: 0.0;
104+
105+
return RecentMemberPaybackStatsRes.of(recentMemberCount, avgPaybackCouponDownloadPerMember);
106+
}
107+
84108
private MemberPayback findMemberPaybackById(Long couponId) {
85109
return memberPaybackRepository.findById(couponId)
86110
.orElseThrow(() -> new CustomException(COUPON_NOT_EXIST));

0 commit comments

Comments
 (0)