Skip to content

feat(search): 실시간 판매 Best와 검색 진입 배너 - #252

Merged
chanwoo7 merged 3 commits into
developfrom
feat/search-realtime-best-banner
Aug 30, 2026
Merged

feat(search): 실시간 판매 Best와 검색 진입 배너#252
chanwoo7 merged 3 commits into
developfrom
feat/search-realtime-best-banner

Conversation

@chanwoo7

Copy link
Copy Markdown
Member

배경

검색 진입 화면(figma search/05) '실시간 판매 Best' 리스트 + 인기 검색어 아래 배너 슬롯 대응(검색 화면 API 2/4). #251 후속.

변경

  • realtimeBestCakes(input: { limit = 10, 최대 20 }): 최근 24시간 유효 주문(RANKING_VALID_ORDER_STATUSES, 인기 점수와 동일 상태 집합) OrderItem.quantity 합 desc. 판매 0건 제외, 동률은 인기 점수 → 리뷰수 → id desc. 실시간 집계, rankedAt = 호출 시각. 카드는 PopularCake 재사용.
    • 랭킹 로직은 product feature(ProductBestSellerService)에 두고 search feature가 배럴로 소비. aggregateProductSoldQuantities는 후속 판매순 정렬도 공유.
  • searchBanner: BannerPlacement.SEARCH 추가(마이그레이션) + placement=SEARCH 배너 1건, 없으면 null. findHomeBanner의 활성·기간·링크 대상 활성 조건을 findFirstBanner로 공용화.
  • 셀러 배너 SDL/DTO/타입에 SEARCH 지면 추가. 시드 배너 1건.

자체 판단(시안 외)

판매 0건 제외, 동률 인기 점수 해소.

테스트

11건 추가. yarn validate 통과(200 suites).

검색 진입 화면(figma search 05) '실시간 판매 Best' 리스트와 인기 검색어 아래 배너 슬롯 대응
(검색 화면 API 2/4). 정책은 문답으로 확정.

- realtimeBestCakes(limit=10, 최대 20): 최근 24시간 유효 주문(RANKING_VALID_ORDER_STATUSES —
  인기 점수와 동일, SUBMITTED 제외는 프로덕션 관행 근거로 사용자 확정) OrderItem.quantity 합
  desc. 판매 0건 제외(데이터 적으면 빈 목록), 동률은 인기 점수 → 리뷰수 → id desc(자체 판단).
  실시간 집계, rankedAt=호출 시각. 카드는 PopularCake 타입 재사용.
  - 랭킹·카드 규칙은 product feature(ProductBestSellerService)에 두고 search feature가
    배럴로 소비. ProductRepository.aggregateProductSoldQuantities 추가(판매순 정렬도 공유 예정).
- searchBanner: BannerPlacement.SEARCH 추가(마이그레이션) + placement=SEARCH 배너 1건,
  없으면 null(홈 배너와 동일, fallback 없음). findHomeBanner의 활성·기간·링크 대상 활성
  조건을 findFirstBanner로 공용화.
- 셀러 배너 SDL/DTO/출력 타입에 SEARCH 지면 추가(등록 가능하도록).
- 시드: SEARCH 배너 1건([SEED] 제목 prefix로 resetSeedScope 정리).

테스트 11건: 수량 합 정렬·rank, 판매 0 제외, 24h/취소·접수/삭제 주문 제외, 비활성 상품·매장
제외, 동률 인기 점수, limit 상한, 카드 필드, 배너 정렬·기간·비활성·링크 대상 제외, resolver 통합.
@coderabbitai

coderabbitai Bot commented Aug 30, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 958a380c-70bb-4c35-896a-2c919fd85364

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown

🧹 knip — dead-code 리포트

Duplicate exports (1)
전체 리포트
Duplicate exports (1)
KEYWORD_RANK_SNAPSHOT_SIZE|MAX_POPULAR_KEYWORDS_LIMIT  src/features/search/constants/search.constants.ts

청소 후보(오탐 가능) · 기준 docs/guide/architecture-conventions.md

@github-actions

Copy link
Copy Markdown

🩺 NestJS Doctor — 90/100 (Excellent)

진단 281건 (error 0).

Category error warning info
architecture 0 0 9
correctness 0 133 0
performance 0 24 16
schema 0 0 86
security 0 13 0
architecture / security 상위 항목
  • info architecture/architecture/no-barrel-export-internals: Barrel file re-exports internal type 'IAuditLogRepository'.
  • warning security/security/no-exposed-env-vars: Direct 'process.env.NODE_ENV' access in 'AuthController'. Use ConfigService instead.
  • warning security/security/require-guards-on-endpoints: Endpoint 'start' has no @UseGuards() at class or method level.
  • warning security/security/require-guards-on-endpoints: Endpoint 'callback' has no @UseGuards() at class or method level.
  • warning security/security/require-guards-on-endpoints: Endpoint 'refresh' has no @UseGuards() at class or method level.
  • warning security/security/require-guards-on-endpoints: Endpoint 'logout' has no @UseGuards() at class or method level.
  • warning security/security/require-guards-on-endpoints: Endpoint 'sellerLogin' has no @UseGuards() at class or method level.
  • warning security/security/require-guards-on-endpoints: Endpoint 'sellerRefresh' has no @UseGuards() at class or method level.
  • warning security/security/require-guards-on-endpoints: Endpoint 'sellerLogout' has no @UseGuards() at class or method level.
  • warning security/security/require-guards-on-endpoints: Endpoint 'devIssueToken' has no @UseGuards() at class or method level.
  • info architecture/architecture/no-barrel-export-internals: Barrel file re-exports internal module '@/features/conversation/repositories/conversation.repository'.
  • info architecture/architecture/no-barrel-export-internals: Barrel file re-exports internal type 'ConversationRepository'.
  • info architecture/architecture/no-barrel-export-internals: Barrel file re-exports internal module '@/features/order/repositories/order.repository'.
  • info architecture/architecture/no-barrel-export-internals: Barrel file re-exports internal type 'OrderRepository'.
  • info architecture/architecture/no-barrel-export-internals: Barrel file re-exports internal module '@/features/product/repositories/product.repository'.

오탐 포함 가능 · 기준 docs/guide/architecture-conventions.md

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7a649ad186

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

'HOME_SUB',
'CATEGORY',
'STORE',
'SEARCH',

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Accept SEARCH in the placement converter

When a seller creates a banner with the newly exposed SEARCH placement, DTO validation succeeds but SellerBannerService.toBannerPlacement() handles only the four older values and throws INVALID_BANNER_PLACEMENT; updates to SEARCH fail through the same path. As a result, production users cannot configure the new search banner through the seller API, so the converter must map SEARCH to BannerPlacement.SEARCH.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

반영: toBannerPlacement에 SEARCH 매핑 추가 + 생성 테스트(placement=SEARCH) 1건.

@github-actions

github-actions Bot commented Aug 30, 2026

Copy link
Copy Markdown

Coverage report

St.
Category Percentage Covered / Total
🟢 Statements 97.82% 5245/5362
🟢 Branches 94.14% 2056/2184
🟢 Functions 96.42% 1024/1062
🟢 Lines 98.39% 4763/4841

Test suite run success

1729 tests passing in 200 suites.

Report generated by 🧪jest coverage report action from 0a6f12f

@codecov

codecov Bot commented Aug 30, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 91.22807% with 5 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...es/product/services/product-best-seller.service.ts 90.00% 0 Missing and 3 partials ⚠️
...eatures/product/repositories/product.repository.ts 66.66% 0 Missing and 2 partials ⚠️

📢 Thoughts on this report? Let us know!

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0a6f12f270

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if (raw === 'HOME_SUB') return BannerPlacement.HOME_SUB;
if (raw === 'CATEGORY') return BannerPlacement.CATEGORY;
if (raw === 'STORE') return BannerPlacement.STORE;
if (raw === 'SEARCH') return BannerPlacement.SEARCH;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Associate linkless SEARCH banners with their creating store

When a seller creates the newly supported SEARCH banner with the default linkType: NONE (the added creation test exercises exactly this input), both link_store_id and link_product_id remain null. SellerRepository.listBannersByStore() and findBannerByIdForStore() only recognize banners through one of those links, so the banner immediately disappears from the seller's list and all subsequent update/delete calls return not found, while findSearchBanner() continues exposing it globally. Persist an explicit owner/store association or require an ownership-bearing link before accepting this placement.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

미반영(기존 설계): 셀러 배너 소유권을 link_store_id/link_product_id로 판정하는 구조는 이 PR 이전부터이며, HOME_MAIN + linkType NONE/URL/CATEGORY 배너도 동일하게 셀러 목록에서 보이지 않음. SEARCH 지면은 CATEGORY/HOME_MAIN과 같은 운영 등록 전제(링크 없는 지면 배너는 운영이 등록). 배너 owner 컬럼 분리는 지면 배너 전반의 별도 과제로 기록.

@chanwoo7
chanwoo7 merged commit f3840a7 into develop Aug 30, 2026
11 checks passed
@chanwoo7
chanwoo7 deleted the feat/search-realtime-best-banner branch August 30, 2026 19:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant