From d705877f21f46db856f4d4be4915ade39cc2065e Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Wed, 29 Oct 2025 21:24:03 +0900 Subject: [PATCH 01/11] =?UTF-8?q?[feat]=20response=20dto=20=EC=84=A0?= =?UTF-8?q?=EC=96=B8=20(#53)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../foodtruck/domain/model/AvailableDate.java | 6 ++ .../foodtruck/domain/model/FoodTruck.java | 13 ++++ .../dto/response/FoodTruckDetailResponse.java | 69 +++++++++++++++++++ 3 files changed, 88 insertions(+) create mode 100644 src/main/java/konkuk/chacall/domain/foodtruck/presentation/dto/response/FoodTruckDetailResponse.java diff --git a/src/main/java/konkuk/chacall/domain/foodtruck/domain/model/AvailableDate.java b/src/main/java/konkuk/chacall/domain/foodtruck/domain/model/AvailableDate.java index aea4a7d..8eed743 100644 --- a/src/main/java/konkuk/chacall/domain/foodtruck/domain/model/AvailableDate.java +++ b/src/main/java/konkuk/chacall/domain/foodtruck/domain/model/AvailableDate.java @@ -36,4 +36,10 @@ public static AvailableDate createAvailableDate(LocalDate startDate, LocalDate e .foodTruck(foodTruck) .build(); } + + public String formatDate() { + return startAt + " ~ " + endAt; + } + + } diff --git a/src/main/java/konkuk/chacall/domain/foodtruck/domain/model/FoodTruck.java b/src/main/java/konkuk/chacall/domain/foodtruck/domain/model/FoodTruck.java index fb6b62c..5e1ca50 100644 --- a/src/main/java/konkuk/chacall/domain/foodtruck/domain/model/FoodTruck.java +++ b/src/main/java/konkuk/chacall/domain/foodtruck/domain/model/FoodTruck.java @@ -143,6 +143,13 @@ public String getServiceAreas(List serviceAreaList) { .collect(Collectors.joining(", ")); } + // 푸드트럭의 운영 기간을 반환해주는 메서드 + public List getAvailableDates(List availableDateList) { + return availableDateList.stream() + .map(AvailableDate::formatDate) + .collect(Collectors.toList()); + } + public void changeViewedStatus(FoodTruckViewedStatus targetViewedStatus) { if(this.foodTruckViewedStatus == targetViewedStatus) { throw new DomainRuleException(ErrorCode.INVALID_FOOD_TRUCK_STATUS_TRANSITION); @@ -155,4 +162,10 @@ public void changeViewedStatus(FoodTruckViewedStatus targetViewedStatus) { this.foodTruckViewedStatus = targetViewedStatus; } + + public void validateViewableStatusForMember() { + if (this.foodTruckViewedStatus != FoodTruckViewedStatus.ON) { + throw new DomainRuleException(ErrorCode.FOOD_TRUCK_NOT_VIEWABLE); + } + } } diff --git a/src/main/java/konkuk/chacall/domain/foodtruck/presentation/dto/response/FoodTruckDetailResponse.java b/src/main/java/konkuk/chacall/domain/foodtruck/presentation/dto/response/FoodTruckDetailResponse.java new file mode 100644 index 0000000..0ec65f2 --- /dev/null +++ b/src/main/java/konkuk/chacall/domain/foodtruck/presentation/dto/response/FoodTruckDetailResponse.java @@ -0,0 +1,69 @@ +package konkuk.chacall.domain.foodtruck.presentation.dto.response; + +import io.swagger.v3.oas.annotations.media.Schema; +import konkuk.chacall.domain.foodtruck.domain.model.AvailableDate; +import konkuk.chacall.domain.foodtruck.domain.model.FoodTruck; +import konkuk.chacall.domain.foodtruck.domain.model.FoodTruckServiceArea; +import konkuk.chacall.domain.foodtruck.domain.value.FoodTruckInfo; + +import java.util.List; + +public record FoodTruckDetailResponse( + @Schema(description = "푸드트럭 식별자", example = "1") + Long foodTruckId, + @Schema(description = "푸드트럭 이름", example = "푸드트럭") + String name, + @Schema(description = "푸드트럭 설명", example = "맛있는 푸드트럭입니다.") + String description, + @Schema(description = "푸드트럭 전화번호", example = "010-1234-5678") + String phoneNumber, + @Schema(description = "푸드트럭 활동 시간", example = "09:00-20:00") + String activeTime, + @Schema(description = "시간 협의 필요 여부", example = "false") + Boolean timeDiscussRequired, + @Schema(description = "호출 가능 지역", example = "서울 광진구, 서울 강남구, 서울 영등포구") + String serviceAreas, + @Schema(description = "푸드트럭 메뉴 카테고리 (라벨 리스트)", example = "[\"한식\",\"분식\"]") + List menuCategories, + @Schema(description = "푸드트럭 제공 가능 수량", example = "200인분 미만") + String availableQuantity, + @Schema(description = "전기 사용 필요 여부", example = "필요") + String needElectricity, + @Schema(description = "결제 방법", example = "무관") + String paymentMethod, + @Schema(description = "푸드트럭 제공 가능 날짜 리스트", example = "[\"2025-10-01 ~ 2025-10-10\",\"2025-11-01 ~ 2025-11-10\"]") + List availableDates, + @Schema(description = "푸드트럭 사진 URL 리스트", example = "[\"http://image.png\",\"http://image2.png\",\"http://image3.png\"]") + List photoUrl, + @Schema(description = "운영 정보", example = "운영정보") + String operatingInfo, + @Schema(description = "추가 옵션 정보", example = "안녕하세요") + String option, + @Schema(description = "푸드트럭 평균 평점", example = "4.5") + Double averageRating, + @Schema(description = "현재 사용자가 저장한 푸드트럭인지 여부", example = "true") + Boolean isSaved +) { + public static FoodTruckDetailResponse from(FoodTruck foodTruck, List serviceAreas, List availableDates, Boolean isSaved) { + FoodTruckInfo foodTruckInfo = foodTruck.getFoodTruckInfo(); + return new FoodTruckDetailResponse( + foodTruck.getFoodTruckId(), + foodTruckInfo.getName(), + foodTruckInfo.getDescription(), + foodTruckInfo.getPhoneNumber(), + foodTruckInfo.getActiveTime(), + foodTruckInfo.getTimeDiscussRequired(), + foodTruck.getServiceAreas(serviceAreas), + foodTruckInfo.getMenuCategoryList().getMenuCategoryLabelList(), + foodTruckInfo.getAvailableQuantity().getValue(), + foodTruckInfo.getNeedElectricity().getValue(), + foodTruckInfo.getPaymentMethod().getValue(), + foodTruck.getAvailableDates(availableDates), + foodTruckInfo.getFoodTruckPhotoList().getUrls(), + foodTruckInfo.getOperatingInfo(), + foodTruckInfo.getOption(), + foodTruck.getRatingInfo().getAverageRating(), + isSaved + ); + } +} From 4d185436ebb69530f7bc6220830f22599965a907 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Wed, 29 Oct 2025 21:24:19 +0900 Subject: [PATCH 02/11] =?UTF-8?q?[feat]=20=ED=91=B8=EB=93=9C=ED=8A=B8?= =?UTF-8?q?=EB=9F=AD=20=EC=83=81=EC=84=B8=EC=A1=B0=ED=9A=8C=20API=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20(#53)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/FoodTruckService.java | 6 ++++++ .../info/FoodTruckInfoService.java | 19 +++++++++++++++++++ .../presentation/FoodTruckController.java | 13 +++++++++++++ 3 files changed, 38 insertions(+) diff --git a/src/main/java/konkuk/chacall/domain/foodtruck/application/FoodTruckService.java b/src/main/java/konkuk/chacall/domain/foodtruck/application/FoodTruckService.java index d9c6b65..e3e7460 100644 --- a/src/main/java/konkuk/chacall/domain/foodtruck/application/FoodTruckService.java +++ b/src/main/java/konkuk/chacall/domain/foodtruck/application/FoodTruckService.java @@ -78,4 +78,10 @@ public void deleteFoodTruckImagesFromS3(Long ownerId, Long foodTruckId, DeleteFo foodTruckImageService.deleteFoodTruckImagesFromS3(owner, foodTruckId, request); } + + public FoodTruckDetailResponse getFoodTruckDetails(Long memberId, Long foodTruckId) { + User member = memberValidator.validateAndGetMember(memberId); + + return foodTruckInfoService.getFoodTruckDetails(member, foodTruckId); + } } diff --git a/src/main/java/konkuk/chacall/domain/foodtruck/application/info/FoodTruckInfoService.java b/src/main/java/konkuk/chacall/domain/foodtruck/application/info/FoodTruckInfoService.java index 64c2fea..fc16a66 100644 --- a/src/main/java/konkuk/chacall/domain/foodtruck/application/info/FoodTruckInfoService.java +++ b/src/main/java/konkuk/chacall/domain/foodtruck/application/info/FoodTruckInfoService.java @@ -9,6 +9,7 @@ import konkuk.chacall.domain.foodtruck.presentation.dto.request.DateRangeRequest; import konkuk.chacall.domain.foodtruck.presentation.dto.request.FoodTruckSearchRequest; import konkuk.chacall.domain.foodtruck.presentation.dto.request.UpdateFoodTruckInfoRequest; +import konkuk.chacall.domain.foodtruck.presentation.dto.response.FoodTruckDetailResponse; import konkuk.chacall.domain.foodtruck.presentation.dto.response.FoodTruckResponse; import konkuk.chacall.domain.member.domain.repository.SavedFoodTruckRepository; import konkuk.chacall.domain.region.domain.model.Region; @@ -133,4 +134,22 @@ private void syncServiceAreas(FoodTruck foodTruck, Set requestedRegionIds) foodTruckServiceAreaRepository.deleteAll(serviceAreasToRemove); } } + + public FoodTruckDetailResponse getFoodTruckDetails(User member, Long foodTruckId) { + FoodTruck foodTruck = foodTruckRepository.findById(foodTruckId) + .orElseThrow(() -> new EntityNotFoundException(ErrorCode.FOOD_TRUCK_NOT_FOUND)); + + switch(member.getRole()) { + case MEMBER -> foodTruck.validateViewableStatusForMember(); + case OWNER -> foodTruck.validateOwner(member.getUserId()); + case ADMIN -> {} + } + + List foodTruckServiceAreas = foodTruckServiceAreaRepository.findAllByFoodTruckId(foodTruckId); + List availableDates = availableDateRepository.findAllByFoodTruckId(foodTruckId); + + boolean isSaved = savedFoodTruckRepository.existsByMemberIdAndFoodTruckId(member.getUserId(), foodTruckId); + + return FoodTruckDetailResponse.from(foodTruck, foodTruckServiceAreas, availableDates, isSaved); + } } diff --git a/src/main/java/konkuk/chacall/domain/foodtruck/presentation/FoodTruckController.java b/src/main/java/konkuk/chacall/domain/foodtruck/presentation/FoodTruckController.java index f6b19cb..c02031b 100644 --- a/src/main/java/konkuk/chacall/domain/foodtruck/presentation/FoodTruckController.java +++ b/src/main/java/konkuk/chacall/domain/foodtruck/presentation/FoodTruckController.java @@ -130,5 +130,18 @@ public BaseResponse deleteFoodTruckImagesFromS3( return BaseResponse.ok(null); } + @Operation( + summary = "푸드트럭 상세조회", + description = "푸드트럭의 상세 정보를 조회합니다." + ) + @ExceptionDescription(SwaggerResponseDescription.GET_FOOD_TRUCK_DETAILS) + @GetMapping("/{foodTruckId}/details") + public BaseResponse getFoodTruckDetails( + @Parameter(description = "푸드트럭 ID", example = "1") @PathVariable final Long foodTruckId, + @Parameter(hidden = true) @UserId final Long memberId + ) { + return BaseResponse.ok(foodTruckService.getFoodTruckDetails(memberId, foodTruckId)); + } + } From 8dc5c08ed59ef6b7ac68a26281619f1598ac3cee Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Wed, 29 Oct 2025 21:24:26 +0900 Subject: [PATCH 03/11] =?UTF-8?q?[feat]=20=ED=95=84=EC=9A=94=ED=95=9C=20?= =?UTF-8?q?=EC=BF=BC=EB=A6=AC=20=EC=84=A0=EC=96=B8=20(#53)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/repository/AvailableDateRepository.java | 5 +++++ .../domain/repository/SavedFoodTruckRepository.java | 9 +++++++++ 2 files changed, 14 insertions(+) diff --git a/src/main/java/konkuk/chacall/domain/foodtruck/domain/repository/AvailableDateRepository.java b/src/main/java/konkuk/chacall/domain/foodtruck/domain/repository/AvailableDateRepository.java index 434641a..4d27221 100644 --- a/src/main/java/konkuk/chacall/domain/foodtruck/domain/repository/AvailableDateRepository.java +++ b/src/main/java/konkuk/chacall/domain/foodtruck/domain/repository/AvailableDateRepository.java @@ -6,9 +6,14 @@ import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; +import java.util.List; + public interface AvailableDateRepository extends JpaRepository { @Modifying @Query("DELETE FROM AvailableDate ad WHERE ad.foodTruck.foodTruckId = :foodTruckId") void deleteAllByFoodTruckId(@Param("foodTruckId") Long foodTruckId); + + @Query("SELECT ad FROM AvailableDate ad WHERE ad.foodTruck.foodTruckId = :foodTruckId") + List findAllByFoodTruckId(Long foodTruckId); } diff --git a/src/main/java/konkuk/chacall/domain/member/domain/repository/SavedFoodTruckRepository.java b/src/main/java/konkuk/chacall/domain/member/domain/repository/SavedFoodTruckRepository.java index dc82731..c723c77 100644 --- a/src/main/java/konkuk/chacall/domain/member/domain/repository/SavedFoodTruckRepository.java +++ b/src/main/java/konkuk/chacall/domain/member/domain/repository/SavedFoodTruckRepository.java @@ -48,4 +48,13 @@ Slice findMemberSavedFoodTruckWithCursor( Set findSavedTruckIdsIn(@Param("userId") Long userId, @Param("foodTruckIds") List foodTruckIds); + @Query(""" + select exists ( + select s + from SavedFoodTruck s + where s.member.userId = :memberId + and s.foodTruck.foodTruckId = :foodTruckId + ) + """) + boolean existsByMemberIdAndFoodTruckId(Long userId, Long foodTruckId); } From 3079d66148697e9ccccab11a628cf21a28430af8 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Wed, 29 Oct 2025 21:24:35 +0900 Subject: [PATCH 04/11] =?UTF-8?q?[docs]=20=EC=8A=A4=EC=9B=A8=EA=B1=B0=20?= =?UTF-8?q?=EB=AA=85=EC=84=B8=20(#53)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chacall/global/common/exception/code/ErrorCode.java | 1 + .../global/common/swagger/SwaggerResponseDescription.java | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/src/main/java/konkuk/chacall/global/common/exception/code/ErrorCode.java b/src/main/java/konkuk/chacall/global/common/exception/code/ErrorCode.java index 4dcb497..cee2d80 100644 --- a/src/main/java/konkuk/chacall/global/common/exception/code/ErrorCode.java +++ b/src/main/java/konkuk/chacall/global/common/exception/code/ErrorCode.java @@ -83,6 +83,7 @@ public enum ErrorCode implements ResponseCode { AVAILABLE_QUANTITY_MISMATCH(HttpStatus.BAD_REQUEST, 110007, "제조 가능 수량 값이 올바르지 않습니다."), NEED_ELECTRICITY_MISMATCH(HttpStatus.BAD_REQUEST, 110008, "전기 사용 여부 값이 올바르지 않습니다."), PAYMENT_METHOD_MISMATCH(HttpStatus.BAD_REQUEST, 110009, "결제 수단 값이 올바르지 않습니다."), + FOOD_TRUCK_NOT_VIEWABLE(HttpStatus.FORBIDDEN, 110010, "노출 가능한 상태의 푸드트럭이 아닙니다."), /** * Image diff --git a/src/main/java/konkuk/chacall/global/common/swagger/SwaggerResponseDescription.java b/src/main/java/konkuk/chacall/global/common/swagger/SwaggerResponseDescription.java index 32c2b4c..695a5f9 100644 --- a/src/main/java/konkuk/chacall/global/common/swagger/SwaggerResponseDescription.java +++ b/src/main/java/konkuk/chacall/global/common/swagger/SwaggerResponseDescription.java @@ -246,6 +246,13 @@ public enum SwaggerResponseDescription { FOOD_TRUCK_NOT_FOUND, FOOD_TRUCK_NOT_OWNED ))), + GET_FOOD_TRUCK_DETAILS(new LinkedHashSet<>(Set.of( + USER_NOT_FOUND, + USER_FORBIDDEN, + FOOD_TRUCK_NOT_FOUND, + FOOD_TRUCK_NOT_OWNED, + FOOD_TRUCK_NOT_VIEWABLE + ))), // Default DEFAULT(new LinkedHashSet<>()) From 051574c5a43065481246dedc0610ed26c1de8932 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Wed, 29 Oct 2025 21:28:25 +0900 Subject: [PATCH 05/11] =?UTF-8?q?[fix]=20=EC=9C=A0=ED=9A=A8=EC=84=B1=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?(#53)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../foodtruck/application/info/FoodTruckInfoService.java | 2 +- .../chacall/domain/foodtruck/domain/model/FoodTruck.java | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/konkuk/chacall/domain/foodtruck/application/info/FoodTruckInfoService.java b/src/main/java/konkuk/chacall/domain/foodtruck/application/info/FoodTruckInfoService.java index fc16a66..8402360 100644 --- a/src/main/java/konkuk/chacall/domain/foodtruck/application/info/FoodTruckInfoService.java +++ b/src/main/java/konkuk/chacall/domain/foodtruck/application/info/FoodTruckInfoService.java @@ -141,7 +141,7 @@ public FoodTruckDetailResponse getFoodTruckDetails(User member, Long foodTruckId switch(member.getRole()) { case MEMBER -> foodTruck.validateViewableStatusForMember(); - case OWNER -> foodTruck.validateOwner(member.getUserId()); + case OWNER -> foodTruck.vaildateViewableStatusForOwner(member.getUserId()); case ADMIN -> {} } diff --git a/src/main/java/konkuk/chacall/domain/foodtruck/domain/model/FoodTruck.java b/src/main/java/konkuk/chacall/domain/foodtruck/domain/model/FoodTruck.java index 5e1ca50..cb1e016 100644 --- a/src/main/java/konkuk/chacall/domain/foodtruck/domain/model/FoodTruck.java +++ b/src/main/java/konkuk/chacall/domain/foodtruck/domain/model/FoodTruck.java @@ -168,4 +168,12 @@ public void validateViewableStatusForMember() { throw new DomainRuleException(ErrorCode.FOOD_TRUCK_NOT_VIEWABLE); } } + + public void vaildateViewableStatusForOwner(Long userId) { + if(!isOwnedBy(userId)) { // 자신이 소유한 푸드트럭이 아니면 + validateViewableStatusForMember(); + } else { // 자신이 소유한 푸드트럭이면 + validateOwner(userId); + } + } } From 926f01e52a6acdc2b33f3756b3b217cdc053c23f Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Wed, 29 Oct 2025 21:29:28 +0900 Subject: [PATCH 06/11] =?UTF-8?q?[fix]=20=EC=9C=A0=ED=9A=A8=EC=84=B1=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?(#53)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../konkuk/chacall/domain/foodtruck/domain/model/FoodTruck.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/konkuk/chacall/domain/foodtruck/domain/model/FoodTruck.java b/src/main/java/konkuk/chacall/domain/foodtruck/domain/model/FoodTruck.java index cb1e016..545752e 100644 --- a/src/main/java/konkuk/chacall/domain/foodtruck/domain/model/FoodTruck.java +++ b/src/main/java/konkuk/chacall/domain/foodtruck/domain/model/FoodTruck.java @@ -172,8 +172,6 @@ public void validateViewableStatusForMember() { public void vaildateViewableStatusForOwner(Long userId) { if(!isOwnedBy(userId)) { // 자신이 소유한 푸드트럭이 아니면 validateViewableStatusForMember(); - } else { // 자신이 소유한 푸드트럭이면 - validateOwner(userId); } } } From 02a7dbff36a3e645b588b156bb99db46fb573723 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Thu, 30 Oct 2025 00:54:33 +0900 Subject: [PATCH 07/11] =?UTF-8?q?[feat]=20=EB=A9=94=EB=89=B4=20=EA=B2=80?= =?UTF-8?q?=EC=83=89=20API=20=EA=B5=AC=ED=98=84=20(#53)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/FoodTruckService.java | 8 ++++++++ .../menu/FoodTruckMenuService.java | 15 ++++++++++++-- .../domain/repository/MenuRepository.java | 11 +++++++++- .../presentation/FoodTruckController.java | 20 ++++++++++++++++--- .../swagger/SwaggerResponseDescription.java | 5 +++++ 5 files changed, 53 insertions(+), 6 deletions(-) diff --git a/src/main/java/konkuk/chacall/domain/foodtruck/application/FoodTruckService.java b/src/main/java/konkuk/chacall/domain/foodtruck/application/FoodTruckService.java index e3e7460..22285d1 100644 --- a/src/main/java/konkuk/chacall/domain/foodtruck/application/FoodTruckService.java +++ b/src/main/java/konkuk/chacall/domain/foodtruck/application/FoodTruckService.java @@ -21,6 +21,8 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.List; + @RequiredArgsConstructor @Service @Transactional(readOnly = true) @@ -84,4 +86,10 @@ public FoodTruckDetailResponse getFoodTruckDetails(Long memberId, Long foodTruck return foodTruckInfoService.getFoodTruckDetails(member, foodTruckId); } + + public List searchFoodTruckMenus(Long foodTruckId, String keyword, Long memberId) { + User member = memberValidator.validateAndGetMember(memberId); + + return foodTruckMenuService.searchFoodTruckMenus(foodTruckId, keyword, member); + } } diff --git a/src/main/java/konkuk/chacall/domain/foodtruck/application/menu/FoodTruckMenuService.java b/src/main/java/konkuk/chacall/domain/foodtruck/application/menu/FoodTruckMenuService.java index 6eaaef5..258fc5a 100644 --- a/src/main/java/konkuk/chacall/domain/foodtruck/application/menu/FoodTruckMenuService.java +++ b/src/main/java/konkuk/chacall/domain/foodtruck/application/menu/FoodTruckMenuService.java @@ -3,10 +3,9 @@ import konkuk.chacall.domain.foodtruck.domain.model.Menu; import konkuk.chacall.domain.foodtruck.domain.repository.FoodTruckRepository; import konkuk.chacall.domain.foodtruck.domain.repository.MenuRepository; -import konkuk.chacall.domain.foodtruck.domain.value.FoodTruckStatus; import konkuk.chacall.domain.foodtruck.presentation.dto.request.FoodTruckMenuRequest; import konkuk.chacall.domain.foodtruck.presentation.dto.response.FoodTruckMenuResponse; -import konkuk.chacall.domain.owner.presentation.dto.response.MyFoodTruckMenuResponse; +import konkuk.chacall.domain.user.domain.model.User; import konkuk.chacall.global.common.dto.CursorPagingRequest; import konkuk.chacall.global.common.dto.CursorPagingResponse; import konkuk.chacall.global.common.dto.SortType; @@ -48,4 +47,16 @@ public CursorPagingResponse getFoodTruckMenus(Long foodTr return CursorPagingResponse.of(content, FoodTruckMenuResponse::menuId, menuSlice.hasNext()); } + + public List searchFoodTruckMenus(Long foodTruckId, String keyword, User member) { + if(!foodTruckRepository.existsById(foodTruckId)) { + throw new EntityNotFoundException(ErrorCode.FOOD_TRUCK_NOT_FOUND); + } + + List menus = menuRepository.searchByKeyword(foodTruckId, keyword); + + return menus.stream() + .map(FoodTruckMenuResponse::from) + .toList(); + } } diff --git a/src/main/java/konkuk/chacall/domain/foodtruck/domain/repository/MenuRepository.java b/src/main/java/konkuk/chacall/domain/foodtruck/domain/repository/MenuRepository.java index b11ef70..e12c011 100644 --- a/src/main/java/konkuk/chacall/domain/foodtruck/domain/repository/MenuRepository.java +++ b/src/main/java/konkuk/chacall/domain/foodtruck/domain/repository/MenuRepository.java @@ -1,7 +1,6 @@ package konkuk.chacall.domain.foodtruck.domain.repository; import konkuk.chacall.domain.foodtruck.domain.model.Menu; -import konkuk.chacall.domain.foodtruck.domain.value.MenuViewedStatus; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.data.jpa.repository.JpaRepository; @@ -9,6 +8,7 @@ import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; +import java.util.List; import java.util.Optional; public interface MenuRepository extends JpaRepository { @@ -70,4 +70,13 @@ Slice findVisibleMenusAsc(@Param("foodTruckId") Long foodTruckId, """) Optional findByMenuIdAndFoodTruckId(@Param("menuId") Long menuId, @Param("foodTruckId") Long foodTruckId); + + @Query(""" + select m + from Menu m + where m.foodTruck.foodTruckId = :foodTruckId + and m.name like concat('%', :keyword, '%') + and m.menuViewedStatus = konkuk.chacall.domain.foodtruck.domain.value.MenuViewedStatus.ON + """) + List searchByKeyword(Long foodTruckId, String keyword); } diff --git a/src/main/java/konkuk/chacall/domain/foodtruck/presentation/FoodTruckController.java b/src/main/java/konkuk/chacall/domain/foodtruck/presentation/FoodTruckController.java index c02031b..f7ee762 100644 --- a/src/main/java/konkuk/chacall/domain/foodtruck/presentation/FoodTruckController.java +++ b/src/main/java/konkuk/chacall/domain/foodtruck/presentation/FoodTruckController.java @@ -25,6 +25,8 @@ import org.springdoc.core.annotations.ParameterObject; import org.springframework.web.bind.annotation.*; +import java.util.List; + @Tag(name = "FoodTruck API", description = "푸드트럭 관련 API") @RestController @RequiredArgsConstructor @@ -106,7 +108,7 @@ public BaseResponse> getFoodTruckMen description = "승인이 완료된 나의 푸드트럭 정보를 기입하거나 수정합니다." ) @ExceptionDescription(SwaggerResponseDescription.UPDATE_FOOD_TRUCK_INFO) - @PutMapping("{foodTruckId}") + @PutMapping("/{foodTruckId}") public BaseResponse updateMyFoodTruckInfo( @Parameter(description = "푸드트럭 ID", example = "1") @PathVariable final Long foodTruckId, @Valid @RequestBody final UpdateFoodTruckInfoRequest request, @@ -120,7 +122,7 @@ public BaseResponse updateMyFoodTruckInfo( description = "S3에서 푸드트럭/메뉴 이미지 객체를 삭제합니다. 사용자가 기존 푸드트럭/메뉴 이미지를 삭제했을 경우 호출해주세요." ) @ExceptionDescription(SwaggerResponseDescription.DELETE_FOOD_TRUCK_IMAGES) - @DeleteMapping("{foodTruckId}/images") + @DeleteMapping("/{foodTruckId}/images") public BaseResponse deleteFoodTruckImagesFromS3( @Parameter(description = "푸드트럭 ID", example = "1") @PathVariable final Long foodTruckId, @Valid @RequestBody final DeleteFoodTruckImagesRequest request, @@ -143,5 +145,17 @@ public BaseResponse getFoodTruckDetails( return BaseResponse.ok(foodTruckService.getFoodTruckDetails(memberId, foodTruckId)); } - + @Operation( + summary = "푸드트럭 메뉴 검색", + description = "푸드트럭 메뉴를 이름으로 검색합니다." + ) + @ExceptionDescription(SwaggerResponseDescription.SEARCH_FOOD_TRUCK_MENUS) + @GetMapping("/{foodTruckId}/menus/search") + public BaseResponse> searchFoodTruckMenus( + @Parameter(description = "푸드트럭 ID", example = "1") @PathVariable final Long foodTruckId, + @Parameter(description = "검색 키워드", example = "치킨") @RequestParam("keyword") final String keyword, + @Parameter(hidden = true) @UserId final Long memberId + ) { + return BaseResponse.ok(foodTruckService.searchFoodTruckMenus(foodTruckId, keyword, memberId)); + } } diff --git a/src/main/java/konkuk/chacall/global/common/swagger/SwaggerResponseDescription.java b/src/main/java/konkuk/chacall/global/common/swagger/SwaggerResponseDescription.java index 695a5f9..870254d 100644 --- a/src/main/java/konkuk/chacall/global/common/swagger/SwaggerResponseDescription.java +++ b/src/main/java/konkuk/chacall/global/common/swagger/SwaggerResponseDescription.java @@ -253,6 +253,11 @@ public enum SwaggerResponseDescription { FOOD_TRUCK_NOT_OWNED, FOOD_TRUCK_NOT_VIEWABLE ))), + SEARCH_FOOD_TRUCK_MENUS(new LinkedHashSet<>(Set.of( + USER_NOT_FOUND, + USER_FORBIDDEN, + FOOD_TRUCK_NOT_FOUND + ))), // Default DEFAULT(new LinkedHashSet<>()) From 636caa4eeba2cebd67d727cdb1da7e85e93eea8e Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Thu, 30 Oct 2025 00:55:16 +0900 Subject: [PATCH 08/11] =?UTF-8?q?[refactor]=20=ED=91=B8=EB=93=9C=ED=8A=B8?= =?UTF-8?q?=EB=9F=AD=EC=9D=B4=20=EC=8A=B9=EC=9D=B8=20=EC=83=81=ED=83=9C?= =?UTF-8?q?=EC=9D=BC=EB=95=8C=EB=A7=8C=20=EC=A1=B0=ED=9A=8C=EB=90=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95=20(#53)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../foodtruck/application/info/FoodTruckInfoService.java | 2 ++ .../global/common/swagger/SwaggerResponseDescription.java | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/konkuk/chacall/domain/foodtruck/application/info/FoodTruckInfoService.java b/src/main/java/konkuk/chacall/domain/foodtruck/application/info/FoodTruckInfoService.java index 8402360..22bf899 100644 --- a/src/main/java/konkuk/chacall/domain/foodtruck/application/info/FoodTruckInfoService.java +++ b/src/main/java/konkuk/chacall/domain/foodtruck/application/info/FoodTruckInfoService.java @@ -139,6 +139,8 @@ public FoodTruckDetailResponse getFoodTruckDetails(User member, Long foodTruckId FoodTruck foodTruck = foodTruckRepository.findById(foodTruckId) .orElseThrow(() -> new EntityNotFoundException(ErrorCode.FOOD_TRUCK_NOT_FOUND)); + foodTruck.validateApprovedStatus(); + switch(member.getRole()) { case MEMBER -> foodTruck.validateViewableStatusForMember(); case OWNER -> foodTruck.vaildateViewableStatusForOwner(member.getUserId()); diff --git a/src/main/java/konkuk/chacall/global/common/swagger/SwaggerResponseDescription.java b/src/main/java/konkuk/chacall/global/common/swagger/SwaggerResponseDescription.java index 870254d..eb65e19 100644 --- a/src/main/java/konkuk/chacall/global/common/swagger/SwaggerResponseDescription.java +++ b/src/main/java/konkuk/chacall/global/common/swagger/SwaggerResponseDescription.java @@ -251,7 +251,8 @@ public enum SwaggerResponseDescription { USER_FORBIDDEN, FOOD_TRUCK_NOT_FOUND, FOOD_TRUCK_NOT_OWNED, - FOOD_TRUCK_NOT_VIEWABLE + FOOD_TRUCK_NOT_VIEWABLE, + FOOD_TRUCK_NOT_APPROVED ))), SEARCH_FOOD_TRUCK_MENUS(new LinkedHashSet<>(Set.of( USER_NOT_FOUND, From f892e233c93b887a1d2c4739ad612f9b2572d93d Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Thu, 30 Oct 2025 01:14:38 +0900 Subject: [PATCH 09/11] =?UTF-8?q?[refactor]=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=20=EC=98=A4=ED=83=80=20=EC=88=98=EC=A0=95=20+=20=EC=BF=BC?= =?UTF-8?q?=EB=A6=AC=EB=AC=B8=20=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(#53)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../foodtruck/application/info/FoodTruckInfoService.java | 2 +- .../chacall/domain/foodtruck/domain/model/FoodTruck.java | 2 +- .../member/domain/repository/SavedFoodTruckRepository.java | 5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/konkuk/chacall/domain/foodtruck/application/info/FoodTruckInfoService.java b/src/main/java/konkuk/chacall/domain/foodtruck/application/info/FoodTruckInfoService.java index 22bf899..60f6d79 100644 --- a/src/main/java/konkuk/chacall/domain/foodtruck/application/info/FoodTruckInfoService.java +++ b/src/main/java/konkuk/chacall/domain/foodtruck/application/info/FoodTruckInfoService.java @@ -143,7 +143,7 @@ public FoodTruckDetailResponse getFoodTruckDetails(User member, Long foodTruckId switch(member.getRole()) { case MEMBER -> foodTruck.validateViewableStatusForMember(); - case OWNER -> foodTruck.vaildateViewableStatusForOwner(member.getUserId()); + case OWNER -> foodTruck.validateViewableStatusForOwner(member.getUserId()); case ADMIN -> {} } diff --git a/src/main/java/konkuk/chacall/domain/foodtruck/domain/model/FoodTruck.java b/src/main/java/konkuk/chacall/domain/foodtruck/domain/model/FoodTruck.java index 545752e..aa13f09 100644 --- a/src/main/java/konkuk/chacall/domain/foodtruck/domain/model/FoodTruck.java +++ b/src/main/java/konkuk/chacall/domain/foodtruck/domain/model/FoodTruck.java @@ -169,7 +169,7 @@ public void validateViewableStatusForMember() { } } - public void vaildateViewableStatusForOwner(Long userId) { + public void validateViewableStatusForOwner(Long userId) { if(!isOwnedBy(userId)) { // 자신이 소유한 푸드트럭이 아니면 validateViewableStatusForMember(); } diff --git a/src/main/java/konkuk/chacall/domain/member/domain/repository/SavedFoodTruckRepository.java b/src/main/java/konkuk/chacall/domain/member/domain/repository/SavedFoodTruckRepository.java index c723c77..089cb30 100644 --- a/src/main/java/konkuk/chacall/domain/member/domain/repository/SavedFoodTruckRepository.java +++ b/src/main/java/konkuk/chacall/domain/member/domain/repository/SavedFoodTruckRepository.java @@ -52,9 +52,10 @@ Set findSavedTruckIdsIn(@Param("userId") Long userId, select exists ( select s from SavedFoodTruck s - where s.member.userId = :memberId + where s.member.userId = :userId and s.foodTruck.foodTruckId = :foodTruckId ) """) - boolean existsByMemberIdAndFoodTruckId(Long userId, Long foodTruckId); + boolean existsByMemberIdAndFoodTruckId(@Param("userId") Long userId, + @Param("foodTruckId") Long foodTruckId); } From b53bdf171f5f23dd42326ad74bc23c13444b3237 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Thu, 30 Oct 2025 01:15:05 +0900 Subject: [PATCH 10/11] =?UTF-8?q?[refactor]=20=EC=B5=9C=EC=8B=A0=EC=88=9C?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=A9=94=EB=89=B4=20=EA=B2=80=EC=83=89?= =?UTF-8?q?=EB=90=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95=20(#53)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/foodtruck/domain/repository/MenuRepository.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/konkuk/chacall/domain/foodtruck/domain/repository/MenuRepository.java b/src/main/java/konkuk/chacall/domain/foodtruck/domain/repository/MenuRepository.java index e12c011..b2d3691 100644 --- a/src/main/java/konkuk/chacall/domain/foodtruck/domain/repository/MenuRepository.java +++ b/src/main/java/konkuk/chacall/domain/foodtruck/domain/repository/MenuRepository.java @@ -76,7 +76,8 @@ Optional findByMenuIdAndFoodTruckId(@Param("menuId") Long menuId, from Menu m where m.foodTruck.foodTruckId = :foodTruckId and m.name like concat('%', :keyword, '%') - and m.menuViewedStatus = konkuk.chacall.domain.foodtruck.domain.value.MenuViewedStatus.ON + and m.menuViewedStatus = konkuk.chacall.domain.foodtruck.domain.value.MenuViewedStatus.ON + order by m.menuId desc """) List searchByKeyword(Long foodTruckId, String keyword); } From cb6894bf3e365a4fc3d48656767c92ebcc6a469e Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Thu, 30 Oct 2025 15:07:23 +0900 Subject: [PATCH 11/11] =?UTF-8?q?[refactor]=20=ED=91=B8=EB=93=9C=ED=8A=B8?= =?UTF-8?q?=EB=9F=AD=20=EC=83=81=EC=84=B8=EC=A1=B0=ED=9A=8C=20API=20?= =?UTF-8?q?=EC=97=94=EB=93=9C=ED=8F=AC=EC=9D=B8=ED=8A=B8=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20(#53)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/foodtruck/presentation/FoodTruckController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/konkuk/chacall/domain/foodtruck/presentation/FoodTruckController.java b/src/main/java/konkuk/chacall/domain/foodtruck/presentation/FoodTruckController.java index f7ee762..c84df2e 100644 --- a/src/main/java/konkuk/chacall/domain/foodtruck/presentation/FoodTruckController.java +++ b/src/main/java/konkuk/chacall/domain/foodtruck/presentation/FoodTruckController.java @@ -137,7 +137,7 @@ public BaseResponse deleteFoodTruckImagesFromS3( description = "푸드트럭의 상세 정보를 조회합니다." ) @ExceptionDescription(SwaggerResponseDescription.GET_FOOD_TRUCK_DETAILS) - @GetMapping("/{foodTruckId}/details") + @GetMapping("/{foodTruckId}") public BaseResponse getFoodTruckDetails( @Parameter(description = "푸드트럭 ID", example = "1") @PathVariable final Long foodTruckId, @Parameter(hidden = true) @UserId final Long memberId