From 1185503e0088fe2afa4ee68255981c8370202eb1 Mon Sep 17 00:00:00 2001 From: Ga Dong Sik <62535229+Nesquitto@users.noreply.github.com> Date: Fri, 16 Feb 2024 18:32:20 +0900 Subject: [PATCH] =?UTF-8?q?[SPR-152]=20feat:=20=EC=95=94=EC=9E=A5=20?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [SPR-152] feat: 프로필 변경, 암장 서비스 변경기능 구현 * [SPR-152] feat: 암장 배경, 프로필 사진, 서비스 수정기능 구현 * [SPR-152] feat: 암장 약도, 가격표 데이터 추가 및 수정기능 구현 * [SPR-152] feat: SwaggerApiError 추가 --- config | 2 +- .../domain/climbinggym/ClimbingGym.java | 15 ++- .../climbinggym/ClimbingGymController.java | 52 +++++++-- .../climbinggym/ClimbingGymService.java | 103 ++++++++++++++---- .../dto/ClimbingGymRequestDto.java | 16 ++- .../dto/ClimbingGymResponseDto.java | 17 ++- .../ClimbingGymBackgroundImage.java | 3 + 7 files changed, 172 insertions(+), 36 deletions(-) diff --git a/config b/config index 81a056cf..b908762a 160000 --- a/config +++ b/config @@ -1 +1 @@ -Subproject commit 81a056cf4fc7cfe272326db676f877c8c0ce3193 +Subproject commit b908762a280f31ed06b7953269e516770f7910c1 diff --git a/src/main/java/com/climeet/climeet_backend/domain/climbinggym/ClimbingGym.java b/src/main/java/com/climeet/climeet_backend/domain/climbinggym/ClimbingGym.java index 65a65840..eae2db87 100644 --- a/src/main/java/com/climeet/climeet_backend/domain/climbinggym/ClimbingGym.java +++ b/src/main/java/com/climeet/climeet_backend/domain/climbinggym/ClimbingGym.java @@ -41,6 +41,10 @@ public class ClimbingGym extends BaseTimeEntity { private String profileImageUrl; + public void updateProfileImageUrl(String profileImageUrl) { + this.profileImageUrl = profileImageUrl; + } + private Float AverageRating = 0.0F; private Float sumRating = 0.0F; @@ -51,15 +55,24 @@ public class ClimbingGym extends BaseTimeEntity { private String address; + private String location; + @Column(columnDefinition = "json") private String businessHours; + @Column(columnDefinition = "json") + private String priceList; + public void updateGymInfo(String tel, String address, String businessHours) { this.tel = tel; this.address = address; this.businessHours = businessHours; } + public void updateGymPriceList(String priceList) { + this.priceList = priceList; + } + public void reviewCreate(Float rating) { this.sumRating += rating; @@ -90,7 +103,7 @@ public void averageRatingCalculate() { private int serviceBitMask = 0; - public void updateServiceBitMask(int value){ + public void updateServiceBitMask(int value) { this.serviceBitMask = value; } diff --git a/src/main/java/com/climeet/climeet_backend/domain/climbinggym/ClimbingGymController.java b/src/main/java/com/climeet/climeet_backend/domain/climbinggym/ClimbingGymController.java index c4495dca..5f8e8837 100644 --- a/src/main/java/com/climeet/climeet_backend/domain/climbinggym/ClimbingGymController.java +++ b/src/main/java/com/climeet/climeet_backend/domain/climbinggym/ClimbingGymController.java @@ -1,6 +1,7 @@ package com.climeet.climeet_backend.domain.climbinggym; -import com.climeet.climeet_backend.domain.climbinggym.dto.ClimbingGymRequestDto.UpdateClimbingGymInfoRequest; +import com.climeet.climeet_backend.domain.climbinggym.dto.ClimbingGymRequestDto.UpdateClimbingGymPriceRequest; +import com.climeet.climeet_backend.domain.climbinggym.dto.ClimbingGymRequestDto.UpdateClimbingGymServiceRequest; import com.climeet.climeet_backend.domain.climbinggym.dto.ClimbingGymResponseDto.AcceptedClimbingGymSimpleResponse; import com.climeet.climeet_backend.domain.climbinggym.dto.ClimbingGymResponseDto.AcceptedClimbingGymSimpleResponseWithFollow; import com.climeet.climeet_backend.domain.climbinggym.dto.ClimbingGymResponseDto.ClimbingGymAverageLevelDetailResponse; @@ -19,12 +20,15 @@ import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; @Tag(name = "ClimbingGym", description = "암장 관련 API") @RestController @@ -60,7 +64,7 @@ public ResponseEntity getClimbingGymInfo( } - @Operation(summary = "암장 프로필 정보 (탭) 불러오기") + @Operation(summary = "암장 프로필 정보 (탭) 불러오기", description = "탭에 들어가는 데이터는 null이 존재할 가능성이 상당히 높습니다.\n 또한 영업시간에서 특정 요일만 값이 없다면 정기휴일입니다.") @SwaggerApiError({ErrorStatus._EMPTY_CLIMBING_GYM, ErrorStatus._ERROR_JSON_PARSE}) @GetMapping("/{gymId}/tab") public ResponseEntity getClimbingGymTabInfo( @@ -69,23 +73,58 @@ public ResponseEntity getClimbingGymTabInfo( } @Operation(summary = "암장 크롤링 정보 입력") - @PostMapping("/info") + @PostMapping("/{gymId}/info") public ResponseEntity updateClimbingGymInfo( - @RequestBody UpdateClimbingGymInfoRequest updateClimbingGymInfoRequest) { + @PathVariable Long gymId) { return ResponseEntity.ok( - climbingGymService.updateClimbingGymInfo(updateClimbingGymInfoRequest)); + climbingGymService.updateClimbingGymInfo(gymId)); } @Operation(summary = "암장 실력분포 조회") @SwaggerApiError({ErrorStatus._EMPTY_CLIMBING_GYM, ErrorStatus._EMPTY_AVERAGE_LEVEL_DATA}) - @GetMapping("/{gymId}/graph/level") + @GetMapping("/{gymId}/skill-distribution") public ResponseEntity> getFollowingUserAverageLevelInClimbingGym( @PathVariable Long gymId, @CurrentUser User user) { return ResponseEntity.ok( climbingGymService.getFollowingUserAverageLevelInClimbingGym(gymId)); } + @Operation(summary = "암장 배경사진 변경 (1개만 등록 가능)") + @SwaggerApiError({ErrorStatus._EMPTY_MANAGER, ErrorStatus._EMPTY_BACKGROUND_IMAGE}) + @PatchMapping("/background-image") + public ResponseEntity changeClimbingGymBackgroundImage(@CurrentUser User user, + @RequestPart MultipartFile image) { + return ResponseEntity.ok(climbingGymService.changeClimbingGymBackgroundImage(user, image)); + } + + @Operation(summary = "암장 프로필 이미지 변경 (1개만 등록 가능)") + @SwaggerApiError({ErrorStatus._EMPTY_MANAGER}) + @PatchMapping("/profile-image") + public ResponseEntity changeClimbingGymProfileImage(@CurrentUser User user, + @RequestPart MultipartFile image) { + return ResponseEntity.ok(climbingGymService.changeClimbingGymProfileImage(user, image)); + } + + @Operation(summary = "암장 제공 서비스 수정", description = "**Enum 설명**\n\n**ServiceBitmask** : 샤워\\_시설, 샤워\\_용품, 수건\\_제공, 간이\\_세면대, 초크\\_대여, 암벽화\\_대여, 삼각대\\_대여, 운동복\\_대여") + @SwaggerApiError({ErrorStatus._EMPTY_MANAGER}) + @PatchMapping("/service") + public ResponseEntity updateClimbingGymService(@CurrentUser User user, + @RequestBody UpdateClimbingGymServiceRequest updateClimbingGymServiceRequest) { + climbingGymService.updateClimbingGymService(user, updateClimbingGymServiceRequest); + return ResponseEntity.ok("암장 제공 서비스를 정상적으로 변경했습니다."); + } + + @Operation(summary = "기본 가격(제공) 추가 & 수정") + @SwaggerApiError({ErrorStatus._EMPTY_MANAGER, ErrorStatus._ERROR_JSON_PARSE}) + @PostMapping("/price") + public ResponseEntity updateClimbingGymPrice(@CurrentUser User user, + @RequestBody UpdateClimbingGymPriceRequest updateClimbingGymPriceRequest) { + climbingGymService.updateClimbingGymPrice(user, updateClimbingGymPriceRequest); + return ResponseEntity.ok("암장 기본 제공을 정상적으로 변경했습니다."); + } + @Operation(summary = "Manager가 등록된 암장 검색 기능 + 팔로잉 여부") + @SwaggerApiError({}) @GetMapping("/search/follow") public ResponseEntity>> getAcceptedClimbingGymSearchingListWithFollow( @RequestParam("gymname") String gymName, @RequestParam int page, @RequestParam int size, @@ -95,5 +134,4 @@ public ResponseEntity>>() { }); + Map priceList = objectMapper.readValue( + climbingGym.getPriceList(), + new TypeReference>() { + }); return ClimbingGymTabInfoResponse.toDTO(climbingGymRepository.save(climbingGym), - businessHoursMap, serviceList); + businessHoursMap, serviceList, priceList); } catch (Exception e) { throw new GeneralException(ErrorStatus._ERROR_JSON_PARSE); } } - public ClimbingGymInfoResponse updateClimbingGymInfo( - - UpdateClimbingGymInfoRequest updateClimbingGymInfoRequest) { - ClimbingGym climbingGym = climbingGymRepository.findById( - updateClimbingGymInfoRequest.getGymId()) + public ClimbingGymInfoResponse updateClimbingGymInfo(Long gymId) { + ClimbingGym climbingGym = climbingGymRepository.findById(gymId) .orElseThrow(() -> new GeneralException(ErrorStatus._EMPTY_CLIMBING_GYM)); RestClient restClient = RestClient.create(); @@ -205,23 +213,55 @@ public List getFollowingUserAverageLevelI .toList(); } - private DifficultyMapping getClosestGymDifficulty(Integer level, - List difficultyMappingList) { - DifficultyMapping difficulty = null; - int minDifference = Integer.MAX_VALUE; - int closestDifficulty = Integer.MAX_VALUE; + public String changeClimbingGymBackgroundImage(User user, MultipartFile image) { + Manager manager = managerRepository.findById(user.getId()) + .orElseThrow(() -> new GeneralException(ErrorStatus._EMPTY_MANAGER)); - for (DifficultyMapping mapping : difficultyMappingList) { - int difference = Math.abs(level - mapping.getDifficulty()); - if (difference < minDifference || (difference == minDifference - && mapping.getDifficulty() < closestDifficulty)) { - minDifference = difference; - closestDifficulty = mapping.getDifficulty(); - difficulty = mapping; - } - } + ClimbingGymBackgroundImage climbingGymBackgroundImage = climbingGymBackgroundImageRepository.findByClimbingGym( + manager.getClimbingGym()) + .orElseThrow(() -> new GeneralException(ErrorStatus._EMPTY_BACKGROUND_IMAGE)); - return difficulty; + String backgroundImageUrl = s3Service.uploadFile(image).getImgUrl(); + climbingGymBackgroundImage.changeImgUrl(backgroundImageUrl); + climbingGymBackgroundImageRepository.save(climbingGymBackgroundImage); + + return backgroundImageUrl; + } + + public String changeClimbingGymProfileImage(User user, MultipartFile image) { + Manager manager = managerRepository.findById(user.getId()) + .orElseThrow(() -> new GeneralException(ErrorStatus._EMPTY_MANAGER)); + ClimbingGym climbingGym = manager.getClimbingGym(); + String profileImageUrl = s3Service.uploadFile(image).getImgUrl(); + climbingGym.updateProfileImageUrl(profileImageUrl); + climbingGymRepository.save(climbingGym); + return profileImageUrl; + } + + public void updateClimbingGymService(User user, + UpdateClimbingGymServiceRequest updateClimbingGymServiceRequest) { + Manager manager = managerRepository.findById(user.getId()) + .orElseThrow(() -> new GeneralException(ErrorStatus._EMPTY_MANAGER)); + ClimbingGym climbingGym = manager.getClimbingGym(); + climbingGym.updateServiceBitMask(bitmaskConverter.convertServiceListToBitmask( + updateClimbingGymServiceRequest.getServiceList())); + climbingGymRepository.save(climbingGym); + } + + public void updateClimbingGymPrice(User user, + UpdateClimbingGymPriceRequest updateClimbingGymPriceRequest) { + Manager manager = managerRepository.findById(user.getId()) + .orElseThrow(() -> new GeneralException(ErrorStatus._EMPTY_MANAGER)); + ClimbingGym climbingGym = manager.getClimbingGym(); + + ObjectMapper objectMapper = new ObjectMapper(); + try { + climbingGym.updateGymPriceList(objectMapper.writeValueAsString( + updateClimbingGymPriceRequest.getPriceMapList())); + climbingGymRepository.save(climbingGym); + } catch (Exception e) { + throw new GeneralException(ErrorStatus._ERROR_JSON_PARSE); + } } public PageResponseDto> searchAcceptedClimbingGymWithFollow( @@ -265,4 +305,23 @@ public PageResponseDto> search } + private DifficultyMapping getClosestGymDifficulty(Integer level, + List difficultyMappingList) { + DifficultyMapping difficulty = null; + int minDifference = Integer.MAX_VALUE; + int closestDifficulty = Integer.MAX_VALUE; + + for (DifficultyMapping mapping : difficultyMappingList) { + int difference = Math.abs(level - mapping.getDifficulty()); + if (difference < minDifference || (difference == minDifference + && mapping.getDifficulty() < closestDifficulty)) { + minDifference = difference; + closestDifficulty = mapping.getDifficulty(); + difficulty = mapping; + } + } + + return difficulty; + } + } \ No newline at end of file diff --git a/src/main/java/com/climeet/climeet_backend/domain/climbinggym/dto/ClimbingGymRequestDto.java b/src/main/java/com/climeet/climeet_backend/domain/climbinggym/dto/ClimbingGymRequestDto.java index cc4abbbd..cd54d90f 100644 --- a/src/main/java/com/climeet/climeet_backend/domain/climbinggym/dto/ClimbingGymRequestDto.java +++ b/src/main/java/com/climeet/climeet_backend/domain/climbinggym/dto/ClimbingGymRequestDto.java @@ -1,5 +1,8 @@ package com.climeet.climeet_backend.domain.climbinggym.dto; +import com.climeet.climeet_backend.domain.climbinggym.enums.ServiceBitmask; +import java.util.List; +import java.util.Map; import lombok.Getter; import lombok.NoArgsConstructor; @@ -7,8 +10,17 @@ public class ClimbingGymRequestDto { @Getter @NoArgsConstructor - public static class UpdateClimbingGymInfoRequest { - private Long gymId; + public static class UpdateClimbingGymServiceRequest { + + private List serviceList; + + } + + @Getter + @NoArgsConstructor + public static class UpdateClimbingGymPriceRequest { + + private Map priceMapList; } } diff --git a/src/main/java/com/climeet/climeet_backend/domain/climbinggym/dto/ClimbingGymResponseDto.java b/src/main/java/com/climeet/climeet_backend/domain/climbinggym/dto/ClimbingGymResponseDto.java index e24c346f..d27901b7 100644 --- a/src/main/java/com/climeet/climeet_backend/domain/climbinggym/dto/ClimbingGymResponseDto.java +++ b/src/main/java/com/climeet/climeet_backend/domain/climbinggym/dto/ClimbingGymResponseDto.java @@ -68,6 +68,7 @@ public static AcceptedClimbingGymSimpleResponse toDTO(ClimbingGym climbingGym, @AllArgsConstructor public static class ClimbingGymDetailResponse { + private Long gymId; private String gymProfileImageUrl; private String gymBackGroundImageUrl; private String gymName; @@ -79,6 +80,7 @@ public static class ClimbingGymDetailResponse { public static ClimbingGymDetailResponse toDTO(ClimbingGym climbingGym, Manager manager, String gymBackGroundImageUrl) { return ClimbingGymDetailResponse.builder() + .gymId(climbingGym.getId()) .gymProfileImageUrl(climbingGym.getProfileImageUrl()) .gymBackGroundImageUrl(gymBackGroundImageUrl) .gymName(climbingGym.getName()) @@ -98,18 +100,23 @@ public static class ClimbingGymTabInfoResponse { private Long gymId; private String address; + private String location; private String tel; private Map> businessHours; private List serviceList; + private Map priceList; public static ClimbingGymTabInfoResponse toDTO(ClimbingGym climbingGym, - Map> businessHours, List serviceList) { + Map> businessHours, List serviceList, + Map priceList) { return ClimbingGymTabInfoResponse.builder() .gymId(climbingGym.getId()) .address(climbingGym.getAddress()) + .location(climbingGym.getLocation()) .tel(climbingGym.getTel()) .businessHours(businessHours) .serviceList(serviceList) + .priceList(priceList) .build(); } } @@ -120,6 +127,7 @@ public static ClimbingGymTabInfoResponse toDTO(ClimbingGym climbingGym, @AllArgsConstructor public static class ClimbingGymInfoResponse { + private Long gymId; private String name; private String address; private String tel; @@ -128,6 +136,7 @@ public static class ClimbingGymInfoResponse { public static ClimbingGymInfoResponse toDTO(ClimbingGym climbingGym, Map> businessHours) { return ClimbingGymInfoResponse.builder() + .gymId(climbingGym.getId()) .name(climbingGym.getName()) .address(climbingGym.getAddress()) .tel(climbingGym.getTel()) @@ -142,6 +151,7 @@ public static ClimbingGymInfoResponse toDTO(ClimbingGym climbingGym, @AllArgsConstructor public static class ClimbingGymAverageLevelDetailResponse { + private Long gymId; private int difficulty; private String gymDifficultyName; private String gymDifficultyColor; @@ -150,6 +160,7 @@ public static class ClimbingGymAverageLevelDetailResponse { public static ClimbingGymAverageLevelDetailResponse toDTO( DifficultyMapping difficultyMapping, double percentage) { return ClimbingGymAverageLevelDetailResponse.builder() + .gymId(difficultyMapping.getClimbingGym().getId()) .difficulty(difficultyMapping.getDifficulty()) .gymDifficultyName(difficultyMapping.getGymDifficultyName()) .gymDifficultyColor(difficultyMapping.getGymDifficultyColor()) @@ -164,7 +175,7 @@ public static ClimbingGymAverageLevelDetailResponse toDTO( @AllArgsConstructor public static class AcceptedClimbingGymSimpleResponseWithFollow { - private Long id; + private Long gymId; private String name; private Long managerId; private Long follower; @@ -175,7 +186,7 @@ public static AcceptedClimbingGymSimpleResponseWithFollow toDTO(ClimbingGym clim Long managerId, Long follower, String profileImageUrl, boolean isFollow) { return AcceptedClimbingGymSimpleResponseWithFollow.builder() - .id(climbingGym.getId()) + .gymId(climbingGym.getId()) .name(climbingGym.getName()) .managerId(managerId) .follower(follower) diff --git a/src/main/java/com/climeet/climeet_backend/domain/climbinggymimage/ClimbingGymBackgroundImage.java b/src/main/java/com/climeet/climeet_backend/domain/climbinggymimage/ClimbingGymBackgroundImage.java index 0c219290..510dcedc 100644 --- a/src/main/java/com/climeet/climeet_backend/domain/climbinggymimage/ClimbingGymBackgroundImage.java +++ b/src/main/java/com/climeet/climeet_backend/domain/climbinggymimage/ClimbingGymBackgroundImage.java @@ -35,5 +35,8 @@ public class ClimbingGymBackgroundImage extends BaseTimeEntity { @NotNull private String imgUrl; + public void changeImgUrl(String url){ + this.imgUrl = url; + } } \ No newline at end of file