[FEAT] 푸드트럭 상태 변경 로직 추가#45
Conversation
Walkthrough푸드트럭 노출 상태(FoodTruckViewedStatus: ON/OFF)를 도메인에 추가하고, 동일 상태 전이 시 예외를 던지는 변경 메서드를 도입했다. 검색·저장 조회에 ON 필터를 적용하고, 사장용 PATCH API·서비스·요청 DTO·스웨거 응답을 추가해 노출 상태를 변경하도록 했다. 개발용 설정의 JPA DDL 모드가 create로 변경되었다. Changes
Sequence Diagram(s)sequenceDiagram
actor Owner as Owner(사장)
participant API as OwnerController
participant SVC as OwnerService
participant MY as MyFoodTruckService
participant FT as FoodTruck(도메인)
Owner->>API: PATCH /me/food-trucks/{id}/change-status\nbody: { status: ON|OFF }
API->>SVC: updateFoodTruckViewedStatus(ownerId, foodTruckId, req)
SVC->>MY: updateFoodTruckViewedStatus(ownerId, foodTruckId, req)
rect rgba(230,245,255,0.6)
note right of MY: 소유자 및 승인 상태 검증
end
MY->>FT: changeViewedStatus(req.status)
alt 동일 상태 전이
FT-->>MY: throw INVALID_FOOD_TRUCK_STATUS_TRANSITION
MY-->>SVC: 예외 전파
SVC-->>API: 예외 전파
API-->>Owner: 에러 응답
else 상태 변경
FT-->>MY: 상태 업데이트 완료
MY-->>SVC: 완료
SVC-->>API: 완료
API-->>Owner: 200 OK (빈 바디)
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (5)
src/main/java/konkuk/chacall/domain/foodtruck/domain/model/FoodTruck.java (1)
126-132: 에러 코드가 명확하지 않을 수 있습니다.
INVALID_FOOD_TRUCK_STATUS_TRANSITION에러 코드는 주로FoodTruckStatus전환에 사용되는데(Line 116 참조),FoodTruckViewedStatus전환에도 동일한 에러 코드를 사용하면 혼란을 줄 수 있습니다. 보다 명확한 에러 메시지를 위해 별도의 에러 코드(예:INVALID_FOOD_TRUCK_VIEWED_STATUS_TRANSITION)를 고려해보세요.src/main/java/konkuk/chacall/domain/foodtruck/domain/repository/infra/FoodTruckSearchRepositoryImpl.java (1)
9-9: 와일드카드 import 대신 명시적 import를 사용하세요.와일드카드 import(
import konkuk.chacall.domain.foodtruck.domain.value.*)는 코드 가독성을 떨어뜨리고 네이밍 충돌을 일으킬 수 있습니다. 사용하는 클래스들을 명시적으로 import하는 것이 좋습니다.다음과 같이 수정하세요:
-import konkuk.chacall.domain.foodtruck.domain.value.*; +import konkuk.chacall.domain.foodtruck.domain.value.AvailableQuantity; +import konkuk.chacall.domain.foodtruck.domain.value.FoodTruckStatus; +import konkuk.chacall.domain.foodtruck.domain.value.FoodTruckViewedStatus; +import konkuk.chacall.domain.foodtruck.domain.value.MenuCategory; +import konkuk.chacall.domain.foodtruck.domain.value.PaymentMethod;src/main/java/konkuk/chacall/domain/owner/application/myfoodtruck/MyFoodTruckService.java (1)
106-114: 승인 상태 검증 로직을 명확히 하세요.Line 109의 주석은 "승인 완료된 상태"라고 하지만
FoodTruckStatus.OFF는 승인 완료가 아니라 운영 중지 상태일 수 있습니다.approveFoodTruck메서드(FoodTruck.java Line 102-117)를 보면OFF는 승인된 상태이지만, 주석과 실제 도메인 의미가 혼란스러울 수 있습니다.또한 이 메서드는 상태를 변경하지만
@Transactional어노테이션이 명시되지 않았습니다. 호출자(OwnerService)에@Transactional이 있어 동작은 하지만, 명시적으로 표시하는 것이 더 명확합니다.다음과 같이 개선을 고려하세요:
+ @Transactional public void updateFoodTruckViewedStatus(Long ownerId, Long foodTruckId, UpdateFoodTruckViewedStatusRequest request) { - // 본인 소유인지, 푸드트럭이 승인 완료된 상태인지 검증 + // 본인 소유인지, 푸드트럭이 운영 가능한 상태(ON 또는 OFF)인지 검증 FoodTruck foodTruck = foodTruckRepository.findByFoodTruckIdAndOwnerIdAndFoodTruckStatusIn(foodTruckId, ownerId, List.of(FoodTruckStatus.ON, FoodTruckStatus.OFF)) .orElseThrow(() -> new BusinessException(ErrorCode.FOOD_TRUCK_NOT_APPROVED));src/main/java/konkuk/chacall/domain/owner/presentation/dto/response/MyFoodTruckResponse.java (1)
22-23: 필드명을 더 구체적으로 변경하는 것을 고려하세요.
status는 너무 일반적인 이름입니다.viewedStatus또는displayStatus와 같이 더 명확한 이름을 사용하면 API 사용자가 이 필드의 목적을 더 쉽게 이해할 수 있습니다.다음 diff를 적용하여 필드명을 개선할 수 있습니다:
- @Schema(description = "푸드트럭 표시 여부", example = "ON/OFF") - String status + @Schema(description = "푸드트럭 표시 여부", example = "ON") + String viewedStatus그리고 Line 42의 생성자 호출도 업데이트:
foodTruck.getServiceAreas(serviceAreas), - foodTruck.getFoodTruckViewedStatus().name() + foodTruck.getFoodTruckViewedStatus().name() // parameter name unchanged in constructor call참고: Schema의 example도 "ON/OFF"에서 "ON"으로 수정하여 실제 값의 예시를 보여주는 것이 더 적절합니다.
src/main/java/konkuk/chacall/domain/owner/presentation/OwnerController.java (1)
199-212: 엔드포인트 경로 네이밍을 검토하세요.현재 경로는
/me/food-trucks/{foodTruckId}/change-status를 사용하고 있는데, 이는 동사를 포함한 액션 기반 네이밍입니다. 더 RESTful한 접근으로는/me/food-trucks/{foodTruckId}/viewed-status와 같이 리소스 기반 네이밍을 사용하는 것이 좋습니다.다만 Line 247의 메뉴 상태 변경 엔드포인트도
/change-status를 사용하고 있어 일관성을 위해 현재 네이밍을 유지하는 것도 합리적입니다.더 RESTful한 경로로 변경하려면:
- @PatchMapping("/me/food-trucks/{foodTruckId}/change-status") + @PatchMapping("/me/food-trucks/{foodTruckId}/viewed-status")또는 기존 메뉴 엔드포인트와의 일관성을 위해 현재 그대로 유지할 수도 있습니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
src/main/java/konkuk/chacall/domain/foodtruck/domain/model/FoodTruck.java(2 hunks)src/main/java/konkuk/chacall/domain/foodtruck/domain/repository/infra/FoodTruckSearchRepositoryImpl.java(2 hunks)src/main/java/konkuk/chacall/domain/foodtruck/domain/value/FoodTruckViewedStatus.java(1 hunks)src/main/java/konkuk/chacall/domain/member/application/foodtruck/SavedFoodTruckService.java(2 hunks)src/main/java/konkuk/chacall/domain/member/domain/repository/SavedFoodTruckRepository.java(2 hunks)src/main/java/konkuk/chacall/domain/owner/application/OwnerService.java(1 hunks)src/main/java/konkuk/chacall/domain/owner/application/myfoodtruck/MyFoodTruckService.java(2 hunks)src/main/java/konkuk/chacall/domain/owner/presentation/OwnerController.java(1 hunks)src/main/java/konkuk/chacall/domain/owner/presentation/dto/request/UpdateFoodTruckViewedStatusRequest.java(1 hunks)src/main/java/konkuk/chacall/domain/owner/presentation/dto/response/MyFoodTruckResponse.java(2 hunks)src/main/java/konkuk/chacall/domain/owner/presentation/dto/response/OwnerReservationDetailResponse.java(3 hunks)src/main/java/konkuk/chacall/global/common/swagger/SwaggerResponseDescription.java(1 hunks)
🔇 Additional comments (12)
src/main/java/konkuk/chacall/domain/foodtruck/domain/model/FoodTruck.java (1)
79-82: LGTM!
foodTruckViewedStatus필드가 올바르게 선언되었습니다. 기본값을OFF로 설정한 것은 PR 설명에 명시된 대로 더미 데이터가 업데이트될 때까지 합리적인 선택입니다.src/main/java/konkuk/chacall/domain/member/application/foodtruck/SavedFoodTruckService.java (1)
59-59: LGTM!저장된 푸드트럭 목록 조회 시
FoodTruckViewedStatus.ON필터를 추가하여 노출 상태가 ON인 푸드트럭만 반환하도록 구현이 올바르게 되었습니다. PR 목표와 일치합니다.src/main/java/konkuk/chacall/domain/foodtruck/domain/repository/infra/FoodTruckSearchRepositoryImpl.java (1)
108-109: LGTM!푸드트럭 검색 시
FoodTruckViewedStatus.ON필터를 추가하여 고객에게 노출되는 푸드트럭만 반환하도록 올바르게 구현되었습니다.src/main/java/konkuk/chacall/domain/owner/presentation/dto/response/OwnerReservationDetailResponse.java (1)
11-12: LGTM!
foodTruckName필드 추가가 적절합니다. PR 목표에 명시된 대로 사장님 예약 상세 정보에 푸드트럭 이름이 포함되었습니다.src/main/java/konkuk/chacall/domain/foodtruck/domain/value/FoodTruckViewedStatus.java (1)
1-15: LGTM!
FoodTruckViewedStatusenum이 올바르게 구현되었습니다. 간단하고 명확한 구조로 ON/OFF 두 가지 상태를 표현하며, 기존 코드베이스의 value object 패턴을 잘 따르고 있습니다.src/main/java/konkuk/chacall/domain/owner/presentation/dto/request/UpdateFoodTruckViewedStatusRequest.java (1)
1-12: LGTM!
UpdateFoodTruckViewedStatusRequestDTO가 올바르게 구현되었습니다.@NotNull검증과@Schema문서화가 적절하게 추가되어 있으며, Java record를 사용한 간결한 구조입니다.src/main/java/konkuk/chacall/domain/owner/application/OwnerService.java (1)
141-148: LGTM!
updateFoodTruckViewedStatus메서드가 올바르게 구현되었습니다. 파사드 패턴을 일관되게 따르며, 사장님 검증 후 적절히MyFoodTruckService로 위임하고 있습니다.@Transactional어노테이션도 적절하게 적용되어 있습니다.src/main/java/konkuk/chacall/domain/owner/presentation/dto/response/MyFoodTruckResponse.java (1)
42-42: 코드 변경 승인!enum의
.name()메서드를 사용하여 문자열로 변환하는 방식은 적절합니다.src/main/java/konkuk/chacall/domain/member/domain/repository/SavedFoodTruckRepository.java (2)
27-29: JPQL 쿼리 수정이 올바릅니다.
foodTruck과의 명시적 JOIN과foodTruckViewedStatus필터링 조건이 정확하게 추가되었습니다. @EntityGraph와 함께 사용하여 N+1 문제를 방지하면서도 필터링 조건을 적용할 수 있습니다.
32-36: findMemberSavedFoodTruckWithCursor 호출부에 status 파라미터가 정상 반영되었습니다.
getSavedFoodTrucks 메서드에서 FoodTruckViewedStatus.ON 인자를 추가하여 호출이 업데이트된 것을 확인했습니다.src/main/java/konkuk/chacall/domain/owner/presentation/OwnerController.java (1)
205-211: 엔드포인트 구현이 적절합니다.src/main/java/konkuk/chacall/global/common/swagger/SwaggerResponseDescription.java (1)
93-98: 에러 코드 정의가 적절합니다.새로운 푸드트럭 상태 변경 API에 대한 에러 코드가 올바르게 정의되었습니다:
- 기본 인증/권한 에러 (USER_NOT_FOUND, USER_FORBIDDEN)
- 비즈니스 로직 에러 (FOOD_TRUCK_NOT_APPROVED, INVALID_FOOD_TRUCK_STATUS_TRANSITION)
Line 109-115의 메뉴 상태 변경 API와 유사한 에러 구조를 따르고 있어 일관성이 있습니다.
| example = "50000") | ||
| int deposit, |
There was a problem hiding this comment.
🧩 Analysis chain
API 호환성 확인 및 데이터 타입 검토가 필요합니다.
deposit 필드 타입을 String에서 int로 변경하는 것은 다음 사항들을 확인해야 합니다:
- API 호환성: 기존 API 소비자에게 영향을 줄 수 있는 breaking change입니다.
- 데이터 타입:
int는 최대 약 21억까지만 표현 가능합니다. 예약금이 큰 경우long타입 사용을 고려하세요. - 메서드 호환성:
reservation.getReservationInfo().getDeposit()이int를 반환하는지 확인이 필요합니다.
다음 스크립트를 실행하여 getDeposit() 메서드의 반환 타입과 사용처를 확인하세요:
Also applies to: 59-59
🏁 Script executed:
#!/bin/bash
# Description: Verify the return type of getDeposit() and check for breaking changes
# Check the return type of getDeposit() method
ast-grep --pattern $'class ReservationInfo {
$$$
$_ getDeposit() {
$$$
}
$$$
}'
# Find all usages of OwnerReservationDetailResponse to check API consumers
rg -nP --type=java -C3 'OwnerReservationDetailResponse'
# Check if there are any references to the old parsingReservationDeposit method
rg -nP --type=java 'parsingReservationDeposit'Length of output: 7908
getDeposit 메서드 반환 타입과 deposit 필드 선언을 확인하기 위해 다음 스크립트를 실행하세요.
🏁 Script executed:
#!/bin/bash
# ReservationInfo.java에서 deposit 필드 및 getDeposit() 메서드 정의 확인
# getDeposit 메서드 검색
rg -n 'getDeposit' -C4 src/main/java/konkuk/chacall/domain/reservation/domain/value/ReservationInfo.java || echo "getDeposit 메서드를 찾을 수 없습니다."
# 파일 상단 120줄 출력하여 deposit 필드 선언 확인
sed -n '1,120p' src/main/java/konkuk/chacall/domain/reservation/domain/value/ReservationInfo.javaLength of output: 3115
getDeposit 언박싱 확인 및 API 호환성 검토 필요
ReservationInfo.getDeposit()는Integer반환 →int로 언박싱 가능함.deposit필드를String→int로 변경하면 기존 API 클라이언트에 breaking change 발생- 최대값(약 21억)을 초과할 가능성은 낮지만, 대규모 금액 처리 시
long사용 고려
| where.and(foodTruck.foodTruckStatus.eq(FoodTruckStatus.ON)); | ||
|
|
||
| // 푸드트럭 노출 여부 | ||
| where.and(foodTruck.foodTruckViewedStatus.eq(FoodTruckViewedStatus.ON)); |
| public void changeViewedStatus(FoodTruckViewedStatus targetViewedStatus) { | ||
| if(this.foodTruckViewedStatus == targetViewedStatus) { | ||
| throw new DomainRuleException(ErrorCode.INVALID_FOOD_TRUCK_STATUS_TRANSITION); | ||
| } | ||
|
|
||
| this.foodTruckViewedStatus = targetViewedStatus; | ||
| } |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/main/resources/application-dev.yml (1)
13-13: 개발 환경에서 스키마 재초기화 설정 변경 검토
update에서create로 변경하면 애플리케이션 시작 시마다 기존 스키마를 삭제하고 새로 생성합니다. 이는 새로운FoodTruckViewedStatus엔티티 변경사항을 안전하게 반영하는 데 적합하지만, 개발 중 매번 재시작할 때마다 데이터가 초기화된다는 점에 유의하세요.제안: 이 변경의 의도를 팀원들이 이해하도록, 다음과 같이 주석을 추가하는 것을 검토하세요:
jpa: hibernate: ddl-auto: create # 개발 환경에서 스키마 일관성 유지: FoodTruckViewedStatus 추가 시 매번 재생성
#️⃣연관된 이슈
📝작업 내용
푸드트럭에 표시 여부 (= 노출 여부) 가 추가되었다고 하여 해당 기능을 구현하였습니다.
푸드트럭 조회 - 고객
푸드트럭 조회 시 푸드트럭 노출 여부가 ON 인 것들만 조회될 수 있도록 변경하였습니다.
일반 유저 - 저장된 푸드트럭 조회
저장된 푸드트럭 조회 시에도 푸드트럭 노출 여부가 ON 인 것들만 조회될 수 있도록 하였습니다.
사장님 - 나의 푸드트럭 조회
나의 푸드트럭 조회시에는 노출여부에 관계 없이 모든 푸드트럭이 조회될 수 있도록 하였습니다.
푸드트럭 표시 상태 변경
기존에 메뉴 표시 상태 변경 API 와 사실상 거의 동일하게 구현하였습니다.
사장님 - 예약 내역 상세 조회
찬영님이 사장님 - 예약 내역 상세 조회에서 푸드트럭 이름 반환 & 예약금을 정수형으로 반환 이 두가지를 요구하셔서 해당 기능들도 추가적으로 구현하였습니다.
스크린샷 (선택)
💬리뷰 요구사항(선택)
foodTruckViewedStatus 라는 컬럼이 추가되다보니 더미데이터도 바꿔주어야할 것 같습니다. 우선 전부다 ON(표시) 상태로 바꿔둘게요
Summary by CodeRabbit
New Features
Documentation