Skip to content

[FEAT] 푸드트럭 메뉴 수정/삭제 API 구현#43

Merged
ksg1227 merged 5 commits into
developfrom
feat/#42-foodtruck-menu-update-delete
Oct 15, 2025
Merged

[FEAT] 푸드트럭 메뉴 수정/삭제 API 구현#43
ksg1227 merged 5 commits into
developfrom
feat/#42-foodtruck-menu-update-delete

Conversation

@ksg1227

@ksg1227 ksg1227 commented Oct 10, 2025

Copy link
Copy Markdown
Contributor

#️⃣연관된 이슈

closes #42

📝작업 내용

푸드트럭 메뉴 수정/삭제 기능을 구현하였습니다.

푸드트럭 메뉴 수정의 경우, 푸드트럭 메뉴 등록과 같이 메뉴의 이름, 이미지 url, 가격, 설명 등을 입력받고 그것들을 기반으로 푸드트럭의 정보를 업데이트 하는 형식인 것으로 확인되었습니다.
따라서 Put 메서드를 사용하도록 구현하였습니다.

푸드트럭 메뉴 삭제의 경우 푸드트럭 메뉴가 삭제될 때 S3에 존재하는 메뉴의 이미지까지 삭제될 수 있도록 CdnUrlResolver, S3Service 를 주입하여 메뉴 삭제시 S3에서 이미지도 동시에 삭제되도록 구현하였습니다.

스크린샷 (선택)

💬리뷰 요구사항(선택)

Summary by CodeRabbit

  • 신규 기능
    • 사장님 전용 메뉴 수정/삭제 엔드포인트 추가: PUT/DELETE /me/food-trucks/{foodTruckId}/menus/{menuId}
    • 메뉴의 이름, 설명, 가격, 사진 URL을 유효성 검증과 함께 업데이트 가능
  • 문서화
    • Swagger에 메뉴 수정/삭제 API 및 오류 케이스(사용자 없음, 권한 없음, 미승인 푸드트럭, 메뉴 없음) 추가하여 가이드와 응답 예측 가능성 개선

@ksg1227 ksg1227 self-assigned this Oct 10, 2025
@ksg1227 ksg1227 linked an issue Oct 10, 2025 that may be closed by this pull request
2 tasks
@ksg1227 ksg1227 requested a review from buzz0331 October 10, 2025 16:10
@coderabbitai

coderabbitai Bot commented Oct 10, 2025

Copy link
Copy Markdown

Walkthrough

푸드트럭 메뉴 수정/삭제 기능이 추가되었습니다. 도메인(Menu)에 업데이트 메서드가 생기고, OwnerController/OwnerService/MyFoodTruckMenuService에 수정/삭제 흐름이 추가되었습니다. 요청 DTO(UpdateMenuRequest)와 Swagger 응답 설명 항목이 신규로 포함되었습니다. 삭제 시 S3 이미지 삭제 처리도 포함됩니다.

Changes

Cohort / File(s) Summary
Owner 메뉴 관리 API 추가
src/main/java/konkuk/chacall/domain/owner/presentation/OwnerController.java, src/main/java/konkuk/chacall/domain/owner/application/OwnerService.java
소유주 인증 후 메뉴 수정(PUT)·삭제(DELETE) 엔드포인트 및 서비스 메서드 추가(@transactional).
내 푸드트럭 메뉴 서비스 확장
src/main/java/konkuk/chacall/domain/owner/application/myfoodtruckmenu/MyFoodTruckMenuService.java
메뉴 update/delete 로직 추가. 소유/승인 상태 검증, 메뉴 존재 검증, 삭제 시 CDN 키 추출 후 S3 이미지 삭제 처리. cdnUrlResolver, s3Service 의존성 도입.
도메인 모델 보강
src/main/java/konkuk/chacall/domain/foodtruck/domain/model/Menu.java
updateMenu(name, price, description, imageUrl) 메서드 추가.
요청 DTO 추가
src/main/java/konkuk/chacall/domain/owner/presentation/dto/request/UpdateMenuRequest.java
메뉴 수정 요청 레코드 추가(name, description, price, photoUrl) 및 검증/스키마 어노테이션 적용.
Swagger 응답 설명 보강
src/main/java/konkuk/chacall/global/common/swagger/SwaggerResponseDescription.java
OWNER_UPDATE_FOOD_TRUCK_MENU, OWNER_DELETE_FOOD_TRUCK_MENU 항목 추가(에러: USER_NOT_FOUND, USER_FORBIDDEN, FOOD_TRUCK_NOT_APPROVED, MENU_NOT_FOUND).

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Owner as Owner
  participant C as OwnerController
  participant S as OwnerService
  participant M as MyFoodTruckMenuService
  participant R as Repositories
  participant D as Domain(Menu)

  rect rgba(200,230,255,0.3)
  note over Owner,C: 메뉴 수정 (PUT /me/food-trucks/{id}/menus/{menuId})
  Owner->>C: UpdateMenuRequest
  C->>S: updateMenu(ownerId, foodTruckId, menuId, request)
  S->>M: updateMenu(...)
  M->>R: validate owner & truck(approved), find menu
  R-->>M: entities
  M->>D: menu.updateMenu(name, price, desc, imageUrl)
  D-->>M: updated
  M-->>S: OK
  S-->>C: OK
  C-->>Owner: 200 BaseResponse<Void>
  end
Loading
sequenceDiagram
  autonumber
  actor Owner as Owner
  participant C as OwnerController
  participant S as OwnerService
  participant M as MyFoodTruckMenuService
  participant R as Repositories
  participant CDN as CdnUrlResolver
  participant S3 as S3Service

  rect rgba(255,230,200,0.3)
  note over Owner,C: 메뉴 삭제 (DELETE /me/food-trucks/{id}/menus/{menuId})
  Owner->>C: Delete request
  C->>S: deleteMenu(ownerId, foodTruckId, menuId)
  S->>M: deleteMenu(...)
  M->>R: validate owner & truck(approved), find menu
  R-->>M: entities
  M->>CDN: resolveKey(menu.imageUrl?)
  CDN-->>M: key or null
  alt key exists
    M->>S3: delete(key)
    S3-->>M: OK
  end
  M->>R: delete menu
  R-->>M: OK
  M-->>S: OK
  S-->>C: OK
  C-->>Owner: 200 BaseResponse<Void>
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

🛠️ feat, ☺️ 상균

Suggested reviewers

  • buzz0331

Poem

귀가 팔랑, 코드에 춤을 추네
메뉴를 고치고, 삭제도 척척하네 🥕
트럭은 승인, 주인은 확인
사진은 S3로 안녕, 깔끔한 마무리!
깡총깡총 PR 위에 달빛이 비치네 ✨

Pre-merge checks and finishing touches

❌ 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%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed 제목이 푸드트럭 메뉴 수정과 삭제 API 구현이라는 핵심 변경 사항을 명확하고 간결하게 요약하고 있어 PR 내용과 완전히 일치합니다.
Linked Issues Check ✅ Passed PR에 포함된 코드 추가와 수정은 모두 메뉴 수정과 삭제 기능을 완전하게 구현하고 S3 이미지 삭제까지 처리하여 링크된 이슈 #42의 모든 요구사항을 충족합니다.
Out of Scope Changes Check ✅ Passed 해당 PR은 메뉴 수정 및 삭제 API 구현에 직접 관련된 파일과 로직만 변경하였으며 그 외의 범위를 벗어나는 수정은 발견되지 않습니다.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/#42-foodtruck-menu-update-delete

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 and usage tips.

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

🧹 Nitpick comments (1)
src/main/java/konkuk/chacall/domain/owner/application/myfoodtruckmenu/MyFoodTruckMenuService.java (1)

92-125: 선택적 리팩토링: 검증 로직 추출을 고려해 보세요.

updateMenudeleteMenu 메서드에서 소유권 및 승인 상태 검증 로직(lines 94-97, 109-111)과 메뉴 조회 로직(lines 100-101, 114-115)이 중복됩니다.

필요시 헬퍼 메서드로 추출하여 코드 중복을 줄일 수 있습니다.

예시:

private Menu validateAndGetMenu(Long ownerId, Long foodTruckId, Long menuId) {
    if (!foodTruckRepository.existsByFoodTruckIdAndOwnerIdAndFoodTruckStatusIn(
            foodTruckId, ownerId, List.of(FoodTruckStatus.ON, FoodTruckStatus.OFF))) {
        throw new BusinessException(ErrorCode.FOOD_TRUCK_NOT_APPROVED);
    }
    
    return menuRepository.findByMenuIdAndFoodTruckId(menuId, foodTruckId)
            .orElseThrow(() -> new BusinessException(ErrorCode.MENU_NOT_FOUND));
}

그러면 두 메서드를 다음과 같이 단순화할 수 있습니다:

public void updateMenu(Long ownerId, Long foodTruckId, Long menuId, UpdateMenuRequest request) {
    Menu menu = validateAndGetMenu(ownerId, foodTruckId, menuId);
    menu.updateMenu(request.name(), request.price(), request.description(), request.photoUrl());
}

public void deleteMenu(Long ownerId, Long foodTruckId, Long menuId) {
    Menu menu = validateAndGetMenu(ownerId, foodTruckId, menuId);
    
    String key = cdnUrlResolver.extractKeyFromUrl(menu.getImageUrl());
    if (key != null) {
        s3Service.delete(key);
    }
    
    menuRepository.delete(menu);
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e554c32 and f10698e.

📒 Files selected for processing (6)
  • src/main/java/konkuk/chacall/domain/foodtruck/domain/model/Menu.java (1 hunks)
  • src/main/java/konkuk/chacall/domain/owner/application/OwnerService.java (1 hunks)
  • src/main/java/konkuk/chacall/domain/owner/application/myfoodtruckmenu/MyFoodTruckMenuService.java (3 hunks)
  • src/main/java/konkuk/chacall/domain/owner/presentation/OwnerController.java (1 hunks)
  • src/main/java/konkuk/chacall/domain/owner/presentation/dto/request/UpdateMenuRequest.java (1 hunks)
  • src/main/java/konkuk/chacall/global/common/swagger/SwaggerResponseDescription.java (1 hunks)
🔇 Additional comments (7)
src/main/java/konkuk/chacall/domain/foodtruck/domain/model/Menu.java (1)

56-61: LGTM!

엔티티 업데이트 메서드가 올바르게 구현되었습니다. 입력 검증은 DTO 레이어에서 처리되므로 이 레벨에서의 구현이 적절합니다.

src/main/java/konkuk/chacall/domain/owner/application/OwnerService.java (1)

167-183: LGTM!

파사드 패턴이 일관되게 적용되었습니다. 사장님 검증 후 서비스 레이어로 위임하는 구조가 기존 메서드들과 동일하며, 트랜잭션 경계도 적절하게 설정되어 있습니다.

src/main/java/konkuk/chacall/global/common/swagger/SwaggerResponseDescription.java (1)

110-121: LGTM!

Swagger 응답 설명이 적절하게 추가되었습니다. 에러 코드 세트가 유사한 오너 메뉴 작업들과 일관성을 유지하고 있습니다.

src/main/java/konkuk/chacall/domain/owner/presentation/OwnerController.java (1)

243-272: LGTM!

두 엔드포인트 모두 기존 컨트롤러 패턴을 일관되게 따르고 있으며, 적절한 어노테이션과 검증이 적용되어 있습니다.

src/main/java/konkuk/chacall/domain/owner/presentation/dto/request/UpdateMenuRequest.java (1)

1-30: LGTM!

DTO 검증이 적절하게 구현되었습니다. 필드별 제약 조건이 엔티티 스키마와 일치하며, 유효성 검증 어노테이션이 올바르게 적용되어 있습니다.

src/main/java/konkuk/chacall/domain/owner/application/myfoodtruckmenu/MyFoodTruckMenuService.java (2)

92-104: LGTM!

메뉴 수정 로직이 올바르게 구현되었습니다. 소유권 검증, 메뉴 조회, 업데이트 순서가 적절하며, JPA 더티 체킹을 통한 영속성 관리가 상위 트랜잭션 컨텍스트에서 정상적으로 작동합니다.


106-125: 메뉴 삭제 로직이 적절하게 구현되었습니다.

S3 이미지 삭제가 포함된 메뉴 삭제 흐름이 올바르게 구현되었습니다. extractKeyFromUrl이 null을 반환하는 경우를 적절히 처리하고 있습니다.

다만, S3 삭제 실패 시 DB에서는 메뉴가 삭제되어 S3에 고아 이미지가 남을 수 있습니다. 현재 구현은 이미지 정리 실패가 전체 작업을 롤백하지 않도록 하는 것으로 보이며, 이는 사용자 경험 측면에서 합리적인 선택일 수 있습니다.

S3 삭제 실패 시의 에러 처리 정책이 의도된 것인지 확인해 주세요. 필요하다면 별도의 이미지 정리 작업이나 로깅을 고려할 수 있습니다.

@buzz0331 buzz0331 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.

고생하셨습니다~~

Comment on lines +117 to +122
String key = cdnUrlResolver.extractKeyFromUrl(menu.getImageUrl());

// 메뉴 이미지를 S3 에서 삭제
if (key != null) {
s3Service.delete(key);
}

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.

메뉴 사진 삭제 좋습니다~

@ksg1227 ksg1227 merged commit eb1b46e into develop Oct 15, 2025
2 checks passed
@ksg1227 ksg1227 deleted the feat/#42-foodtruck-menu-update-delete branch October 15, 2025 13:14
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.

[FEAT] 푸드트럭 메뉴 수정/삭제 API 구현

2 participants