Skip to content

feat: 기사 반려 내역 조회 API - #62

Merged
soooob43 merged 12 commits into
devfrom
feature/received-estimate-requests
Jul 30, 2026
Merged

feat: 기사 반려 내역 조회 API#62
soooob43 merged 12 commits into
devfrom
feature/received-estimate-requests

Conversation

@soooob43

@soooob43 soooob43 commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

📌 작업 내용

기사님이 본인이 반려한 견적 요청 내역을 조회할 수 있도록 API 구현 완료했습니다.

✅ 변경 사항

  • 기사 반려 내역 조회 API 추가GET /api/estimates/rejections
  • 로그인한 기사 본인의 반려 내역만 조회
  • 기사 권한(MOVER) 인증 및 인가 적용
  • 반려 사유 및 원본 견적 요청 정보 반환고객 정보
    이사 유형 및 이사 날짜
    출발지·도착지 주소와 지역
    지정 견적 여부
    반려 사유 및 반려 일시
  • 프론트 반려 요청 페이지와 API 연동

🧪 테스트

  • 서버 실행 확인
  • API 동작 확인
  • DB 연동 확인
  • 로그 확인
  • 기타:

테스트 방법

  1. GET http://localhost:5000/api/estimates/requests?limit=10 조회 후 아이디 하나 선택
  2. POST {{baseUrl}}/api/estimates/requests/{{requestId}}/reject
    ** body 안에는 {
    "reason": "해당 날짜에는 기존 예약이 있어 이사 진행이 어렵습니다."
    }
  3. GET {{baseUrl}}/api/estimates/rejections 로 요청 보내서 확인
    응답 데이터
    {
    "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
    }
    }

📷 스크린샷 (선택)

image image

🔥 체크리스트

  • 코드 컨벤션을 준수했습니다.
  • 불필요한 console.log를 제거했습니다.
  • ESLint 오류가 없습니다.
  • 변경 사항을 직접 테스트했습니다.
  • 관련 문서를 업데이트했습니다. (필요 시)

🙏 To Reviewer

Summary by CodeRabbit

  • 새로운 기능
    • 기사가 기사 견적 반려 내역을 조회할 수 있는 GET /rejections를 추가했습니다.
    • 반려 사유/반려 시각과 함께 관련 이사 요청 정보(주소·지역·이사 유형 등) 및 지정 여부를 제공합니다.
    • 최신 순으로 제공되며 cursor/limit 기반 페이징을 지원합니다.
  • 개선 사항
    • 고객 확정 처리 시 moveDate가 반영되고, ESTIMATE_CONFIRMED 알림 생성이 추가되었습니다.

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

기사의 견적 반려 기록을 GET /rejections로 조회하는 기능을 추가했습니다. 쿼리 검증, 커서 페이지네이션, 반려 기록과 연결된 견적 요청 정보 매핑, MOVER 인증·인가를 적용합니다.

Changes

견적 반려 내역 조회

Layer / File(s) Summary
반려 내역 계약과 페이지네이션
src/modules/estimate/estimate.validator.ts, src/modules/estimate/estimate.type.ts, src/modules/estimate/estimate.repository.ts
cursorlimit 검증, 반려 목록 응답 타입, 관련 견적 요청 정보 조회 및 커서 페이지네이션을 추가합니다.
반려 내역 응답 매핑
src/modules/estimate/estimate.service.ts
반려 메타데이터와 견적 요청 정보를 응답 형태로 변환하고 hasNextPage, nextCursor를 반환합니다.
인증 API 연결
src/modules/estimate/estimate.route.ts, src/modules/estimate/estimate.controller.ts
MOVER 인증·인가와 쿼리 검증을 거친 GET /rejections 요청을 서비스에 연결하고 성공 응답을 반환합니다.

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 응답
Loading

Possibly related PRs

Suggested labels: 🏢코드리뷰

Suggested reviewers: obebe-creator

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed PR의 핵심 변경인 기사 반려 내역 조회 API 추가를 짧고 명확하게 요약합니다.
Description check ✅ Passed 필수 섹션인 작업 내용, 변경 사항, 테스트, 스크린샷, 체크리스트, To Reviewer를 대부분 채워 템플릿 요건을 충족합니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/received-estimate-requests

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

@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: 1

🧹 Nitpick comments (1)
src/modules/estimate/estimate.repository.ts (1)

404-405: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

repository에 DbClient 기본 인자를 추가해 주세요.

현재 findRejectionsprisma를 직접 참조해 트랜잭션 클라이언트를 전달할 수 없습니다. 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

📥 Commits

Reviewing files that changed from the base of the PR and between 3629c54 and bedab92.

📒 Files selected for processing (4)
  • src/modules/estimate/estimate.controller.ts
  • src/modules/estimate/estimate.repository.ts
  • src/modules/estimate/estimate.route.ts
  • src/modules/estimate/estimate.service.ts

Comment thread src/modules/estimate/estimate.repository.ts Outdated

@Obebe-creator Obebe-creator left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

코드 위주로 확인했습니다.

기사 견적 반려 내역 조회 API를 estimate 모듈 안에 추가한 방향은 기존 “기사 견적 요청/제안/반려” 흐름과 잘 맞아 보입니다. 컨트롤러에서 인증된 moverId를 사용하고, service에서 응답 형태를 가공하는 구조도 기존 코드 흐름과 유사합니다.

인라인 코멘트로는 남기지 않았던 부분이지만 반려 내역 조회 범위를 moverId만으로 둘지, 비활성/삭제성 데이터나 고객 상태까지 고려할지 기준 확인이 필요해 보입니다. 추가로 repository의 db: DbClient = prisma 패턴과 응답 타입 분리 여부는 팀 컨벤션 차원에서 검토 부탁드립니다. お疲れ様です🙇‍♂️


//기사 견적 반려 내역 조회
findRejections(moverId: string) {
return prisma.estimateRequestRejection.findMany({

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

컨벤션 확인 제안입니다.

같은 estimate.repository.ts 안에서도 트랜잭션 재사용 가능성이 있는 메서드들은 db: DbClient = prisma 형태로 받고 있는 것으로 보입니다.

이번 findRejections는 단순 조회라 트랜잭션 안에서 호출될 가능성은 낮아 보이지만, 새로 추가되는 repository 메서드라면 팀 컨벤션에 맞춰 아래처럼 기본 인자 패턴을 적용해도 좋을 것 같습니다.

findRejections(moverId: string, db: DbClient = prisma) {
  return db.estimateRequestRejection.findMany(...)
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

확인 제안입니다.

getRejections가 새 API 응답 형태를 직접 구성하고 있어서, estimate.type.ts에 반려 내역 응답 타입을 정의해두면 컨트롤러/서비스 응답 계약을 추적하기 더 쉬울 것 같습니다.

기존 견적 요청 목록 쪽은 MoverEstimateRequestListItem, MoverEstimateRequestListResult처럼 타입을 분리해두고 있어서, 반려 내역도 MoverEstimateRejectionListItem 같은 타입을 두면 FE와 맞춰볼 때 필드 변경을 관리하기 좋아 보입니다.

@soooob43 soooob43 Jul 30, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

기존 MoverEstimateRequestListItem, MoverEstimateRequestListResult 패턴과 동일하게 반려 내역의 item/result 타입을 estimate.type.ts에 분리 완료했습니다. 서비스 반환 타입과 매핑 결과에도 적용했으며, 이번에 추가한 cursor 페이지네이션 응답도 함께 포함하는 식으로 수정 완료했습니다.

Comment thread src/modules/estimate/estimate.route.ts Outdated
"/rejections",
authenticate,
authorize("MOVER"),
estimateController.getRejections,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

라우터에서 asyncHandler로 감싼 핸들러와 컨트롤러 내부 try-catch로 처리한 핸들러가 섞여 있어, 한 방식으로 통일하면 좋을 것 같습니다.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

앗 넵 확인 감사합니다. 신규 반려 내역 조회 핸들러는 컨트롤러 내부 try-catch를 제거하고 라우터에서 asyncHandler로 감싸는 방식으로 수정 완료했습니다!

@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: 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, 목록 조회는 findManycountPromise.all로 함께 호출해야 합니다.

  • src/modules/estimate/estimate.repository.ts#L408-L453: findMany와 동일한 where 조건의 countPromise.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

📥 Commits

Reviewing files that changed from the base of the PR and between bedab92 and bb71ad1.

📒 Files selected for processing (6)
  • src/modules/estimate/estimate.controller.ts
  • src/modules/estimate/estimate.repository.ts
  • src/modules/estimate/estimate.route.ts
  • src/modules/estimate/estimate.service.ts
  • src/modules/estimate/estimate.type.ts
  • src/modules/estimate/estimate.validator.ts

Comment thread src/modules/estimate/estimate.controller.ts
Comment thread src/modules/estimate/estimate.validator.ts

@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: 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

📥 Commits

Reviewing files that changed from the base of the PR and between bb71ad1 and 00fa6d6.

📒 Files selected for processing (1)
  • src/modules/estimate/estimate.validator.ts

Comment thread src/modules/estimate/estimate.validator.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants