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
Expand Up @@ -3,5 +3,7 @@
/** SLS_13_01 (피크타임) */
public record PeakTimeAvgProjection(
Integer timeSlot2H, // 2시간 슬롯
Long orderCount // 주문 건수
Long netAmount, // 실매출 평균
Long orderCount, // 주문건수 평균
Long operatingWeeks // 운영주차
) {}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
import java.util.List;

/** MNU_04 (식자재 소진량) */
public record IngredientUsageResponse(List<IngredientUsageItem> items)
public record IngredientUsageResponse(
boolean hasIngredient, // 매장 식재료 등록 여부
List<IngredientUsageItem> items)
implements DashboardAnalysisResponse, DetailAnalysisResponse {

public record IngredientUsageItem(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
/** SLS_13_01 (피크타임) */
public record DashboardPeakTimeResponse(
int timeSlot2H, // 2시간 슬롯
long orderCount, // 주문 건수
long netAmount, // 실매출
Integer todayPeak,
Integer comparisonPeak,
Integer diff,
ShiftDirection shiftDirection,
boolean beforeComparisonPeak)
implements DashboardAnalysisResponse {}
double orderCount, // 주문 건수
double netAmount, // 실매출
Comment on lines +9 to +10
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P4: long에서 double로 변경한 이유가 있을까요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

평균을 보내줘야 해서 double로 수정했습니다!

Integer todayPeak, // 오늘 peak 시간
Integer comparisonPeak, // 비교 기간 peak 시간
Integer diff, // |todayPeak - comparisonPeak|
ShiftDirection shiftDirection, // 비교 기간 대비 peak 이동 방향
boolean beforeComparisonPeak // 현재 시간이 비교 기간 peak 이전인지
) implements DashboardAnalysisResponse {}
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
package com.checkmate.backend.domain.analysis.dto.response.sales;

import com.checkmate.backend.domain.analysis.dto.response.DetailAnalysisResponse;
import com.checkmate.backend.domain.analysis.enums.ShiftDirection;
import java.util.List;

/** SLS_13_01 (피크타임) */
public record DetailPeakTimeResponse(List<PeakTimeItem> items // 시간대별 주문건수 및 실매출
public record DetailPeakTimeResponse(
List<PeakTimeItem> todayItems,
List<PeakTimeItem> week4Items,
Integer todayPeak, // 오늘 peak 시간
Integer comparisonPeak, // 비교 기간 peak 시간
Integer diff, // |todayPeak - comparisonPeak|
ShiftDirection shiftDirection, // 비교 기간 대비 peak 이동 방향
boolean beforeComparisonPeak // 현재 시간이 비교 기간 peak 이전인지
) implements DetailAnalysisResponse {}
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
/** SLS_13_01 (피크타임) */
public record PeakTimeItem(
int timeSlot2H, // 2시간 슬롯
long orderCount, // 주문 건수
long netAmount // 실매출
Double orderCount, // 주문 건수
Double netAmount // 실매출
) {

public static PeakTimeItem of(TodayPeakTimeProjection projection) {
return new PeakTimeItem(
projection.timeSlot2H(), projection.orderCount(), projection.netAmount());
projection.timeSlot2H(),
(double) projection.orderCount(),
(double) projection.netAmount());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ public boolean supports(AnalysisCardCode analysisCardCode) {
@Override
public AnalysisResponse process(MenuAnalysisContext context) {

boolean hasIngredient =
ingredientRepository.existsIngredientsByStoreId(context.getStoreId());

// 식재료 사용량 갖고 온다.
List<IngredientUsageProjection> ingredientUsageProjections =
menuAnalysisRepository.findIngredientUsage(
Expand Down Expand Up @@ -63,7 +66,8 @@ public AnalysisResponse process(MenuAnalysisContext context) {
baseUnit));
}

IngredientUsageResponse response = new IngredientUsageResponse(ingredientUsageItems);
IngredientUsageResponse response =
new IngredientUsageResponse(hasIngredient, ingredientUsageItems);

return new AnalysisResponse(context.getAnalysisCardCode(), response, response);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,17 +144,23 @@ public AnalysisResponse process(MenuAnalysisContext context) {
pairedMenus));
}

DetailPopularMenuCombinationResponse.PopularMenuCombinationItem popularMenuCombinationItem =
items.get(0);

String firstMenuName = popularMenuCombinationItem.baseMenuName();
DetailPopularMenuCombinationResponse.PopularMenuCombinationItem.PairedMenuItem
pairedMenuItem = popularMenuCombinationItem.pairedMenus().get(0);
String secondMenuName = pairedMenuItem.menuName();

DetailPopularMenuCombinationResponse response =
new DetailPopularMenuCombinationResponse(items);

String firstMenuName = null;
String secondMenuName = null;

if (!items.isEmpty()) {

DetailPopularMenuCombinationResponse.PopularMenuCombinationItem firstItem =
items.get(0);

if (!firstItem.pairedMenus().isEmpty()) {
firstMenuName = firstItem.baseMenuName();
secondMenuName = firstItem.pairedMenus().get(0).menuName();
}
}

DashboardPopularMenuCombinationResponse dashboardResponse =
new DashboardPopularMenuCombinationResponse(firstMenuName, secondMenuName);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,12 @@ public AnalysisResponse process(SalesAnalysisContext context) {
List<PeakTimeAvgProjection> peakTimeAvgProjections =
salesAnalysisRepository.findPeakTimeAvg(
context.getStoreId(),
context.getStartDate(),
context.getEndDate(),
context.getComparisonStart(),
context.getComparisonEnd(),
dayOfWeekValue);

// 운영 주차를 갖고 와야 함

// 피크 계산
Integer todayPeak = findPeakHourToday(todayPeakTimeProjections);
Integer comparisonPeak = findPeakHourAvg(peakTimeAvgProjections);
Expand All @@ -62,24 +64,30 @@ public AnalysisResponse process(SalesAnalysisContext context) {
// 현재 시점이 비교 피크 이전인지
boolean beforeComparisonPeak = isBeforeBaselinePeak(anchor, comparisonPeak);

// 없는 슬롯은 0을 채운다
Map<Integer, PeakTimeItem> itemMap =
/*
* 현재 시점
* */

// 없는 슬롯은 null로 채운다
Map<Integer, PeakTimeItem> todayItemMap =
todayPeakTimeProjections.stream()
.map(PeakTimeItem::of)
.collect(Collectors.toMap(PeakTimeItem::timeSlot2H, Function.identity()));

List<PeakTimeItem> items = new ArrayList<>();
List<PeakTimeItem> todayItems = new ArrayList<>();

for (int slot = 0; slot <= 22; slot += 2) {
items.add(itemMap.getOrDefault(slot, new PeakTimeItem(slot, 0L, 0L)));
todayItems.add(todayItemMap.getOrDefault(slot, new PeakTimeItem(slot, null, null)));
}

int currentTimeSlot = TimeUtil.get2HourSlot(anchor);
PeakTimeItem currentItem = itemMap.get(currentTimeSlot);
PeakTimeItem currentItem = todayItemMap.get(currentTimeSlot);

long orderCount = Optional.ofNullable(currentItem).map(PeakTimeItem::orderCount).orElse(0L);
double orderCount =
Optional.ofNullable(currentItem).map(PeakTimeItem::orderCount).orElse(0.0);

long netAmount = Optional.ofNullable(currentItem).map(PeakTimeItem::netAmount).orElse(0L);
double netAmount =
Optional.ofNullable(currentItem).map(PeakTimeItem::netAmount).orElse(0.0);

DashboardPeakTimeResponse dashboard =
new DashboardPeakTimeResponse(
Expand All @@ -92,7 +100,36 @@ public AnalysisResponse process(SalesAnalysisContext context) {
direction,
beforeComparisonPeak);

DetailPeakTimeResponse detail = new DetailPeakTimeResponse(items);
/*
* 비교기간
* */

// 없는 슬롯은 null로 채운다
Map<Integer, PeakTimeItem> week4ItemMap =
peakTimeAvgProjections.stream()
.map(
p ->
new PeakTimeItem(
p.timeSlot2H(),
(double) p.orderCount() / p.operatingWeeks(),
(double) p.netAmount() / p.operatingWeeks()))
.collect(Collectors.toMap(PeakTimeItem::timeSlot2H, Function.identity()));

List<PeakTimeItem> week4Items = new ArrayList<>();

for (int slot = 0; slot <= 22; slot += 2) {
week4Items.add(week4ItemMap.getOrDefault(slot, new PeakTimeItem(slot, null, null)));
}

DetailPeakTimeResponse detail =
new DetailPeakTimeResponse(
todayItems,
week4Items,
todayPeak,
comparisonPeak,
diff,
direction,
beforeComparisonPeak);

return new AnalysisResponse(context.getAnalysisCardCode(), dashboard, detail);
}
Expand Down Expand Up @@ -120,21 +157,21 @@ private Integer calculateDiff(Integer todayPeak, Integer comparisonPeak) {
return Math.abs(todayPeak - comparisonPeak);
}

private ShiftDirection resolveDirection(Integer today, Integer baseline) {
private ShiftDirection resolveDirection(Integer today, Integer comparisonPeak) {

if (today == null || baseline == null) return ShiftDirection.UNKNOWN;
if (today == null || comparisonPeak == null) return ShiftDirection.UNKNOWN;

if (today.equals(baseline)) return ShiftDirection.SAME;
if (today.equals(comparisonPeak)) return ShiftDirection.SAME;

return today < baseline ? ShiftDirection.EARLY : ShiftDirection.LATE;
return today < comparisonPeak ? ShiftDirection.EARLY : ShiftDirection.LATE;
}

private boolean isBeforeBaselinePeak(LocalDateTime anchor, Integer baselinePeak) {
private boolean isBeforeBaselinePeak(LocalDateTime anchor, Integer comparisonPeak) {

if (baselinePeak == null) return false;
if (comparisonPeak == null) return false;

int currentHour = anchor.getHour();

return currentHour < baselinePeak;
return currentHour < comparisonPeak;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,7 @@ List<String> findNameByStoreIdAndKeyword(

@Query("select i from Ingredient i where i.id in :ingredientIds")
List<Ingredient> findAllByIds(@Param("ingredientIds") List<Long> ingredientIds);

@Query("select count(i)>0 from Ingredient i" + " where i.store.id=:storeId")
boolean existsIngredientsByStoreId(@Param("storeId") Long storeId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
public enum OrderChannel {
POS("POS", "POS"),
KIOSK("KIOSK", "키오스크"),
DELIVERY_APP("DELIVERY_APP", "배달앱");
DELIVERY_APP("DELIVERY_APP", "배달앱"),
ETC("ETC", "기타");

private final String value; // DB 저장 값
private final String description; // UI/표시용
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ List<TodayPeakTimeProjection> findTodayPeakTime(

// 비교기간 계산 쿼리
@Query(
"select new com.checkmate.backend.domain.analysis.dto.projection.sales.PeakTimeAvgProjection(o.timeSlot2H, count(*)) "
"select new com.checkmate.backend.domain.analysis.dto.projection.sales.PeakTimeAvgProjection(o.timeSlot2H, sum(o.netAmount), count(o), count(distinct (function('date_trunc','week',o.orderDate)))) "
+ " from Order o"
+ " where o.store.id=:storeId"
+ " and o.orderDate >= :startDate and o.orderDate < :endDate"
Expand Down