Skip to content

chore: 릴리즈 — 매장 정렬·매장 선택(pickupStores) API - #533

Merged
chanwoo7 merged 4 commits into
mainfrom
develop
Oct 15, 2026
Merged

chanwoo7 merged 4 commits into
mainfrom
develop

Conversation

@chanwoo7

@chanwoo7 chanwoo7 commented Oct 15, 2026 •

Copy link
Copy Markdown
Member

검색 결과 매장 탭의 정렬과 홈 메인 검색 결과(매장 선택) 화면 API를 운영에 반영합니다.

  • feat: 매장 목록 정렬 공용화 · searchStores 정렬 추가 #531 매장 목록 정렬 공용화 · searchStores 정렬 추가
    • enum StoreSort { POPULAR, LATEST, BEST_SELLING }, "추천순"은 POPULAR(기본)
    • 인기순은 기존 산식, 판매순은 최근 30일 유효 주문 수량 합, 등록순은 created_at 내림차순, 동률은 id 내림차순
    • SearchStoresInput.sort는 선택 입력이라 기존 호출은 그대로 인기순
  • feat: 매장 선택(메인 검색 결과) pickupStores 쿼리 추가 #532 pickupStores 쿼리 추가
    • 입력: 날짜(필수)·시간(선택)·지역·정렬·offset/limit, 항목: 매장 카드 + 좌표(지도 마커)
    • 시간을 주면 그 슬롯이 정확히 예약 가능한 매장만, 지난 날짜는 PICKUP_DATE_PAST(400)
    • 오늘 픽업과 같은 판정 로직을 공용 서비스로 분리해 재사용(todayPickupStores 동작 불변)

운영 반영 사항입니다.

  • 마이그레이션 없음, 시크릿 변경 없음.
  • SDL은 추가만 있어 FE codegen이 그대로 통과합니다. FE 연동(pickupStores 호출, 정렬 옵션 정리)은 FE 쪽에서 진행합니다.

Summary by CodeRabbit

  • 신규 기능
    • 매장을 픽업 날짜와 시간, 지역에 따라 검색할 수 있습니다. 검색 결과에는 매장 정보와 좌표가 포함되며, 페이지 단위로 조회할 수 있습니다.
    • 매장 검색과 픽업 매장 목록의 정렬 기준으로 인기순, 최신순, 최근 30일 판매순을 선택할 수 있습니다.
  • 버그 수정
    • 과거 날짜의 픽업 조회 시 명확한 오류를 반환합니다.

검색 결과 매장 탭 시안에 '추천순 ▾' 정렬 시트(등록순·인기순·판매순)가 있는데 searchStores는 인기순 고정이었음. 메인 검색 결과(매장 선택) 화면도 같은 정렬을 쓰므로 정렬을 store 공용으로 둠.

- SDL: enum StoreSort { POPULAR, LATEST, BEST_SELLING } 추가, SearchStoresInput.sort(기본 POPULAR) 추가. '추천순' 라벨은 상품 검색과 같이 POPULAR로 해석
- StoreListingService.sortStores: 인기순은 기존 산식(scoreStores), 판매순은 최근 30일 유효 주문 수량 합(상품 검색 판매순과 같은 정의, 판매 0건도 뒤에 남김), 등록순은 created_at desc. 동률은 id desc
- 인기순만 카드 통계를 넘기고, 나머지는 buildCards 기본 집계에 맡김
- StoreRepository: 후보 select를 상수 1벌로 합치고 created_at 추가

테스트
- store-listing.service.spec: 정렬 3종·동률·30일 밖 판매 제외·통계 유무 4건
- store-search.service.spec: sort 지정·정렬 뒤 페이지 자르기, 생략·null이면 인기순 2건
- store-search-query.resolver.spec: sort 전달 1건
- 반증: 등록순·판매순 비교 방향을 뒤집으면 3건 실패
홈 메인 검색(지역·픽업 날짜·시간 → 검색하기) 결과인 매장 선택 화면에 맞는 API가 없어 FE가 todayPickupStores로 임시 연결 중이었음(오늘 외 날짜 미지원, 시간은 클라이언트 필터, 지도 마커 없음, 정렬 미전달).

- SDL: pickupStores(input: PickupStoresInput!): PickupStoreConnection!(비로그인 가능)
  - date 필수("YYYY-MM-DD" KST), time 선택("HH:mm"), regionIds, sort(StoreSort, 기본 인기순), offset/limit(≤50)
  - 항목은 StoreCard + latitude/longitude(지도 마커, 미설정 null). 슬롯은 싣지 않음(시안 카드에 없음)
- 시간 필터: 그 슬롯이 정확히 예약 가능한 매장만(영업시간·리드타임·capacity·휴무 반영). 생략·null이면 그날 슬롯이 하나라도 있는 매장
- 검증: 형식 오류 INVALID_DATE / INVALID_TIME_VALUE, 오늘보다 앞선 날짜는 신규 PICKUP_DATE_PAST(400). 정책 상한(MAX_DAYS_AHEAD 365일)을 넘으면 조회 없이 빈 결과
- StorePickupAvailabilityService.openSlotsOn: todayPickupStores에 있던 "후보 × 하루 → 예약 가능 매장" 판정(벌크 조회 4회 + evaluatePickupDay)을 날짜 인자로 분리. todayPickupStores도 이것을 오늘로 호출(동작 불변)
- 후보 select에 좌표 추가, toCoordinate를 store-detail 매퍼에서 export해 재사용

테스트
- store-pickup-stores.service.spec 20건: 날짜 판정(요일 휴무·미설정·다른 요일·특별휴무·capacity·max_days_ahead·리드타임·오늘), 시간 필터(정확 일치·격자 밖·리드타임 마감·생략/null), 입력 검증 표 9건, 정렬·지역·페이지·좌표
- store-pickup-stores-query.resolver.spec 2건(찜 여부·비로그인)
- 오늘 픽업 service·resolver spec은 provider만 추가하고 그대로 통과
- 반증: 시간 필터 제거·available 무시·과거 검사 제거·날짜 무시·좌표 제거·sort 무시 6가지 모두 실패로 잡힘
feat: 매장 목록 정렬 공용화 · searchStores 정렬 추가
feat: 매장 선택(메인 검색 결과) pickupStores 쿼리 추가
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-15T09:15:31.502235Z a10f5a2 PR opened
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@coderabbitai

coderabbitai Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: CaQuick/caquick-be/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 01c1fe06-d831-4d42-9794-ef20ac07a053
📥 Commits

Reviewing files that changed from the base of the PR and between b3fe44f and a10f5a2.

📒 Files selected for processing: 24
  • src/common/errors/error-catalog.ts
  • src/features/store/constants/store-sort.constants.ts
  • src/features/store/dto/inputs/pickup-stores.input.ts
  • src/features/store/dto/inputs/search-stores.input.ts
  • src/features/store/repositories/store.repository.ts
  • src/features/store/resolvers/store-pickup-stores-query.resolver.spec.ts
  • src/features/store/resolvers/store-pickup-stores-query.resolver.ts
  • src/features/store/resolvers/store-search-query.resolver.spec.ts
  • src/features/store/resolvers/store-today-pickup-query.resolver.spec.ts
  • src/features/store/services/store-detail-mappers.helper.ts
  • src/features/store/services/store-listing.service.spec.ts
  • src/features/store/services/store-listing.service.ts
  • src/features/store/services/store-pickup-availability.service.ts
  • src/features/store/services/store-pickup-stores.service.spec.ts
  • src/features/store/services/store-pickup-stores.service.ts
  • src/features/store/services/store-search.service.spec.ts
  • src/features/store/services/store-search.service.ts
  • src/features/store/services/store-today-pickup.service.spec.ts
  • src/features/store/services/store-today-pickup.service.ts
  • src/features/store/store-pickup-stores.graphql
  • src/features/store/store-search.graphql
  • src/features/store/store.module.ts
  • src/features/store/store.types.graphql
  • src/features/store/types/store-pickup-stores-output.type.ts

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

📝 Walkthrough

매장 검색에 인기순·최신순·판매량순 정렬을 추가했습니다. 날짜와 예약 가능 슬롯을 기준으로 매장을 조회하는 픽업 검색 GraphQL API도 추가했습니다. 오늘 픽업 서비스는 공통 슬롯 계산 서비스를 사용합니다.

Changes: 매장 검색 및 픽업

Layer / File(s) Summary
정렬 기준과 매장 검색 적용
src/features/store/constants/*, src/features/store/dto/inputs/search-stores.input.ts, src/features/store/store.types.graphql, src/features/store/store-search.graphql, src/features/store/repositories/store.repository.ts, src/features/store/services/store-listing.service.ts, src/features/store/services/store-search.service.ts, src/features/store/services/*spec.ts, src/features/store/resolvers/store-search-query.resolver.spec.ts
POPULAR, LATEST, BEST_SELLING 정렬 기준을 정의했습니다. 매장 목록과 검색은 정렬 후 페이지화하며, 정렬별 조회 결과와 카드 통계 검증을 추가했습니다.
픽업 가능 슬롯 계산과 오늘 픽업 연동
src/features/store/services/store-pickup-availability.service.ts, src/features/store/services/store-today-pickup.service.ts, src/features/store/services/store-today-pickup.service.spec.ts, src/features/store/resolvers/store-today-pickup-query.resolver.spec.ts
공통 서비스가 영업시간, 특별휴무, 수용량, 예약 수를 기준으로 픽업 가능 슬롯을 계산합니다. 오늘 픽업 서비스는 반환된 슬롯이 있는 매장만 사용합니다.
픽업 매장 검색 API
src/common/errors/error-catalog.ts, src/features/store/dto/inputs/pickup-stores.input.ts, src/features/store/store-pickup-stores.graphql, src/features/store/types/store-pickup-stores-output.type.ts, src/features/store/resolvers/store-pickup-stores-query.resolver.ts, src/features/store/services/store-pickup-stores.service.ts, src/features/store/store.module.ts, src/features/store/services/store-detail-mappers.helper.ts, src/features/store/services/store-pickup-stores.service.spec.ts, src/features/store/resolvers/store-pickup-stores-query.resolver.spec.ts
pickupStores 쿼리와 입력·응답 타입을 추가했습니다. 서비스는 날짜와 시간을 검증하고, 슬롯·지역·정렬 조건으로 매장을 필터링해 좌표와 페이지 정보를 반환합니다. 로그인 사용자의 찜 여부와 비로그인 기본값을 검증합니다.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant GraphQLClient
  participant StorePickupStoresQueryResolver
  participant StorePickupStoresService
  participant StorePickupAvailabilityService
  participant Prisma
  GraphQLClient->>StorePickupStoresQueryResolver: pickupStores(input, user)
  StorePickupStoresQueryResolver->>StorePickupStoresService: pickupStores(input, accountId)
  StorePickupStoresService->>Prisma: 활성 매장 조회
  StorePickupStoresService->>StorePickupAvailabilityService: openSlotsOn(stores, day, now)
  StorePickupAvailabilityService->>Prisma: 영업시간, 휴무, 수용량, 예약 수 조회
  StorePickupAvailabilityService-->>StorePickupStoresService: 매장별 슬롯 맵
  StorePickupStoresService-->>StorePickupStoresQueryResolver: 페이지화된 매장 연결
  StorePickupStoresQueryResolver-->>GraphQLClient: 픽업 매장 결과
Loading
Merge Risk: ⚪ Minimal · up to a10f5

The pickup date is handled consistently across validation and slot lookup. No merge-blocking issue was established; the PR is ready for normal checks.

Pre-merge checks: Passed 3 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 9 functions across 21 files. (3 skipped: 3… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 3 passed
Check name Status Explanation
Title check Passed 제목은 매장 정렬 기능과 pickupStores API 추가라는 주요 변경 내용을 간결하게 설명합니다.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 9 functions across 21 files. (3 skipped: 3 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

🩺 NestJS Doctor — 90/100 (Excellent)

진단 486건 (error 12).

Category error warning info
architecture 1 1 44
correctness 0 268 0
performance 0 36 28
schema 0 0 76
security 11 21 0
architecture / security 상위 항목
  • error architecture/architecture/no-manual-instantiation: Manual instantiation of 'OutboxRepository' detected. Use dependency injection instead.
  • 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.
  • warning security/security/require-guards-on-endpoints: Endpoint 'adminLogin' has no @UseGuards() at class or method level.
  • warning security/security/require-guards-on-endpoints: Endpoint 'adminRefresh' has no @UseGuards() at class or method level.
  • warning security/security/require-guards-on-endpoints: Endpoint 'adminLogout' has no @UseGuards() at class or method level.
  • warning security/security/require-guards-on-endpoints: Endpoint 'getJwks' has no @UseGuards() at class or method level.

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

@github-actions

Copy link
Copy Markdown

🧹 knip — dead-code 리포트

Unused exported types (1)
전체 리포트
Unused exported types (1)
RateLimitPolicy  type  src/global/rate-limit/index.ts:4:8

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

@codecov

codecov Bot commented Oct 15, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.45763% with 3 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...c/features/store/services/store-listing.service.ts 78.57% 0 Missing and 3 partials ⚠️

📢 Thoughts on this report? Let us know!

@github-actions

Copy link
Copy Markdown

Coverage report

St.❔
Category Percentage Covered / Total
🟢 Statements
98.02% (+0.02% 🔼)
10791/11009
🟢 Branches
92.95% (+0.03% 🔼)
4112/4424
🟢 Functions
97.55% (+0.02% 🔼)
2150/2204
🟢 Lines
98.59% (+0.02% 🔼)
9818/9958
Show new covered files 🐣
St.❔
File Statements Branches Functions Lines
🟢
... / store-pickup-stores-query.resolver.ts
100% 100% 100% 100%
🟢
... / pickup-stores.input.ts
100% 100% 100% 100%
🟢
... / store-sort.constants.ts
100% 100% 100% 100%
🟢
... / store-pickup-stores.service.ts
100% 100% 100% 100%
🟢
... / store-pickup-availability.service.ts
100% 100% 100% 100%
Show files with reduced coverage 🔻
St.❔
File Statements Branches Functions Lines
🟢
... / store-listing.service.ts
98.31% (-1.69% 🔻)
88% (-12% 🔻)
100% 100%

Test suite run success

4292 tests passing in 386 suites.

Report generated by 🧪jest coverage report action from a10f5a2

@chanwoo7
chanwoo7 merged commit 4afb407 into main Oct 15, 2026
27 checks passed
@chanwoo7
chanwoo7 deleted the develop branch October 15, 2026 09:16
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