Skip to content

refactor(store): 픽업 가능 판정 정책 단일화 (evaluatePickupDay) - #220

Merged
chanwoo7 merged 2 commits into
developfrom
refactor/store-pickup-policy
Aug 27, 2026
Merged

refactor(store): 픽업 가능 판정 정책 단일화 (evaluatePickupDay)#220
chanwoo7 merged 2 commits into
developfrom
refactor/store-pickup-policy

Conversation

@chanwoo7

@chanwoo7 chanwoo7 commented Aug 27, 2026

Copy link
Copy Markdown
Member

무엇을 왜

매장의 픽업 가능 여부를 판정하는 규칙 — 특별휴무, 요일 영업시간, 일일 capacity 소진, 리드타임 컷오프 — 이 두 서비스에 따로 구현되어 있었습니다. 오늘 픽업 리스트(store-today-pickup.service)와 상품 상세의 달력/시간 슬롯(store-pickup-schedule.service)이 슬롯 생성 헬퍼만 공유하고 판정 분기는 각자 들고 있는 구조라, 규칙이 바뀔 때 한쪽만 고치면 두 화면이 조용히 어긋납니다. 주문 생성이 isPickupSlotAvailable로 세 번째 소비자가 된 지금은 더 미룰 이유가 없어서 판정을 단일 소스로 추출했습니다(#206).

어떻게

새 파일 store-pickup-policy.helper.ts 하나에 판정을 모았습니다. evaluatePickupDay가 하루치 판정(선택 불가 사유 + 슬롯)을 돌려주는 순수 함수이고, 시각은 호출부가 ClockService로 주입하므로 DI 없이 동작합니다. 판정 순서는 기존 evaluateDay의 것을 로직 변경 없이 그대로 옮겼습니다: 과거 → 범위 초과 → 특별휴무 → 요일 휴무/미설정 → capacity 소진 → 잔여 가용 슬롯 없음.

두 서비스는 이 함수의 소비자로 재배선했습니다. pickup-schedule 쪽에는 벌크 조회 결과를 정책 입력으로 바꾸는 어댑터만 남았고, 시간 슬롯 API와 주문 재검증이 판정과 슬롯 계산을 따로 하던 이중 계산도 함께 사라졌습니다. today-pickup 쪽은 매장 루프의 인라인 분기 4개를 정책 호출 하나로 바꿨는데, '오늘'은 과거/범위초과 검사가 항상 통과하므로 결과가 달라지지 않습니다. 정책 입력에 필요한 max_days_ahead를 랭킹 후보 row에 추가한 것이 repository의 유일한 변경입니다.

첫 커밋은 이 작업과 무관합니다 — 오전에 올라간 prettier 3.9(#219)가 유니언 타입 개행 규칙을 바꿔서 기존 파일 8개에 포맷 diff가 생겼고, 리팩토링 diff와 섞이지 않게 커밋을 분리해 뒀습니다.

검증

이 PR의 합격 기준은 "기존 spec을 한 글자도 안 고치고 통과"입니다. today-pickup · pickup-schedule · 슬롯 헬퍼 spec 3종이 무변경으로 green이면 동작 보존이 증명되는 구조인데, 그대로 통과했습니다. 여기에 정책 함수 자체의 단위 spec 11케이스를 새로 붙였습니다 — 판정 순서 고정, capacity 경계(정확히 소진 vs 1 미달), max_days_ahead 경계일, 리드타임의 초 단위 올림, 미래 날짜 컷오프. yarn validate 전체 green입니다(191 suites / 1,647 tests).

Closes #206

의존성 업데이트(PR #219)로 prettier가 3.8 → 3.9로 올라가며
유니언 타입 개행 규칙이 바뀌었다. lint --fix 산출물만 반영한 커밋으로,
코드 변경은 없다.

Claude-Session: https://claude.ai/code/session_01KfiGgWooJdsa4iPQPmqvBj
이슈 #206: 매장 픽업 가능 판정 규칙(특별휴무·요일 영업시간·일일 capacity
소진·리드타임 컷오프)이 store-today-pickup.service와
store-pickup-schedule.service에 각각 구현되어 있어, 규칙 불일치(한쪽만
수정) 버그 가능성이 있었다. 주문 생성(createOrder)은 이미
isPickupSlotAvailable을 경유하므로 남은 중복은 이 두 곳이었다.

- store-pickup-policy.helper.ts 신설: DI-free 순수 함수 evaluatePickupDay/
  buildPickupDaySlots로 판정 단일 소스화. 판정 순서(과거 → 범위 초과 →
  특별휴무 → 요일 휴무/미설정 → capacity → 잔여 슬롯 없음)는 기존
  evaluateDay와 동일하게 이관.
- pickup-schedule.service: private evaluateDay/buildDaySlots 제거,
  벌크 컨텍스트 → 정책 입력 변환(pickupDayInput)만 남김. 시간 슬롯과
  주문 재검증은 정책 결과 슬롯을 재사용해 이중 계산 제거.
- today-pickup.service: 매장 루프의 인라인 4분기 → 정책 호출로 대체.
  '오늘'은 PAST/OUT_OF_RANGE가 항상 통과라 동작 동일.
- store.repository: 랭킹 후보 row에 max_days_ahead 추가(정책 입력 충족용).

회귀: 기존 spec 3종(today-pickup.service·pickup-schedule.service·
today-pickup.helper) 무변경 통과. 신규 store-pickup-policy.helper.spec
11케이스(판정 순서·capacity/리드타임/max_days_ahead 경계·미래 날짜 컷오프).
전체 validate green (191 suites / 1,647 tests).

Claude-Session: https://claude.ai/code/session_01KfiGgWooJdsa4iPQPmqvBj
@coderabbitai

coderabbitai Bot commented Aug 27, 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: 38bb4d10-40f4-4f5b-a30d-74fda316b919

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 리포트

Unused exports (2)
전체 리포트
Unused exports (2)
RegionRepository  src/features/region/index.ts:3:10
StoreRepository   src/features/store/index.ts:3:10

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

@github-actions

Copy link
Copy Markdown

🩺 NestJS Doctor — 89/100 (Good)

진단 283건 (error 0).

Category error warning info
architecture 0 0 13
correctness 0 130 0
performance 0 24 17
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

@codecov

codecov Bot commented Aug 27, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@github-actions

Copy link
Copy Markdown

Coverage report

St.
Category Percentage Covered / Total
🟢 Statements 97.66% 5011/5131
🟢 Branches 93.96% 2037/2168
🟢 Functions 96.22% 968/1006
🟢 Lines 98.21% 4562/4645

Test suite run success

1647 tests passing in 191 suites.

Report generated by 🧪jest coverage report action from eafa963

@chanwoo7
chanwoo7 merged commit 2263b28 into develop Aug 27, 2026
12 checks passed
@chanwoo7
chanwoo7 deleted the refactor/store-pickup-policy branch August 27, 2026 13:56
chanwoo7 added a commit that referenced this pull request Aug 27, 2026
refactor(store): 픽업 가능 판정 정책 단일화 (evaluatePickupDay)
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