add year sales

This commit is contained in:
박서은 2025-06-13 15:16:23 +09:00
parent cc871cddab
commit 69964d970c
9 changed files with 75 additions and 15 deletions

View File

@ -1,5 +1,6 @@
package com.won.smarketing.store.dto;
import com.won.smarketing.store.entity.Sales;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
@ -7,6 +8,7 @@ import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.util.List;
/**
* 매출 응답 DTO
@ -33,4 +35,7 @@ public class SalesResponse {
@Schema(description = "목표 매출 대비 달성율 (%)", example = "85.2")
private BigDecimal goalAchievementRate;
@Schema(description = "일년 동안의 매출액")
private List<Sales> yearSales;
}

View File

@ -48,7 +48,11 @@ public class StoreCreateRequest {
@Schema(description = "SNS 계정 정보", example = "인스타그램: @mystore")
@Size(max = 500, message = "SNS 계정 정보는 500자 이하여야 합니다")
private String snsAccounts;
private String instaAccounts;
@Size(max = 500, message = "SNS 계정 정보는 500자 이하여야 합니다")
@Schema(description = "블로그 계정 정보", example = "블로그: mystore")
private String blogAccounts;
@Schema(description = "매장 설명", example = "따뜻한 분위기의 동네 카페입니다.")
@Size(max = 1000, message = "매장 설명은 1000자 이하여야 합니다")

View File

@ -47,8 +47,11 @@ public class StoreResponse {
@Schema(description = "좌석 수", example = "20")
private Integer seatCount;
@Schema(description = "SNS 계정 정보", example = "인스타그램: @mystore")
private String snsAccounts;
@Schema(description = "블로그 계정 정보", example = "블로그: mystore")
private String blogAccounts;
@Schema(description = "인스타 계정 정보", example = "인스타그램: @mystore")
private String instaAccounts;
@Schema(description = "매장 설명", example = "따뜻한 분위기의 동네 카페입니다.")
private String description;

View File

@ -43,9 +43,13 @@ public class StoreUpdateRequest {
@Schema(description = "좌석 수", example = "20")
private Integer seatCount;
@Schema(description = "SNS 계정 정보", example = "인스타그램: @mystore")
@Schema(description = "인스타 계정 정보", example = "인스타그램: @mystore")
@Size(max = 500, message = "인스타 계정 정보는 500자 이하여야 합니다")
private String instaAccounts;
@Schema(description = "블로그 계정 정보", example = "블로그: mystore")
@Size(max = 500, message = "SNS 계정 정보는 500자 이하여야 합니다")
private String snsAccounts;
private String blogAccounts;
@Schema(description = "매장 설명", example = "따뜻한 분위기의 동네 카페입니다.")
@Size(max = 1000, message = "매장 설명은 1000자 이하여야 합니다")

View File

@ -54,8 +54,11 @@ public class Store {
@Column(name = "seat_count")
private Integer seatCount;
@Column(name = "sns_accounts", length = 500)
private String snsAccounts;
@Column(name = "insta_accounts", length = 500)
private String instaAccounts;
@Column(name = "blog_accounts", length = 500)
private String blogAccounts;
@Column(name = "description", length = 1000)
private String description;
@ -81,12 +84,13 @@ public class Store {
* @param businessHours 영업시간
* @param closedDays 휴무일
* @param seatCount 좌석
* @param snsAccounts SNS 계정 정보
* @param instaAccounts SNS 계정 정보
* @param blogAccounts SNS 계정 정보
* @param description 설명
*/
public void updateStore(String storeName, String businessType, String address,
String phoneNumber, String businessHours, String closedDays,
Integer seatCount, String snsAccounts, String description) {
Integer seatCount, String instaAccounts, String blogAccounts, String description) {
if (storeName != null && !storeName.trim().isEmpty()) {
this.storeName = storeName;
}
@ -100,7 +104,8 @@ public class Store {
this.businessHours = businessHours;
this.closedDays = closedDays;
this.seatCount = seatCount;
this.snsAccounts = snsAccounts;
this.instaAccounts = instaAccounts;
this.blogAccounts = blogAccounts;
this.description = description;
}

View File

@ -8,7 +8,9 @@ import org.springframework.stereotype.Repository;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* 매출 정보 데이터 접근을 위한 Repository
@ -64,4 +66,20 @@ public interface SalesRepository extends JpaRepository<Sales, Long> {
"AND EXTRACT(YEAR FROM sales_date) = EXTRACT(YEAR FROM CURRENT_DATE) " +
"AND EXTRACT(MONTH FROM sales_date) = EXTRACT(MONTH FROM CURRENT_DATE)", nativeQuery = true)
BigDecimal findMonthSalesByStoreIdNative(@Param("storeId") Long storeId);
/**
* 매장의 최근 365일 매출 데이터 조회 (날짜와 함께)
*
* @param storeId 매장 ID
* @return 최근 365일 매출 데이터 (날짜 오름차순)
*/
@Query("SELECT s FROM Sales s " +
"WHERE s.storeId = :storeId " +
"AND s.salesDate >= :startDate " +
"AND s.salesDate <= :endDate " +
"ORDER BY s.salesDate ASC")
List<Sales> findSalesDataLast365Days(
@Param("storeId") Long storeId,
@Param("startDate") LocalDate startDate,
@Param("endDate") LocalDate endDate);
}

View File

@ -176,7 +176,8 @@ public class BlobStorageServiceImpl implements BlobStorageService {
.businessHours(store.getBusinessHours())
.closedDays(store.getClosedDays())
.seatCount(store.getSeatCount())
.snsAccounts(store.getSnsAccounts())
.blogAccounts(store.getBlogAccounts())
.instaAccounts(store.getInstaAccounts())
.storeImage(fileUrl)
.description(store.getDescription())
.createdAt(store.getCreatedAt())

View File

@ -11,6 +11,7 @@ import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
import java.util.stream.Collectors;
/**
* 매출 관리 서비스 구현체
@ -22,7 +23,6 @@ import java.util.List;
public class SalesServiceImpl implements SalesService {
private final SalesRepository salesRepository;
private final StoreRepository storeRepository;
/**
* 매출 정보 조회
@ -43,9 +43,12 @@ public class SalesServiceImpl implements SalesService {
// 전일 대비 매출 변화량 계산
BigDecimal previousDayComparison = todaySales.subtract(yesterdaySales);
//오늘로부터 1년 전까지의 매출 리스트
return SalesResponse.builder()
.todaySales(todaySales)
.monthSales(monthSales)
.yearSales(getSalesAmountListLast365Days(storeId))
.previousDayComparison(previousDayComparison)
.build();
}
@ -80,4 +83,18 @@ public class SalesServiceImpl implements SalesService {
.map(Sales::getSalesAmount)
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
/**
* 최근 365일 매출 금액 리스트 조회
*
* @param storeId 매장 ID
* @return 최근 365일 매출 금액 리스트
*/
private List<Sales> getSalesAmountListLast365Days(Long storeId) {
LocalDate endDate = LocalDate.now();
LocalDate startDate = endDate.minusDays(365);
// Sales 엔티티 전체를 조회하는 메서드 사용
return salesRepository.findSalesDataLast365Days(storeId, startDate, endDate);
}
}

View File

@ -57,7 +57,8 @@ public class StoreServiceImpl implements StoreService {
.businessHours(request.getBusinessHours())
.closedDays(request.getClosedDays())
.seatCount(request.getSeatCount())
.snsAccounts(request.getSnsAccounts())
.blogAccounts(request.getBlogAccounts())
.instaAccounts(request.getInstaAccounts())
.description(request.getDescription())
.build();
@ -126,7 +127,8 @@ public class StoreServiceImpl implements StoreService {
request.getBusinessHours(),
request.getClosedDays(),
request.getSeatCount(),
request.getSnsAccounts(),
request.getInstaAccounts(),
request.getBlogAccounts(),
request.getDescription()
);
@ -152,7 +154,8 @@ public class StoreServiceImpl implements StoreService {
.businessHours(store.getBusinessHours())
.closedDays(store.getClosedDays())
.seatCount(store.getSeatCount())
.snsAccounts(store.getSnsAccounts())
.blogAccounts(store.getBlogAccounts())
.instaAccounts(store.getInstaAccounts())
.description(store.getDescription())
.createdAt(store.getCreatedAt())
.updatedAt(store.getUpdatedAt())