Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.nowait.applicationadmin.order.service;

import java.time.LocalDate;
import java.util.List;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -81,15 +82,15 @@ public OrderStatusUpdateResponseDto updateOrderStatus(Long orderId, OrderStatus
}

@Transactional(readOnly = true)
public OrderSalesSumDetail getSaleSumByStoreId(MemberDetails memberDetails) {
public OrderSalesSumDetail getSaleSumByStoreId(MemberDetails memberDetails, LocalDate date) {
User user = userRepository.findById(memberDetails.getId()).orElseThrow(UserNotFoundException::new);
Long storeId = user.getStoreId();

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

return statisticCustomRepository.findSalesSumByStoreId(storeId);
return statisticCustomRepository.findSalesSumByStoreId(storeId, date);
}

@Transactional(readOnly = true)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package com.nowait.applicationadmin.statistic.controller;

import java.time.LocalDate;
import java.util.List;

import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

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

@GetMapping("/sales")
@Operation(summary = "오늘의 매출 조회", description = "오늘의 매출을 조회합니다.")
@Operation(summary = "지정일 매출 조회", description = "날짜(date) 파라미터로 매출을 조회합니다. 포맷: yyyy-MM-dd")
@ApiResponse(responseCode = "200", description = "오늘의 매출 조회 성공")
public ResponseEntity<?> getTodaySales(@AuthenticationPrincipal MemberDetails memberDetails) {
OrderSalesSumDetail sales = orderService.getSaleSumByStoreId(memberDetails);
public ResponseEntity<?> getTodaySales(
@AuthenticationPrincipal MemberDetails memberDetails,
@RequestParam(value = "date", required = false)
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date) {
LocalDate targetDate = (date != null ? date : LocalDate.now());
OrderSalesSumDetail sales = orderService.getSaleSumByStoreId(memberDetails, targetDate);

if (sales.isAllZero()) {
return ResponseEntity.ok(ApiUtils.success("해당일 매출 데이터가 없습니다."));
}

return ResponseEntity
.status(HttpStatus.OK)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,19 @@ public class StoreRankingDto {
private final Long departmentId;
private final String departmentName;
private final Integer totalSales;
private final Integer orderCount;
private final Long currentRank;
private final Integer delta;
private final String profileUrl;

public StoreRankingDto(Long storeId, String storeName, Long departmentId, String departmentName, Integer totalSales,
Long currentRank, Integer delta, String profileUrl) {
Integer orderCount, Long currentRank, Integer delta, String profileUrl) {
this.storeId = storeId;
this.storeName = storeName;
this.departmentId = departmentId;
this.departmentName = departmentName;
this.totalSales = totalSales;
this.orderCount = orderCount;
this.currentRank = currentRank;
this.delta = delta;
this.profileUrl = profileUrl;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public void init() {
refresh();
}

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ public class RankingServiceImpl implements RankingService {
private final UserRepository userRepository;
private final RankingQueryService rankingQuery;


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

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

Map<Long, Integer> orderCountMap = statisticCustomRepository.findOrderCountByStoreIds(storeIds);

// 3) redis 에서 storeId 정보 가져오기
List<StoreInfo> infos = statisticCustomRepository.findStoreInfoByIds(storeIds);

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

// 3) 매핑 → 최종 DTO
// 4) 매핑 → 최종 DTO
return entries.stream()
.map(e -> {
StoreInfo info = infoMap.get(e.getStoreId());
Integer orderCount = orderCountMap.getOrDefault(e.getStoreId(), 0);
return new StoreRankingDto(
e.getStoreId(),
info.getStoreName(),
info.getDepartmentId(),
info.getDepartmentName(),
e.getTotalSales(),
orderCount,
e.getCurrentRank(),
e.getDelta(),
info.getProfileUrl()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.nowait.domainadminrdb.statistic.dto;

import java.time.LocalDate;

import lombok.Builder;
import lombok.Getter;

Expand All @@ -10,12 +12,18 @@ public class OrderSalesSumDetail {
private Integer todaySalesSum;
private Integer yesterdaySalesSum;
private Integer cumulativeSalesBeforeYesterday;
private LocalDate date;

public OrderSalesSumDetail(Long storeId, Integer todaySalesSum, Integer yesterdaySalesSum,
Integer cumulativeSalesBeforeYesterday) {
Integer cumulativeSalesBeforeYesterday, LocalDate date) {
this.storeId = storeId;
this.todaySalesSum = todaySalesSum;
this.yesterdaySalesSum = yesterdaySalesSum;
this.cumulativeSalesBeforeYesterday = cumulativeSalesBeforeYesterday;
this.date = date;
}

public boolean isAllZero() {
return todaySalesSum == 0 && yesterdaySalesSum == 0 && cumulativeSalesBeforeYesterday == 0;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.nowait.domainadminrdb.statistic.repository;

import java.time.LocalDate;
import java.util.List;
import java.util.Map;

import com.nowait.domainadminrdb.statistic.dto.OrderSalesSumDetail;
import com.nowait.domainadminrdb.statistic.dto.StoreInfo;
Expand All @@ -11,10 +13,12 @@

public interface StatisticCustomRepository {

OrderSalesSumDetail findSalesSumByStoreId(Long storeId);
OrderSalesSumDetail findSalesSumByStoreId(Long storeId, LocalDate date);

List<TopSalesStoresDetail> getTop4PlusMine(Long storeId);

Map<Long, Integer> findOrderCountByStoreIds(List<Long> storeIds);


// redis 사용하는 부분
List<StoreSales> findTotalSales();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,25 +45,19 @@ public StatisticCustomRepositoryImpl(JPAQueryFactory queryFactory) {
private static final QStoreImage si = QStoreImage.storeImage;

@Override
public OrderSalesSumDetail findSalesSumByStoreId(Long storeId) {
// 1. 날짜 기준 설정 (시작은 자정, 끝은 다음 날 자정)
LocalDate today = LocalDate.now();
LocalDate yesterday = today.minusDays(1);

LocalDateTime todayStart = today.atStartOfDay();
LocalDateTime todayEnd = today.plusDays(1).atStartOfDay(); // 내일 00:00:00

LocalDateTime yesterdayStart = yesterday.atStartOfDay();
LocalDateTime yesterdayEnd = today.atStartOfDay();
public OrderSalesSumDetail findSalesSumByStoreId(Long storeId, LocalDate date) {
// 1) 시작, 끝 날짜 설정
LocalDateTime start = date.atStartOfDay(); // 해당 날짜의 자정
LocalDateTime end = date.plusDays(1).atStartOfDay();

// 2. 오늘 매출 합산
Integer todaySum = queryFactory
// 2) target 날짜 해당하는 매출 합산
Integer targetSum = queryFactory
.select(u.totalPrice.sum())
.from(u)
.where(
u.store.storeId.eq(storeId),
u.createdAt.goe(todayStart),
u.createdAt.lt(todayEnd),
u.createdAt.goe(start),
u.createdAt.lt(end),
u.status.eq(COOKED)
)
.fetchOne();
Expand All @@ -74,8 +68,8 @@ public OrderSalesSumDetail findSalesSumByStoreId(Long storeId) {
.from(u)
.where(
u.store.storeId.eq(storeId),
u.createdAt.goe(yesterdayStart),
u.createdAt.lt(yesterdayEnd),
u.createdAt.goe(start),
u.createdAt.lt(start.minusDays(1)),
u.status.eq(COOKED)
)
.fetchOne();
Expand All @@ -85,21 +79,21 @@ public OrderSalesSumDetail findSalesSumByStoreId(Long storeId) {
.from(u)
.where(
u.store.storeId.eq(storeId),
u.createdAt.lt(yesterdayEnd),
u.createdAt.lt(start),
u.status.eq(COOKED)
)
.fetchOne();

// null 방어 처리
if (todaySum == null)
todaySum = 0;
if (targetSum == null)
targetSum = 0;
if (yesterdaySum == null)
yesterdaySum = 0;
if (cumulativeSalesBeforeYesterday == null)
cumulativeSalesBeforeYesterday = 0;

// 4. 응답 객체 생성
return new OrderSalesSumDetail(storeId, todaySum, yesterdaySum, cumulativeSalesBeforeYesterday);
return new OrderSalesSumDetail(storeId, targetSum, yesterdaySum, cumulativeSalesBeforeYesterday, date);
}

@Override
Expand Down Expand Up @@ -148,6 +142,32 @@ public List<TopSalesStoresDetail> getTop4PlusMine(Long userStoreId) {
return result;
}

@Override
public Map<Long, Integer> findOrderCountByStoreIds(List<Long> storeIds) {
LocalDate today = LocalDate.now();
LocalDateTime start = today.atStartOfDay();
LocalDateTime end = today.plusDays(1).atStartOfDay();

List<Tuple> rows = queryFactory
.select(u.store.storeId, u.count())
.from(u)
.where(
u.store.storeId.in(storeIds),
u.createdAt.goe(start),
u.createdAt.lt(end),
u.status.eq(COOKED)
)
.groupBy(u.store.storeId)
.fetch();

// Tuple → Map<Long,Integer>
return rows.stream()
.collect(Collectors.toMap(
t -> t.get(u.store.storeId),
t -> t.get(u.count()).intValue()
));
}

private List<Tuple> getAllStores(LocalDateTime todayStart, LocalDateTime todayEnd) {
return queryFactory
.select(u.store.storeId, u.store.name, u.store.departmentId, u.totalPrice.sum())
Expand Down