Skip to content

Commit e242532

Browse files
authored
Merge pull request #144 from GTable/refactor/#141-Store-sales
Refactor: 날짜별 매출 조회 기능 구현 및 주점 랭킹 내 주문 건수 필드 추가
2 parents eedc495 + 4b164a2 commit e242532

8 files changed

Lines changed: 82 additions & 32 deletions

File tree

nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/order/service/OrderService.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.nowait.applicationadmin.order.service;
22

3+
import java.time.LocalDate;
34
import java.util.List;
45
import java.util.stream.Collectors;
56

@@ -81,15 +82,15 @@ public OrderStatusUpdateResponseDto updateOrderStatus(Long orderId, OrderStatus
8182
}
8283

8384
@Transactional(readOnly = true)
84-
public OrderSalesSumDetail getSaleSumByStoreId(MemberDetails memberDetails) {
85+
public OrderSalesSumDetail getSaleSumByStoreId(MemberDetails memberDetails, LocalDate date) {
8586
User user = userRepository.findById(memberDetails.getId()).orElseThrow(UserNotFoundException::new);
8687
Long storeId = user.getStoreId();
8788

8889
if (!Role.SUPER_ADMIN.equals(user.getRole()) && !user.getStoreId().equals(storeId)) {
8990
throw new OrderViewUnauthorizedException();
9091
}
9192

92-
return statisticCustomRepository.findSalesSumByStoreId(storeId);
93+
return statisticCustomRepository.findSalesSumByStoreId(storeId, date);
9394
}
9495

9596
@Transactional(readOnly = true)

nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/statistic/controller/StatisticsController.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
package com.nowait.applicationadmin.statistic.controller;
22

3+
import java.time.LocalDate;
34
import java.util.List;
45

6+
import org.springframework.format.annotation.DateTimeFormat;
57
import org.springframework.http.HttpStatus;
68
import org.springframework.http.ResponseEntity;
79
import org.springframework.security.core.annotation.AuthenticationPrincipal;
810
import org.springframework.web.bind.annotation.GetMapping;
911
import org.springframework.web.bind.annotation.RequestMapping;
12+
import org.springframework.web.bind.annotation.RequestParam;
1013
import org.springframework.web.bind.annotation.RestController;
1114

1215
import com.nowait.applicationadmin.order.service.OrderService;
@@ -34,10 +37,18 @@ public class StatisticsController {
3437
private final PopularMenuRedisService popularMenuRedisService;
3538

3639
@GetMapping("/sales")
37-
@Operation(summary = "오늘의 매출 조회", description = "오늘의 매출을 조회합니다.")
40+
@Operation(summary = "지정일 매출 조회", description = "날짜(date) 파라미터로 매출을 조회합니다. 포맷: yyyy-MM-dd")
3841
@ApiResponse(responseCode = "200", description = "오늘의 매출 조회 성공")
39-
public ResponseEntity<?> getTodaySales(@AuthenticationPrincipal MemberDetails memberDetails) {
40-
OrderSalesSumDetail sales = orderService.getSaleSumByStoreId(memberDetails);
42+
public ResponseEntity<?> getTodaySales(
43+
@AuthenticationPrincipal MemberDetails memberDetails,
44+
@RequestParam(value = "date", required = false)
45+
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date) {
46+
LocalDate targetDate = (date != null ? date : LocalDate.now());
47+
OrderSalesSumDetail sales = orderService.getSaleSumByStoreId(memberDetails, targetDate);
48+
49+
if (sales.isAllZero()) {
50+
return ResponseEntity.ok(ApiUtils.success("해당일 매출 데이터가 없습니다."));
51+
}
4152

4253
return ResponseEntity
4354
.status(HttpStatus.OK)

nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/statistic/dto/StoreRankingDto.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,19 @@ public class StoreRankingDto {
99
private final Long departmentId;
1010
private final String departmentName;
1111
private final Integer totalSales;
12+
private final Integer orderCount;
1213
private final Long currentRank;
1314
private final Integer delta;
1415
private final String profileUrl;
1516

1617
public StoreRankingDto(Long storeId, String storeName, Long departmentId, String departmentName, Integer totalSales,
17-
Long currentRank, Integer delta, String profileUrl) {
18+
Integer orderCount, Long currentRank, Integer delta, String profileUrl) {
1819
this.storeId = storeId;
1920
this.storeName = storeName;
2021
this.departmentId = departmentId;
2122
this.departmentName = departmentName;
2223
this.totalSales = totalSales;
24+
this.orderCount = orderCount;
2325
this.currentRank = currentRank;
2426
this.delta = delta;
2527
this.profileUrl = profileUrl;

nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/statistic/scheduler/RankingRefreshScheduler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public void init() {
3535
refresh();
3636
}
3737

38-
@Scheduled(cron = "*/30 * * * * *") // 매 5분마다 실행
38+
@Scheduled(cron = "0 */5 * * * *") // 매 5분마다 실행
3939
public void refresh() {
4040
log.info("RankingRefreshScheduler.refresh() called at {}", LocalDateTime.now());
4141

nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/statistic/service/impl/RankingServiceImpl.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ public class RankingServiceImpl implements RankingService {
3131
private final UserRepository userRepository;
3232
private final RankingQueryService rankingQuery;
3333

34-
3534
@Override
3635
@Transactional(readOnly = true)
3736
public List<StoreRankingDto> getStatisticsRankings(MemberDetails memberDetails) {
@@ -45,27 +44,32 @@ public List<StoreRankingDto> getStatisticsRankings(MemberDetails memberDetails)
4544
// 1) Redis에서 Top4+내주점: storeId, totalSales, currentRank, delta
4645
List<RankingEntry> entries = rankingQuery.getRankings(userStoreId, 5);
4746

48-
// 2) redis 에서 storeId 정보 가져오기
47+
// 2) 주문 건수 조회
4948
List<Long> storeIds = entries.stream()
5049
.map(RankingEntry::getStoreId)
5150
.toList();
5251

52+
Map<Long, Integer> orderCountMap = statisticCustomRepository.findOrderCountByStoreIds(storeIds);
53+
54+
// 3) redis 에서 storeId 정보 가져오기
5355
List<StoreInfo> infos = statisticCustomRepository.findStoreInfoByIds(storeIds);
5456

5557
// StoreInfo를 storeId로 매핑
5658
Map<Long, StoreInfo> infoMap = infos.stream()
5759
.collect(Collectors.toMap(StoreInfo::getStoreId, Function.identity()));
5860

59-
// 3) 매핑 → 최종 DTO
61+
// 4) 매핑 → 최종 DTO
6062
return entries.stream()
6163
.map(e -> {
6264
StoreInfo info = infoMap.get(e.getStoreId());
65+
Integer orderCount = orderCountMap.getOrDefault(e.getStoreId(), 0);
6366
return new StoreRankingDto(
6467
e.getStoreId(),
6568
info.getStoreName(),
6669
info.getDepartmentId(),
6770
info.getDepartmentName(),
6871
e.getTotalSales(),
72+
orderCount,
6973
e.getCurrentRank(),
7074
e.getDelta(),
7175
info.getProfileUrl()

nowait-domain/domain-admin-rdb/src/main/java/com/nowait/domainadminrdb/statistic/dto/OrderSalesSumDetail.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.nowait.domainadminrdb.statistic.dto;
22

3+
import java.time.LocalDate;
4+
35
import lombok.Builder;
46
import lombok.Getter;
57

@@ -10,12 +12,18 @@ public class OrderSalesSumDetail {
1012
private Integer todaySalesSum;
1113
private Integer yesterdaySalesSum;
1214
private Integer cumulativeSalesBeforeYesterday;
15+
private LocalDate date;
1316

1417
public OrderSalesSumDetail(Long storeId, Integer todaySalesSum, Integer yesterdaySalesSum,
15-
Integer cumulativeSalesBeforeYesterday) {
18+
Integer cumulativeSalesBeforeYesterday, LocalDate date) {
1619
this.storeId = storeId;
1720
this.todaySalesSum = todaySalesSum;
1821
this.yesterdaySalesSum = yesterdaySalesSum;
1922
this.cumulativeSalesBeforeYesterday = cumulativeSalesBeforeYesterday;
23+
this.date = date;
24+
}
25+
26+
public boolean isAllZero() {
27+
return todaySalesSum == 0 && yesterdaySalesSum == 0 && cumulativeSalesBeforeYesterday == 0;
2028
}
2129
}

nowait-domain/domain-admin-rdb/src/main/java/com/nowait/domainadminrdb/statistic/repository/StatisticCustomRepository.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.nowait.domainadminrdb.statistic.repository;
22

3+
import java.time.LocalDate;
34
import java.util.List;
5+
import java.util.Map;
46

57
import com.nowait.domainadminrdb.statistic.dto.OrderSalesSumDetail;
68
import com.nowait.domainadminrdb.statistic.dto.StoreInfo;
@@ -11,10 +13,12 @@
1113

1214
public interface StatisticCustomRepository {
1315

14-
OrderSalesSumDetail findSalesSumByStoreId(Long storeId);
16+
OrderSalesSumDetail findSalesSumByStoreId(Long storeId, LocalDate date);
1517

1618
List<TopSalesStoresDetail> getTop4PlusMine(Long storeId);
1719

20+
Map<Long, Integer> findOrderCountByStoreIds(List<Long> storeIds);
21+
1822

1923
// redis 사용하는 부분
2024
List<StoreSales> findTotalSales();

nowait-domain/domain-admin-rdb/src/main/java/com/nowait/domainadminrdb/statistic/repository/StatisticCustomRepositoryImpl.java

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -45,25 +45,19 @@ public StatisticCustomRepositoryImpl(JPAQueryFactory queryFactory) {
4545
private static final QStoreImage si = QStoreImage.storeImage;
4646

4747
@Override
48-
public OrderSalesSumDetail findSalesSumByStoreId(Long storeId) {
49-
// 1. 날짜 기준 설정 (시작은 자정, 끝은 다음 날 자정)
50-
LocalDate today = LocalDate.now();
51-
LocalDate yesterday = today.minusDays(1);
52-
53-
LocalDateTime todayStart = today.atStartOfDay();
54-
LocalDateTime todayEnd = today.plusDays(1).atStartOfDay(); // 내일 00:00:00
55-
56-
LocalDateTime yesterdayStart = yesterday.atStartOfDay();
57-
LocalDateTime yesterdayEnd = today.atStartOfDay();
48+
public OrderSalesSumDetail findSalesSumByStoreId(Long storeId, LocalDate date) {
49+
// 1) 시작, 끝 날짜 설정
50+
LocalDateTime start = date.atStartOfDay(); // 해당 날짜의 자정
51+
LocalDateTime end = date.plusDays(1).atStartOfDay();
5852

59-
// 2. 오늘 매출 합산
60-
Integer todaySum = queryFactory
53+
// 2) target 날짜 해당하는 매출 합산
54+
Integer targetSum = queryFactory
6155
.select(u.totalPrice.sum())
6256
.from(u)
6357
.where(
6458
u.store.storeId.eq(storeId),
65-
u.createdAt.goe(todayStart),
66-
u.createdAt.lt(todayEnd),
59+
u.createdAt.goe(start),
60+
u.createdAt.lt(end),
6761
u.status.eq(COOKED)
6862
)
6963
.fetchOne();
@@ -74,8 +68,8 @@ public OrderSalesSumDetail findSalesSumByStoreId(Long storeId) {
7468
.from(u)
7569
.where(
7670
u.store.storeId.eq(storeId),
77-
u.createdAt.goe(yesterdayStart),
78-
u.createdAt.lt(yesterdayEnd),
71+
u.createdAt.goe(start),
72+
u.createdAt.lt(start.minusDays(1)),
7973
u.status.eq(COOKED)
8074
)
8175
.fetchOne();
@@ -85,21 +79,21 @@ public OrderSalesSumDetail findSalesSumByStoreId(Long storeId) {
8579
.from(u)
8680
.where(
8781
u.store.storeId.eq(storeId),
88-
u.createdAt.lt(yesterdayEnd),
82+
u.createdAt.lt(start),
8983
u.status.eq(COOKED)
9084
)
9185
.fetchOne();
9286

9387
// null 방어 처리
94-
if (todaySum == null)
95-
todaySum = 0;
88+
if (targetSum == null)
89+
targetSum = 0;
9690
if (yesterdaySum == null)
9791
yesterdaySum = 0;
9892
if (cumulativeSalesBeforeYesterday == null)
9993
cumulativeSalesBeforeYesterday = 0;
10094

10195
// 4. 응답 객체 생성
102-
return new OrderSalesSumDetail(storeId, todaySum, yesterdaySum, cumulativeSalesBeforeYesterday);
96+
return new OrderSalesSumDetail(storeId, targetSum, yesterdaySum, cumulativeSalesBeforeYesterday, date);
10397
}
10498

10599
@Override
@@ -148,6 +142,32 @@ public List<TopSalesStoresDetail> getTop4PlusMine(Long userStoreId) {
148142
return result;
149143
}
150144

145+
@Override
146+
public Map<Long, Integer> findOrderCountByStoreIds(List<Long> storeIds) {
147+
LocalDate today = LocalDate.now();
148+
LocalDateTime start = today.atStartOfDay();
149+
LocalDateTime end = today.plusDays(1).atStartOfDay();
150+
151+
List<Tuple> rows = queryFactory
152+
.select(u.store.storeId, u.count())
153+
.from(u)
154+
.where(
155+
u.store.storeId.in(storeIds),
156+
u.createdAt.goe(start),
157+
u.createdAt.lt(end),
158+
u.status.eq(COOKED)
159+
)
160+
.groupBy(u.store.storeId)
161+
.fetch();
162+
163+
// Tuple → Map<Long,Integer>
164+
return rows.stream()
165+
.collect(Collectors.toMap(
166+
t -> t.get(u.store.storeId),
167+
t -> t.get(u.count()).intValue()
168+
));
169+
}
170+
151171
private List<Tuple> getAllStores(LocalDateTime todayStart, LocalDateTime todayEnd) {
152172
return queryFactory
153173
.select(u.store.storeId, u.store.name, u.store.departmentId, u.totalPrice.sum())

0 commit comments

Comments
 (0)