Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
1e6141a
refactor: ApiResult에 error 필드 null로 처리되는 문제 해결
Jjiggu Jul 14, 2025
de18a50
chore(build): QueryDsl을 사용하기 위한 의존성 추가
Jjiggu Jul 14, 2025
ed760cc
feat(Order): 매출 조회를 위한 sales 엔드포인트 추가
Jjiggu Jul 14, 2025
acda7bf
feat(Order): 매출 조회를 위한 getSaleSumByStoreId 추가
Jjiggu Jul 14, 2025
96b96bb
feat(Order): 매출 조회를 위한 OrderSalesSumResponse dto 추가
Jjiggu Jul 14, 2025
26d87dd
feat(Order): extends OrderCustomRepository
Jjiggu Jul 14, 2025
804d127
feat(Order): QueryDsl 사용을 위한 config 추가
Jjiggu Jul 14, 2025
33e68c1
feat(Order): 매출 조회하는 findSalesSumByStoreId 추가
Jjiggu Jul 14, 2025
f03d1ec
refactor(storepayment): 패키지명 수정
Jjiggu Jul 14, 2025
2ded712
refactor(UserOrder): 코드 컨벤션 수정
Jjiggu Jul 14, 2025
7cbf0d0
feat(UserOrder): 매출 순위 기능 구현
Jjiggu Jul 15, 2025
66e4f3f
feat(Department): 학과 정보를 위한 department 엔티티 생성
Jjiggu Jul 15, 2025
20ffe4b
feat: Redis 모듈 추가
Jjiggu Jul 15, 2025
fdc23dc
refactor(Department): Java 네이밍 컨벤션에 맞게 변수 이름 수정
Jjiggu Jul 15, 2025
4707bf5
refactor: private 접근 제한자 추가
Jjiggu Jul 15, 2025
125ffc2
refactor(UserOrder): 스웨거 어노테이션 추가
Jjiggu Jul 15, 2025
1ec1a60
refactor(UserOrder): null 체크 전에 zeroTuple을 사용하여 NullPointerException …
Jjiggu Jul 15, 2025
8261602
refactor(UserOrder): 누적매출에 맞는 변수명으로 변경
Jjiggu Jul 15, 2025
e745550
refactor(UserOrder): null 체크 전에 myStore를 사용하여 NullPointerException 방지
Jjiggu Jul 15, 2025
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 @@ -17,6 +17,8 @@
import com.nowait.applicationadmin.order.dto.OrderStatusUpdateResponseDto;
import com.nowait.applicationadmin.order.service.OrderService;
import com.nowait.common.api.ApiUtils;
import com.nowait.domaincorerdb.order.dto.OrderSalesSumDetail;
import com.nowait.domaincorerdb.order.dto.TopSalesStoresDetail;
import com.nowait.domaincorerdb.user.entity.MemberDetails;

import io.swagger.v3.oas.annotations.Operation;
Expand All @@ -31,36 +33,66 @@
@RequiredArgsConstructor
public class OrderController {

private final OrderService orderService;
private final OrderService orderService;

@GetMapping("/{storeId}")
@Operation(summary = "주점별 주문리스트 조회", description = "특정 주점에 대한 예약리스트 조회")
@ApiResponse(responseCode = "200", description = "주리스트 조회")
public ResponseEntity<?> getOrderListByStoreId(@PathVariable Long storeId,
@AuthenticationPrincipal MemberDetails memberDetails) {
List<OrderResponseDto> response = orderService.findAllOrders(storeId,memberDetails);
return ResponseEntity
.status(HttpStatus.OK)
.body(
ApiUtils.success(
response
)
);
}
@GetMapping("/{storeId}")
@Operation(summary = "주점별 주문리스트 조회", description = "특정 주점에 대한 예약리스트 조회")
@ApiResponse(responseCode = "200", description = "주리스트 조회")
public ResponseEntity<?> getOrderListByStoreId(@PathVariable Long storeId,
@AuthenticationPrincipal MemberDetails memberDetails) {
List<OrderResponseDto> response = orderService.findAllOrders(storeId, memberDetails);
return ResponseEntity
.status(HttpStatus.OK)
.body(
ApiUtils.success(
response
)
);
}

@PatchMapping("/status/{orderId}")
@Operation(summary = "주문 상태 변경", description = "특정 주문의 상태를 변경.")
@ApiResponse(responseCode = "200", description = "주문 상태 변경 성공")
@ApiResponse(responseCode = "400", description = "주문을 찾을 수 없음")
public ResponseEntity<?> updateOrderStatus(
@PathVariable Long orderId,
@RequestBody@Valid OrderStatusUpdateRequestDto requestDto,
@AuthenticationPrincipal MemberDetails memberDetails
) {
OrderStatusUpdateResponseDto response = orderService.updateOrderStatus(
orderId,requestDto.getOrderStatus(),memberDetails);
return ResponseEntity
.status(HttpStatus.OK)
.body(ApiUtils.success(response));
}
@PatchMapping("/status/{orderId}")
@Operation(summary = "주문 상태 변경", description = "특정 주문의 상태를 변경.")
@ApiResponse(responseCode = "200", description = "주문 상태 변경 성공")
@ApiResponse(responseCode = "400", description = "주문을 찾을 수 없음")
public ResponseEntity<?> updateOrderStatus(
@PathVariable Long orderId,
@RequestBody @Valid OrderStatusUpdateRequestDto requestDto,
@AuthenticationPrincipal MemberDetails memberDetails
) {
OrderStatusUpdateResponseDto response = orderService.updateOrderStatus(
orderId, requestDto.getOrderStatus(), memberDetails);
return ResponseEntity
.status(HttpStatus.OK)
.body(ApiUtils.success(response));
}

@GetMapping("/sales")
@Operation(summary = "오늘의 매출 조회", description = "오늘의 매출을 조회합니다.")
@ApiResponse(responseCode = "200", description = "오늘의 매출 조회 성공")
public ResponseEntity<?> getTodaySales(@AuthenticationPrincipal MemberDetails memberDetails) {
OrderSalesSumDetail sales = orderService.getSaleSumByStoreId(memberDetails);

return ResponseEntity
.status(HttpStatus.OK)
.body(
ApiUtils.success(
sales
)
);
}

@GetMapping("/top-sales")
@Operation(summary = "오늘의 매출 상위 5개 주점 조회", description = "오늘의 매출이 가장 높은 상위 5개 주점을 조회합니다.")
@ApiResponse(responseCode = "200", description = "오늘의 매출 상위 5개 주점 조회 성공")
public ResponseEntity<?> getTopSalesStores(@AuthenticationPrincipal MemberDetails memberDetails) {
List<TopSalesStoresDetail> topSalesStoresDetail = orderService.getTop5StoresBySalesToday(memberDetails);

return ResponseEntity
.status(HttpStatus.OK)
.body(
ApiUtils.success(
topSalesStoresDetail
)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import com.nowait.applicationadmin.order.dto.OrderResponseDto;
import com.nowait.applicationadmin.order.dto.OrderStatusUpdateResponseDto;
import com.nowait.common.enums.Role;
import com.nowait.domaincorerdb.order.dto.OrderSalesSumDetail;
import com.nowait.domaincorerdb.order.dto.TopSalesStoresDetail;
import com.nowait.domaincorerdb.order.entity.OrderStatus;
import com.nowait.domaincorerdb.order.entity.UserOrder;
import com.nowait.domaincorerdb.order.exception.OrderNotFoundException;
Expand All @@ -33,27 +35,50 @@ public class OrderService {

@Transactional(readOnly = true)
public List<OrderResponseDto> findAllOrders(Long storeId, MemberDetails memberDetails) {
User user = userRepository.findById(memberDetails.getId()).orElseThrow(UserNotFoundException::new);
storeRepository.findByStoreIdAndDeletedFalse(storeId)
.orElseThrow(StoreNotFoundException::new);
User user = userRepository.findById(memberDetails.getId()).orElseThrow(UserNotFoundException::new);
storeRepository.findByStoreIdAndDeletedFalse(storeId).orElseThrow(StoreNotFoundException::new);
if (!Role.SUPER_ADMIN.equals(user.getRole()) && !user.getStoreId().equals(storeId)) {
throw new OrderViewUnauthorizedException();
}
return orderRepository.findAllByStore_StoreId(storeId).stream()
return orderRepository.findAllByStore_StoreId(storeId)
.stream()
.map(OrderResponseDto::fromEntity)
.collect(Collectors.toList());
}

@Transactional
public OrderStatusUpdateResponseDto updateOrderStatus(Long orderId, OrderStatus newStatus,
MemberDetails memberDetails) {
User user = userRepository.findById(memberDetails.getId()).orElseThrow(UserNotFoundException::new);
UserOrder userOrder = orderRepository.findById(orderId)
.orElseThrow(OrderNotFoundException::new);
User user = userRepository.findById(memberDetails.getId()).orElseThrow(UserNotFoundException::new);
UserOrder userOrder = orderRepository.findById(orderId).orElseThrow(OrderNotFoundException::new);
if (!Role.SUPER_ADMIN.equals(user.getRole()) && !user.getStoreId().equals(userOrder.getStore().getStoreId())) {
throw new OrderUpdateUnauthorizedException();
}
userOrder.updateStatus(newStatus);
return OrderStatusUpdateResponseDto.fromEntity(userOrder);
}

@Transactional(readOnly = true)
public OrderSalesSumDetail getSaleSumByStoreId(MemberDetails memberDetails) {
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();
}
Comment thread
Jjiggu marked this conversation as resolved.

return orderRepository.findSalesSumByStoreId(storeId);
}

@Transactional(readOnly = true)
public List<TopSalesStoresDetail> getTop5StoresBySalesToday(MemberDetails memberDetails) {
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 orderRepository.getTop4PlusMine(storeId);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.nowait.applicationadmin.storePayment.controller;
package com.nowait.applicationadmin.storepayment.controller;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
Expand All @@ -10,10 +10,10 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.nowait.applicationadmin.storePayment.dto.StorePaymentCreateRequest;
import com.nowait.applicationadmin.storePayment.dto.StorePaymentCreateResponse;
import com.nowait.applicationadmin.storePayment.dto.StorePaymentUpdateRequest;
import com.nowait.applicationadmin.storePayment.service.StorePaymentService;
import com.nowait.applicationadmin.storepayment.dto.StorePaymentCreateRequest;
import com.nowait.applicationadmin.storepayment.dto.StorePaymentCreateResponse;
import com.nowait.applicationadmin.storepayment.dto.StorePaymentUpdateRequest;
import com.nowait.applicationadmin.storepayment.service.StorePaymentService;
import com.nowait.common.api.ApiUtils;
import com.nowait.domaincorerdb.user.entity.MemberDetails;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
package com.nowait.applicationadmin.storePayment.dto;
package com.nowait.applicationadmin.storepayment.dto;


import com.nowait.domaincorerdb.storepayment.entity.StorePayment;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.nowait.applicationadmin.storePayment.dto;
package com.nowait.applicationadmin.storepayment.dto;

import java.time.LocalDateTime;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.nowait.applicationadmin.storePayment.dto;
package com.nowait.applicationadmin.storepayment.dto;

import java.time.LocalDateTime;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.nowait.applicationadmin.storePayment.dto;
package com.nowait.applicationadmin.storepayment.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package com.nowait.applicationadmin.storePayment.service;
package com.nowait.applicationadmin.storepayment.service;

import com.nowait.applicationadmin.storePayment.dto.StorePaymentCreateRequest;
import com.nowait.applicationadmin.storePayment.dto.StorePaymentCreateResponse;
import com.nowait.applicationadmin.storePayment.dto.StorePaymentReadDto;
import com.nowait.applicationadmin.storePayment.dto.StorePaymentUpdateRequest;
import com.nowait.applicationadmin.storepayment.dto.StorePaymentCreateRequest;
import com.nowait.applicationadmin.storepayment.dto.StorePaymentCreateResponse;
import com.nowait.applicationadmin.storepayment.dto.StorePaymentReadDto;
import com.nowait.applicationadmin.storepayment.dto.StorePaymentUpdateRequest;
import com.nowait.domaincorerdb.user.entity.MemberDetails;

public interface StorePaymentService {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package com.nowait.applicationadmin.storePayment.service;
package com.nowait.applicationadmin.storepayment.service;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.nowait.applicationadmin.storePayment.dto.StorePaymentCreateRequest;
import com.nowait.applicationadmin.storePayment.dto.StorePaymentCreateResponse;
import com.nowait.applicationadmin.storePayment.dto.StorePaymentReadDto;
import com.nowait.applicationadmin.storePayment.dto.StorePaymentUpdateRequest;
import com.nowait.applicationadmin.storepayment.dto.StorePaymentCreateRequest;
import com.nowait.applicationadmin.storepayment.dto.StorePaymentCreateResponse;
import com.nowait.applicationadmin.storepayment.dto.StorePaymentReadDto;
import com.nowait.applicationadmin.storepayment.dto.StorePaymentUpdateRequest;
Comment on lines +6 to +9

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

레거시 패키지(storePayment) 참조가 남아 있지 않은지 확인 바랍니다
IDE 리팩터링으로 누락된 클래스가 있을 수 있습니다. 아래 스크립트로 잔존 패키지명을 검색해 보세요.


🏁 Script executed:

#!/bin/bash
# repo 내 남은 'storePayment' 패키지 경로 탐색
rg --fixed-strings 'applicationadmin.storePayment' -n

Length of output: 53


추가 검증을 위해 다양한 케이스로 검색을 재시도합니다.


🏁 Script executed:

#!/bin/bash
# 케이스에 관계없이 'storePayment' 문자열 검색
rg -n 'storePayment'
rg -n 'storepayment'

# 파일 및 디렉토리 이름에 'storePayment' 포함 여부 확인
find . -type f -iname '*storePayment*'
find . -type d -iname '*storePayment*'

Length of output: 19778


레거시 패키지명(storePayment)이 여전히 남아 있습니다
camel-case 디렉토리/패키지명을 모두 소문자(storepayment)로 통일해주세요.

아래 경로들을 점검 및 수정해야 합니다:

  • nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/storePayment/ (controller, dto, service)
  • nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/storePayment/ (entity, exception, repository)
🤖 Prompt for AI Agents
In
nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/storePayment/service/StorePaymentServiceImpl.java
lines 6 to 9, the import statements use the legacy camel-case package name
'storePayment'. Update all package names and directory paths from 'storePayment'
to lowercase 'storepayment' consistently across the project, including
controller, dto, service, entity, exception, and repository packages as
specified, to unify the package naming convention.

import com.nowait.common.enums.Role;
import com.nowait.domaincorerdb.storepayment.entity.StorePayment;
import com.nowait.domaincorerdb.storepayment.exception.StorePaymentAlreadyExistsException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,5 @@ public T getResponse() {
return response;
}

public ApiError getError() {
return error;
}
// public ApiError getError() { return success ? null : error; }
}
8 changes: 7 additions & 1 deletion nowait-domain/domain-core-rdb/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,20 @@ dependencies {
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'org.springframework.boot:spring-boot-starter-validation'

//QueryDsl
implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
annotationProcessor "com.querydsl:querydsl-apt:5.0.0:jakarta"
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
annotationProcessor "jakarta.persistence:jakarta.persistence-api"

// SWAGGER
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.6.0'

compileOnly 'org.projectlombok:lombok:1.18.26'
annotationProcessor 'org.projectlombok:lombok:1.18.26'

// Jackson
api 'com.fasterxml.jackson.core:jackson-databind:2.15.2' // Jackson 핵심
api 'com.fasterxml.jackson.core:jackson-databind:2.15.2'
api 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.2'

testImplementation 'org.junit.jupiter:junit-jupiter'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.nowait.domaincorerdb.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.querydsl.jpa.impl.JPAQueryFactory;

import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;

@Configuration
public class QueryDslConfig {
@PersistenceContext
private EntityManager entityManager;

@Bean
public JPAQueryFactory jpaQueryFactory() {
return new JPAQueryFactory(entityManager);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.nowait.domaincorerdb.department.entity;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Table(name = "departments")
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
Comment on lines +15 to +16

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

엔티티 생성을 위한 팩토리 메서드 추가를 고려하세요.

현재 AllArgsConstructor가 private으로 설정되어 있어 외부에서 엔티티를 직접 생성할 수 없습니다. 엔티티 생성을 위한 정적 팩토리 메서드를 추가하는 것을 권장합니다.

 @AllArgsConstructor(access = AccessLevel.PRIVATE)
 public class Department {
+
+    public static Department create(String name) {
+        return new Department(null, name);
+    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class Department {
public static Department create(String name) {
return new Department(null, name);
}
// … rest of the entity’s fields and methods …
}
🤖 Prompt for AI Agents
In
nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/department/entity/Department.java
around lines 15 to 16, the class uses a private AllArgsConstructor which
prevents external instantiation. To fix this, add a public static factory method
that internally calls the private constructor to create and return a new
Department instance, enabling controlled and clear entity creation.

public class Department {

@Id
private Long id;

@Column(nullable = false)
private String name;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.nowait.domaincorerdb.order.dto;

import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
public class OrderSalesSumDetail {
private Long storeId;
private Integer todaySalesSum;
private Integer yesterdaySalesSum;
private Integer cumulativeSalesBeforeYesterday;

public OrderSalesSumDetail(Long storeId, Integer todaySalesSum, Integer yesterdaySalesSum,
Integer cumulativeSalesBeforeYesterday) {
this.storeId = storeId;
this.todaySalesSum = todaySalesSum;
this.yesterdaySalesSum = yesterdaySalesSum;
this.cumulativeSalesBeforeYesterday = cumulativeSalesBeforeYesterday;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.nowait.domaincorerdb.order.dto;

import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
public class TopSalesStoresDetail {
private Long storeId;
private String storeName;
private Long departmentId;
private String departmentName;
private Integer totalSales;
private Long storeRank;

public TopSalesStoresDetail(Long storeId, String storeName, Long departmentId, String departmentName, Integer totalSales,
Long storeRank) {
this.storeId = storeId;
this.storeName = storeName;
this.departmentId = departmentId;
this.departmentName = departmentName;
this.totalSales = totalSales;
this.storeRank = storeRank;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.nowait.domaincorerdb.order.repository;

import java.util.List;

import com.nowait.domaincorerdb.order.dto.OrderSalesSumDetail;
import com.nowait.domaincorerdb.order.dto.TopSalesStoresDetail;

public interface OrderCustomRepository {

OrderSalesSumDetail findSalesSumByStoreId(Long storeId);

List<TopSalesStoresDetail> getTop4PlusMine(Long storeId);
}
Loading