diff --git a/src/main/java/com/campus/campus/domain/councilpost/application/dto/request/PostRequest.java b/src/main/java/com/campus/campus/domain/councilpost/application/dto/request/PostRequest.java index c96c70c9..f7ac0beb 100644 --- a/src/main/java/com/campus/campus/domain/councilpost/application/dto/request/PostRequest.java +++ b/src/main/java/com/campus/campus/domain/councilpost/application/dto/request/PostRequest.java @@ -5,7 +5,6 @@ import com.campus.campus.domain.councilpost.domain.entity.PostCategory; import com.campus.campus.domain.councilpost.domain.entity.ThumbnailIcon; -import com.campus.campus.domain.place.application.dto.response.SavedPlaceInfo; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.v3.oas.annotations.media.Schema; @@ -23,24 +22,7 @@ public record PostRequest( @NotBlank String content, - @Schema(example = - """ - "placeName": "숙명여자대학교", - "placeKey": "string", - "address": "서울특별시 용산구 청파로47길 99", - "category": "교육,학문>대학교", - "link": "https://map.naver.com/v5/search/%EC%88%99%EB%AA%85%EC%97%AC%EC%9E%90%EB%8C%80%ED%95%99%EA%B5%90+%EC%A0%9C1%EC%BA%A0%ED%8D%BC%EC%8A%A4?c=37.545947,126.964578,15,0,0,0,dh", - "telephone": "010-1234-1234", - "coordinate": { - "latitude": 0.1, - "longitude": 0.1 - }, - "imgUrls": [ - "string" - ] - """, - description = "/search API에서 반환된 결과 중 하나를 선택") - SavedPlaceInfo place, + String place, @Schema(example = "2025-04-10T18:00") @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm") diff --git a/src/main/java/com/campus/campus/domain/councilpost/application/dto/response/GetPostResponse.java b/src/main/java/com/campus/campus/domain/councilpost/application/dto/response/GetPostResponse.java index 76c9a213..1bb451c8 100644 --- a/src/main/java/com/campus/campus/domain/councilpost/application/dto/response/GetPostResponse.java +++ b/src/main/java/com/campus/campus/domain/councilpost/application/dto/response/GetPostResponse.java @@ -22,7 +22,7 @@ public record GetPostResponse( PostCategory category, String title, String content, - String placeName, + String place, LocalDate startDate, LocalDate endDate, LocalDateTime startDateTime, diff --git a/src/main/java/com/campus/campus/domain/councilpost/application/dto/response/PostListItemResponse.java b/src/main/java/com/campus/campus/domain/councilpost/application/dto/response/PostListItemResponse.java index 5e25a13a..345f1924 100644 --- a/src/main/java/com/campus/campus/domain/councilpost/application/dto/response/PostListItemResponse.java +++ b/src/main/java/com/campus/campus/domain/councilpost/application/dto/response/PostListItemResponse.java @@ -9,7 +9,7 @@ public record PostListItemResponse( Long id, PostCategory category, String title, - Long placeId, + String place, LocalDateTime endDateTime, String thumbnailImageUrl, ThumbnailIcon thumbnailIcon, diff --git a/src/main/java/com/campus/campus/domain/councilpost/application/mapper/StudentCouncilPostMapper.java b/src/main/java/com/campus/campus/domain/councilpost/application/mapper/StudentCouncilPostMapper.java index 0ac41511..d04cc829 100644 --- a/src/main/java/com/campus/campus/domain/councilpost/application/mapper/StudentCouncilPostMapper.java +++ b/src/main/java/com/campus/campus/domain/councilpost/application/mapper/StudentCouncilPostMapper.java @@ -7,19 +7,18 @@ import org.springframework.stereotype.Component; import com.campus.campus.domain.council.domain.entity.StudentCouncil; -import com.campus.campus.domain.councilpost.application.dto.request.PostRequest; -import com.campus.campus.domain.councilpost.application.dto.response.GetActivePartnershipListForUserResponse; import com.campus.campus.domain.councilpost.application.dto.response.GetLikedPostResponse; -import com.campus.campus.domain.councilpost.application.dto.response.GetPostForUserResponse; -import com.campus.campus.domain.councilpost.application.dto.response.GetPostListForCouncilResponse; import com.campus.campus.domain.councilpost.application.dto.response.GetPostResponse; -import com.campus.campus.domain.councilpost.application.dto.response.GetUpcomingEventListForCouncilResponse; import com.campus.campus.domain.councilpost.application.dto.response.LikePostResponse; +import com.campus.campus.domain.councilpost.application.dto.response.GetPostListForCouncilResponse; +import com.campus.campus.domain.councilpost.application.dto.response.GetUpcomingEventListForCouncilResponse; +import com.campus.campus.domain.councilpost.application.dto.response.GetActivePartnershipListForUserResponse; import com.campus.campus.domain.councilpost.application.dto.response.PostListItemResponse; +import com.campus.campus.domain.councilpost.application.dto.request.PostRequest; +import com.campus.campus.domain.councilpost.application.dto.response.GetPostForUserResponse; import com.campus.campus.domain.councilpost.domain.entity.LikePost; import com.campus.campus.domain.councilpost.domain.entity.PostImage; import com.campus.campus.domain.councilpost.domain.entity.StudentCouncilPost; -import com.campus.campus.domain.place.domain.entity.Place; import com.campus.campus.domain.user.domain.entity.User; import lombok.RequiredArgsConstructor; @@ -32,10 +31,8 @@ public PostListItemResponse toPostListItemResponse(StudentCouncilPost post, bool post.getId(), post.getCategory(), post.getTitle(), - post.getPlace().getPlaceId(), - post.isEvent() - ? post.getStartDateTime() - : post.getEndDateTime(), + post.getPlace(), + post.isEvent() ? post.getStartDateTime() : post.getEndDateTime(), post.getThumbnailImageUrl(), post.getThumbnailIcon(), isLiked @@ -47,7 +44,7 @@ public GetPostListForCouncilResponse toGetPostListForCouncilResponse(StudentCoun post.getId(), post.getCategory(), post.getTitle(), - post.getPlace().getPlaceName(), + post.getPlace(), post.isEvent() ? post.getStartDateTime() : post.getEndDateTime(), post.getThumbnailImageUrl(), post.getThumbnailIcon() @@ -59,7 +56,7 @@ public GetUpcomingEventListForCouncilResponse toGetUpcomingEventListForCouncilRe post.getId(), post.getCategory(), post.getTitle(), - post.getPlace().getPlaceName(), + post.getPlace(), post.getStartDateTime(), post.getThumbnailIcon() ); @@ -69,7 +66,7 @@ public GetActivePartnershipListForUserResponse toGetActivePartnershipListForUser return new GetActivePartnershipListForUserResponse( post.getId(), post.getTitle(), - post.getPlace().getPlaceName(), + post.getPlace(), post.getThumbnailImageUrl() ); } @@ -84,7 +81,7 @@ public GetPostResponse toGetPostResponse(StudentCouncilPost post, List i .category(post.getCategory()) .title(post.getTitle()) .content(post.getContent()) - .placeName(post.getPlace().getPlaceName()) + .place(post.getPlace()) .thumbnailImageUrl(post.getThumbnailImageUrl()) .thumbnailIcon(post.getThumbnailIcon()) .images(images != null ? images : Collections.emptyList()); @@ -99,9 +96,6 @@ public GetPostResponse toGetPostResponse(StudentCouncilPost post, List i return builder.build(); } - // - // public StudentCouncilPost createStudentCouncilPost(StudentCouncil writer, PostRequest dto, - // LocalDateTime startDateTime, LocalDateTime endDateTime, Place place) { public GetPostForUserResponse toGetPostForUserResponse(StudentCouncilPost post, List images, Long currentUserId, boolean isLiked) { var writer = post.getWriter(); @@ -112,7 +106,7 @@ public GetPostForUserResponse toGetPostForUserResponse(StudentCouncilPost post, .category(post.getCategory()) .title(post.getTitle()) .content(post.getContent()) - .place(post.getPlace().getPlaceName()) + .place(post.getPlace()) .thumbnailImageUrl(post.getThumbnailImageUrl()) .thumbnailIcon(post.getThumbnailIcon()) .isLiked(isLiked) @@ -140,20 +134,20 @@ public GetLikedPostResponse toGetLikedPostResponse(StudentCouncilPost post) { return new GetLikedPostResponse( post.getId(), post.getTitle(), - post.getPlace().getPlaceName(), + post.getPlace(), post.isEvent() ? post.getStartDateTime() : post.getEndDateTime(), post.getThumbnailImageUrl() ); } - public StudentCouncilPost createStudentCouncilPost(StudentCouncil writer, Place place, PostRequest dto, + public StudentCouncilPost createStudentCouncilPost(StudentCouncil writer, PostRequest dto, LocalDateTime startDateTime, LocalDateTime endDateTime) { return StudentCouncilPost.builder() .writer(writer) .category(dto.category()) .title(dto.title()) .content(dto.content()) - .place(place) + .place(dto.place()) .startDateTime(startDateTime) .endDateTime(endDateTime) .thumbnailImageUrl(dto.thumbnailImageUrl()) diff --git a/src/main/java/com/campus/campus/domain/councilpost/application/service/StudentCouncilPostService.java b/src/main/java/com/campus/campus/domain/councilpost/application/service/StudentCouncilPostService.java index 9e717a82..189d088a 100644 --- a/src/main/java/com/campus/campus/domain/councilpost/application/service/StudentCouncilPostService.java +++ b/src/main/java/com/campus/campus/domain/councilpost/application/service/StudentCouncilPostService.java @@ -14,11 +14,11 @@ import com.campus.campus.domain.council.application.exception.StudentCouncilNotFoundException; import com.campus.campus.domain.council.domain.entity.StudentCouncil; import com.campus.campus.domain.council.domain.repository.StudentCouncilRepository; -import com.campus.campus.domain.councilpost.application.dto.request.PostRequest; import com.campus.campus.domain.councilpost.application.dto.response.GetPostListForCouncilResponse; import com.campus.campus.domain.councilpost.application.dto.response.GetPostResponse; import com.campus.campus.domain.councilpost.application.dto.response.GetUpcomingEventListForCouncilResponse; import com.campus.campus.domain.councilpost.application.dto.response.NormalizedDateTime; +import com.campus.campus.domain.councilpost.application.dto.request.PostRequest; import com.campus.campus.domain.councilpost.application.exception.NotPostWriterException; import com.campus.campus.domain.councilpost.application.exception.PostImageLimitExceededException; import com.campus.campus.domain.councilpost.application.exception.PostNotFoundException; @@ -30,9 +30,6 @@ import com.campus.campus.domain.councilpost.domain.entity.StudentCouncilPost; import com.campus.campus.domain.councilpost.domain.repository.PostImageRepository; import com.campus.campus.domain.councilpost.domain.repository.StudentCouncilPostRepository; -import com.campus.campus.domain.partnership.application.service.PartnershipService; -import com.campus.campus.domain.place.application.service.PlaceService; -import com.campus.campus.domain.place.domain.entity.Place; import com.campus.campus.global.oci.application.service.PresignedUrlService; import lombok.RequiredArgsConstructor; @@ -51,9 +48,6 @@ public class StudentCouncilPostService { private static final int MAX_IMAGE_COUNT = 10; private static final long UPCOMING_EVENT_WINDOW_HOURS = 72L; - private final PlaceService placeService; - private final StudentCouncilPostRepository studentCouncilPostRepository; - private final PartnershipService partnershipService; @Transactional public GetPostResponse create(Long councilId, PostRequest dto) { @@ -71,18 +65,12 @@ public GetPostResponse create(Long councilId, PostRequest dto) { NormalizedDateTime normalized = dto.category().validateAndNormalize(dto); - //Place 객체 생성 - Place place = placeService.findOrCreatePlace(dto); - StudentCouncilPost post = studentCouncilPostMapper.createStudentCouncilPost( - writer, place, dto, normalized.startDateTime(), normalized.endDateTime() + writer, dto, normalized.startDateTime(), normalized.endDateTime() ); postRepository.save(post); - //제휴 엔티티 생성 - partnershipService.create(post, place); - if (dto.imageUrls() != null) { for (String imageUrl : dto.imageUrls()) { postImageRepository.save(studentCouncilPostMapper.createPostImage(post, imageUrl)); @@ -215,15 +203,10 @@ public GetPostResponse update(Long councilId, Long postId, PostRequest dto) { String oldThumbnailUrl = post.getThumbnailImageUrl(); List oldImages = postImageRepository.findAllByPost(post); - Place place = post.getPlace(); - if (!dto.place().placeName().equals(place.getPlaceName())) { - place = placeService.findOrCreatePlace(dto); - } - post.update( dto.title(), dto.content(), - place, + dto.place(), normalized.startDateTime(), normalized.endDateTime(), dto.thumbnailImageUrl(), diff --git a/src/main/java/com/campus/campus/domain/councilpost/domain/entity/StudentCouncilPost.java b/src/main/java/com/campus/campus/domain/councilpost/domain/entity/StudentCouncilPost.java index d0de71fd..60b34db8 100644 --- a/src/main/java/com/campus/campus/domain/councilpost/domain/entity/StudentCouncilPost.java +++ b/src/main/java/com/campus/campus/domain/councilpost/domain/entity/StudentCouncilPost.java @@ -4,7 +4,6 @@ import java.time.LocalDateTime; import com.campus.campus.domain.council.domain.entity.StudentCouncil; -import com.campus.campus.domain.place.domain.entity.Place; import com.campus.campus.global.entity.BaseEntity; import jakarta.persistence.Column; @@ -46,9 +45,7 @@ public class StudentCouncilPost extends BaseEntity { @Column(columnDefinition = "TEXT") private String content; - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "place_id") - private Place place; + private String place; private LocalDateTime startDateTime; private LocalDateTime endDateTime; @@ -61,7 +58,7 @@ public class StudentCouncilPost extends BaseEntity { public void update( String title, String content, - Place place, + String place, LocalDateTime startDateTime, LocalDateTime endDateTime, String thumbnailImageUrl, diff --git a/src/main/java/com/campus/campus/domain/councilpost/domain/repository/PostImageRepository.java b/src/main/java/com/campus/campus/domain/councilpost/domain/repository/PostImageRepository.java index 77f990da..34b1b7a7 100644 --- a/src/main/java/com/campus/campus/domain/councilpost/domain/repository/PostImageRepository.java +++ b/src/main/java/com/campus/campus/domain/councilpost/domain/repository/PostImageRepository.java @@ -3,12 +3,9 @@ import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; import com.campus.campus.domain.councilpost.domain.entity.PostImage; import com.campus.campus.domain.councilpost.domain.entity.StudentCouncilPost; -import com.campus.campus.domain.place.application.dto.response.partnership.PostImageSummary; public interface PostImageRepository extends JpaRepository { @@ -17,26 +14,4 @@ public interface PostImageRepository extends JpaRepository { void deleteByPost(StudentCouncilPost post); List findAllByPostOrderByIdAsc(StudentCouncilPost post); - - @Query(""" - SELECT NEW com.campus.campus.domain.place.application.dto.response.partnership.PostImageSummary - (post.place.placeId, - img.imageUrl) - FROM PostImage img - JOIN img.post post - WHERE post.category='PARTNERSHIP' - AND post.place.placeId in :placeIds - ORDER BY img.id asc - """) - List findPartnershipImagesByPlaceIds( - @Param("placeIds") List placeIds - ); - - @Query(""" - select pi.imageUrl - from PostImage pi - where pi.post = :post - order by pi.id asc - """) - List findImageUrlsByPost(@Param("post") StudentCouncilPost post); } diff --git a/src/main/java/com/campus/campus/domain/councilpost/domain/repository/StudentCouncilPostRepository.java b/src/main/java/com/campus/campus/domain/councilpost/domain/repository/StudentCouncilPostRepository.java index 6fa08fdd..1898f73b 100644 --- a/src/main/java/com/campus/campus/domain/councilpost/domain/repository/StudentCouncilPostRepository.java +++ b/src/main/java/com/campus/campus/domain/councilpost/domain/repository/StudentCouncilPostRepository.java @@ -205,87 +205,4 @@ Page findUpcomingMajorEvents( @Param("limit") LocalDateTime limit, Pageable pageable ); - - @Query(""" - SELECT p - FROM StudentCouncilPost p - WHERE p.place.placeId=:placeId - and p.writer.id=:councilId - and p.category='PARTNERSHIP' - order by p.createdAt desc - """) - Optional findByCouncilIdAndPlaceId( - @Param("placeId") Long placeId, - @Param("councilId") Long councilId - ); - - @EntityGraph(attributePaths = {"writer", "writer.school", "writer.college", "writer.major", "place"}) - @Query(""" - SELECT p - FROM StudentCouncilPost p - JOIN p.writer w - LEFT JOIN w.school s - LEFT JOIN w.college c - LEFT JOIN w.major m - WHERE w.deletedAt IS NULL - AND p.category = :category - AND p.startDateTime <= :now - AND p.endDateTime >= :now - AND ( - (w.councilType = :majorType AND m.majorId = :majorId) - OR (w.councilType = :collegeType AND c.collegeId = :collegeId) - OR (w.councilType = :schoolType AND s.schoolId = :schoolId) - ) - AND (:cursor IS NULL OR p.id < :cursor) - ORDER BY p.id DESC - """) - List findByUserScopeWithCursor( - @Param("majorId") Long majorId, - @Param("collegeId") Long collegeId, - @Param("schoolId") Long schoolId, - @Param("category") PostCategory category, - @Param("majorType") CouncilType majorType, - @Param("collegeType") CouncilType collegeType, - @Param("schoolType") CouncilType schoolType, - @Param("cursor") Long cursor, - @Param("now") LocalDateTime now, - Pageable pageable - ); - - @Query(""" - SELECT p - FROM StudentCouncilPost p - JOIN p.writer w - JOIN p.place pl - LEFT JOIN w.school s - LEFT JOIN w.college c - LEFT JOIN w.major m - WHERE w.deletedAt IS NULL - AND p.category = :category - AND p.startDateTime <= :now - AND p.endDateTime >= :now - AND pl.coordinate.latitude BETWEEN :minLat AND :maxLat - AND pl.coordinate.longitude BETWEEN :minLng AND :maxLng - AND ( - (w.councilType = :majorType AND m.majorId = :majorId) - OR (w.councilType = :collegeType AND c.collegeId = :collegeId) - OR (w.councilType = :schoolType AND s.schoolId = :schoolId) - ) - ORDER BY p.id DESC - """) - List findPinsInBounds( - @Param("majorId") Long majorId, - @Param("collegeId") Long collegeId, - @Param("schoolId") Long schoolId, - @Param("category") PostCategory category, - @Param("majorType") CouncilType majorType, - @Param("collegeType") CouncilType collegeType, - @Param("schoolType") CouncilType schoolType, - @Param("minLat") Double minLat, - @Param("maxLat") Double maxLat, - @Param("minLng") Double minLng, - @Param("maxLng") Double maxLng, - @Param("now") LocalDateTime now - ); - } diff --git a/src/main/java/com/campus/campus/domain/councilpost/presentation/StudentCouncilPostController.java b/src/main/java/com/campus/campus/domain/councilpost/presentation/StudentCouncilPostController.java index d82afc3b..81ba6472 100644 --- a/src/main/java/com/campus/campus/domain/councilpost/presentation/StudentCouncilPostController.java +++ b/src/main/java/com/campus/campus/domain/councilpost/presentation/StudentCouncilPostController.java @@ -88,33 +88,13 @@ public class StudentCouncilPostController { value = """ { "category": "PARTNERSHIP", - "title": "봉구스밥버거 제휴 할인", - "content": "중앙대 학생증 제시 시 전 메뉴 10% 할인", - "place": { - "placeName": "봉구스밥버거 중앙대후문점", - "placeKey": "cf5691fce0965a6a20d76601e88a019b9ed22733c21c52fe77ac6f6a20db9b88", - "address": "서울특별시 동작구 상도1동 645-2", - "category": "음식점>분식", - "link": "https://map.naver.com/v5/search/%EB%B4%89%EA%B5%AC%EC%8A%A4%EB%B0%A5%EB%B2%84%EA%B1%B0+%EC%A4%91%EC%95%99%EB%8C%80%ED%9B%84%EB%AC%B8%EC%A0%90?c=37.504750,126.951452,15,0,0,0,dh", - "telephone": "", - "coordinate": { - "latitude": 37.5047501, - "longitude": 126.9514519 - }, - "imgUrls": [ - "https://maps.googleapis.com/maps/api/place/photo?maxWidth=800&photo_reference=example1", - "https://maps.googleapis.com/maps/api/place/photo?maxWidth=800&photo_reference=example2", - "https://maps.googleapis.com/maps/api/place/photo?maxWidth=800&photo_reference=example3" - ] - }, + "title": "카페 할인", + "content": "10% 할인", + "place": "OO카페", "startDateTime": "2025-04-01T00:00", "endDateTime": "2025-04-30T23:59", - "thumbnailIcon": "FOOD", - "thumbnailImageUrl": null, - "imageUrls": [ - "https://cdn.campus.com/post/image1.jpg", - "https://cdn.campus.com/post/image2.jpg" - ] + "thumbnailIcon": "CAFE", + "imageUrls": [] } """ ) diff --git a/src/main/java/com/campus/campus/domain/partnership/application/dto/response/PartnershipPinResponse.java b/src/main/java/com/campus/campus/domain/partnership/application/dto/response/PartnershipPinResponse.java deleted file mode 100644 index 1dc74fe1..00000000 --- a/src/main/java/com/campus/campus/domain/partnership/application/dto/response/PartnershipPinResponse.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.campus.campus.domain.partnership.application.dto.response; - -import io.swagger.v3.oas.annotations.media.Schema; - -public record PartnershipPinResponse( - - @Schema(description = "제휴글 ID", example = "10") - Long postId, - - @Schema(description = "장소 ID", example = "4") - Long placeId, - - @Schema(description = "장소 이름", example = "매머드익스프레스 중앙대점") - String placeName, - - @Schema(description = "장소 위도", example = "37.50775") - double latitude, - - @Schema(description = "장소 경도", example = "126.96059") - double longitude -) { -} diff --git a/src/main/java/com/campus/campus/domain/partnership/application/service/PartnershipService.java b/src/main/java/com/campus/campus/domain/partnership/application/service/PartnershipService.java deleted file mode 100644 index a2bf5db5..00000000 --- a/src/main/java/com/campus/campus/domain/partnership/application/service/PartnershipService.java +++ /dev/null @@ -1,193 +0,0 @@ -package com.campus.campus.domain.partnership.application.service; - -import java.time.LocalDateTime; -import java.util.AbstractMap; -import java.util.List; -import java.util.Map; - -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import com.campus.campus.domain.council.domain.entity.CouncilType; -import com.campus.campus.domain.councilpost.application.exception.PostNotFoundException; -import com.campus.campus.domain.councilpost.domain.entity.PostCategory; -import com.campus.campus.domain.councilpost.domain.entity.StudentCouncilPost; -import com.campus.campus.domain.councilpost.domain.repository.PostImageRepository; -import com.campus.campus.domain.councilpost.domain.repository.StudentCouncilPostRepository; -import com.campus.campus.domain.partnership.application.dto.response.PartnershipPinResponse; -import com.campus.campus.domain.partnership.domain.entity.Partnership; -import com.campus.campus.domain.partnership.domain.entity.PartnershipStatus; -import com.campus.campus.domain.partnership.domain.repository.PartnershipRepository; -import com.campus.campus.domain.place.application.dto.response.partnership.PartnershipResponse; -import com.campus.campus.domain.place.application.mapper.PlaceMapper; -import com.campus.campus.domain.place.domain.entity.Place; -import com.campus.campus.domain.place.domain.repository.LikedPlacesRepository; -import com.campus.campus.domain.place.domain.repository.PlaceRepository; -import com.campus.campus.domain.user.application.exception.UserNotFoundException; -import com.campus.campus.domain.user.domain.entity.User; -import com.campus.campus.domain.user.domain.repository.UserRepository; -import com.campus.campus.global.util.jwt.GeoUtil; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; - -@Slf4j -@RequiredArgsConstructor -@Service -public class PartnershipService { - - private final PartnershipRepository partnershipRepository; - private final UserRepository userRepository; - private final LikedPlacesRepository likedPlacesRepository; - private final PostImageRepository postImageRepository; - private final PlaceMapper placeMapper; - private final StudentCouncilPostRepository studentCouncilPostRepository; - private final PlaceRepository placeRepository; - - @Transactional - public List getPartnershipPlaces(Long userId, Long cursor, int size, double userLat, - double userLng) { - User user = userRepository.findById(userId) - .orElseThrow(UserNotFoundException::new); - - Long majorId = user.getMajor().getMajorId(); - Long collegeId = user.getCollege().getCollegeId(); - Long schoolId = user.getSchool().getSchoolId(); - - Pageable pageable = PageRequest.of(0, size); - - //유저가 속한 학생회들의 제휴글(major/college/school) 전부 조회 - List posts = studentCouncilPostRepository.findByUserScopeWithCursor( - majorId, - collegeId, - schoolId, - PostCategory.PARTNERSHIP, - CouncilType.MAJOR_COUNCIL, - CouncilType.COLLEGE_COUNCIL, - CouncilType.SCHOOL_COUNCIL, - cursor, - LocalDateTime.now(), - pageable - ); - - return posts.stream() - .map(post -> { - Place place = post.getPlace(); - - double distanceMeter = GeoUtil.distanceMeter( - userLat, userLng, - place.getCoordinate().latitude(), - place.getCoordinate().longitude() - ); - - // post + distance를 함께 묶음 - return new AbstractMap.SimpleEntry<>(post, distanceMeter); - }) - .sorted(Map.Entry.comparingByValue()) // 거리순 정렬 - .limit(size) - .map(entry -> { - StudentCouncilPost post = entry.getKey(); - double distanceMeter = entry.getValue(); - double rounded = Math.round(distanceMeter * 100.0) / 100.0; - - return placeMapper.toPartnershipResponse( - user, - post, - post.getPlace(), - isLiked(post.getPlace(), user), - getImgUrls(post), - rounded - ); - }) - .toList(); - } - - private boolean isLiked(Place place, User user) { - return likedPlacesRepository.existsByUserAndPlace(user, place); - } - - private List getImgUrls(StudentCouncilPost post) { - return postImageRepository.findImageUrlsByPost(post); - } - - // 제휴 엔티티 생성 - @Transactional - public Partnership create(StudentCouncilPost post, Place place) { - - // 1. 제휴 기간 결정 - LocalDateTime startDate = post.getStartDateTime(); - LocalDateTime endDate = post.getEndDateTime(); - - // 2. 초기 상태 결정 - PartnershipStatus status = - LocalDateTime.now().isAfter(endDate) - ? PartnershipStatus.EXPIRED - : PartnershipStatus.ACTIVE; - - // 3. Partnership 생성 - Partnership partnership = Partnership.builder() - .post(post) - .place(place) - .startDate(startDate) - .endDate(endDate) - .status(status) - .build(); - - // 4. 저장 - return partnershipRepository.save(partnership); - } - - @Transactional - public List findPartnerInBounds(Long userId, Double minLat, Double maxLat, Double minLng, - Double maxLng) { - User user = userRepository.findById(userId) - .orElseThrow(UserNotFoundException::new); - - Long majorId = user.getMajor().getMajorId(); - Long collegeId = user.getCollege().getCollegeId(); - Long schoolId = user.getSchool().getSchoolId(); - List posts = studentCouncilPostRepository.findPinsInBounds( - majorId, - collegeId, - schoolId, - PostCategory.PARTNERSHIP, - CouncilType.MAJOR_COUNCIL, - CouncilType.COLLEGE_COUNCIL, - CouncilType.SCHOOL_COUNCIL, - minLat, - maxLat, - minLng, - maxLng, - LocalDateTime.now() - ); - - // 엔티티 → 응답 DTO 변환 - List responses = posts.stream() - .map(post -> placeMapper.toPartnershipPinResponse(post, post.getPlace())) - .toList(); - return responses; - } - - @Transactional - public PartnershipResponse getPartnershipDetail(Long postId, Long userId, double userLat, - double userLng) { - StudentCouncilPost post = studentCouncilPostRepository.findById(postId) - .orElseThrow(PostNotFoundException::new); - Place place = post.getPlace(); - - User user = userRepository.findById(userId) - .orElseThrow(UserNotFoundException::new); - - double distanceMeter = GeoUtil.distanceMeter( - userLat, userLng, - place.getCoordinate().latitude(), - place.getCoordinate().longitude() - ); - double rounded = Math.round(distanceMeter * 100.0) / 100.0; - - return placeMapper.toPartnershipResponse(user, post, place, isLiked(place, user), getImgUrls(post), rounded); - } - -} diff --git a/src/main/java/com/campus/campus/domain/partnership/domain/entity/Partnership.java b/src/main/java/com/campus/campus/domain/partnership/domain/entity/Partnership.java deleted file mode 100644 index 41fca1e7..00000000 --- a/src/main/java/com/campus/campus/domain/partnership/domain/entity/Partnership.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.campus.campus.domain.partnership.domain.entity; - -import java.time.LocalDateTime; - -import com.campus.campus.domain.councilpost.domain.entity.StudentCouncilPost; -import com.campus.campus.domain.place.domain.entity.Place; - -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.EnumType; -import jakarta.persistence.Enumerated; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; -import jakarta.persistence.OneToOne; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.NoArgsConstructor; - -@Entity -@Builder -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor(access = AccessLevel.PROTECTED) -public class Partnership { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "partnership_id") - private Long id; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "place_id", nullable = false) - private Place place; - - @OneToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "post_id", nullable = false) - private StudentCouncilPost post; - - @Enumerated(EnumType.STRING) - private PartnershipStatus status; //ACTIVE, EXPIRED, SUSPENDED - - private LocalDateTime startDate; - private LocalDateTime endDate; - -} diff --git a/src/main/java/com/campus/campus/domain/partnership/domain/entity/PartnershipStatus.java b/src/main/java/com/campus/campus/domain/partnership/domain/entity/PartnershipStatus.java deleted file mode 100644 index 7243f28f..00000000 --- a/src/main/java/com/campus/campus/domain/partnership/domain/entity/PartnershipStatus.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.campus.campus.domain.partnership.domain.entity; - -public enum PartnershipStatus { - - ACTIVE, // 현재 제휴 중 - EXPIRED, // 제휴 기간 만료 - SUSPENDED; // 일시 중단 (관리자/정책에 의함) - - /** - * 사용자에게 노출 가능한 상태인지 여부 - */ - public boolean isVisible() { - return this == ACTIVE; - } - - /** - * 혜택 제공이 가능한 상태인지 여부 - */ - public boolean isBenefitAvailable() { - return this == ACTIVE; - } -} - diff --git a/src/main/java/com/campus/campus/domain/partnership/domain/repository/PartnershipRepository.java b/src/main/java/com/campus/campus/domain/partnership/domain/repository/PartnershipRepository.java deleted file mode 100644 index a44a9951..00000000 --- a/src/main/java/com/campus/campus/domain/partnership/domain/repository/PartnershipRepository.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.campus.campus.domain.partnership.domain.repository; - -import java.time.LocalDateTime; -import java.util.List; - -import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; - -import com.campus.campus.domain.council.domain.entity.CouncilType; -import com.campus.campus.domain.partnership.domain.entity.Partnership; -import com.campus.campus.domain.partnership.domain.entity.PartnershipStatus; -import com.campus.campus.domain.place.application.dto.response.partnership.PartnershipPlaceSummary; - -public interface PartnershipRepository extends JpaRepository { - - @Query(""" - select new com.campus.campus.domain.place.application.dto.response.partnership.PartnershipPlaceSummary( - pt.id, - p.placeId, - p.placeKey, - p.placeName, - p.placeCategory, - p.address, - p.coordinate.latitude, - p.coordinate.longitude, - council.councilType - ) - from Partnership pt - join pt.place p - join pt.post post - join post.writer council - where pt.status = :activeStatus - and :today between pt.startDate and pt.endDate - and council.deletedAt is null - and ( - (council.councilType = :majorType - and council.major.majorId = :majorId) - or (council.councilType = :collegeType - and council.college.collegeId = :collegeId) - or (council.councilType = :schoolType - and council.school.schoolId = :schoolId) - ) - and (:cursor is null or pt.id < :cursor) - order by pt.id desc - """) - List findActivePartnershipPlaces( - @Param("today") LocalDateTime today, - @Param("majorId") Long majorId, - @Param("collegeId") Long collegeId, - @Param("schoolId") Long schoolId, - @Param("cursor") Long cursor, - @Param("activeStatus") PartnershipStatus activeStatus, - @Param("majorType") CouncilType majorType, - @Param("collegeType") CouncilType collegeType, - @Param("schoolType") CouncilType schoolType, - Pageable pageable - ); -} - diff --git a/src/main/java/com/campus/campus/domain/partnership/presentation/PartnershipController.java b/src/main/java/com/campus/campus/domain/partnership/presentation/PartnershipController.java deleted file mode 100644 index 126f4f5d..00000000 --- a/src/main/java/com/campus/campus/domain/partnership/presentation/PartnershipController.java +++ /dev/null @@ -1,124 +0,0 @@ -package com.campus.campus.domain.partnership.presentation; - -import java.util.List; - -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -import com.campus.campus.domain.partnership.application.dto.response.PartnershipPinResponse; -import com.campus.campus.domain.partnership.application.service.PartnershipService; -import com.campus.campus.domain.place.application.dto.response.partnership.PartnershipResponse; -import com.campus.campus.global.annotation.CurrentUserId; -import com.campus.campus.global.common.response.CommonResponse; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ExampleObject; -import lombok.RequiredArgsConstructor; - -@RestController -@RequestMapping("/api/partnership") -@RequiredArgsConstructor -public class PartnershipController { - - private final PartnershipService partnershipService; - - @GetMapping("/list") - @Operation(summary = "리스트로 제휴 전체 조회", description = "무한 스크롤 방식으로 제휴 장소 목록을 조회합니다.") - public CommonResponse> getPartnershipPlaces( - @CurrentUserId Long userId, - @Parameter( - description = "현재 위치의 위도", - example = "37.50415" - ) - @RequestParam double lat, - @Parameter( - description = "현재 위치의 경도", - example = "126.9570" - ) - @RequestParam double lng, - @Parameter( - description = """ - 무한 스크롤 커서 값. - - 첫 요청 시 null - - 다음 요청부터는 이전 응답의 nextCursor 값 - """, - examples = { - @ExampleObject( - name = "첫 요청", - value = "null" - ), - @ExampleObject( - name = "다음 요청", - value = "120" - ) - } - ) - @RequestParam(required = false) Long cursor, - @Parameter( - description = "한 번에 조회할 개수", - example = "5" - ) - @RequestParam(defaultValue = "5") int size) { - List response = partnershipService.getPartnershipPlaces(userId, cursor, size, lat, lng); - return CommonResponse.success(PartnershipResponseCode.CHECK_PARTNERSHIP_PLACES_SUCCESS, response); - } - - @GetMapping("/map") - @Operation( - summary = "지도에서 제휴 장소 조회", - description = """ - 현재 지도 화면(bounds) 안에 있는 제휴 장소들을 조회합니다. - - bounds는 지도 화면의 남서/북동 좌표입니다. - - 지도 이동 또는 확대/축소 시 재호출됩니다. - """) - public CommonResponse> getPartnershipMap( - @CurrentUserId Long userId, - @Parameter( - description = "지도 화면의 남쪽(최소) 위도", - example = "37.497" - ) - @RequestParam Double minLat, - @Parameter( - description = "지도 화면의 북쪽(최대) 위도", - example = "37.512" - ) - @RequestParam Double maxLat, - @Parameter( - description = "지도 화면의 서쪽(최소) 경도", - example = "126.953" - ) - @RequestParam Double minLng, - @Parameter( - description = "지도 화면의 동쪽(최대) 경도", - example = "126.982" - ) - @RequestParam Double maxLng - ) { - return CommonResponse.success( - PartnershipResponseCode.CHECK_PARTNERSHIP_PLACES_SUCCESS, - partnershipService.findPartnerInBounds(userId, minLat, maxLat, minLng, maxLng) - ); - } - - @GetMapping("/detail") - @Operation(summary = "제휴 장소 상세 조회(맵에서 핀 클릭 시)") - public CommonResponse getPartnershipDetail( - @Parameter(description = "현재 위치의 위도", example = "37.50415") - @RequestParam double lat, - - @Parameter(description = "현재 위치의 경도", example = "126.9570") - @RequestParam double lng, - - @Parameter(description = "제휴글 ID", example = "10") - @RequestParam Long postId, - - @CurrentUserId Long userId - ) { - return CommonResponse.success( - PartnershipResponseCode.CHECK_ONE_PARTNERSHIP_PLACE_SUCCESS, - partnershipService.getPartnershipDetail(postId, userId, lat, lng)); - } -} diff --git a/src/main/java/com/campus/campus/domain/partnership/presentation/PartnershipResponseCode.java b/src/main/java/com/campus/campus/domain/partnership/presentation/PartnershipResponseCode.java deleted file mode 100644 index f8504161..00000000 --- a/src/main/java/com/campus/campus/domain/partnership/presentation/PartnershipResponseCode.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.campus.campus.domain.partnership.presentation; - -import org.springframework.http.HttpStatus; - -import com.campus.campus.global.common.response.ResponseCodeInterface; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -@Getter -@AllArgsConstructor -public enum PartnershipResponseCode implements ResponseCodeInterface { - - PLACE_SAVE_SUCCESS(200, HttpStatus.OK, "좋아요 처리가 완료되었습니다."), - CHECK_PARTNERSHIP_PLACES_SUCCESS(200, HttpStatus.OK, "제휴 장소 리스트 조회가 완료되었습니다."), - CHECK_ONE_PARTNERSHIP_PLACE_SUCCESS(200, HttpStatus.OK, "제휴 장소 단건 조회가 완료되었습니다."); - - private final int code; - private final HttpStatus status; - private final String message; -} diff --git a/src/main/java/com/campus/campus/domain/place/application/dto/response/SavedPlaceInfo.java b/src/main/java/com/campus/campus/domain/place/application/dto/response/SavedPlaceInfo.java index 3cfefb6a..6563eacd 100644 --- a/src/main/java/com/campus/campus/domain/place/application/dto/response/SavedPlaceInfo.java +++ b/src/main/java/com/campus/campus/domain/place/application/dto/response/SavedPlaceInfo.java @@ -32,10 +32,5 @@ public record SavedPlaceInfo( @Schema(description = "이미지 url") List imgUrls - // @Schema(description = "좋아요 여부") - // boolean isLiked, - // - // @Schema(description = "제휴 있을 시, 태그도 함께 반환") - // List tags ) { } diff --git a/src/main/java/com/campus/campus/domain/place/application/dto/response/geocoder/AddressResponse.java b/src/main/java/com/campus/campus/domain/place/application/dto/response/geocoder/AddressResponse.java deleted file mode 100644 index ac29c679..00000000 --- a/src/main/java/com/campus/campus/domain/place/application/dto/response/geocoder/AddressResponse.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.campus.campus.domain.place.application.dto.response.geocoder; - -import java.util.List; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -@Getter -@AllArgsConstructor -public class AddressResponse { - - private Response response; - - @Getter - public static class Response { - private String status; - private List result; - } - - @Getter - public static class Result { - private String type; - private String text; - private Structure structure; - } - - @Getter - public static class Structure { - private String level1; - private String level2; - private String level3; - private String level4L; - private String level4A; - } -} diff --git a/src/main/java/com/campus/campus/domain/place/application/dto/response/partnership/PartnershipMapResponse.java b/src/main/java/com/campus/campus/domain/place/application/dto/response/partnership/PartnershipMapResponse.java deleted file mode 100644 index e80186cc..00000000 --- a/src/main/java/com/campus/campus/domain/place/application/dto/response/partnership/PartnershipMapResponse.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.campus.campus.domain.place.application.dto.response.partnership; - -import java.util.List; - -public record PartnershipMapResponse( - Long placeId, - Double latitude, - Double longitude, - List tags -) { -} - diff --git a/src/main/java/com/campus/campus/domain/place/application/dto/response/partnership/PartnershipMapSummary.java b/src/main/java/com/campus/campus/domain/place/application/dto/response/partnership/PartnershipMapSummary.java deleted file mode 100644 index 73a34516..00000000 --- a/src/main/java/com/campus/campus/domain/place/application/dto/response/partnership/PartnershipMapSummary.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.campus.campus.domain.place.application.dto.response.partnership; - -import com.campus.campus.domain.council.domain.entity.CouncilType; - -public record PartnershipMapSummary( - Long placeId, - Double latitude, - Double longitude, - CouncilType councilType -) { -} - diff --git a/src/main/java/com/campus/campus/domain/place/application/dto/response/partnership/PartnershipPlaceSummary.java b/src/main/java/com/campus/campus/domain/place/application/dto/response/partnership/PartnershipPlaceSummary.java deleted file mode 100644 index 675e2a48..00000000 --- a/src/main/java/com/campus/campus/domain/place/application/dto/response/partnership/PartnershipPlaceSummary.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.campus.campus.domain.place.application.dto.response.partnership; - -import com.campus.campus.domain.council.domain.entity.CouncilType; - -public record PartnershipPlaceSummary( - Long partnershipId, //추가 - - Long placeId, - String placeKey, - String name, - String category, - String address, - Double latitude, - Double longitude, - - // Long councilId, - CouncilType councilType -) { -} diff --git a/src/main/java/com/campus/campus/domain/place/application/dto/response/partnership/PartnershipResponse.java b/src/main/java/com/campus/campus/domain/place/application/dto/response/partnership/PartnershipResponse.java deleted file mode 100644 index d5f1442a..00000000 --- a/src/main/java/com/campus/campus/domain/place/application/dto/response/partnership/PartnershipResponse.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.campus.campus.domain.place.application.dto.response.partnership; - -import java.time.LocalDate; -import java.util.List; - -public record PartnershipResponse( - Long placeId, - String placeKey, - String name, - String category, - String address, - Double latitude, - Double longitude, - String tag, //(ex.) 총학생회, 사회과학대학, IT공학과 - boolean isLiked, - double star, //리뷰 평점 - String partnerTitle, //제휴 제목 - double distance, //거리(m) - LocalDate endDate, //제휴 끝나는 시점 - - //StudentCouncilPost 이미지 받아오기 - List imgUrls -) { -} diff --git a/src/main/java/com/campus/campus/domain/place/application/dto/response/partnership/PartnershipScrollResponse.java b/src/main/java/com/campus/campus/domain/place/application/dto/response/partnership/PartnershipScrollResponse.java deleted file mode 100644 index 8b0d3f6a..00000000 --- a/src/main/java/com/campus/campus/domain/place/application/dto/response/partnership/PartnershipScrollResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.campus.campus.domain.place.application.dto.response.partnership; - -import java.util.List; - -public record PartnershipScrollResponse( - List items, - boolean hasNext, - Long nextCursor -) { -} diff --git a/src/main/java/com/campus/campus/domain/place/application/dto/response/partnership/PostImageSummary.java b/src/main/java/com/campus/campus/domain/place/application/dto/response/partnership/PostImageSummary.java deleted file mode 100644 index dc7ca3a8..00000000 --- a/src/main/java/com/campus/campus/domain/place/application/dto/response/partnership/PostImageSummary.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.campus.campus.domain.place.application.dto.response.partnership; - -public record PostImageSummary( - Long placeId, - String imageUrl -) { -} diff --git a/src/main/java/com/campus/campus/domain/place/application/exception/ErrorCode.java b/src/main/java/com/campus/campus/domain/place/application/exception/ErrorCode.java index 0b4a035c..c50ca038 100644 --- a/src/main/java/com/campus/campus/domain/place/application/exception/ErrorCode.java +++ b/src/main/java/com/campus/campus/domain/place/application/exception/ErrorCode.java @@ -15,8 +15,7 @@ public enum ErrorCode implements ErrorCodeInterface { PLACE_NOT_FOUND(2602, HttpStatus.NOT_FOUND, "해당 장소를 찾을 수 없습니다."), SHA256_NOT_SUPPORTED(2603, HttpStatus.INTERNAL_SERVER_ERROR, "SHA-256이 지원되지 않습니다."), NAVER_API_ERROR(2604, HttpStatus.INTERNAL_SERVER_ERROR, "네이버 api 호출에 실패하였습니다."), - PLACE_CREATION_ERROR(2605, HttpStatus.INTERNAL_SERVER_ERROR, "Place 생성에 오류가 발생하였습니다."), - GEOCODER_ERROR(2605, HttpStatus.INTERNAL_SERVER_ERROR, "좌표 -> 주소 변환 과정에서 오류가 발생하였습니다.."); + PLACE_CREATION_ERROR(2605, HttpStatus.INTERNAL_SERVER_ERROR, "Place 생성에 오류가 발생하였습니다."); private final int code; private final HttpStatus status; diff --git a/src/main/java/com/campus/campus/domain/place/application/exception/GeoCoderException.java b/src/main/java/com/campus/campus/domain/place/application/exception/GeoCoderException.java deleted file mode 100644 index 5f3fd85a..00000000 --- a/src/main/java/com/campus/campus/domain/place/application/exception/GeoCoderException.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.campus.campus.domain.place.application.exception; - -import com.campus.campus.global.common.exception.ApplicationException; - -public class GeoCoderException extends ApplicationException { - public GeoCoderException() { - super(ErrorCode.GEOCODER_ERROR); - } -} diff --git a/src/main/java/com/campus/campus/domain/place/application/mapper/PlaceMapper.java b/src/main/java/com/campus/campus/domain/place/application/mapper/PlaceMapper.java index 74876c90..2839e259 100644 --- a/src/main/java/com/campus/campus/domain/place/application/mapper/PlaceMapper.java +++ b/src/main/java/com/campus/campus/domain/place/application/mapper/PlaceMapper.java @@ -4,14 +4,9 @@ import org.springframework.stereotype.Component; -import com.campus.campus.domain.council.domain.entity.CouncilType; -import com.campus.campus.domain.councilpost.domain.entity.StudentCouncilPost; -import com.campus.campus.domain.partnership.application.dto.response.PartnershipPinResponse; import com.campus.campus.domain.place.application.dto.response.LikeResponse; import com.campus.campus.domain.place.application.dto.response.SavedPlaceInfo; -import com.campus.campus.domain.place.application.dto.response.geocoder.AddressResponse; import com.campus.campus.domain.place.application.dto.response.naver.NaverSearchResponse; -import com.campus.campus.domain.place.application.dto.response.partnership.PartnershipResponse; import com.campus.campus.domain.place.domain.entity.Coordinate; import com.campus.campus.domain.place.domain.entity.LikedPlace; import com.campus.campus.domain.place.domain.entity.Place; @@ -40,49 +35,10 @@ public SavedPlaceInfo toSavedPlaceInfo(NaverSearchResponse.Item item, String pla ); } - public PartnershipPinResponse toPartnershipPinResponse(StudentCouncilPost post, Place place) { - return new PartnershipPinResponse( - post.getId(), - place.getPlaceId(), - place.getPlaceName(), - place.getCoordinate().latitude(), - place.getCoordinate().longitude() - ); - } - - public PartnershipResponse toPartnershipResponse(User user, StudentCouncilPost post, Place place, boolean isLiked, - List imgUrls, double distance) { - return new PartnershipResponse( - place.getPlaceId(), - place.getPlaceKey(), - place.getPlaceName(), - place.getPlaceCategory(), - place.getAddress(), - place.getCoordinate().latitude(), - place.getCoordinate().longitude(), - resolveTag(post, user), - isLiked, - 5.0, //리뷰 구현 이후 수정 예정 - post.getTitle(), - distance, - post.getEndDateTime().toLocalDate(), - imgUrls - ); - } - - private String resolveTag(StudentCouncilPost post, User user) { - CouncilType councilType = post.getWriter().getCouncilType(); - return switch (councilType) { - case SCHOOL_COUNCIL -> "총학생회"; - case COLLEGE_COUNCIL -> user.getCollege().getCollegeName(); - case MAJOR_COUNCIL -> user.getMajor().getMajorName(); - }; - } - - public Place createPlace(SavedPlaceInfo savedPlaceInfo) { + public Place createPlace(SavedPlaceInfo savedPlaceInfo, String placeName) { return Place.builder() .placeKey(savedPlaceInfo.placeKey()) - .placeName(savedPlaceInfo.placeName()) + .placeName(placeName) .placeCategory(savedPlaceInfo.category()) .phone(savedPlaceInfo.telephone()) .address(savedPlaceInfo.address()) @@ -91,14 +47,6 @@ public Place createPlace(SavedPlaceInfo savedPlaceInfo) { .build(); } - public String toStringAddress(AddressResponse nowAddress) { - return nowAddress.getResponse().getResult().stream() - .filter(r -> "road".equalsIgnoreCase(r.getType()) || "parcel".equalsIgnoreCase(r.getType())) - .findFirst() - .map(AddressResponse.Result::getText) - .orElse(null); - } - public PlaceImages createPlaceImages(String placeKey, String googleImageUrl) { return PlaceImages.builder() .placeKey(placeKey) diff --git a/src/main/java/com/campus/campus/domain/place/application/service/PlaceService.java b/src/main/java/com/campus/campus/domain/place/application/service/PlaceService.java index 6dce7ebd..81a05fe1 100644 --- a/src/main/java/com/campus/campus/domain/place/application/service/PlaceService.java +++ b/src/main/java/com/campus/campus/domain/place/application/service/PlaceService.java @@ -14,11 +14,9 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import com.campus.campus.domain.councilpost.application.dto.request.PostRequest; import com.campus.campus.domain.place.application.dto.response.LikeResponse; import com.campus.campus.domain.place.application.dto.response.SavedPlaceInfo; import com.campus.campus.domain.place.application.dto.response.SearchCandidateResponse; -import com.campus.campus.domain.place.application.dto.response.geocoder.AddressResponse; import com.campus.campus.domain.place.application.dto.response.naver.NaverSearchResponse; import com.campus.campus.domain.place.application.exception.NaverMapAPIException; import com.campus.campus.domain.place.application.exception.PlaceCreationException; @@ -31,7 +29,6 @@ import com.campus.campus.domain.place.domain.repository.LikedPlacesRepository; import com.campus.campus.domain.place.domain.repository.PlaceImagesRepository; import com.campus.campus.domain.place.domain.repository.PlaceRepository; -import com.campus.campus.domain.place.infrastructure.geocoder.GeoCoderClient; import com.campus.campus.domain.place.infrastructure.google.GooglePlaceClient; import com.campus.campus.domain.place.infrastructure.naver.NaverMapClient; import com.campus.campus.domain.user.application.exception.UserNotFoundException; @@ -58,20 +55,10 @@ public class PlaceService { private final LikedPlacesRepository likedPlacesRepository; private final UserRepository userRepository; private final ExecutorService executorService; - private final GeoCoderClient geoCoderClient; - - public List search(double lat, double lng, String keyword) { - //현위치 좌표 -> 주소로 변환 - AddressResponse geocoderRes = geoCoderClient.getAddress(lat, lng); - String nowAddress = placeMapper.toStringAddress(geocoderRes); - - //주소 + 키워드 합쳐서 검색하도록 함 - String searchWord = nowAddress + keyword; - log.info("nowAddress={}", nowAddress); - log.info("searchWord={}", searchWord); + public List search(String keyword) { //네이버에서 특정 장소 기본정보 받아오기 - NaverSearchResponse naverSearchResponse = naverMapClient.searchPlaces(searchWord, 5); + NaverSearchResponse naverSearchResponse = naverMapClient.searchPlaces(keyword, 5); List candidates = naverSearchResponse.items().stream() .map(item -> { @@ -105,21 +92,6 @@ public List search(double lat, double lng, String keyword) { return futures.stream().map(CompletableFuture::join).toList(); } - @Transactional - public Place findOrCreatePlace(PostRequest request) { - SavedPlaceInfo place = request.place(); - String placeKey = place.placeKey(); - - //이미 Place 존재하는지 확인 - Optional existing = placeRepository.findByPlaceKey(placeKey); - if (existing.isPresent()) { - return existing.get(); - } - - //저장되어 있지 않는 Place의 경우, 객체 생성 후 저장 - return placeRepository.save(placeMapper.createPlace(place)); - } - //장소 저장 @Transactional public LikeResponse likePlace(SavedPlaceInfo placeInfo, Long userId) { @@ -145,7 +117,7 @@ public LikeResponse likePlace(SavedPlaceInfo placeInfo, Long userId) { .orElseGet(() -> { //없으면 생성 String placeName = stripHtml(placeInfo.placeName()); - Place newPlace = placeRepository.save(placeMapper.createPlace(placeInfo)); + Place newPlace = placeRepository.save(placeMapper.createPlace(placeInfo, placeName)); //신규 생성된 경우에만 이미지 저장 migrateImagesToOci(newPlace.getPlaceKey(), placeInfo.imgUrls()); @@ -168,10 +140,6 @@ private SavedPlaceInfo convertToSavedPlaceInfo(SearchCandidateResponse response, List placeImages = !cached.isEmpty() ? cached : googleClient.fetchImages(response.name(), response.address(), 3); - //좋아요 있는지 확인 - - //제휴 장소인지 확인 - return placeMapper.toSavedPlaceInfo(response.item(), response.name(), response.placeKey(), response.naverPlaceUrl(), placeImages == null ? List.of() : placeImages ); @@ -244,5 +212,4 @@ private void migrateImagesToOci(String placeKey, List imageUrls) { } } - } diff --git a/src/main/java/com/campus/campus/domain/place/domain/repository/LikedPlacesRepository.java b/src/main/java/com/campus/campus/domain/place/domain/repository/LikedPlacesRepository.java index 3a644c3c..298b61eb 100644 --- a/src/main/java/com/campus/campus/domain/place/domain/repository/LikedPlacesRepository.java +++ b/src/main/java/com/campus/campus/domain/place/domain/repository/LikedPlacesRepository.java @@ -1,31 +1,14 @@ package com.campus.campus.domain.place.domain.repository; -import java.util.List; import java.util.Optional; -import java.util.Set; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; import com.campus.campus.domain.place.domain.entity.LikedPlace; -import com.campus.campus.domain.place.domain.entity.Place; -import com.campus.campus.domain.user.domain.entity.User; public interface LikedPlacesRepository extends JpaRepository { - Optional findByUserIdAndPlace_PlaceKey(Long userId, String placeKey); - - @Query(""" - SELECT lp.place.placeId - FROM LikedPlace lp - WHERE lp.user.id=:userId - and lp.place.placeId in :placeIds - """) - Set findLikedPlaceIds( - @Param("userId") Long userId, - @Param("placeIds") List placeIds - ); + boolean existsByUserIdAndPlace_PlaceKey(Long userId, String placeKey); - boolean existsByUserAndPlace(User user, Place place); + Optional findByUserIdAndPlace_PlaceKey(Long userId, String placeKey); } diff --git a/src/main/java/com/campus/campus/domain/place/domain/repository/PlaceRepository.java b/src/main/java/com/campus/campus/domain/place/domain/repository/PlaceRepository.java index 29159521..2efaf28a 100644 --- a/src/main/java/com/campus/campus/domain/place/domain/repository/PlaceRepository.java +++ b/src/main/java/com/campus/campus/domain/place/domain/repository/PlaceRepository.java @@ -1,87 +1,13 @@ package com.campus.campus.domain.place.domain.repository; -import java.util.List; import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; -import com.campus.campus.domain.place.application.dto.response.partnership.PartnershipMapSummary; import com.campus.campus.domain.place.domain.entity.Place; public interface PlaceRepository extends JpaRepository { // placeKey 기준으로 Place 조회 Optional findByPlaceKey(String placeKey); - - //제휴 가게 조회(학과) - // @Query(""" - // select new com.campus.campus.domain.place.application.dto.response.partnership.PartnershipPlaceSummary( - // p.placeId, - // p.placeKey, - // p.placeName, - // p.placeCategory, - // p.address, - // p.coordinate.latitude, - // p.coordinate.longitude, - // - // council.councilType - // ) - // from StudentCouncilPost post - // join post.place p - // join post.writer council - // where post.category = :category - // and ( - // (council.councilType = 'MAJOR' - // and council.major.majorId = :majorId) - // or (council.councilType = 'COLLEGE' - // and council.college.collegeId = :collegeId) - // or (council.councilType = 'SCHOOL' - // and council.school.schoolId = :schoolId) - // ) - // and (:cursor is null or p.placeId<:cursor) - // order by p.placeId desc - // """) - // List findPartnershipPlaces( - // @Param("category") PostCategory category, - // @Param("majorId") Long majorId, - // @Param("collegeId") Long collegeId, - // @Param("schoolId") Long schoolId, - // @Param("cursor") Long cursor, - // Pageable pageable - // ); - - @Query(""" - select distinct new com.campus.campus.domain.place.application.dto.response.partnership.PartnershipMapSummary( - p.placeId, - p.coordinate.latitude, - p.coordinate.longitude, - council.councilType - ) - from StudentCouncilPost post - join post.place p - join post.writer council - where post.category = 'PARTNERSHIP' - and p.coordinate.latitude between :minLat and :maxLat - and p.coordinate.longitude between :minLng and :maxLng - and ( - (council.councilType = 'MAJOR' - and council.major.majorId = :majorId) - or (council.councilType = 'COLLEGE' - and council.college.collegeId = :collegeId) - or (council.councilType = 'SCHOOL' - and council.school.schoolId = :schoolId) - ) - """) - List findPartnershipPlacesForMap( - @Param("minLat") double minLat, - @Param("maxLat") double maxLat, - @Param("minLng") double minLng, - @Param("maxLng") double maxLng, - @Param("majorId") Long majorId, - @Param("collegeId") Long collegeId, - @Param("schoolId") Long schoolId - ); - } diff --git a/src/main/java/com/campus/campus/domain/place/infrastructure/geocoder/GeoCoderClient.java b/src/main/java/com/campus/campus/domain/place/infrastructure/geocoder/GeoCoderClient.java deleted file mode 100644 index f7265123..00000000 --- a/src/main/java/com/campus/campus/domain/place/infrastructure/geocoder/GeoCoderClient.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.campus.campus.domain.place.infrastructure.geocoder; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; -import org.springframework.web.reactive.function.client.WebClient; - -import com.campus.campus.domain.place.application.dto.response.geocoder.AddressResponse; -import com.campus.campus.domain.place.application.exception.GeoCoderException; - -import lombok.extern.slf4j.Slf4j; -import reactor.core.publisher.Mono; - -@Component -@Slf4j -public class GeoCoderClient { - private static final String BASE_URL = "https://api.vworld.kr"; - private final WebClient webClient; - private final String apiKey; - - public GeoCoderClient( - @Value("${map.geocoder.api-key}") String apiKey - ) { - this.apiKey = apiKey; - this.webClient = WebClient.builder().baseUrl(BASE_URL).build(); - } - - /* - * 현재 위치 위/경도 -> 주소 - */ - public AddressResponse getAddress(double lat, double lng) { - AddressResponse response = webClient.get() - .uri(uriBuilder -> uriBuilder - .path("/req/address") - .queryParam("service", "address") - .queryParam("request", "getAddress") - .queryParam("key", apiKey) - .queryParam("point", lng + "," + lat) - .queryParam("crs", "epsg:4326") - .queryParam("type", "both") - .queryParam("format", "json") - .build()) - .retrieve() - .onStatus( - status -> status.isError(), - res -> Mono.error(new GeoCoderException()) - ) - .bodyToMono(AddressResponse.class).block(); - - return response; - } -} diff --git a/src/main/java/com/campus/campus/domain/place/infrastructure/naver/NaverDirectionsClient.java b/src/main/java/com/campus/campus/domain/place/infrastructure/naver/NaverDirectionsClient.java deleted file mode 100644 index 723864b1..00000000 --- a/src/main/java/com/campus/campus/domain/place/infrastructure/naver/NaverDirectionsClient.java +++ /dev/null @@ -1,50 +0,0 @@ -// package com.campus.campus.domain.place.infrastructure.naver; -// -// import org.springframework.beans.factory.annotation.Value; -// import org.springframework.stereotype.Component; -// import org.springframework.web.client.RestClient; -// import org.springframework.web.reactive.function.client.WebClient; -// -// import lombok.extern.slf4j.Slf4j; -// -// @Component -// @Slf4j -// public class NaverDirectionsClient { -// -// private final WebClient webClient; -// private final String clientId; -// private final String clientSecret; -// -// public NaverDirectionsClient( -// RestClient restClient, -// @Value("${map.naver.client-id}") String clientId, -// @Value("${map.naver.client-secret}") String clientSecret) { -// this.restClient = restClient; -// this.clientId = clientId; -// this.clientSecret = clientSecret; -// } -// -// public int getWalkingTimeSeconds( -// double startLat, double startLng, -// double goalLat, double goalLng -// ) { -// DirectionsResponse response = webClient.get() -// .uri(uriBuilder -> uriBuilder -// .path("/map-direction/v1/driving") -// .queryParam("start", startLng + "," + startLat) -// .queryParam("goal", goalLng + "," + goalLat) -// .queryParam("option", "pedestrian") -// .build() -// ) -// .retrieve() -// .bodyToMono(DirectionsResponse.class) -// .block(); -// -// return response.getRoute() -// .getTraoptimal() -// .get(0) -// .getSummary() -// .getDuration(); // 초 단위 -// } -// -// } diff --git a/src/main/java/com/campus/campus/domain/place/presentation/PlaceController.java b/src/main/java/com/campus/campus/domain/place/presentation/PlaceController.java index 48605f69..1d54c726 100644 --- a/src/main/java/com/campus/campus/domain/place/presentation/PlaceController.java +++ b/src/main/java/com/campus/campus/domain/place/presentation/PlaceController.java @@ -2,7 +2,6 @@ import java.util.List; -import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -12,14 +11,11 @@ import com.campus.campus.domain.place.application.dto.response.LikeResponse; import com.campus.campus.domain.place.application.dto.response.SavedPlaceInfo; -import com.campus.campus.domain.place.application.dto.response.geocoder.AddressResponse; import com.campus.campus.domain.place.application.service.PlaceService; -import com.campus.campus.domain.place.infrastructure.geocoder.GeoCoderClient; import com.campus.campus.global.annotation.CurrentUserId; import com.campus.campus.global.common.response.CommonResponse; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; @@ -29,47 +25,14 @@ public class PlaceController { private final PlaceService placeService; - private final GeoCoderClient geoCoderClient; @GetMapping("/search") - @Operation(summary = "현위치 기반 가까운 순으로 장소 키워드 검색", description = "검색 결과 5개 검색되도록 함") - public CommonResponse> getPlaceInfo( - @Parameter( - description = "검색할 키워드", - example = "스타벅스" - ) - @RequestParam String keyword, - @Parameter( - description = "현재 위치의 위도", - example = "37.50415" - ) - @RequestParam double lat, - @Parameter( - description = "현재 위치의 경도", - example = "126.9570" - ) - @RequestParam double lng - ) { - List searchResponse = placeService.search(lat, lng, keyword); + @Operation(summary = "장소 키워드로 검색", description = "검색 결과 5개 검색되도록 함") + public CommonResponse> getPlaceInfo(@RequestParam String keyword) { + List searchResponse = placeService.search(keyword); return CommonResponse.success(PlaceResponseCode.PLACE_SEARCH_SUCCESS, searchResponse); } - @GetMapping - public ResponseEntity getAddress( - @Parameter( - description = "현재 위치의 위도", - example = "37.50415" - ) - @RequestParam double lat, - @Parameter( - description = "현재 위치의 경도", - example = "126.9570" - ) - @RequestParam double lng - ) { - return ResponseEntity.ok(geoCoderClient.getAddress(lat, lng)); - } - @PostMapping("/like-place") @Operation(summary = "장소 좋아요 누르기") public CommonResponse likePlace(@Valid @RequestBody SavedPlaceInfo request, @@ -77,7 +40,4 @@ public CommonResponse likePlace(@Valid @RequestBody SavedPlaceInfo LikeResponse response = placeService.likePlace(request, userId); return CommonResponse.success(PlaceResponseCode.PLACE_SAVE_SUCCESS, response); } - - //가게 상세 조회 (리뷰 기능 구현 완료 후) - } diff --git a/src/main/java/com/campus/campus/domain/place/presentation/PlaceResponseCode.java b/src/main/java/com/campus/campus/domain/place/presentation/PlaceResponseCode.java index 0b1a6920..15164b37 100644 --- a/src/main/java/com/campus/campus/domain/place/presentation/PlaceResponseCode.java +++ b/src/main/java/com/campus/campus/domain/place/presentation/PlaceResponseCode.java @@ -11,8 +11,7 @@ @AllArgsConstructor public enum PlaceResponseCode implements ResponseCodeInterface { PLACE_SAVE_SUCCESS(200, HttpStatus.OK, "좋아요 처리가 완료되었습니다."), - PLACE_SEARCH_SUCCESS(200, HttpStatus.OK, "키워드 장소 검색이 성공적으로 완료되었습니다."), - CHECK_PARTNERSHIP_PLACE_SUCCESS(200, HttpStatus.OK, "제휴 장소 조회가 완료되었습니다."); + PLACE_SEARCH_SUCCESS(200, HttpStatus.OK, "키워드 장소 검색이 성공적으로 완료되었습니다."); private final int code; private final HttpStatus status; diff --git a/src/main/java/com/campus/campus/domain/user/application/service/KakaoOauthService.java b/src/main/java/com/campus/campus/domain/user/application/service/KakaoOauthService.java index 5d23b1ee..6a44d0b3 100644 --- a/src/main/java/com/campus/campus/domain/user/application/service/KakaoOauthService.java +++ b/src/main/java/com/campus/campus/domain/user/application/service/KakaoOauthService.java @@ -47,9 +47,8 @@ public class KakaoOauthService { private long refreshTokenExpirationSeconds; @Transactional - public OauthLoginResponse login(String authorizationCode) { - KakaoTokenResponse kakaoToken = getToken(authorizationCode); - KakaoUserResponse kakaoUser = getUserInfo(kakaoToken.accessToken()); + public OauthLoginResponse login(String kakaoAccessToken) { + KakaoUserResponse kakaoUser = getUserInfo(kakaoAccessToken); User user = findOrCreateUser(kakaoUser); @@ -97,28 +96,6 @@ public boolean unlink(Long kakaoId) { } } - private KakaoTokenResponse getToken(String authorizationCode) { - RestClient client = RestClient.create(); - - MultiValueMap body = new LinkedMultiValueMap<>(); - body.add("grant_type", "authorization_code"); - body.add("client_id", kakaoOauthProperty.getClientId()); - body.add("redirect_uri", kakaoOauthProperty.getRedirectUri()); - body.add("code", authorizationCode); - - if (kakaoOauthProperty.getClientSecret() != null && - !kakaoOauthProperty.getClientSecret().isBlank()) { - body.add("client_secret", kakaoOauthProperty.getClientSecret()); - } - - return client.post() - .uri(KAUTH_BASE_URL + "/oauth/token") - .contentType(MediaType.APPLICATION_FORM_URLENCODED) - .body(body) - .retrieve() - .body(KakaoTokenResponse.class); - } - private KakaoUserResponse getUserInfo(String kakaoAccessToken) { RestClient client = RestClient.create(); diff --git a/src/main/java/com/campus/campus/domain/user/presentation/AuthController.java b/src/main/java/com/campus/campus/domain/user/presentation/AuthController.java index 9c36270c..a6012080 100644 --- a/src/main/java/com/campus/campus/domain/user/presentation/AuthController.java +++ b/src/main/java/com/campus/campus/domain/user/presentation/AuthController.java @@ -24,9 +24,9 @@ public class AuthController { private final KakaoOauthService kakaoOauthService; @PostMapping("/login/kakao") - @Operation(summary = "카카오 로그인") - public CommonResponse kakaoLogin(@RequestParam("code") String code) { - OauthLoginResponse response = kakaoOauthService.login(code); + @Operation(summary = "카카오 로그인 (Native App 방식)") + public CommonResponse kakaoLogin(@RequestParam("token") String kakaoAccessToken) { + OauthLoginResponse response = kakaoOauthService.login(kakaoAccessToken); return CommonResponse.success(UserResponseCode.LOGIN_SUCCESS, response); } diff --git a/src/main/java/com/campus/campus/global/config/PermitUrlConfig.java b/src/main/java/com/campus/campus/global/config/PermitUrlConfig.java index 171fc2d6..50243973 100644 --- a/src/main/java/com/campus/campus/global/config/PermitUrlConfig.java +++ b/src/main/java/com/campus/campus/global/config/PermitUrlConfig.java @@ -30,10 +30,7 @@ public String[] getPublicUrl() { "/jwt/token/reissue", "/managers/login", "/places/search", - "/storage/presigned", - "/places", - "/api/partnership/list", - "/api/partnership/map" + "/storage/presigned" }; } } diff --git a/src/main/java/com/campus/campus/global/util/jwt/GeoUtil.java b/src/main/java/com/campus/campus/global/util/jwt/GeoUtil.java deleted file mode 100644 index e6dcb9b5..00000000 --- a/src/main/java/com/campus/campus/global/util/jwt/GeoUtil.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.campus.campus.global.util.jwt; - -public class GeoUtil { - - private static final double EARTH_RADIUS_KM = 6371.0; - - private GeoUtil() { - } - - public static double distanceKm( - double lat1, double lon1, - double lat2, double lon2 - ) { - double dLat = Math.toRadians(lat2 - lat1); - double dLon = Math.toRadians(lon2 - lon1); - - double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) - + Math.cos(Math.toRadians(lat1)) - * Math.cos(Math.toRadians(lat2)) - * Math.sin(dLon / 2) * Math.sin(dLon / 2); - - double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); - return EARTH_RADIUS_KM * c; - } - - public static double distanceMeter( - double lat1, double lon1, - double lat2, double lon2 - ) { - return distanceKm(lat1, lon1, lat2, lon2) * 1000; - } -} - diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml index d41798f3..e9971244 100644 --- a/src/main/resources/application-local.yml +++ b/src/main/resources/application-local.yml @@ -62,7 +62,5 @@ map: google: places: api-key: ${GOOGLE_PLACES_API_KEY} - geocoder: - api-key: ${GEOCODER_API_KEY} server-uri: http://localhost:8080 \ No newline at end of file