mirror of
https://github.com/won-ktds/smarketing-backend.git
synced 2025-12-06 07:06:24 +00:00
Merge branch 'main' of https://github.com/won-ktds/smarketing-backend
This commit is contained in:
commit
8679eba53e
@ -1,5 +1,9 @@
|
||||
package com.won.smarketing.store.config;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
|
||||
|
||||
@ -10,7 +14,6 @@ import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
|
||||
@Configuration
|
||||
@EnableJpaAuditing
|
||||
public class JpaConfig {
|
||||
}리는 50자 이하여야 합니다")
|
||||
private String category;
|
||||
|
||||
@Schema(description = "가격", example = "4500", required = true)
|
||||
|
||||
@ -12,7 +12,7 @@ import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import jakarta.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
||||
@ -12,7 +12,7 @@ import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
/**
|
||||
* 매장 관리를 위한 REST API 컨트롤러
|
||||
|
||||
@ -6,8 +6,8 @@ import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.Size;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
/**
|
||||
* 메뉴 수정 요청 DTO
|
||||
|
||||
@ -7,6 +7,8 @@ import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 매출 정보 데이터 접근을 위한 Repository
|
||||
@ -16,29 +18,50 @@ import java.math.BigDecimal;
|
||||
public interface SalesRepository extends JpaRepository<Sales, Long> {
|
||||
|
||||
/**
|
||||
* 매장의 오늘 매출 조회
|
||||
* 매장의 특정 날짜 매출 조회
|
||||
*
|
||||
* @param storeId 매장 ID
|
||||
* @param salesDate 매출 날짜
|
||||
* @return 해당 날짜 매출 목록
|
||||
*/
|
||||
List<Sales> findByStoreIdAndSalesDate(Long storeId, LocalDate salesDate);
|
||||
|
||||
/**
|
||||
* 매장의 특정 기간 매출 조회
|
||||
*
|
||||
* @param storeId 매장 ID
|
||||
* @param startDate 시작 날짜
|
||||
* @param endDate 종료 날짜
|
||||
* @return 해당 기간 매출 목록
|
||||
*/
|
||||
List<Sales> findByStoreIdAndSalesDateBetween(Long storeId, LocalDate startDate, LocalDate endDate);
|
||||
|
||||
/**
|
||||
* 매장의 오늘 매출 조회 (네이티브 쿼리)
|
||||
*
|
||||
* @param storeId 매장 ID
|
||||
* @return 오늘 매출
|
||||
*/
|
||||
@Query("SELECT COALESCE(SUM(s.salesAmount), 0) FROM Sales s WHERE s.storeId = :storeId AND s.salesDate = CURRENT_DATE")
|
||||
BigDecimal findTodaySalesByStoreId(@Param("storeId") Long storeId);
|
||||
@Query(value = "SELECT COALESCE(SUM(sales_amount), 0) FROM sales WHERE store_id = :storeId AND sales_date = CURRENT_DATE", nativeQuery = true)
|
||||
BigDecimal findTodaySalesByStoreIdNative(@Param("storeId") Long storeId);
|
||||
|
||||
/**
|
||||
* 매장의 이번 달 매출 조회
|
||||
* 매장의 어제 매출 조회 (네이티브 쿼리)
|
||||
*
|
||||
* @param storeId 매장 ID
|
||||
* @return 어제 매출
|
||||
*/
|
||||
@Query(value = "SELECT COALESCE(SUM(sales_amount), 0) FROM sales WHERE store_id = :storeId AND sales_date = CURRENT_DATE - INTERVAL '1 day'", nativeQuery = true)
|
||||
BigDecimal findYesterdaySalesByStoreIdNative(@Param("storeId") Long storeId);
|
||||
|
||||
/**
|
||||
* 매장의 이번 달 매출 조회 (네이티브 쿼리)
|
||||
*
|
||||
* @param storeId 매장 ID
|
||||
* @return 이번 달 매출
|
||||
*/
|
||||
@Query("SELECT COALESCE(SUM(s.salesAmount), 0) FROM Sales s WHERE s.storeId = :storeId AND YEAR(s.salesDate) = YEAR(CURRENT_DATE) AND MONTH(s.salesDate) = MONTH(CURRENT_DATE)")
|
||||
BigDecimal findMonthSalesByStoreId(@Param("storeId") Long storeId);
|
||||
|
||||
/**
|
||||
* 매장의 전일 대비 매출 변화량 조회
|
||||
*
|
||||
* @param storeId 매장 ID
|
||||
* @return 전일 대비 매출 변화량
|
||||
*/
|
||||
@Query("SELECT COALESCE((SELECT SUM(s1.salesAmount) FROM Sales s1 WHERE s1.storeId = :storeId AND s1.salesDate = CURRENT_DATE) - (SELECT SUM(s2.salesAmount) FROM Sales s2 WHERE s2.storeId = :storeId AND s2.salesDate = CURRENT_DATE - 1), 0)")
|
||||
BigDecimal findPreviousDayComparisonByStoreId(@Param("storeId") Long storeId);
|
||||
@Query(value = "SELECT COALESCE(SUM(sales_amount), 0) FROM sales WHERE store_id = :storeId " +
|
||||
"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);
|
||||
}
|
||||
@ -83,7 +83,7 @@ public class MenuServiceImpl implements MenuService {
|
||||
.orElseThrow(() -> new BusinessException(ErrorCode.MENU_NOT_FOUND));
|
||||
|
||||
// 메뉴 정보 업데이트
|
||||
menu.updateMenuInfo(
|
||||
menu.updateMenu(
|
||||
request.getMenuName(),
|
||||
request.getCategory(),
|
||||
request.getPrice(),
|
||||
|
||||
@ -1,60 +1,84 @@
|
||||
package com.won.smarketing.store.service;
|
||||
|
||||
import com.won.smarketing.store.dto.SalesResponse;
|
||||
import com.won.smarketing.store.entity.Sales;
|
||||
import com.won.smarketing.store.repository.SalesRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 매출 서비스 구현체
|
||||
* 매출 조회 기능 구현 (현재는 Mock 데이터)
|
||||
* 매출 관리 서비스 구현체
|
||||
* 매출 조회 기능 구현
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional(readOnly = true)
|
||||
public class SalesServiceImpl implements SalesService {
|
||||
|
||||
private final SalesRepository salesRepository;
|
||||
|
||||
/**
|
||||
* 매출 정보 조회
|
||||
* 현재는 Mock 데이터를 반환 (실제로는 매출 데이터 조회 로직 필요)
|
||||
*
|
||||
* @return 매출 정보
|
||||
* @return 매출 정보 (오늘, 월간, 전일 대비)
|
||||
*/
|
||||
@Override
|
||||
public SalesResponse getSales() {
|
||||
log.info("매출 정보 조회");
|
||||
// TODO: 현재는 더미 데이터 반환, 실제로는 현재 로그인한 사용자의 매장 ID를 사용해야 함
|
||||
Long storeId = 1L; // 임시로 설정
|
||||
|
||||
// Mock 데이터 (실제로는 데이터베이스에서 조회)
|
||||
BigDecimal todaySales = new BigDecimal("150000");
|
||||
BigDecimal monthSales = new BigDecimal("4500000");
|
||||
BigDecimal yesterdaySales = new BigDecimal("125000");
|
||||
BigDecimal targetSales = new BigDecimal("176000");
|
||||
// 오늘 매출 계산
|
||||
BigDecimal todaySales = calculateSalesByDate(storeId, LocalDate.now());
|
||||
|
||||
// 전일 대비 변화 계산
|
||||
// 이번 달 매출 계산
|
||||
BigDecimal monthSales = calculateMonthSales(storeId);
|
||||
|
||||
// 어제 매출 계산
|
||||
BigDecimal yesterdaySales = calculateSalesByDate(storeId, LocalDate.now().minusDays(1));
|
||||
|
||||
// 전일 대비 매출 변화량 계산
|
||||
BigDecimal previousDayComparison = todaySales.subtract(yesterdaySales);
|
||||
BigDecimal previousDayChangeRate = yesterdaySales.compareTo(BigDecimal.ZERO) > 0
|
||||
? previousDayComparison.divide(yesterdaySales, 4, RoundingMode.HALF_UP)
|
||||
.multiply(new BigDecimal("100"))
|
||||
: BigDecimal.ZERO;
|
||||
|
||||
// 목표 대비 달성률 계산
|
||||
BigDecimal goalAchievementRate = targetSales.compareTo(BigDecimal.ZERO) > 0
|
||||
? todaySales.divide(targetSales, 4, RoundingMode.HALF_UP)
|
||||
.multiply(new BigDecimal("100"))
|
||||
: BigDecimal.ZERO;
|
||||
|
||||
return SalesResponse.builder()
|
||||
.todaySales(todaySales)
|
||||
.monthSales(monthSales)
|
||||
.previousDayComparison(previousDayComparison)
|
||||
.previousDayChangeRate(previousDayChangeRate)
|
||||
.goalAchievementRate(goalAchievementRate)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 특정 날짜의 매출 계산
|
||||
*
|
||||
* @param storeId 매장 ID
|
||||
* @param date 날짜
|
||||
* @return 해당 날짜 매출
|
||||
*/
|
||||
private BigDecimal calculateSalesByDate(Long storeId, LocalDate date) {
|
||||
List<Sales> salesList = salesRepository.findByStoreIdAndSalesDate(storeId, date);
|
||||
return salesList.stream()
|
||||
.map(Sales::getSalesAmount)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
}
|
||||
|
||||
/**
|
||||
* 이번 달 매출 계산
|
||||
*
|
||||
* @param storeId 매장 ID
|
||||
* @return 이번 달 매출
|
||||
*/
|
||||
private BigDecimal calculateMonthSales(Long storeId) {
|
||||
LocalDate now = LocalDate.now();
|
||||
LocalDate startOfMonth = now.withDayOfMonth(1);
|
||||
LocalDate endOfMonth = now.withDayOfMonth(now.lengthOfMonth());
|
||||
|
||||
List<Sales> salesList = salesRepository.findByStoreIdAndSalesDateBetween(storeId, startOfMonth, endOfMonth);
|
||||
return salesList.stream()
|
||||
.map(Sales::getSalesAmount)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
}
|
||||
}
|
||||
@ -1,31 +1,33 @@
|
||||
server:
|
||||
port: ${SERVER_PORT:8082}
|
||||
servlet:
|
||||
context-path: /
|
||||
|
||||
spring:
|
||||
application:
|
||||
name: store-service
|
||||
datasource:
|
||||
url: jdbc:postgresql://${POSTGRES_HOST:localhost}:${POSTGRES_PORT:5432}/${POSTGRES_DB:storedb}
|
||||
url: jdbc:postgresql://${POSTGRES_HOST:localhost}:${POSTGRES_PORT:5432}/${POSTGRES_DB:StoreDB}
|
||||
username: ${POSTGRES_USER:postgres}
|
||||
password: ${POSTGRES_PASSWORD:postgres}
|
||||
driver-class-name: org.postgresql.Driver
|
||||
jpa:
|
||||
hibernate:
|
||||
ddl-auto: ${JPA_DDL_AUTO:update}
|
||||
show-sql: ${JPA_SHOW_SQL:true}
|
||||
ddl-auto: ${DDL_AUTO:update}
|
||||
show-sql: ${SHOW_SQL:true}
|
||||
properties:
|
||||
hibernate:
|
||||
dialect: org.hibernate.dialect.PostgreSQLDialect
|
||||
format_sql: true
|
||||
|
||||
springdoc:
|
||||
swagger-ui:
|
||||
path: /swagger-ui.html
|
||||
operations-sorter: method
|
||||
api-docs:
|
||||
path: /api-docs
|
||||
data:
|
||||
redis:
|
||||
host: ${REDIS_HOST:localhost}
|
||||
port: ${REDIS_PORT:6379}
|
||||
password: ${REDIS_PASSWORD:}
|
||||
|
||||
logging:
|
||||
level:
|
||||
com.won.smarketing.store: ${LOG_LEVEL:DEBUG}
|
||||
|
||||
jwt:
|
||||
secret: ${JWT_SECRET:mySecretKeyForJWTTokenGenerationAndValidation123456789}
|
||||
access-token-validity: ${JWT_ACCESS_VALIDITY:3600000}
|
||||
refresh-token-validity: ${JWT_REFRESH_VALIDITY:604800000}
|
||||
Loading…
x
Reference in New Issue
Block a user