From 6f4ac28ff91c12551e23f54b2510a7c4d8cf0eb0 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Thu, 30 Oct 2025 02:15:20 +0900 Subject: [PATCH 1/7] =?UTF-8?q?[feat]=20request=20enum=20=ED=8C=8C?= =?UTF-8?q?=EC=8B=B1=EC=9D=84=20=EC=9C=84=ED=95=9C=20static=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EC=B6=94=EA=B0=80=20(#55)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../foodtruck/domain/value/FoodTruckStatus.java | 12 ++++++++++++ .../global/common/exception/code/ErrorCode.java | 1 + 2 files changed, 13 insertions(+) diff --git a/src/main/java/konkuk/chacall/domain/foodtruck/domain/value/FoodTruckStatus.java b/src/main/java/konkuk/chacall/domain/foodtruck/domain/value/FoodTruckStatus.java index 5687631..c8da52e 100644 --- a/src/main/java/konkuk/chacall/domain/foodtruck/domain/value/FoodTruckStatus.java +++ b/src/main/java/konkuk/chacall/domain/foodtruck/domain/value/FoodTruckStatus.java @@ -1,5 +1,8 @@ package konkuk.chacall.domain.foodtruck.domain.value; +import com.fasterxml.jackson.annotation.JsonCreator; +import konkuk.chacall.global.common.exception.DomainRuleException; +import konkuk.chacall.global.common.exception.code.ErrorCode; import lombok.Getter; import lombok.RequiredArgsConstructor; @@ -11,4 +14,13 @@ public enum FoodTruckStatus { REJECTED("승인 거부"); // 관리자가 승인을 거부한 상태 private final String description; + + public static FoodTruckStatus from(String status) { + for (FoodTruckStatus foodTruckStatus : FoodTruckStatus.values()) { + if (foodTruckStatus.getDescription().equals(status)) { + return foodTruckStatus; + } + } + throw new DomainRuleException(ErrorCode.FOOD_TRUCK_STATUS_MISMATCH); + } } \ No newline at end of file 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..beffb51 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_STATUS_MISMATCH(HttpStatus.BAD_REQUEST, 110010, "푸드트럭 상태 값이 올바르지 않습니다."), /** * Image From 686bf323e8e95c1be5adaf2b801225b04723cddd Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Thu, 30 Oct 2025 02:15:36 +0900 Subject: [PATCH 2/7] =?UTF-8?q?[feat]=20=EC=9A=B4=EC=98=81=EC=9E=90?= =?UTF-8?q?=EC=9A=A9=20=EC=84=9C=EB=B9=84=EC=8A=A4=20=EB=82=B4=EC=97=90=20?= =?UTF-8?q?=EB=AA=A8=EB=93=A0=20=ED=91=B8=EB=93=9C=ED=8A=B8=EB=9F=AD=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20api=20=EA=B5=AC=ED=98=84=20(#55)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/user/application/UserService.java | 10 +++++ .../user/application/admin/AdminService.java | 39 +++++++++++++++++++ .../user/presentation/UserController.java | 19 ++++++++- 3 files changed, 67 insertions(+), 1 deletion(-) diff --git a/src/main/java/konkuk/chacall/domain/user/application/UserService.java b/src/main/java/konkuk/chacall/domain/user/application/UserService.java index 3e8852e..c8ba1a8 100644 --- a/src/main/java/konkuk/chacall/domain/user/application/UserService.java +++ b/src/main/java/konkuk/chacall/domain/user/application/UserService.java @@ -1,11 +1,13 @@ package konkuk.chacall.domain.user.application; +import konkuk.chacall.domain.foodtruck.presentation.dto.response.FoodTruckResponse; import konkuk.chacall.domain.user.application.admin.AdminService; import konkuk.chacall.domain.user.application.validator.AdminValidator; import konkuk.chacall.domain.user.presentation.dto.request.ApproveFoodTruckStatusRequest; import konkuk.chacall.domain.user.domain.model.User; import konkuk.chacall.domain.user.domain.repository.UserRepository; import konkuk.chacall.domain.user.presentation.dto.request.UpdateUserInfoRequest; +import konkuk.chacall.domain.user.presentation.dto.response.FoodTruckForAdminResponse; import konkuk.chacall.domain.user.presentation.dto.response.UserResponse; import konkuk.chacall.global.common.exception.EntityNotFoundException; import konkuk.chacall.global.common.exception.code.ErrorCode; @@ -17,6 +19,8 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.List; + @Service @RequiredArgsConstructor @Transactional(readOnly = true) @@ -62,4 +66,10 @@ public ImageResponse createUserImagePresignedUrl(Long userId, ImageRequest reque KeyUtils::buildUserProfileImageKey ); } + + public List getAllFoodTrucks(Long userId, String status) { + adminValidator.validateAdmin(userId); + + return adminService.getAllFoodTrucks(status); + } } diff --git a/src/main/java/konkuk/chacall/domain/user/application/admin/AdminService.java b/src/main/java/konkuk/chacall/domain/user/application/admin/AdminService.java index 93b996d..e292ec0 100644 --- a/src/main/java/konkuk/chacall/domain/user/application/admin/AdminService.java +++ b/src/main/java/konkuk/chacall/domain/user/application/admin/AdminService.java @@ -1,18 +1,27 @@ package konkuk.chacall.domain.user.application.admin; import konkuk.chacall.domain.foodtruck.domain.model.FoodTruck; +import konkuk.chacall.domain.foodtruck.domain.model.FoodTruckDocument; +import konkuk.chacall.domain.foodtruck.domain.repository.FoodTruckDocumentRepository; import konkuk.chacall.domain.foodtruck.domain.repository.FoodTruckRepository; +import konkuk.chacall.domain.foodtruck.domain.value.FoodTruckStatus; import konkuk.chacall.domain.user.presentation.dto.request.ApproveFoodTruckStatusRequest; +import konkuk.chacall.domain.user.presentation.dto.response.FoodTruckForAdminResponse; import konkuk.chacall.global.common.exception.EntityNotFoundException; import konkuk.chacall.global.common.exception.code.ErrorCode; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + @Service @RequiredArgsConstructor public class AdminService { private final FoodTruckRepository foodTruckRepository; + private final FoodTruckDocumentRepository foodTruckDocumentRepository; public void approveFoodTruckStatus(Long foodTruckId, ApproveFoodTruckStatusRequest request) { FoodTruck foodTruck = foodTruckRepository.findById(foodTruckId) @@ -21,4 +30,34 @@ public void approveFoodTruckStatus(Long foodTruckId, ApproveFoodTruckStatusReque foodTruck.approveFoodTruck(request.status()); } + public List getAllFoodTrucks(String status) { + List foodTruckList; + + if(status != null && !status.isEmpty()) { + FoodTruckStatus foodTruckStatus = FoodTruckStatus.from(status); + foodTruckList = foodTruckRepository.findAllByFoodTruckStatus(foodTruckStatus); + } else { + foodTruckList = foodTruckRepository.findAll(); + } + + Map> documentMap = foodTruckDocumentRepository.findAllInFoodTruckIds( + foodTruckList.stream() + .map(FoodTruck::getFoodTruckId) + .toList() + ).stream() + .collect( + Collectors.groupingBy(document -> document.getFoodTruck().getFoodTruckId()) + ); + + + return foodTruckList.stream() + .map(foodTruck -> FoodTruckForAdminResponse.from( + foodTruck, + documentMap.getOrDefault(foodTruck.getFoodTruckId(), List.of()).stream() + .map(FoodTruckDocument::getDocumentUrl) + .collect(Collectors.toList()) + ) + ) + .collect(Collectors.toList()); + } } diff --git a/src/main/java/konkuk/chacall/domain/user/presentation/UserController.java b/src/main/java/konkuk/chacall/domain/user/presentation/UserController.java index fedfdac..4a60566 100644 --- a/src/main/java/konkuk/chacall/domain/user/presentation/UserController.java +++ b/src/main/java/konkuk/chacall/domain/user/presentation/UserController.java @@ -7,6 +7,7 @@ import konkuk.chacall.domain.user.presentation.dto.request.ApproveFoodTruckStatusRequest; import konkuk.chacall.domain.user.application.UserService; import konkuk.chacall.domain.user.presentation.dto.request.UpdateUserInfoRequest; +import konkuk.chacall.domain.user.presentation.dto.response.FoodTruckForAdminResponse; import konkuk.chacall.domain.user.presentation.dto.response.UserResponse; import konkuk.chacall.global.common.annotation.ExceptionDescription; import konkuk.chacall.global.common.annotation.UserId; @@ -17,6 +18,8 @@ import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; +import java.util.List; + @Tag(name = "User API", description = "전체 사용자(마이페이지) 관련 API") @RestController @RequestMapping("/users") @@ -53,7 +56,7 @@ public BaseResponse updateUserInfo( } @Operation( - summary = "푸드트럭 승인 상태 변경", + summary = "[운영자용] 푸드트럭 승인 상태 변경", description = "운영자 - 푸드트럭 승인 상태를 변경합니다." ) @ExceptionDescription(SwaggerResponseDescription.APPROVE_FOOD_TRUCK_STATUS) @@ -79,4 +82,18 @@ public BaseResponse getProfilePresignedUrl( ) { return BaseResponse.ok(userService.createUserImagePresignedUrl(userId, request)); } + + @Operation( + summary = "[운영자용] 서비스내에 모든 푸드트럭 조회", + description = "운영자 - 서비스내에 모든 푸드트럭을 조회합니다." + ) + @ExceptionDescription(SwaggerResponseDescription.GET_ALL_FOOD_TRUCKS) + @GetMapping("/admin/food-trucks") + public BaseResponse> getAllFoodTrucks ( + @Parameter(hidden = true) @UserId final Long userId, + @Parameter(description = "푸드트럭 승인 상태 필터링 (APPROVED, PENDING, REJECTED) / 안 보낼 경우 전체", example = "APPROVED") + @RequestParam(required = false) final String status + ) { + return BaseResponse.ok(userService.getAllFoodTrucks(userId, status)); + } } From 68f1181f41614b07ccd3b401788989c934a8cb9e Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Thu, 30 Oct 2025 02:15:48 +0900 Subject: [PATCH 3/7] =?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(#55)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/repository/FoodTruckDocumentRepository.java | 10 ++++++++++ .../domain/repository/FoodTruckRepository.java | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/src/main/java/konkuk/chacall/domain/foodtruck/domain/repository/FoodTruckDocumentRepository.java b/src/main/java/konkuk/chacall/domain/foodtruck/domain/repository/FoodTruckDocumentRepository.java index 44d77d8..97f49b0 100644 --- a/src/main/java/konkuk/chacall/domain/foodtruck/domain/repository/FoodTruckDocumentRepository.java +++ b/src/main/java/konkuk/chacall/domain/foodtruck/domain/repository/FoodTruckDocumentRepository.java @@ -2,6 +2,16 @@ import konkuk.chacall.domain.foodtruck.domain.model.FoodTruckDocument; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +import java.util.Collection; +import java.util.List; public interface FoodTruckDocumentRepository extends JpaRepository { + @Query(""" + SELECT ftd + FROM FoodTruckDocument ftd + WHERE ftd.foodTruck.foodTruckId IN :foodTruckIds + """) + List findAllInFoodTruckIds(List foodTruckIds); } diff --git a/src/main/java/konkuk/chacall/domain/foodtruck/domain/repository/FoodTruckRepository.java b/src/main/java/konkuk/chacall/domain/foodtruck/domain/repository/FoodTruckRepository.java index 740d120..79370a7 100644 --- a/src/main/java/konkuk/chacall/domain/foodtruck/domain/repository/FoodTruckRepository.java +++ b/src/main/java/konkuk/chacall/domain/foodtruck/domain/repository/FoodTruckRepository.java @@ -5,10 +5,12 @@ import konkuk.chacall.domain.foodtruck.domain.value.FoodTruckStatus; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; +import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; +import java.util.List; import java.util.Optional; public interface FoodTruckRepository extends JpaRepository, FoodTruckSearchRepository { @@ -46,4 +48,6 @@ boolean existsByFoodTruckIdAndOwnerIdAndFoodTruckStatus( boolean existsByFoodTruckInfo_Name(String name); + @EntityGraph(attributePaths = {"owner"}) + List findAllByFoodTruckStatus(FoodTruckStatus foodTruckStatus); } From 20c1f102af33740cac4a1067bfedebde230ccd16 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Thu, 30 Oct 2025 02:15:58 +0900 Subject: [PATCH 4/7] =?UTF-8?q?[docs]=20dto=20=EC=84=A0=EC=96=B8=20?= =?UTF-8?q?=EB=B0=8F=20api=20=EB=AA=85=EC=84=B8=20(#55)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../response/FoodTruckForAdminResponse.java | 29 +++++++++++++++++++ .../swagger/SwaggerResponseDescription.java | 4 +++ 2 files changed, 33 insertions(+) create mode 100644 src/main/java/konkuk/chacall/domain/user/presentation/dto/response/FoodTruckForAdminResponse.java diff --git a/src/main/java/konkuk/chacall/domain/user/presentation/dto/response/FoodTruckForAdminResponse.java b/src/main/java/konkuk/chacall/domain/user/presentation/dto/response/FoodTruckForAdminResponse.java new file mode 100644 index 0000000..a5ea269 --- /dev/null +++ b/src/main/java/konkuk/chacall/domain/user/presentation/dto/response/FoodTruckForAdminResponse.java @@ -0,0 +1,29 @@ +package konkuk.chacall.domain.user.presentation.dto.response; + +import io.swagger.v3.oas.annotations.media.Schema; +import konkuk.chacall.domain.foodtruck.domain.model.FoodTruck; + +import java.util.List; + +public record FoodTruckForAdminResponse( + @Schema(description = "푸드트럭 ID", example = "1") + Long foodTruckId, + @Schema(description = "푸드트럭 이름", example = "차콜 푸드트럭") + String foodTruckName, + @Schema(description = "푸드트럭 사장님 이름", example = "홍길동") + String ownerName, + @Schema(description = "푸드트럭 상태", example = "승인 대기") + String foodTruckStatus, + @Schema(description = "푸드트럭 서류 URL 목록 (사업자 등록증 포함)", example = "[\"https://cdn.chacall.com/foodtrucks/osori/doc1.jpg\", \"https://cdn.chacall.com/foodtrucks/osori/doc2.jpg\", \"https://cdn.chacall.com/foodtrucks/osori/doc3.jpg\", \"https://cdn.chacall.com/foodtrucks/osori/doc4.jpg\", \"https://cdn.chacall.com/foodtrucks/osori/doc5.jpg\"]") + List foodTruckDocumentUrls +) { + public static FoodTruckForAdminResponse from(FoodTruck foodTruck, List foodTruckDocumentUrls) { + return new FoodTruckForAdminResponse( + foodTruck.getFoodTruckId(), + foodTruck.getFoodTruckInfo().getName(), + foodTruck.getOwner().getName(), + foodTruck.getFoodTruckStatus().getDescription(), + foodTruckDocumentUrls + ); + } +} 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..43f675b 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,10 @@ public enum SwaggerResponseDescription { FOOD_TRUCK_NOT_FOUND, FOOD_TRUCK_NOT_OWNED ))), + GET_ALL_FOOD_TRUCKS(new LinkedHashSet<>(Set.of( + USER_NOT_FOUND, + USER_FORBIDDEN + ))), // Default DEFAULT(new LinkedHashSet<>()) From 26d494cd6621a3e997f3114a8c0cd2da74ac9b35 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Thu, 30 Oct 2025 14:57:44 +0900 Subject: [PATCH 5/7] =?UTF-8?q?[refactor]=20findAll=20=EC=98=A4=EB=B2=84?= =?UTF-8?q?=EB=9D=BC=EC=9D=B4=EB=93=9C=20(#55)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../foodtruck/domain/repository/FoodTruckRepository.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/konkuk/chacall/domain/foodtruck/domain/repository/FoodTruckRepository.java b/src/main/java/konkuk/chacall/domain/foodtruck/domain/repository/FoodTruckRepository.java index 79370a7..a197eb7 100644 --- a/src/main/java/konkuk/chacall/domain/foodtruck/domain/repository/FoodTruckRepository.java +++ b/src/main/java/konkuk/chacall/domain/foodtruck/domain/repository/FoodTruckRepository.java @@ -50,4 +50,7 @@ boolean existsByFoodTruckIdAndOwnerIdAndFoodTruckStatus( @EntityGraph(attributePaths = {"owner"}) List findAllByFoodTruckStatus(FoodTruckStatus foodTruckStatus); + + @EntityGraph(attributePaths = {"owner"}) + List findAll(); } From e15191807c55d088e9849afa2ad4fb332c38b0dd Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Thu, 30 Oct 2025 15:09:36 +0900 Subject: [PATCH 6/7] =?UTF-8?q?[docs]=20=EC=9E=98=EB=AA=BB=EB=90=9C=20api?= =?UTF-8?q?=20=EB=AA=85=EC=84=B8=20=EC=88=98=EC=A0=95=20(#55)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../konkuk/chacall/domain/user/presentation/UserController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/konkuk/chacall/domain/user/presentation/UserController.java b/src/main/java/konkuk/chacall/domain/user/presentation/UserController.java index 4a60566..759daa9 100644 --- a/src/main/java/konkuk/chacall/domain/user/presentation/UserController.java +++ b/src/main/java/konkuk/chacall/domain/user/presentation/UserController.java @@ -91,7 +91,7 @@ public BaseResponse getProfilePresignedUrl( @GetMapping("/admin/food-trucks") public BaseResponse> getAllFoodTrucks ( @Parameter(hidden = true) @UserId final Long userId, - @Parameter(description = "푸드트럭 승인 상태 필터링 (APPROVED, PENDING, REJECTED) / 안 보낼 경우 전체", example = "APPROVED") + @Parameter(description = "푸드트럭 승인 상태 필터링 (승인 대기, 승인 완료, 승인 거절)", example = "승인 대기") @RequestParam(required = false) final String status ) { return BaseResponse.ok(userService.getAllFoodTrucks(userId, status)); From 8cd4535f07c879f797a3407c0043db42ccbb7dc9 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Thu, 30 Oct 2025 15:16:16 +0900 Subject: [PATCH 7/7] =?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=EC=88=98=EC=A0=95=20(#55)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chacall/domain/user/presentation/UserController.java | 2 +- .../global/common/swagger/SwaggerResponseDescription.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/konkuk/chacall/domain/user/presentation/UserController.java b/src/main/java/konkuk/chacall/domain/user/presentation/UserController.java index 759daa9..4b705b1 100644 --- a/src/main/java/konkuk/chacall/domain/user/presentation/UserController.java +++ b/src/main/java/konkuk/chacall/domain/user/presentation/UserController.java @@ -91,7 +91,7 @@ public BaseResponse getProfilePresignedUrl( @GetMapping("/admin/food-trucks") public BaseResponse> getAllFoodTrucks ( @Parameter(hidden = true) @UserId final Long userId, - @Parameter(description = "푸드트럭 승인 상태 필터링 (승인 대기, 승인 완료, 승인 거절)", example = "승인 대기") + @Parameter(description = "푸드트럭 승인 상태 필터링 (승인 대기, 승인 완료, 승인 거부)", example = "승인 대기") @RequestParam(required = false) final String status ) { return BaseResponse.ok(userService.getAllFoodTrucks(userId, status)); 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 43f675b..c99cfff 100644 --- a/src/main/java/konkuk/chacall/global/common/swagger/SwaggerResponseDescription.java +++ b/src/main/java/konkuk/chacall/global/common/swagger/SwaggerResponseDescription.java @@ -248,7 +248,8 @@ public enum SwaggerResponseDescription { ))), GET_ALL_FOOD_TRUCKS(new LinkedHashSet<>(Set.of( USER_NOT_FOUND, - USER_FORBIDDEN + USER_FORBIDDEN, + FOOD_TRUCK_STATUS_MISMATCH ))), // Default