From cd3f188c4385b6301bc80030b394fff9ae6b8e71 Mon Sep 17 00:00:00 2001 From: bngsh Date: Thu, 7 Sep 2023 21:39:54 +0900 Subject: [PATCH 1/4] =?UTF-8?q?feat:=20#25=20=EC=9A=B4=EB=8F=99=20?= =?UTF-8?q?=EC=A2=85=EB=A3=8C=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../walkie/controller/WalkingController.java | 8 +++ .../com/whyranoid/walkie/dto/HistoryDto.java | 52 +++++++++++++++++++ .../querydsl/WalkingLikeRepositoryCustom.java | 3 ++ .../querydsl/WalkingLikeRepositoryImpl.java | 23 ++++++++ .../walkie/service/WalkingService.java | 13 ++++- 5 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/whyranoid/walkie/dto/HistoryDto.java diff --git a/src/main/java/com/whyranoid/walkie/controller/WalkingController.java b/src/main/java/com/whyranoid/walkie/controller/WalkingController.java index f293faf..8afc45f 100644 --- a/src/main/java/com/whyranoid/walkie/controller/WalkingController.java +++ b/src/main/java/com/whyranoid/walkie/controller/WalkingController.java @@ -1,5 +1,6 @@ package com.whyranoid.walkie.controller; +import com.whyranoid.walkie.dto.HistoryDto; import com.whyranoid.walkie.dto.WalkingDto; import com.whyranoid.walkie.dto.WalkingLikeDto; import com.whyranoid.walkie.service.WalkingService; @@ -47,4 +48,11 @@ public ResponseEntity countWalkingLike(@RequestParam Long walkieId, @Reque public ResponseEntity getTotalWalkingLike(@RequestParam Long walkieId, @RequestParam String authId) { return ResponseEntity.ok(walkingService.getTotalWalkingLike(walkieId, authId)); } + + @Operation(description = "운동 종료 시 데이터 저장하기") + @ApiResponse(description = "저장 성공 시 기록의 DB pk값, 실패 시 -1") + @PostMapping("/save") + public ResponseEntity saveWalkingHistory(@RequestBody HistoryDto historyDto) { + return ResponseEntity.ok(walkingService.saveWalkingHistory(historyDto)); + } } diff --git a/src/main/java/com/whyranoid/walkie/dto/HistoryDto.java b/src/main/java/com/whyranoid/walkie/dto/HistoryDto.java new file mode 100644 index 0000000..17153c5 --- /dev/null +++ b/src/main/java/com/whyranoid/walkie/dto/HistoryDto.java @@ -0,0 +1,52 @@ +package com.whyranoid.walkie.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class HistoryDto { + + @Schema(description = "요청 필수 파라미터 - 워키 아이디", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") + private Long walkieId; + + @Schema(description = "요청 필수 파라미터 - 구글 uid", requiredMode = Schema.RequiredMode.REQUIRED, example = "super-secret-key") + private String authId; + + @Schema(description = "요청 필수 파라미터 - 히스토리 아이디", requiredMode = Schema.RequiredMode.REQUIRED, example = "57245") + private Long historyId; + + @Schema(description = "요청 필수 파라미터 - 운동을 끝낸 시각", requiredMode = Schema.RequiredMode.REQUIRED, example = "2023-09-09 09:09:09") + private String endTime; + + @Schema(description = "요청 필수 파라미터 - 운동한 시간(초)", requiredMode = Schema.RequiredMode.REQUIRED, example = "39431") + private Integer totalTime; + + @Schema(description = "요청 파라미터 - 운동한 거리(미터)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1842.5") + private Double distance; + + @Schema(description = "요청 파라미터 - 소비 칼로리", requiredMode = Schema.RequiredMode.REQUIRED, example = "300") + private Integer calorie; + + @Schema(description = "요청 파라미터 - 걸음 수", requiredMode = Schema.RequiredMode.REQUIRED, example = "3094") + private Integer step; + + @Schema(description = "요청 필수 파라미터 - 달린 경로", requiredMode = Schema.RequiredMode.REQUIRED) + private String path; + + @Builder + public HistoryDto(Long walkieId, String authId, Long historyId, String date, String endTime, Integer totalTime, Double distance, Integer calorie, Integer step, String path) { + this.walkieId = walkieId; + this.authId = authId; + this.historyId = historyId; + this.endTime = endTime; + this.totalTime = totalTime; + this.distance = distance; + this.calorie = calorie; + this.step = step; + this.path = path; + } +} diff --git a/src/main/java/com/whyranoid/walkie/repository/querydsl/WalkingLikeRepositoryCustom.java b/src/main/java/com/whyranoid/walkie/repository/querydsl/WalkingLikeRepositoryCustom.java index ea4fede..c5b9889 100644 --- a/src/main/java/com/whyranoid/walkie/repository/querydsl/WalkingLikeRepositoryCustom.java +++ b/src/main/java/com/whyranoid/walkie/repository/querydsl/WalkingLikeRepositoryCustom.java @@ -1,5 +1,6 @@ package com.whyranoid.walkie.repository.querydsl; +import com.whyranoid.walkie.dto.HistoryDto; import com.whyranoid.walkie.dto.WalkingLikeDto; public interface WalkingLikeRepositoryCustom { @@ -7,4 +8,6 @@ public interface WalkingLikeRepositoryCustom { Long findWalkingLikeCount(Long walkieId); WalkingLikeDto findWalkingLikePeople(Long walkieId); + + Long updateCurrentWalkingHistory(HistoryDto historyDto); } diff --git a/src/main/java/com/whyranoid/walkie/repository/querydsl/WalkingLikeRepositoryImpl.java b/src/main/java/com/whyranoid/walkie/repository/querydsl/WalkingLikeRepositoryImpl.java index 4d8a19a..0628d39 100644 --- a/src/main/java/com/whyranoid/walkie/repository/querydsl/WalkingLikeRepositoryImpl.java +++ b/src/main/java/com/whyranoid/walkie/repository/querydsl/WalkingLikeRepositoryImpl.java @@ -3,6 +3,7 @@ import com.querydsl.jpa.JPAExpressions; import com.querydsl.jpa.JPQLQuery; import com.querydsl.jpa.impl.JPAQueryFactory; +import com.whyranoid.walkie.dto.HistoryDto; import com.whyranoid.walkie.dto.QWalkieDto; import com.whyranoid.walkie.dto.WalkieDto; import com.whyranoid.walkie.dto.WalkingLikeDto; @@ -11,6 +12,7 @@ import java.util.List; import static com.whyranoid.walkie.domain.QHistory.history; +import static com.whyranoid.walkie.domain.QWalkie.walkie; import static com.whyranoid.walkie.domain.QWalkingLike.walkingLike; @RequiredArgsConstructor @@ -37,6 +39,27 @@ public WalkingLikeDto findWalkingLikePeople(Long walkieId) { .build(); } + @Override + public Long updateCurrentWalkingHistory(HistoryDto historyDto) { + Long updatedHistory = queryFactory.update(history) + .set(history.distance, historyDto.getDistance()) + .set(history.endTime, historyDto.getEndTime()) + .set(history.totalTime, historyDto.getTotalTime()) + .set(history.calorie, historyDto.getCalorie()) + .set(history.step, historyDto.getStep()) + .set(history.path, historyDto.getPath()) + .where(history.historyId.eq(historyDto.getHistoryId())) + .execute(); + + Long updatedWalkie = queryFactory.update(walkie) + .set(walkie.status, 'N') + .where(walkie.userId.eq(historyDto.getWalkieId())) + .execute(); + + if (updatedHistory == 1 && updatedWalkie == 1) return historyDto.getHistoryId(); + return -1L; + } + public JPQLQuery findCurrentHistory(Long walkieId) { return JPAExpressions .select(history.historyId) diff --git a/src/main/java/com/whyranoid/walkie/service/WalkingService.java b/src/main/java/com/whyranoid/walkie/service/WalkingService.java index 9bdc5e3..0c2a581 100644 --- a/src/main/java/com/whyranoid/walkie/service/WalkingService.java +++ b/src/main/java/com/whyranoid/walkie/service/WalkingService.java @@ -3,6 +3,7 @@ import com.whyranoid.walkie.domain.History; import com.whyranoid.walkie.domain.Walkie; import com.whyranoid.walkie.domain.WalkingLike; +import com.whyranoid.walkie.dto.HistoryDto; import com.whyranoid.walkie.dto.WalkingDto; import com.whyranoid.walkie.dto.WalkingLikeDto; import com.whyranoid.walkie.repository.HistoryRepository; @@ -33,7 +34,8 @@ public Long startWalking(WalkingDto walkingDto) { Walkie walkie = walkieRepository.findById(walkingDto.getWalkieId()).orElseThrow(EntityNotFoundException::new); History input = History.builder() - .startTime(walkingDto.getStartTime().toString()) + //.date(walkingDto.getStartTime()) // TODO 날짜 형식 반영 + .startTime(walkingDto.getStartTime()) // TODO 날짜 형식 반영 .user(walkie) .build(); @@ -75,4 +77,13 @@ public WalkingLikeDto getTotalWalkingLike(Long walkieId, String authId) { return walkingLikeRepository.findWalkingLikePeople(walkieId); } + + public Long saveWalkingHistory(HistoryDto historyDto) { + Walkie authWalkie = walkieRepository.findByAuthId(historyDto.getAuthId()).orElseThrow(EntityNotFoundException::new); + + if (!authWalkie.getUserId().equals(historyDto.getWalkieId())) throw new InvalidParameterException(); + + return walkingLikeRepository.updateCurrentWalkingHistory(historyDto); + + } } From 4a2d1f2eae65e6702bc6867a38f6cb78c3c00088 Mon Sep 17 00:00:00 2001 From: bngsh Date: Wed, 13 Sep 2023 21:36:59 +0900 Subject: [PATCH 2/4] =?UTF-8?q?fix:=20=EC=8A=A4=EC=9B=A8=EA=B1=B0=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(ApiResponse=20=EC=B6=94=EA=B0=80)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../walkie/controller/FollowController.java | 24 +++++++++++++++---- .../walkie/controller/WalkieController.java | 22 ++++++++++++----- .../walkie/controller/WalkingController.java | 23 ++++++++++++------ .../com/whyranoid/walkie/dto/FollowDto.java | 6 ++--- 4 files changed, 54 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/whyranoid/walkie/controller/FollowController.java b/src/main/java/com/whyranoid/walkie/controller/FollowController.java index 7451082..8e07e36 100644 --- a/src/main/java/com/whyranoid/walkie/controller/FollowController.java +++ b/src/main/java/com/whyranoid/walkie/controller/FollowController.java @@ -5,6 +5,10 @@ import com.whyranoid.walkie.service.FollowService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; @@ -26,34 +30,44 @@ public class FollowController { private final FollowService followService; - @Operation(description = "팔로우하기") + @Operation(summary = "팔로우하기") + @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = FollowDto.class)), + description = "성공 시 요청한 정보를 그대로 리턴") @PostMapping("/follow") public ResponseEntity follow(@RequestBody FollowDto followRequest) { return ResponseEntity.ok(followService.doFollow(followRequest)); } - @Operation(description = "언팔로우하기") + @Operation(summary = "언팔로우하기") + @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = FollowDto.class)), + description = "성공 시 요청 정보에 unfollow = follow를 추가해 리턴") @DeleteMapping("/unfollow") public ResponseEntity unfollow(@RequestBody FollowDto followRequest) { return ResponseEntity.ok(followService.doUnfollow(followRequest)); } - @Operation(description = "내가 팔로우하는 사람 리스트 가져오기") + @Operation(summary = "내가 팔로우하는 사람 리스트 가져오기") @Parameter(name = "워키 아이디", required = true, description = "팔로잉 리스트를 가져올 유저의 id", example = "3") + @ApiResponse(responseCode = "200", content = @Content(array = @ArraySchema(schema = @Schema(implementation = WalkieDto.class))), + description = "성공 시 id가 팔로우하는 유저 정보의 리스트를 반환") @GetMapping("/{walkie}/following") public ResponseEntity> getFollowingList(@PathVariable("walkie") Long walkieId) { return ResponseEntity.ok(followService.getFollowingList(walkieId)); } - @Operation(description = "나를 팔로우하는 사람 리스트 가져오기") + @Operation(summary = "나를 팔로우하는 사람 리스트 가져오기") @Parameter(name = "워키 아이디", required = true, description = "팔로워 리스트를 가져올 유저의 id", example = "3") + @ApiResponse(responseCode = "200", content = @Content(array = @ArraySchema(schema = @Schema(implementation = WalkieDto.class))), + description = "성공 시 id를 팔로우하는 유저 정보의 리스트를 반환") @GetMapping("/{walkie}/follower") public ResponseEntity> getFollowerList(@PathVariable("walkie") Long walkieId) { return ResponseEntity.ok(followService.getFollowerList(walkieId)); } - @Operation(description = "운동 중인 친구 목록 조회") + @Operation(summary = "운동 중인 친구 목록 조회") @Parameter(name = "워키 아이디", required = true, description = "운동 중인 친구 목록을 가져올 유저의 id", example = "3") + @ApiResponse(responseCode = "200", content = @Content(array = @ArraySchema(schema = @Schema(implementation = WalkieDto.class))), + description = "성공 시 id가 팔로우 하고 운동 중인 유저 정보의 리스트를 반환") @GetMapping("/{walkie}/walking-followings") public ResponseEntity> getWalkingFollowingList(@PathVariable("walkie") Long walkieId) { return ResponseEntity.ok(followService.getWalkingFollowingList(walkieId)); diff --git a/src/main/java/com/whyranoid/walkie/controller/WalkieController.java b/src/main/java/com/whyranoid/walkie/controller/WalkieController.java index 7751f17..6ed442b 100644 --- a/src/main/java/com/whyranoid/walkie/controller/WalkieController.java +++ b/src/main/java/com/whyranoid/walkie/controller/WalkieController.java @@ -8,10 +8,18 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.GetMapping; +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.RestController; @Tag(name = "WalkieController") @RequiredArgsConstructor @@ -21,16 +29,18 @@ public class WalkieController { private final WalkieService walkieService; - @Operation(description = "소셜 로그인 이후 워키 회원가입 요청") + @Operation(summary = "회원가입", description = "소셜 로그인 이후 워키 회원가입 요청") + @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = WalkieSignUpResponse.class)), + description = "성공 시 요청한 아이디, 닉네임과 hasDuplicated=false를, 닉네임 중복 시 hasDuplicated=true를 반환") @PostMapping("/signup") public ResponseEntity signUp(@RequestBody WalkieSignUpRequest walkieSignUpRequest) { return ResponseEntity.ok(walkieService.joinWalkie(walkieSignUpRequest)); } - @Operation(description = "닉네임 중복 확인 -- 회원가입과 동일한 dto 사용") - @Parameters({ - @Parameter(name = "userName", required = true, description = "닉네임", example = "군자동 불주먹") - }) + @Operation(summary = "닉네임 중복 확인", description = "회원가입과 동일한 dto를 응답으로 사용") + @Parameter(name = "userName", required = true, description = "닉네임", example = "군자동 불주먹") + @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = WalkieSignUpResponse.class)), + description = "통과 시 false, 중복 시 true를 반환") @GetMapping("/signup/check") public ResponseEntity check(@RequestParam String userName) { return ResponseEntity.ok( diff --git a/src/main/java/com/whyranoid/walkie/controller/WalkingController.java b/src/main/java/com/whyranoid/walkie/controller/WalkingController.java index 8afc45f..0563a81 100644 --- a/src/main/java/com/whyranoid/walkie/controller/WalkingController.java +++ b/src/main/java/com/whyranoid/walkie/controller/WalkingController.java @@ -3,8 +3,11 @@ import com.whyranoid.walkie.dto.HistoryDto; import com.whyranoid.walkie.dto.WalkingDto; import com.whyranoid.walkie.dto.WalkingLikeDto; +import com.whyranoid.walkie.dto.response.WalkieSignUpResponse; import com.whyranoid.walkie.service.WalkingService; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; @@ -24,33 +27,39 @@ public class WalkingController { private final WalkingService walkingService; - @Operation(description = "운동 시작 정보 저장") + @Operation(summary = "운동 시작 정보 저장") + @ApiResponse(responseCode = "200", description = "OK -- 생성된 히스토리 아이디 반환") @PostMapping("/start") - @ApiResponse(responseCode = "200", description = "OK -- 생성된 히스토리 아이디") public ResponseEntity startWalking(@RequestBody WalkingDto walkingDto) { return ResponseEntity.ok(walkingService.startWalking(walkingDto)); } - @Operation(description = "운동 중인 친구에게 좋아요 보내기") + @Operation(summary = "운동 중인 친구에게 좋아요 보내기") + @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = WalkingLikeDto.class)), + description = "성공 시 요청 그대로 반환") @PostMapping("/send-like") public ResponseEntity sendWalkingLike(@RequestBody WalkingLikeDto walkingLikeDto) { return ResponseEntity.ok(walkingService.sendWalkingLike(walkingLikeDto)); } - @Operation(description = "운동 중에 받은 좋아요 수 가져오기") + @Operation(summary = "운동 중에 받은 좋아요 수 가져오기") + @ApiResponse(responseCode = "200", description = "성공 시 좋아요 수 리턴, 실패 시 Exception") @GetMapping("/count-like") public ResponseEntity countWalkingLike(@RequestParam Long walkieId, @RequestParam String authId) { return ResponseEntity.ok(walkingService.countWalkingLike(walkieId, authId)); } - @Operation(description = "운동 종료 시 받은 좋아요 수와 좋아요 누른 사람 프로필 가져오기") + @Operation(summary = "운동 종료 시 받은 좋아요 수와 좋아요 누른 사람 프로필 가져오기") + @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = WalkingLikeDto.class)), + description = "성공 시 운동한 사람의 아이디, 받은 좋아요 수, 좋아요 누른 사람의 유저 정보 리스트를 반환") @GetMapping("/count-total") public ResponseEntity getTotalWalkingLike(@RequestParam Long walkieId, @RequestParam String authId) { return ResponseEntity.ok(walkingService.getTotalWalkingLike(walkieId, authId)); } - @Operation(description = "운동 종료 시 데이터 저장하기") - @ApiResponse(description = "저장 성공 시 기록의 DB pk값, 실패 시 -1") + @Operation(summary = "운동 종료 시 데이터 저장하기") + @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = WalkieSignUpResponse.class)), + description = "저장 성공 시 기록의 DB pk값, 실패 시 -1") @PostMapping("/save") public ResponseEntity saveWalkingHistory(@RequestBody HistoryDto historyDto) { return ResponseEntity.ok(walkingService.saveWalkingHistory(historyDto)); diff --git a/src/main/java/com/whyranoid/walkie/dto/FollowDto.java b/src/main/java/com/whyranoid/walkie/dto/FollowDto.java index 78e88e0..0da27cc 100644 --- a/src/main/java/com/whyranoid/walkie/dto/FollowDto.java +++ b/src/main/java/com/whyranoid/walkie/dto/FollowDto.java @@ -12,13 +12,13 @@ @AllArgsConstructor public class FollowDto { - @Schema(description = "팔로우 신청 유저 아이디", requiredMode = Schema.RequiredMode.REQUIRED, example = "24576") + @Schema(description = "[요청 필수] 팔로우 신청 유저 아이디", requiredMode = Schema.RequiredMode.REQUIRED, example = "24576") private Long followerId; - @Schema(description = "팔로우 받은 유저 아이디", requiredMode = Schema.RequiredMode.REQUIRED, example = "1608") + @Schema(description = "[요청 필수] 팔로우 받은 유저 아이디", requiredMode = Schema.RequiredMode.REQUIRED, example = "1608") private Long followedId; - @Schema(description = "(검증용) 언팔로우 되었는지 여부", example = "false") + @Schema(description = "(검증용) 언팔로우 시 true 반환", example = "true") private boolean unfollow; @QueryProjection From 77a66381a82713e0d5056d418c164a5e907bb5d0 Mon Sep 17 00:00:00 2001 From: bngsh Date: Wed, 13 Sep 2023 21:40:13 +0900 Subject: [PATCH 3/4] =?UTF-8?q?fix:=20=ED=9E=88=EC=8A=A4=ED=86=A0=EB=A6=AC?= =?UTF-8?q?=EC=9D=98=20=EA=B2=BD=EB=A1=9C=20=ED=94=84=EB=A1=9C=ED=8D=BC?= =?UTF-8?q?=ED=8B=B0=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/whyranoid/walkie/domain/History.java | 2 -- src/main/java/com/whyranoid/walkie/dto/HistoryDto.java | 4 ---- .../walkie/repository/querydsl/WalkingLikeRepositoryImpl.java | 1 - .../java/com/whyranoid/walkie/service/HistoryService.java | 1 - 4 files changed, 8 deletions(-) diff --git a/src/main/java/com/whyranoid/walkie/domain/History.java b/src/main/java/com/whyranoid/walkie/domain/History.java index 95a8bce..41a7dc2 100644 --- a/src/main/java/com/whyranoid/walkie/domain/History.java +++ b/src/main/java/com/whyranoid/walkie/domain/History.java @@ -43,8 +43,6 @@ public class History { private Integer step; - private String path; - @ManyToOne @JoinColumn(name = "user_id", nullable = false) private Walkie user; diff --git a/src/main/java/com/whyranoid/walkie/dto/HistoryDto.java b/src/main/java/com/whyranoid/walkie/dto/HistoryDto.java index 17153c5..d38c77f 100644 --- a/src/main/java/com/whyranoid/walkie/dto/HistoryDto.java +++ b/src/main/java/com/whyranoid/walkie/dto/HistoryDto.java @@ -34,9 +34,6 @@ public class HistoryDto { @Schema(description = "요청 파라미터 - 걸음 수", requiredMode = Schema.RequiredMode.REQUIRED, example = "3094") private Integer step; - @Schema(description = "요청 필수 파라미터 - 달린 경로", requiredMode = Schema.RequiredMode.REQUIRED) - private String path; - @Builder public HistoryDto(Long walkieId, String authId, Long historyId, String date, String endTime, Integer totalTime, Double distance, Integer calorie, Integer step, String path) { this.walkieId = walkieId; @@ -47,6 +44,5 @@ public HistoryDto(Long walkieId, String authId, Long historyId, String date, Str this.distance = distance; this.calorie = calorie; this.step = step; - this.path = path; } } diff --git a/src/main/java/com/whyranoid/walkie/repository/querydsl/WalkingLikeRepositoryImpl.java b/src/main/java/com/whyranoid/walkie/repository/querydsl/WalkingLikeRepositoryImpl.java index 0628d39..1d1be60 100644 --- a/src/main/java/com/whyranoid/walkie/repository/querydsl/WalkingLikeRepositoryImpl.java +++ b/src/main/java/com/whyranoid/walkie/repository/querydsl/WalkingLikeRepositoryImpl.java @@ -47,7 +47,6 @@ public Long updateCurrentWalkingHistory(HistoryDto historyDto) { .set(history.totalTime, historyDto.getTotalTime()) .set(history.calorie, historyDto.getCalorie()) .set(history.step, historyDto.getStep()) - .set(history.path, historyDto.getPath()) .where(history.historyId.eq(historyDto.getHistoryId())) .execute(); diff --git a/src/main/java/com/whyranoid/walkie/service/HistoryService.java b/src/main/java/com/whyranoid/walkie/service/HistoryService.java index 18dbb1d..5807289 100644 --- a/src/main/java/com/whyranoid/walkie/service/HistoryService.java +++ b/src/main/java/com/whyranoid/walkie/service/HistoryService.java @@ -31,7 +31,6 @@ public List getHistory(Long walkieId) { .totalTime(history.getTotalTime()) .calorie(history.getCalorie()) .step(history.getStep()) - .path(history.getPath()) .build() )); return result.stream().toList(); From f18fcd349f7f6b89f7e3045b6ef203613340d3b1 Mon Sep 17 00:00:00 2001 From: bngsh Date: Thu, 14 Sep 2023 21:45:36 +0900 Subject: [PATCH 4/4] =?UTF-8?q?feat:=20#25=20=EA=B2=8C=EC=8B=9C=EA=B8=80?= =?UTF-8?q?=EC=97=90=20=EC=A2=8B=EC=95=84=EC=9A=94=20=EB=88=84=EB=A5=B4?= =?UTF-8?q?=EA=B8=B0=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/CommunityController.java | 11 +++++ .../com/whyranoid/walkie/domain/PostLike.java | 44 ++++++++++++++++++ .../com/whyranoid/walkie/dto/PostDto.java | 41 +++++++++++++++++ .../com/whyranoid/walkie/dto/PostLikeDto.java | 45 +++++++++++++++++++ .../walkie/repository/PostLikeRepository.java | 14 ++++++ .../walkie/repository/PostRepository.java | 11 +++++ .../querydsl/PostLikeRepositoryCustom.java | 8 ++++ .../querydsl/PostLikeRepositoryImpl.java | 39 ++++++++++++++++ .../walkie/service/CommunityService.java | 38 ++++++++++++++++ 9 files changed, 251 insertions(+) create mode 100644 src/main/java/com/whyranoid/walkie/domain/PostLike.java create mode 100644 src/main/java/com/whyranoid/walkie/dto/PostDto.java create mode 100644 src/main/java/com/whyranoid/walkie/dto/PostLikeDto.java create mode 100644 src/main/java/com/whyranoid/walkie/repository/PostLikeRepository.java create mode 100644 src/main/java/com/whyranoid/walkie/repository/PostRepository.java create mode 100644 src/main/java/com/whyranoid/walkie/repository/querydsl/PostLikeRepositoryCustom.java create mode 100644 src/main/java/com/whyranoid/walkie/repository/querydsl/PostLikeRepositoryImpl.java diff --git a/src/main/java/com/whyranoid/walkie/controller/CommunityController.java b/src/main/java/com/whyranoid/walkie/controller/CommunityController.java index f08ca45..b9d176f 100644 --- a/src/main/java/com/whyranoid/walkie/controller/CommunityController.java +++ b/src/main/java/com/whyranoid/walkie/controller/CommunityController.java @@ -1,6 +1,7 @@ package com.whyranoid.walkie.controller; import com.google.firebase.auth.FirebaseAuthException; +import com.whyranoid.walkie.dto.PostLikeDto; import com.whyranoid.walkie.service.CommunityService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -13,6 +14,7 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.ResponseEntity; 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.RestController; @@ -47,4 +49,13 @@ public ResponseEntity uploadPost( ) throws IOException, FirebaseAuthException { return ResponseEntity.ok(communityService.uploadPost(image, walkieId, content, colorMode, historyContent)); } + + @Operation(summary = "게시글에 좋아요 누르기") + @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = PostLikeDto.class)), + description = "성공 시 요청에 게시글의 현재 좋아요 수를 넣어 반환, 중복 좋아요 시 좋아요 수에 -1을 넣어 반환, 실패 시 예외발생") + @PostMapping("/send-like") + public ResponseEntity sendPostLike(@RequestBody PostLikeDto postLikeDto) { + return ResponseEntity.ok(communityService.sendPostLike(postLikeDto)); + } + } diff --git a/src/main/java/com/whyranoid/walkie/domain/PostLike.java b/src/main/java/com/whyranoid/walkie/domain/PostLike.java new file mode 100644 index 0000000..f98c45f --- /dev/null +++ b/src/main/java/com/whyranoid/walkie/domain/PostLike.java @@ -0,0 +1,44 @@ +package com.whyranoid.walkie.domain; + +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.ToString; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.OneToOne; + +@Entity +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@ToString +public class PostLike { + + @Id + @Column(name = "post_like_id") + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long postLikeId; + + @OneToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "liker") + private Walkie liker; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "post") + private Post post; + + @Builder + public PostLike(Long postLikeId, Walkie liker, Post post) { + this.postLikeId = postLikeId; + this.liker = liker; + this.post = post; + } +} diff --git a/src/main/java/com/whyranoid/walkie/dto/PostDto.java b/src/main/java/com/whyranoid/walkie/dto/PostDto.java new file mode 100644 index 0000000..525ec91 --- /dev/null +++ b/src/main/java/com/whyranoid/walkie/dto/PostDto.java @@ -0,0 +1,41 @@ +package com.whyranoid.walkie.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class PostDto { + + @Schema(description = "[응답] 워키 아이디", example = "3") + private Long viewerId; + + @Schema(description = "[응답] 작성자 아이디", example = "2") + private Long posterId; + + @Schema(description = "[응답] 게시글 pk", example = "26343") + private Long postId; + + @Schema(description = "[응답] 좋아요 여부", example = "true") + private Boolean liked; + + @Schema(description = "[응답] 좋아요 개수", example = "36") + private Integer likeCount; + + @Schema(description = "[응답] 사진파일 URI", example = "") + private String photo; + + @Schema(description = "[응답] 게시글 내용", example = "오운완.") + private String content; + + @Schema(description = "[응답] 게시 시각", example = "2023-09-09 09:09:09") + private String date; + + @Schema(description = "[응답] 글씨색 설정", example = "0") + private Integer colorMode; + + @Schema(description = "[응답] 기록 데이터", example = "") + private String historyContent; +} diff --git a/src/main/java/com/whyranoid/walkie/dto/PostLikeDto.java b/src/main/java/com/whyranoid/walkie/dto/PostLikeDto.java new file mode 100644 index 0000000..5632677 --- /dev/null +++ b/src/main/java/com/whyranoid/walkie/dto/PostLikeDto.java @@ -0,0 +1,45 @@ +package com.whyranoid.walkie.dto; + +import com.querydsl.core.annotations.QueryProjection; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class PostLikeDto { + + @Schema(description = "요청 필수 파라미터 - 좋아요 누른 유저의 워키 아이디", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") + private Long likerId; + + @Schema(description = "요청 필수 파라미터 - 좋아요 받은 글의 포스트 아이디", requiredMode = Schema.RequiredMode.REQUIRED, example = "6521") + private Long postId; + + @Schema(description = "응답 파라미터 - 좋아요 누른 유저 수", example = "62") + private Long likerCount; + + @Schema(description = "응답 파라미터 - 좋아요 누른 유저들의 프로필") + private List likerProfiles; + + @QueryProjection + public PostLikeDto(Long likerId, Long postId) { + this.likerId = likerId; + this.postId = postId; + } + + @Builder + public PostLikeDto(Long likerId, Long postId, Long likerCount, List likerProfiles) { + this.likerId = likerId; + this.postId = postId; + this.likerCount = likerCount; + this.likerProfiles = likerProfiles; + } + + public void setLikerCount(Long likerCount) { + this.likerCount = likerCount; + } +} diff --git a/src/main/java/com/whyranoid/walkie/repository/PostLikeRepository.java b/src/main/java/com/whyranoid/walkie/repository/PostLikeRepository.java new file mode 100644 index 0000000..3d47b7b --- /dev/null +++ b/src/main/java/com/whyranoid/walkie/repository/PostLikeRepository.java @@ -0,0 +1,14 @@ +package com.whyranoid.walkie.repository; + +import com.whyranoid.walkie.domain.Post; +import com.whyranoid.walkie.domain.PostLike; +import com.whyranoid.walkie.domain.Walkie; +import com.whyranoid.walkie.repository.querydsl.PostLikeRepositoryCustom; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface PostLikeRepository extends JpaRepository, PostLikeRepositoryCustom { + + List findByPostAndLiker(Post post, Walkie liker); +} diff --git a/src/main/java/com/whyranoid/walkie/repository/PostRepository.java b/src/main/java/com/whyranoid/walkie/repository/PostRepository.java new file mode 100644 index 0000000..0ba8421 --- /dev/null +++ b/src/main/java/com/whyranoid/walkie/repository/PostRepository.java @@ -0,0 +1,11 @@ +package com.whyranoid.walkie.repository; + +import com.whyranoid.walkie.domain.Post; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface PostRepository extends JpaRepository { + + Optional findByPostId(Long postId); +} diff --git a/src/main/java/com/whyranoid/walkie/repository/querydsl/PostLikeRepositoryCustom.java b/src/main/java/com/whyranoid/walkie/repository/querydsl/PostLikeRepositoryCustom.java new file mode 100644 index 0000000..449d4d8 --- /dev/null +++ b/src/main/java/com/whyranoid/walkie/repository/querydsl/PostLikeRepositoryCustom.java @@ -0,0 +1,8 @@ +package com.whyranoid.walkie.repository.querydsl; + +public interface PostLikeRepositoryCustom { + + Long findPostLikeCount(Long postId); + +// PostLikeDto findPostLikePeople(Long postId); +} diff --git a/src/main/java/com/whyranoid/walkie/repository/querydsl/PostLikeRepositoryImpl.java b/src/main/java/com/whyranoid/walkie/repository/querydsl/PostLikeRepositoryImpl.java new file mode 100644 index 0000000..a384329 --- /dev/null +++ b/src/main/java/com/whyranoid/walkie/repository/querydsl/PostLikeRepositoryImpl.java @@ -0,0 +1,39 @@ +package com.whyranoid.walkie.repository.querydsl; + +import com.querydsl.jpa.impl.JPAQueryFactory; +import lombok.RequiredArgsConstructor; + +import static com.whyranoid.walkie.domain.QPostLike.postLike; + +@RequiredArgsConstructor +public class PostLikeRepositoryImpl implements PostLikeRepositoryCustom { + + private final JPAQueryFactory queryFactory; + + @Override + public Long findPostLikeCount(Long postId) { + return queryFactory + .select(postLike) + .from(postLike) + .where(postLike.post.postId.eq(postId) + .and(postLike.liker.isNotNull())) + .stream().count(); + } + +// @Override +// public PostLikeDto findPostLikePeople(Long postId) { +// return PostLikeDto.builder() +// .postId(postId) +// .likerCount(findPostLikeCount(postId)) +// .likerProfiles(findLikerList(postId)) +// .build(); +// } +// +// public List findLikerList(Long postId) { +// return queryFactory +// .select(new QWalkieDto(postLike.liker)) +// .from(postLike) +// .where(postLike.post.postId.eq(postId)) +// .fetch(); +// } +} diff --git a/src/main/java/com/whyranoid/walkie/service/CommunityService.java b/src/main/java/com/whyranoid/walkie/service/CommunityService.java index b035ea2..5d31f6c 100644 --- a/src/main/java/com/whyranoid/walkie/service/CommunityService.java +++ b/src/main/java/com/whyranoid/walkie/service/CommunityService.java @@ -6,8 +6,13 @@ import com.google.firebase.cloud.StorageClient; import com.whyranoid.walkie.ApiBaseUrlSingleton; import com.whyranoid.walkie.domain.Post; +import com.whyranoid.walkie.domain.PostLike; +import com.whyranoid.walkie.domain.Walkie; +import com.whyranoid.walkie.dto.PostLikeDto; import com.whyranoid.walkie.dto.response.ApiResponse; import com.whyranoid.walkie.repository.CommunityRepository; +import com.whyranoid.walkie.repository.PostLikeRepository; +import com.whyranoid.walkie.repository.PostRepository; import com.whyranoid.walkie.repository.WalkieRepository; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; @@ -15,10 +20,13 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; +import javax.persistence.EntityNotFoundException; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; @Service @@ -27,6 +35,8 @@ public class CommunityService { private final CommunityRepository communityRepository; private final WalkieRepository walkieRepository; + private final PostRepository postRepository; + private final PostLikeRepository postLikeRepository; @Value("${app.firebase-bucket-name}") private String firebaseBucket; @@ -56,4 +66,32 @@ public String uploadImage(MultipartFile image, String nameFile) Blob blob = bucket.create(nameFile, content, image.getContentType()); return blob.getMediaLink(); } + + public PostLikeDto sendPostLike(PostLikeDto postLikeDto) { + Post post = postRepository.findByPostId(postLikeDto.getPostId()).orElseThrow(EntityNotFoundException::new); + Walkie liker = walkieRepository.findById(postLikeDto.getLikerId()).orElseThrow(EntityNotFoundException::new); + + PostLike input = PostLike.builder() + .post(post) + .liker(liker) + .build(); + + List already = new ArrayList<>(postLikeRepository.findByPostAndLiker(post, liker)); + if (!already.isEmpty()) { + postLikeRepository.delete(already.get(0)); + postLikeDto.setLikerCount(-1L); + } + else { + postLikeRepository.save(input); + postLikeDto.setLikerCount(countPostLike(postLikeDto.getPostId())); + } + + return postLikeDto; + } + + public Long countPostLike(Long postId) { + Post post = postRepository.findByPostId(postId).orElseThrow(EntityNotFoundException::new); + + return postLikeRepository.findPostLikeCount(postId); + } }