Skip to content

Commit

Permalink
Feat: #8 지도 관련 api
Browse files Browse the repository at this point in the history
* fix : api 경로 수정

* feat : 현재 영역에서 쓰레기통 조회

* feat : 현재 위치로부터 사각 영역내 쓰레기통 조회

* feat : 카테고리별 조회 추가

* docs : 스웨거 정리

* docs : uri 수정
  • Loading branch information
gourderased authored Jun 4, 2024
1 parent a522999 commit dc9d0d3
Show file tree
Hide file tree
Showing 16 changed files with 173 additions and 66 deletions.
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ dependencies {
implementation 'org.springframework.cloud:spring-cloud-starter-config'
//애플 인증 서버에 JSON Web Key(JWK)를 가져올 때 사용
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'

implementation 'org.hibernate:hibernate-spatial:6.4.4.Final'
}

tasks.named('test') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
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;
Expand Down Expand Up @@ -44,4 +46,10 @@ public ApiResponse<TokenRefreshSimpleInfo> refreshToken(@RequestParam String ref
return ApiResponse.onSuccess(authService.updateUserToken(refreshToken));
}

@GetMapping("/check-nickname/{nickname}")
@Operation(summary = "닉네임 중복 확인", description = "true : 사용가능한 닉네임, false : 사용 불가능한 닉네임")
public ApiResponse<Boolean> checkNickName(@PathVariable String nickName){
boolean status = authService.checkNickNameDuplicate(nickName);
return ApiResponse.onSuccess(status);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,11 @@ public TokenRefreshSimpleInfo updateUserToken(String refreshToken) {

}


}
@Transactional
public boolean checkNickNameDuplicate(String name){
if(userRepository.findByNickname(name).isPresent()){
return false;
}
return true;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package com.example.nzgeneration.domain.trashcan;

public enum TrashCategory {
PLASTIC, PAPER, GENERAL
PLASTIC, PAPER, GENERAL, ALL
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.example.nzgeneration.domain.trashcan;

import com.example.nzgeneration.global.utils.BaseTimeEntity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
Expand All @@ -12,6 +13,7 @@
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.locationtech.jts.geom.Point;

@Entity
@Getter
Expand All @@ -24,8 +26,13 @@ public class Trashcan extends BaseTimeEntity {
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(name = "trash_category")
@Enumerated(EnumType.STRING)
private TrashCategory trashCategory;

@Column(name = "representative_image_url")
private String representativeImageUrl;

@Column(name = "trashcan_point")
private Point trashcanPoint;
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,80 @@
package com.example.nzgeneration.domain.trashcan;

import com.example.nzgeneration.domain.trashcan.dto.TrashcanRequestDto.GetTrashcansRequest;
import com.example.nzgeneration.domain.trashcan.dto.TrashcanResponseDto.GetTrashcanResponse;
import com.example.nzgeneration.domain.trashcan.dto.TrashcanResponseDto.GetTrashcanResponses;
import com.example.nzgeneration.domain.user.User;
import com.example.nzgeneration.domain.user.UserService;
import com.example.nzgeneration.global.common.response.ApiResponse;
import com.example.nzgeneration.global.common.response.code.status.ErrorStatus;
import com.example.nzgeneration.global.common.response.exception.GeneralException;
import com.example.nzgeneration.global.security.CurrentUser;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Polygon;
import org.springframework.web.bind.annotation.GetMapping;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
@Tag(name = "쓰레기통 조회", description = "쓰레기통 조회 API")
public class TrashcanController {

private final TrashcanService trashcanService;
private final UserService userService;

@GetMapping
@GetMapping("api/trashcan/{id}")
@Operation(
summary = "쓰레기통 상세 조회"
)
public ApiResponse<GetTrashcanResponse> getTrashcan(@PathVariable Long id) {
return ApiResponse.onSuccess(trashcanService.getTrashcan(id));
}

@PostMapping("api/trashcans/")
@Operation(
summary = "영역 내 쓰레기통 조회",
description = "영역의 네 좌표값으로 영역 내 거점을 조회.<br>영역의 좌표값은 위도와 경도 <br>카테고리는 all할 경우 전체 조회"
)
public ApiResponse<GetTrashcanResponses> getTrashcans(
@RequestBody GetTrashcansRequest request, @RequestParam TrashCategory trashCategory) {

//다각형 객체 초기화
Polygon polygon = null;

try {
GeometryFactory geometryFactory = new GeometryFactory();
//request 객체에서 좌표를 가져와 Coordinate객체 리스트를 생성
List<Coordinate> coordinatesPolygon = List.of(
new Coordinate(request.getTopLeftPoint().getX(), request.getTopLeftPoint().getY()),
new Coordinate(request.getBottomLeftPoint().getX(), request.getBottomLeftPoint().getY()),
new Coordinate(request.getBottomRightPoint().getX(), request.getBottomRightPoint().getY()),
new Coordinate(request.getTopRightPoint().getX(), request.getTopRightPoint().getY()),
new Coordinate(request.getTopLeftPoint().getX(), request.getTopLeftPoint().getY())
);
polygon = geometryFactory.createPolygon(coordinatesPolygon.toArray(new Coordinate[0]));
} catch (NullPointerException e) {
throw new GeneralException(ErrorStatus._TRASHCAN_COORDINATE_INVALID);
} catch (IllegalArgumentException e) {
throw new GeneralException(ErrorStatus._TRASHCAN_POLYGON_INVALID);
}
return ApiResponse.onSuccess(trashcanService.getTrashcans(polygon, trashCategory));
}

@Operation(
summary = "쓰레기통 스탬프 찍기"
)
@PostMapping("api/user/trashcan-stamp")
public ApiResponse<String> addStamp(@CurrentUser User user) {
userService.addStamp(user);
return ApiResponse.onSuccess("스탬프 찍기 성공");
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
package com.example.nzgeneration.domain.trashcan;

import java.util.List;
import org.locationtech.jts.geom.Polygon;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

public interface TrashcanRepository extends JpaRepository<Trashcan, Long> {

}
//polygon안에 trashcanPoint가 포함되는지 확인
@Query(value = "SELECT tc FROM Trashcan tc WHERE ST_CONTAINS(:polygon, tc.trashcanPoint) = true AND tc.trashCategory = :trashCategory")
List<Trashcan> findTrashcansByPolygonAndTrashCategory(@Param("polygon") Polygon polygon, @Param("trashCategory") TrashCategory trashCategory);

@Query(value = "SELECT tc FROM Trashcan tc WHERE ST_CONTAINS(:polygon, tc.trashcanPoint)")
List<Trashcan> findTrashcansByPolygon(@Param("polygon") Polygon polygon);
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package com.example.nzgeneration.domain.trashcan;

import com.example.nzgeneration.domain.trashcan.dto.TrashcanResponseDto.GetTrashcanResponse;
import com.example.nzgeneration.domain.trashcan.dto.TrashcanResponseDto.GetTrashcanResponses;
import com.example.nzgeneration.global.common.response.code.status.ErrorStatus;
import com.example.nzgeneration.global.common.response.exception.GeneralException;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.locationtech.jts.geom.Polygon;
import org.springframework.data.geo.Point;
import org.springframework.stereotype.Service;

@Service
Expand All @@ -21,4 +25,28 @@ public GetTrashcanResponse getTrashcan(Long id) {
.imageUrl(trashcan.getRepresentativeImageUrl())
.build();
}

/**
* 원형 거점 내 쓰레기통 카테고리 별 조회
*/
public GetTrashcanResponses getTrashcans(Polygon polygon, TrashCategory trashCategory) {
List<Trashcan> trashcans = null;

//전체 조회
if(trashCategory.equals(TrashCategory.ALL)) {
trashcans = trashcanRepository.findTrashcansByPolygon(polygon);
}
//카테고리별 조회
else {
trashcans = trashcanRepository.findTrashcansByPolygonAndTrashCategory(polygon, trashCategory);
}
List<GetTrashcanResponse> trashcanResponses = trashcans.stream().map(trashcan ->
GetTrashcanResponse.builder()
.id(trashcan.getId())
.trashcanPoint(new Point(trashcan.getTrashcanPoint().getX(), trashcan.getTrashcanPoint().getY()))
.imageUrl(trashcan.getRepresentativeImageUrl())
.build()
).toList();
return new GetTrashcanResponses(trashcanResponses);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
package com.example.nzgeneration.domain.trashcan.dto;

public class TrashcanRequestDto {
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.data.geo.Point;

public class TrashcanRequestDto {

@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class GetTrashcansRequest {
private Point currentPoint;
private Point topLeftPoint;
private Point topRightPoint;
private Point bottomRightPoint;
private Point bottomLeftPoint;
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package com.example.nzgeneration.domain.trashcan.dto;

import com.example.nzgeneration.domain.trashcan.TrashCategory;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.data.geo.Point;

public class TrashcanResponseDto {

Expand All @@ -13,7 +14,17 @@ public class TrashcanResponseDto {
@NoArgsConstructor
@AllArgsConstructor
public static class GetTrashcanResponse {
String trashCategory;
String imageUrl;
private Long id;
private String trashCategory;
private String imageUrl;
private Point trashcanPoint;
}

@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class GetTrashcanResponses {
List<GetTrashcanResponse> trashcans;
}
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
package com.example.nzgeneration.domain.trashcanerrorreport;

import com.example.nzgeneration.global.common.response.ApiResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
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.RestController;

@RestController
@RequiredArgsConstructor
@Tag(name = "쓰레기통 오류 신고", description = "쓰레기통 오류 신고 API")
public class TrashcanErrorReportController {

private final TrashcanErrorReportService trashcanErrorReportService;

@PostMapping("trashcan-error/{trashcan-id}")
@PostMapping("/api/trashcan-error/{trashcan-id}")
@Operation(
summary = "쓰레기통 오류 신고"
)
public ApiResponse<String> addError(@PathVariable(value = "trashcan-id") Long id) {
return ApiResponse.onSuccess(trashcanErrorReportService.addError(id));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import com.example.nzgeneration.domain.trashcanreport.dto.TrashcanReportRequestDto.AddTrashcanReportRequest;
import com.example.nzgeneration.domain.user.User;
import com.example.nzgeneration.global.common.response.ApiResponse;
import com.example.nzgeneration.global.security.CurrentUser;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
Expand All @@ -15,7 +14,7 @@ public class TrashcanReportController {

private final TrashcanReportService trashcanReportService;

@PostMapping("trashcan")
@PostMapping("/api/trashcan")
public ApiResponse<String> addTrashcanReport(
@RequestBody AddTrashcanReportRequest addTrashcanReportRequest) {
trashcanReportService.addTrashcanReport(addTrashcanReportRequest.getMapX(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.example.nzgeneration.global.common.response.ApiResponse;
import com.example.nzgeneration.global.security.CurrentUser;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
Expand All @@ -20,20 +21,10 @@
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/user")
@Tag(name = "유저 관련", description = "유저 관련 API")
public class UserController {
private final UserService userService;

@PostMapping("/stamp")
public ApiResponse<String> addStamp(@CurrentUser User user) {
userService.addStamp(user);
return ApiResponse.onSuccess("스탬프 찍기 성공");
}
@GetMapping("/check-nickname/{nickName}")
@Operation(summary = "닉네임 중복 확인", description = "true : 사용가능한 닉네임, false : 사용 불가능한 닉네임")
public ApiResponse<Boolean> checkNickName(@PathVariable String nickName){
boolean status = userService.checkNickNameDuplicate(nickName);
return ApiResponse.onSuccess(status);
}
@PatchMapping("/nickname/{nickName}")
@Operation(summary = "닉네임 수정")
public ApiResponse<String> updateNickName(@CurrentUser User user, @PathVariable String nickName){
Expand Down
Loading

0 comments on commit dc9d0d3

Please sign in to comment.