Skip to content

Feat : Admin 통계 기능 추가#106

Merged
Jjiggu merged 19 commits into
developfrom
feature/#103-Store-SalesSum
Jul 15, 2025
Merged

Feat : Admin 통계 기능 추가#106
Jjiggu merged 19 commits into
developfrom
feature/#103-Store-SalesSum

Conversation

@Jjiggu

@Jjiggu Jjiggu commented Jul 15, 2025

Copy link
Copy Markdown
Contributor

작업 요약

  • 매출 조회 기능 추가
  • 주점 매출 순위 기능 추가

Issue Link

#103

문제점 및 어려움

주점 순위 변동 기능 추가 예정

해결 방안

Reference

Summary by CodeRabbit

  • 신규 기능

    • 오늘 매출 요약 및 상위 5개 매장 매출 조회 API가 추가되었습니다.
    • 매장별, 부서별 매출 순위 조회가 가능합니다.
  • 버그 수정

    • 패키지 명칭이 일관성 있게 소문자로 정정되었습니다.
  • 빌드/환경

    • QueryDSL(Jakarta EE 지원) 및 Redis 관련 의존성이 추가되었습니다.
    • Redis 설정 및 캐시 서비스가 도입되었습니다.
  • 기타

    • 신규 JPA 엔티티(Department) 및 DTO가 추가되었습니다.
    • 커스텀 레포지토리 및 구현체가 도입되었습니다.

@Jjiggu Jjiggu self-assigned this Jul 15, 2025
@Jjiggu Jjiggu added the enhancement New feature or request label Jul 15, 2025
@coderabbitai

coderabbitai Bot commented Jul 15, 2025

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

## Walkthrough

이번 변경 사항에서는 주문 및 매출 요약 기능을 위한 새로운 API 엔드포인트와 서비스 메서드가 추가되었습니다. QueryDSL 및 Redis를 위한 설정 및 의존성이 도입되었으며, 매장별/부서별 매출 집계와 랭킹 조회를 위한 DTO, 레포지토리, 엔티티가 새로 생성되었습니다. 일부 패키지명 표기 일관성도 정비되었습니다.

## Changes

| 파일/경로 그룹 | 변경 요약 |
|---|---|
| OrderController, OrderService | 매장 오늘 매출 요약 및 TOP 5 매장 매출 조회용 GET 엔드포인트 및 서비스 메서드 추가 |
| .../order/dto/OrderSalesSumDetail.java<br>.../order/dto/TopSalesStoresDetail.java | 매출 요약, TOP 매장 랭킹 정보를 위한 DTO 클래스 추가 |
| .../order/repository/OrderCustomRepository.java<br>.../order/repository/OrderCustomRepositoryImpl.java | 매출 요약, TOP 매장 랭킹 조회용 커스텀 레포지토리 및 구현체 추가 |
| .../order/repository/OrderRepository.java | OrderCustomRepository 상속 추가 |
| .../department/entity/Department.java | 부서 엔티티 신규 추가 |
| .../storePayment/controller, dto, service | 패키지명을 storePayment → storepayment로 소문자 일관화 |
| nowait-common/src/main/java/com/nowait/common/api/ApiResult.java | getError() 메서드 제거(주석 처리) |
| nowait-domain/domain-core-rdb/build.gradle | QueryDSL(Jakarta) 관련 의존성 및 annotation processor 추가, 포맷팅 정비 |
| .../config/QueryDslConfig.java | QueryDSL JPAQueryFactory 빈 등록용 설정 클래스 추가 |
| nowait-domain/domain-redis/build.gradle | Redis 모듈 신규 Gradle 빌드 스크립트 추가 |
| .../config/RedisConfig.java | Redis 연결 및 직렬화 설정용 Spring Config 클래스 추가 |
| .../service/StoreRankCacheService.java | RedisTemplate<String, String> 필드만 가진 서비스 클래스 추가 |
| settings.gradle | :nowait-domain:domain-redis 모듈 빌드에 포함 |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant Client
    participant OrderController
    participant OrderService
    participant OrderRepository
    participant OrderCustomRepository

    Client->>OrderController: GET /sales (오늘 매출 요약)
    OrderController->>OrderService: getSaleSumByStoreId(memberDetails)
    OrderService->>OrderRepository: findSalesSumByStoreId(storeId)
    OrderRepository->>OrderCustomRepository: findSalesSumByStoreId(storeId)
    OrderCustomRepository-->>OrderRepository: OrderSalesSumDetail
    OrderRepository-->>OrderService: OrderSalesSumDetail
    OrderService-->>OrderController: OrderSalesSumDetail
    OrderController-->>Client: ApiResult.success(OrderSalesSumDetail)

    Client->>OrderController: GET /top-sales (TOP 5 매장 매출)
    OrderController->>OrderService: getTop5StoresBySalesToday(memberDetails)
    OrderService->>OrderRepository: getTop4PlusMine(storeId)
    OrderRepository->>OrderCustomRepository: getTop4PlusMine(storeId)
    OrderCustomRepository-->>OrderRepository: List<TopSalesStoresDetail>
    OrderRepository-->>OrderService: List<TopSalesStoresDetail>
    OrderService-->>OrderController: List<TopSalesStoresDetail>
    OrderController-->>Client: ApiResult.success(List<TopSalesStoresDetail>)
sequenceDiagram
    participant Admin
    participant StorePaymentController
    participant StorePaymentService

    Admin->>StorePaymentController: (기존 엔드포인트 호출)
    StorePaymentController->>StorePaymentService: (기존 서비스 호출)
    Note right of StorePaymentController: 패키지명만 변경, 로직 동일
Loading
sequenceDiagram
    participant Spring
    participant QueryDslConfig
    participant RedisConfig

    Spring->>QueryDslConfig: 컨테이너 초기화 시
    QueryDslConfig->>Spring: JPAQueryFactory 빈 등록

    Spring->>RedisConfig: 컨테이너 초기화 시
    RedisConfig->>Spring: RedisConnectionFactory, RedisTemplate 빈 등록
Loading

Suggested reviewers

  • HyemIin

<!-- walkthrough_end -->
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->

---

<details>
<summary>📜 Recent review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 20ffe4bf106bf5f78ed82540145c92fbcf4c22bc and e7455508fd3b82148ce4c91ae49b8883cf20b95f.

</details>

<details>
<summary>📒 Files selected for processing (4)</summary>

* `nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/order/controller/OrderController.java` (2 hunks)
* `nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/department/entity/Department.java` (1 hunks)
* `nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/order/dto/OrderSalesSumDetail.java` (1 hunks)
* `nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/order/repository/OrderCustomRepositoryImpl.java` (1 hunks)

</details>

</details>
<!-- finishing_touch_checkbox_start -->

<details open="true">
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=GTable/NoWait_BE_MultiModule&utm_content=106):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Explain this complex logic.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai explain this code block.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and explain its main purpose.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->

@github-actions github-actions Bot requested a review from HyemIin July 15, 2025 10:59

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 14

🧹 Nitpick comments (3)
nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/order/dto/OrderSalesSumDetail.java (2)

14-20: @builder와 명시적 생성자 중복 사용

Lombok의 @Builder 어노테이션과 명시적 생성자를 동시에 사용하고 있습니다. 일반적으로 @Builder만 사용하거나, 특별한 이유가 있다면 @AllArgsConstructor를 추가하는 것이 더 명확합니다.

+@AllArgsConstructor
 @Getter
 @Builder
 public class OrderSalesSumDetail {
-	public OrderSalesSumDetail(Long storeId, Integer todaySalesSum, Integer yesterdaySalesSum,
-		Integer previousDaySales) {
-		this.storeId = storeId;
-		this.todaySalesSum = todaySalesSum;
-		this.yesterdaySalesSum = yesterdaySalesSum;
-		this.previousDaySales = previousDaySales;
-	}

8-21: Java 14+ record 클래스 사용 고려

불변 데이터 전송을 위한 DTO의 경우 Java 14+의 record 클래스를 사용하면 더 간결하고 안전한 코드를 작성할 수 있습니다.

-@Getter
-@Builder
-public class OrderSalesSumDetail {
-	Long storeId;
-	Integer todaySalesSum;
-	Integer yesterdaySalesSum;
-	Integer previousDaySales;
-
-	public OrderSalesSumDetail(Long storeId, Integer todaySalesSum, Integer yesterdaySalesSum,
-		Integer previousDaySales) {
-		this.storeId = storeId;
-		this.todaySalesSum = todaySalesSum;
-		this.yesterdaySalesSum = yesterdaySalesSum;
-		this.previousDaySales = previousDaySales;
-	}
-}
+public record OrderSalesSumDetail(
+	Long storeId,
+	Integer todaySalesSum,
+	Integer yesterdaySalesSum,
+	Integer previousDaySales
+) {}
nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/order/dto/TopSalesStoresDetail.java (1)

16-24: 명시적 생성자와 @builder 중복 사용

OrderSalesSumDetail과 동일한 이슈로, @Builder와 명시적 생성자를 동시에 사용하고 있습니다. 일관성을 위해 @AllArgsConstructor를 사용하는 것을 권장합니다.

+@AllArgsConstructor
 @Getter
 @Builder
 public class TopSalesStoresDetail {
-	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;
-	}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b1c6485 and 20ffe4b.

📒 Files selected for processing (22)
  • nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/order/controller/OrderController.java (2 hunks)
  • nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/order/service/OrderService.java (2 hunks)
  • nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/storePayment/controller/StorePaymentController.java (2 hunks)
  • nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/storePayment/dto/StorePaymentCreateRequest.java (1 hunks)
  • nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/storePayment/dto/StorePaymentCreateResponse.java (1 hunks)
  • nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/storePayment/dto/StorePaymentReadDto.java (1 hunks)
  • nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/storePayment/dto/StorePaymentUpdateRequest.java (1 hunks)
  • nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/storePayment/service/StorePaymentService.java (1 hunks)
  • nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/storePayment/service/StorePaymentServiceImpl.java (1 hunks)
  • nowait-common/src/main/java/com/nowait/common/api/ApiResult.java (1 hunks)
  • nowait-domain/domain-core-rdb/build.gradle (1 hunks)
  • nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/config/QueryDslConfig.java (1 hunks)
  • nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/department/entity/Department.java (1 hunks)
  • nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/order/dto/OrderSalesSumDetail.java (1 hunks)
  • nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/order/dto/TopSalesStoresDetail.java (1 hunks)
  • nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/order/repository/OrderCustomRepository.java (1 hunks)
  • nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/order/repository/OrderCustomRepositoryImpl.java (1 hunks)
  • nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/order/repository/OrderRepository.java (1 hunks)
  • nowait-domain/domain-redis/build.gradle (1 hunks)
  • nowait-domain/domain-redis/src/main/java/com/nowait/domaincoreredis/config/RedisConfig.java (1 hunks)
  • nowait-domain/domain-redis/src/main/java/com/nowait/domaincoreredis/service/StoreRankCacheService.java (1 hunks)
  • settings.gradle (1 hunks)
🔇 Additional comments (21)
nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/storePayment/service/StorePaymentServiceImpl.java (1)

1-1: 패키지 네이밍 일관성 개선 👍
CamelCase → 소문자로 통일하여 자바 관례에 맞췄습니다. 모듈 전반의 리팩터링 방향과도 일치합니다.

nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/storePayment/controller/StorePaymentController.java (2)

1-1: 패키지 경로 소문자화 확인
컨트롤러도 동일하게 수정되어 모듈 간 의존성이 깨지지 않습니다.


13-16: import 경로 동기화 OK
DTO·Service 모두 새 패키지로 맞춰져 있습니다. 남은 레거시 import 가 없는지 위 검증 스크립트로 추가 확인을 권장합니다.

nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/storePayment/service/StorePaymentService.java (1)

1-6: 인터페이스 패키지 정정 완료
서비스 인터페이스도 소문자 패키지로 일관화되어 구현체·컨트롤러와 매칭됩니다.

nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/storePayment/dto/StorePaymentCreateRequest.java (1)

1-2: DTO 패키지 네이밍 통일 완료
엔티티 매핑 로직에 영향 없는 단순 경로 변경이며 문제 없습니다.

nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/storePayment/dto/StorePaymentCreateResponse.java (1)

1-1: DTO 패키지 경로 소문자화 적용 확인
다른 DTO·서비스 파일들과 동일하게 수정되었습니다.

nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/storePayment/dto/StorePaymentReadDto.java (1)

1-1: 패키지명 소문자 통일 완료 및 레거시 경로 없음 확인

storePayment → storepayment로 변경이 전 프로젝트에 일관되게 적용되었으며, legacy 경로가 남아있지 않음을 검증 스크립트로 확인했습니다.

nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/storePayment/dto/StorePaymentUpdateRequest.java (1)

1-1: 패키지명 정비 확인 필요

StorePaymentUpdateRequest 역시 소문자 패키지로 변경되었습니다. 빌드·IDE 캐시가 간혹 이전 경로를 기억해 충돌을 일으키므로, 프로젝트 클린-리빌드 또는 Gradle clean 실행을 권장드립니다.

nowait-common/src/main/java/com/nowait/common/api/ApiResult.java (1)

22-22: ApiResult.getError() 사용처 없음 확인 — 안전하게 제거 가능

  • 리포지토리 전체에서 .getError() 호출을 검색한 결과, 어떠한 참조도 발견되지 않았습니다.
nowait-domain/domain-core-rdb/build.gradle (1)

34-39: QueryDSL 설정이 올바르게 추가되었습니다.

Jakarta EE 지원 버전과 필요한 어노테이션 프로세서가 모두 포함되어 있어 QueryDSL 기능을 정상적으로 사용할 수 있습니다.

nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/order/repository/OrderRepository.java (1)

12-12: 커스텀 리포지토리 확장이 올바르게 구현되었습니다.

Spring Data JPA의 표준 패턴을 따라 OrderCustomRepository를 확장하여 커스텀 쿼리 기능을 추가했습니다.

nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/config/QueryDslConfig.java (1)

11-20: QueryDSL 설정이 올바르게 구현되었습니다.

표준적인 QueryDSL 설정 패턴을 따라 JPAQueryFactory 빈을 생성하고 EntityManager를 주입받아 사용하고 있습니다.

nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/order/repository/OrderCustomRepository.java (1)

8-13: 잘 설계된 커스텀 리포지토리 인터페이스

메서드 이름이 명확하고 적절한 DTO 타입을 반환하는 깔끔한 인터페이스 설계입니다. Spring Data JPA의 커스텀 리포지토리 패턴을 올바르게 따르고 있습니다.

nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/order/dto/TopSalesStoresDetail.java (1)

9-14: 필드 가시성 설정 우수

필드들이 적절히 private로 선언되어 있어 캡슐화가 잘 되어 있습니다. 다른 DTO 클래스들과 일관성을 위해 이 패턴을 따르는 것이 좋습니다.

nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/order/controller/OrderController.java (1)

69-82: API 문서화 완성도 우수

매출 조회 엔드포인트가 적절한 @Operation 어노테이션과 @ApiResponse로 잘 문서화되어 있습니다. 보안과 응답 패턴도 일관성 있게 구현되었습니다.

nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/order/service/OrderService.java (3)

61-71: 트랜잭션 어노테이션 사용 우수

읽기 전용 트랜잭션 어노테이션을 적절히 사용하여 성능 최적화를 고려했습니다.


73-83: 일관된 서비스 구조

기존 메서드들과 동일한 패턴을 따르는 일관된 구조로 구현되어 있습니다. 사용자 조회, 권한 검사, 리포지토리 호출의 흐름이 명확합니다.


78-80: 동일한 불필요한 권한 검사 로직

getSaleSumByStoreId 메서드와 동일한 불필요한 권한 검사가 반복되고 있습니다.

-		if (!Role.SUPER_ADMIN.equals(user.getRole()) && !user.getStoreId().equals(storeId)) {
-			throw new OrderViewUnauthorizedException();
-		}
+		// storeId는 user.getStoreId()에서 가져온 값이므로 추가 검사 불필요

Likely an incorrect or invalid review comment.

nowait-domain/domain-redis/build.gradle (1)

1-36: 빌드 설정이 적절합니다.

Redis 모듈을 위한 Gradle 빌드 설정이 올바르게 구성되었습니다. 필요한 의존성들이 포함되어 있고, Java 17 설정과 프로젝트 구조가 적절합니다.

settings.gradle (1)

9-9: 새로운 Redis 모듈이 올바르게 추가되었습니다.

프로젝트 설정에 nowait-domain:domain-redis 모듈이 적절하게 추가되었습니다.

nowait-domain/domain-redis/src/main/java/com/nowait/domaincoreredis/config/RedisConfig.java (1)

13-17: Redis 설정 프로퍼티 확인 필요

현재 코드베이스에서 spring.data.redis.hostspring.data.redis.port 설정이 *.yml/*.yaml/*.properties 파일에서 검색되지 않습니다.
아래 항목을 직접 확인해주세요.

  • application.yml 또는 application.properties 파일에
    • spring.data.redis.host
    • spring.data.redis.port
      설정이 정의되어 있는지

Comment on lines +6 to +9
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;

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.

Comment on lines +15 to +16
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PRIVATE)

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.

Comment on lines +19 to +20
@Id
private Long Id;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

ID 필드에 자동 생성 전략과 네이밍 컨벤션을 적용하세요.

  1. @GeneratedValue 어노테이션이 없어서 ID 값을 수동으로 설정해야 합니다.
  2. 필드명이 Java 네이밍 컨벤션을 따르지 않습니다 (Idid).

다음과 같이 수정하세요:

 @Id
-private Long Id;
+@GeneratedValue(strategy = GenerationType.IDENTITY)
+private Long id;
📝 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
@Id
private Long Id;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
🤖 Prompt for AI Agents
In
nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/department/entity/Department.java
at lines 19-20, the ID field lacks the @GeneratedValue annotation for automatic
ID generation and uses incorrect naming convention with 'Id'. Rename the field
to 'id' following Java conventions and add the @GeneratedValue annotation to
enable automatic ID generation.

Comment on lines +104 to +119
Integer userRank = rankMap.get(userStoreId);

// 3. 상위 5개 주점 조회 (내 주점 포함 여부는 나중에 확인)
List<TopSalesStoresDetail> result = getTopNStores(allStores, rankMap, 5);
Set<Long> already = result.stream()
.map(TopSalesStoresDetail::getStoreId)
.collect(Collectors.toSet());

// 4. 내 주점 추가 (내 주점이 포함되지 않으면 추가)
TopSalesStoresDetail myStore = getMyStoreDetail(allStores, rankMap, userStoreId);
if (myStore == null)
myStore = getZeroSalesStore(userStoreId);

if (myStore != null && !already.contains(userStoreId)) {
// 내 주점이 5위 이하로 밀린 경우
if (userRank > 5) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

userRank가 null일 때 NullPointerException이 발생할 수 있습니다.

매출이 없는 store의 경우 rankMap에 존재하지 않아 userRank가 null이 될 수 있습니다.

다음과 같이 null 체크를 추가하세요:

 		// 4. 내 주점 추가 (내 주점이 포함되지 않으면 추가)
 		TopSalesStoresDetail myStore = getMyStoreDetail(allStores, rankMap, userStoreId);
 		if (myStore == null)
 			myStore = getZeroSalesStore(userStoreId);
 
 		if (myStore != null && !already.contains(userStoreId)) {
 			// 내 주점이 5위 이하로 밀린 경우
-			if (userRank > 5) {
+			if (userRank != null && userRank > 5) {
📝 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
Integer userRank = rankMap.get(userStoreId);
// 3. 상위 5개 주점 조회 (내 주점 포함 여부는 나중에 확인)
List<TopSalesStoresDetail> result = getTopNStores(allStores, rankMap, 5);
Set<Long> already = result.stream()
.map(TopSalesStoresDetail::getStoreId)
.collect(Collectors.toSet());
// 4. 내 주점 추가 (내 주점이 포함되지 않으면 추가)
TopSalesStoresDetail myStore = getMyStoreDetail(allStores, rankMap, userStoreId);
if (myStore == null)
myStore = getZeroSalesStore(userStoreId);
if (myStore != null && !already.contains(userStoreId)) {
// 내 주점이 5위 이하로 밀린 경우
if (userRank > 5) {
Integer userRank = rankMap.get(userStoreId);
// 3. 상위 5개 주점 조회 (내 주점 포함 여부는 나중에 확인)
List<TopSalesStoresDetail> result = getTopNStores(allStores, rankMap, 5);
Set<Long> already = result.stream()
.map(TopSalesStoresDetail::getStoreId)
.collect(Collectors.toSet());
// 4. 내 주점 추가 (내 주점이 포함되지 않으면 추가)
TopSalesStoresDetail myStore = getMyStoreDetail(allStores, rankMap, userStoreId);
if (myStore == null)
myStore = getZeroSalesStore(userStoreId);
if (myStore != null && !already.contains(userStoreId)) {
// 내 주점이 5위 이하로 밀린 경우
if (userRank != null && userRank > 5) {
🤖 Prompt for AI Agents
In
nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/order/repository/OrderCustomRepositoryImpl.java
around lines 104 to 119, userRank retrieved from rankMap can be null if the
userStoreId has no sales, causing a NullPointerException when compared. Add a
null check for userRank before using it in comparisons or logic, and handle the
null case appropriately to avoid exceptions.

@Service
public class StoreRankCacheService {

private RedisTemplate<String, String> redisTemplate;

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

RedisTemplate 타입 불일치를 확인하세요.

StoreRankCacheServiceRedisTemplate<String, String>을 사용하지만, RedisConfig에서는 RedisTemplate<String, Object>를 제공합니다. 타입 일치를 위해 설정을 수정하거나 별도의 Bean을 정의해야 합니다.

다음 스크립트를 실행하여 RedisConfig의 Bean 정의를 확인하세요:


🏁 Script executed:

#!/bin/bash
# RedisConfig에서 RedisTemplate Bean 정의 확인
ast-grep --pattern 'RedisTemplate<$_, $_> $_() {
  $$$
}'

Length of output: 59


아래 스크립트를 실행해 RedisConfig.java 파일 위치를 찾고, 해당 파일에서 RedisTemplate Bean 정의를 확인해 주세요.


🏁 Script executed:

#!/bin/bash
# 1. RedisConfig.java 위치 찾기
echo "== RedisConfig.java 파일 위치 =="
fd -e java | grep -i RedisConfig.java

# 2. 찾은 파일에서 RedisTemplate Bean 정의 검색
config_file=$(fd -e java | grep -i RedisConfig.java | head -n1)
if [[ -n "$config_file" ]]; then
  echo "== $config_file 내용 중 @Bean 및 RedisTemplate 검색 =="
  grep -R "@Bean" -n "$config_file" | grep -C3 "RedisTemplate"
  echo "== $config_file 내용 중 Generic 타입으로 RedisTemplate 검색 =="
  grep -R "RedisTemplate<" -n "$config_file"
else
  echo "RedisConfig.java 파일을 찾을 수 없습니다."
fi

Length of output: 1392


RedisTemplate 제네릭 타입 불일치

StoreRankCacheService에서는 RedisTemplate<String, String>을 사용하지만, RedisConfig에서 제공하는 Bean은 RedisTemplate<String, Object>입니다. 이대로 두면 스프링 빈 주입 시 타입 불일치로 예외가 발생할 수 있으니, 아래 중 하나를 적용해 주세요.

  • Service 필드 타입을 RedisTemplate<String, Object>로 변경
  • RedisConfigRedisTemplate<String, String> 전용 Bean(@bean) 정의

검토 파일:

  • nowait-domain/domain-redis/src/main/java/com/nowait/domaincoreredis/service/StoreRankCacheService.java
  • nowait-domain/domain-redis/src/main/java/com/nowait.domaincoreredis/config/RedisConfig.java
🤖 Prompt for AI Agents
In
nowait-domain/domain-redis/src/main/java/com/nowait/domaincoreredis/service/StoreRankCacheService.java
at line 9, the RedisTemplate field uses RedisTemplate<String, String> but the
RedisConfig provides RedisTemplate<String, Object>, causing a type mismatch on
Spring bean injection. To fix this, either change the field type in
StoreRankCacheService to RedisTemplate<String, Object> or define a new
RedisTemplate<String, String> bean in RedisConfig and inject that instead.

⚠️ Potential issue

RedisTemplate 의존성 주입이 누락되었습니다.

redisTemplate 필드가 초기화되지 않았습니다. 이는 서비스 사용 시 NullPointerException을 발생시킬 수 있습니다.

+	public StoreRankCacheService(RedisTemplate<String, String> redisTemplate) {
+		this.redisTemplate = redisTemplate;
+	}
+
 	private RedisTemplate<String, String> redisTemplate;

또는 필드 주입을 사용하는 경우:

+	@Autowired
 	private RedisTemplate<String, String> redisTemplate;
📝 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
private RedisTemplate<String, String> redisTemplate;
public StoreRankCacheService(RedisTemplate<String, String> redisTemplate) {
this.redisTemplate = redisTemplate;
}
private RedisTemplate<String, String> redisTemplate;
Suggested change
private RedisTemplate<String, String> redisTemplate;
@Autowired
private RedisTemplate<String, String> redisTemplate;
🤖 Prompt for AI Agents
In
nowait-domain/domain-redis/src/main/java/com/nowait/domaincoreredis/service/StoreRankCacheService.java
at line 9, the redisTemplate field is declared but not injected, which can cause
NullPointerException when used. Fix this by adding dependency injection for
redisTemplate, either by annotating the field with @Autowired or by adding a
constructor that accepts RedisTemplate<String, String> and assigns it to the
field.

Comment on lines +25 to +31
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();

redisTemplate.setConnectionFactory(redisConnectionFactory());

redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());

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

RedisTemplate 타입과 시리얼라이저 불일치를 수정하세요.

RedisTemplate<String, Object>로 타입을 선언했지만 모든 시리얼라이저가 StringRedisSerializer로 설정되어 있습니다. 이는 타입 불일치를 야기합니다.

다음 중 하나를 선택하여 수정하세요:

옵션 1: 타입을 String으로 변경 (권장)

 @Bean
-public RedisTemplate<String, Object> redisTemplate() {
-	RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
+public RedisTemplate<String, String> redisTemplate() {
+	RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();

옵션 2: Object 타입에 적합한 시리얼라이저 사용

-	redisTemplate.setValueSerializer(new StringRedisSerializer());
+	redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
-	redisTemplate.setHashValueSerializer(new StringRedisSerializer());
+	redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
🤖 Prompt for AI Agents
In
nowait-domain/domain-redis/src/main/java/com/nowait/domaincoreredis/config/RedisConfig.java
around lines 25 to 31, the RedisTemplate is declared as RedisTemplate<String,
Object> but all serializers are set to StringRedisSerializer, causing a type
mismatch. To fix this, either change the RedisTemplate type to
RedisTemplate<String, String> to match the serializers or keep
RedisTemplate<String, Object> and replace the value serializer with one suitable
for Object types, such as GenericJackson2JsonRedisSerializer.

@Jjiggu Jjiggu merged commit e624bfb into develop Jul 15, 2025
1 check was pending
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant