feat: 기사 반려 내역 조회 API - #62
Conversation
…into feature/received-estimate-requests
…into feature/received-estimate-requests
…into feature/received-estimate-requests
📝 WalkthroughWalkthrough기사의 견적 반려 기록을 Changes견적 반려 내역 조회
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant MOVER
participant estimateRouter
participant estimateController
participant moverEstimateRequestService
participant moverEstimateRequestRepository
MOVER->>estimateRouter: GET /rejections?cursor&limit
estimateRouter->>estimateController: 인증, MOVER 인가, 쿼리 검증 후 getRejections
estimateRouter->>estimateController: asyncHandler로 비동기 오류 전달
estimateController->>moverEstimateRequestService: getRejections(moverId, query)
moverEstimateRequestService->>moverEstimateRequestRepository: findRejections(moverId, query)
moverEstimateRequestRepository-->>moverEstimateRequestService: 반려 내역과 견적 요청 정보
moverEstimateRequestService-->>estimateController: items와 pagination
estimateController-->>MOVER: 200 success/data 응답
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/modules/estimate/estimate.repository.ts (1)
404-405: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winrepository에
DbClient기본 인자를 추가해 주세요.현재
findRejections가prisma를 직접 참조해 트랜잭션 클라이언트를 전달할 수 없습니다.createEstimateRejection과 동일하게db: DbClient = prisma를 받고db.estimateRequestRejection.findMany(...)를 사용해 주세요.As per path instructions, repository는 트랜잭션 클라이언트를 받을 수 있도록
db: DbClient = prisma기본 인자를 유지해야 합니다.수정 예시
- findRejections(moverId: string) { - return prisma.estimateRequestRejection.findMany({ + findRejections(moverId: string, db: DbClient = prisma) { + return db.estimateRequestRejection.findMany({🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/modules/estimate/estimate.repository.ts` around lines 404 - 405, Update findRejections to accept db: DbClient = prisma, matching createEstimateRejection, and use db.estimateRequestRejection.findMany instead of the direct prisma reference so transaction clients can be passed.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/modules/estimate/estimate.repository.ts`:
- Around line 404-442: Update findRejections and its validator-to-service call
chain to accept pagination parameters, apply skip and take to the rejection
findMany query, and run the matching count query in parallel with Promise.all.
Return the paged records together with total/page metadata, preserving the
existing filters, selected fields, and ordering.
---
Nitpick comments:
In `@src/modules/estimate/estimate.repository.ts`:
- Around line 404-405: Update findRejections to accept db: DbClient = prisma,
matching createEstimateRejection, and use db.estimateRequestRejection.findMany
instead of the direct prisma reference so transaction clients can be passed.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: af3fc072-ceec-4972-a34d-66db85bc88e0
📒 Files selected for processing (4)
src/modules/estimate/estimate.controller.tssrc/modules/estimate/estimate.repository.tssrc/modules/estimate/estimate.route.tssrc/modules/estimate/estimate.service.ts
Obebe-creator
left a comment
There was a problem hiding this comment.
코드 위주로 확인했습니다.
기사 견적 반려 내역 조회 API를 estimate 모듈 안에 추가한 방향은 기존 “기사 견적 요청/제안/반려” 흐름과 잘 맞아 보입니다. 컨트롤러에서 인증된 moverId를 사용하고, service에서 응답 형태를 가공하는 구조도 기존 코드 흐름과 유사합니다.
인라인 코멘트로는 남기지 않았던 부분이지만 반려 내역 조회 범위를 moverId만으로 둘지, 비활성/삭제성 데이터나 고객 상태까지 고려할지 기준 확인이 필요해 보입니다. 추가로 repository의 db: DbClient = prisma 패턴과 응답 타입 분리 여부는 팀 컨벤션 차원에서 검토 부탁드립니다. お疲れ様です🙇♂️
|
|
||
| //기사 견적 반려 내역 조회 | ||
| findRejections(moverId: string) { | ||
| return prisma.estimateRequestRejection.findMany({ |
There was a problem hiding this comment.
컨벤션 확인 제안입니다.
같은 estimate.repository.ts 안에서도 트랜잭션 재사용 가능성이 있는 메서드들은 db: DbClient = prisma 형태로 받고 있는 것으로 보입니다.
이번 findRejections는 단순 조회라 트랜잭션 안에서 호출될 가능성은 낮아 보이지만, 새로 추가되는 repository 메서드라면 팀 컨벤션에 맞춰 아래처럼 기본 인자 패턴을 적용해도 좋을 것 같습니다.
findRejections(moverId: string, db: DbClient = prisma) {
return db.estimateRequestRejection.findMany(...)
}There was a problem hiding this comment.
findRejections(
moverId: string,
query: MoverEstimateRejectionListQuery,
db: DbClient = prisma,
) {
return db.estimateRequestRejection.findMany({
// ...
});
}
앗 확인 감사합니다. estimate repository의 기존 컨벤션에 맞춰 db: DbClient = prisma 기본 인자 패턴 적용하고, 직접 prisma를 참조하던 부분도 전달받은 db를 사용하도록 수정했습니다!
| - 2026.07.30 add 윤소정 | ||
| 기사 견적 반려 내역 조회 | ||
| */ | ||
| async getRejections(moverId: string) { |
There was a problem hiding this comment.
확인 제안입니다.
getRejections가 새 API 응답 형태를 직접 구성하고 있어서, estimate.type.ts에 반려 내역 응답 타입을 정의해두면 컨트롤러/서비스 응답 계약을 추적하기 더 쉬울 것 같습니다.
기존 견적 요청 목록 쪽은 MoverEstimateRequestListItem, MoverEstimateRequestListResult처럼 타입을 분리해두고 있어서, 반려 내역도 MoverEstimateRejectionListItem 같은 타입을 두면 FE와 맞춰볼 때 필드 변경을 관리하기 좋아 보입니다.
There was a problem hiding this comment.
기존 MoverEstimateRequestListItem, MoverEstimateRequestListResult 패턴과 동일하게 반려 내역의 item/result 타입을 estimate.type.ts에 분리 완료했습니다. 서비스 반환 타입과 매핑 결과에도 적용했으며, 이번에 추가한 cursor 페이지네이션 응답도 함께 포함하는 식으로 수정 완료했습니다.
| "/rejections", | ||
| authenticate, | ||
| authorize("MOVER"), | ||
| estimateController.getRejections, |
There was a problem hiding this comment.
라우터에서 asyncHandler로 감싼 핸들러와 컨트롤러 내부 try-catch로 처리한 핸들러가 섞여 있어, 한 방식으로 통일하면 좋을 것 같습니다.
There was a problem hiding this comment.
앗 넵 확인 감사합니다. 신규 반려 내역 조회 핸들러는 컨트롤러 내부 try-catch를 제거하고 라우터에서 asyncHandler로 감싸는 방식으로 수정 완료했습니다!
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/modules/estimate/estimate.repository.ts (1)
408-453: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win반려 목록의 전체 건수 계약을 복원하세요.
커서 조회는 적용됐지만
count를 병렬 조회하지 않아 API가 전체 건수를 반환할 수 없습니다. As per path instructions, 목록 조회는findMany와count를Promise.all로 함께 호출해야 합니다.
src/modules/estimate/estimate.repository.ts#L408-L453:findMany와 동일한where조건의count를Promise.all로 실행하고 함께 반환하세요.src/modules/estimate/estimate.service.ts#L169-L195: repository의totalCount를 받아pagination에 전달하세요.src/modules/estimate/estimate.type.ts#L139-L145:pagination.totalCount: number를 추가하세요.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/modules/estimate/estimate.repository.ts` around lines 408 - 453, Restore the rejection-list total count contract: in src/modules/estimate/estimate.repository.ts lines 408-453, update findRejections to run findMany and a count with the same moverId where condition via Promise.all and return both results; in src/modules/estimate/estimate.service.ts lines 169-195, consume the repository totalCount and pass it into pagination; in src/modules/estimate/estimate.type.ts lines 139-145, add pagination.totalCount as a required number.Source: Path instructions
src/modules/estimate/estimate.service.ts (1)
780-787: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift확정과 알림 레코드를 같은 원자성 경계로 묶어야 합니다. 지금은 트랜잭션 커밋 후 알림 저장이 실행돼, 알림 생성만 실패해도 견적 확정은 반영된 채 API가 에러로 끝납니다. 재시도해도 이미 확정 상태라
CONFLICT만 반복되므로, 알림 생성도 같은 트랜잭션에 넣거나 outbox로 분리해 주세요.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/modules/estimate/estimate.service.ts` around lines 780 - 787, Update the estimate confirmation flow around notificationService.createNotification so estimate confirmation and notification persistence share the same atomicity boundary. Move notification creation into the existing transaction, or enqueue it through an outbox within that transaction, ensuring notification failure rolls back confirmation and retries do not leave a confirmed estimate without its notification.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/modules/estimate/estimate.controller.ts`:
- Around line 67-75: Update the getRejections request handler to accept next,
wrap its service call and response logic in try/catch, and pass caught errors to
next(error), matching the existing getList handler pattern.
In `@src/modules/estimate/estimate.validator.ts`:
- Around line 69-72: Update moverEstimateRejectionListQuerySchema so the cursor
and limit validations provide Korean error messages instead of Zod’s default
English messages. Add messages to the cursor regex and limit coercion, integer,
positive, and maximum validations while preserving the existing optional/default
behavior and constraints.
---
Outside diff comments:
In `@src/modules/estimate/estimate.repository.ts`:
- Around line 408-453: Restore the rejection-list total count contract: in
src/modules/estimate/estimate.repository.ts lines 408-453, update findRejections
to run findMany and a count with the same moverId where condition via
Promise.all and return both results; in src/modules/estimate/estimate.service.ts
lines 169-195, consume the repository totalCount and pass it into pagination; in
src/modules/estimate/estimate.type.ts lines 139-145, add pagination.totalCount
as a required number.
In `@src/modules/estimate/estimate.service.ts`:
- Around line 780-787: Update the estimate confirmation flow around
notificationService.createNotification so estimate confirmation and notification
persistence share the same atomicity boundary. Move notification creation into
the existing transaction, or enqueue it through an outbox within that
transaction, ensuring notification failure rolls back confirmation and retries
do not leave a confirmed estimate without its notification.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 0f51f9f1-097d-4e7c-8fa0-3e5e59e1f891
📒 Files selected for processing (6)
src/modules/estimate/estimate.controller.tssrc/modules/estimate/estimate.repository.tssrc/modules/estimate/estimate.route.tssrc/modules/estimate/estimate.service.tssrc/modules/estimate/estimate.type.tssrc/modules/estimate/estimate.validator.ts
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/modules/estimate/estimate.validator.ts`:
- Line 71: Update the cursor validation rule in the estimate validator so the
optional cursor accepts only positive integers and rejects 0, using the existing
Korean error message. Keep validation handled through the current Zod schema and
preserve acceptance of valid values beginning with 1–9.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 1d9856e1-3986-4782-a1fd-b2fdb5e585a9
📒 Files selected for processing (1)
src/modules/estimate/estimate.validator.ts
📌 작업 내용
기사님이 본인이 반려한 견적 요청 내역을 조회할 수 있도록 API 구현 완료했습니다.
✅ 변경 사항
이사 유형 및 이사 날짜
출발지·도착지 주소와 지역
지정 견적 여부
반려 사유 및 반려 일시
🧪 테스트
테스트 방법
** body 안에는 {
"reason": "해당 날짜에는 기존 예약이 있어 이사 진행이 어렵습니다."
}
응답 데이터
{
"id": 1,
"reason": "반려 사유",
"rejectedAt": "2026-07-30T04:00:00.000Z",
"request": {
"id": 213,
"customer": {
"id": "customer-id",
"name": "조고객"
},
"moveType": "HOME",
"moveDate": "2026-07-30T00:00:00.000Z",
"fromAddress": "출발지 주소",
"toAddress": "도착지 주소",
"fromRegion": "경기",
"toRegion": "경기",
"isDesignated": true
}
}
📷 스크린샷 (선택)
🔥 체크리스트
🙏 To Reviewer
Summary by CodeRabbit
GET /rejections를 추가했습니다.moveDate가 반영되고,ESTIMATE_CONFIRMED알림 생성이 추가되었습니다.