Skip to content

Commit

Permalink
Merge pull request #269 from prgrms-web-devcourse-final-project/develop
Browse files Browse the repository at this point in the history
[add] 지도에서 글타래 찾기 -> 회원 (user) 추가
  • Loading branch information
Dom1046 authored Jan 2, 2025
2 parents 3560c27 + bd2d24a commit 91622e3
Show file tree
Hide file tree
Showing 14 changed files with 267 additions and 115 deletions.
21 changes: 2 additions & 19 deletions src/main/java/com/mallangs/domain/ai/AIPromptController.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,13 @@
import com.mallangs.domain.article.service.ArticleService;
import com.mallangs.domain.board.dto.response.SightingListResponse;
import com.mallangs.domain.board.service.BoardService;
import com.mallangs.domain.member.entity.Member;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
Expand Down Expand Up @@ -59,25 +57,10 @@ public class AIPromptController {
public ResponseEntity<List<SightAIResponse>> getArticleByArticleIdByAI(
@Parameter(description = "조회할 글타래 ID", required = true) @PathVariable Long articleId) {

String memberRole;
Long memberId;

Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();

if (principal instanceof Member member) {
memberRole = member.getMemberRole().name();
memberId = member.getMemberId();
} else {
memberRole = "ROLE_GUEST";
memberId = -1L;
}
log.info("role: {} memberId: {}", memberRole, memberId);

//단전조회, 실종글타래 조회
ArticleResponse articleResponse = articleService.getArticleById(articleId, memberRole,
memberId);
ArticleResponse articleResponse = articleService.getLostArticleById(articleId);

//질문 제작
//질문제작
StringBuilder question = new StringBuilder();

// JSON 형식에 대한 예시 설명
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,12 @@ public class MapBoundsResponse {
private double longitude;

private String description;


public MapBoundsResponse(Long articleId, String type, double latitude, double longitude, String description) {
this.articleId = articleId;
this.type = type;
this.latitude = latitude;
this.longitude = longitude;
this.description = description;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public List<MapBoundsResponse> findArticlesInBoundsByType(double southWestLat,
);
}

// 장소 / 사용자 등록 위치
// 장소
@Override
public List<MapBoundsResponse> findPlaceArticlesInBoundsByType(double southWestLat,
double southWestLon, double northEastLat, double northEastLon, boolean isPublicData) {
Expand Down Expand Up @@ -143,4 +143,34 @@ public List<MapBoundsResponse> findPlaceArticlesInBoundsByCategory(double southW
);
}

//사용자 등록 위치
@Override
public List<MapBoundsResponse> findUserInBoundsByCategory(double southWestLat,
double southWestLon, double northEastLat, double northEastLon) {

String query = String.format(
"SELECT m.member_id, ST_X(a.point) AS longitude, " +
"ST_Y(a.point) AS latitude, a.region_3depth_h_name " +
"FROM address a "
+ "JOIN member m ON m.member_id = a.member_id "
+ "WHERE MBRContains(ST_GeomFromText('POLYGON((%f %f, %f %f, %f %f, %f %f, %f %f))', 4326), a.point) ",
southWestLat, southWestLon,
southWestLat, northEastLon,
northEastLat, northEastLon,
northEastLat, southWestLon,
southWestLat, southWestLon);

log.info(query);

return jdbcTemplate.query(query, (rs, rowNum) ->
new MapBoundsResponse(
rs.getLong("member_id"),
"user",
rs.getDouble("latitude"), // geography의 x 값
rs.getDouble("longitude"), // geography의 y 값
rs.getString("region_3depth_h_name")
)
);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,7 @@ List<MapBoundsResponse> findPlaceArticlesInBoundsByCategory(double southWestLat,
double southWestLon,
double northEastLat, double northEastLon, String placeCategory, boolean isPublicData);

List<MapBoundsResponse> findUserInBoundsByCategory(double southWestLat,
double southWestLon, double northEastLat, double northEastLon);

}
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,13 @@ public ArticleResponse createArticle(ArticleCreateRequest articleCreateRequest,
.orElseThrow(() -> new MallangsCustomException(ErrorCode.MEMBER_NOT_FOUND));

// 팩토리 매니저를 통해 적절한 팩토리 선택 -> 팩토리의 역할:
log.info("articleCreateRequest: {}",articleCreateRequest.toString());
log.info("articleCreateRequest 설명: {}",articleCreateRequest.getArticleType().getDescription());
log.info("articleCreateRequest: {}", articleCreateRequest.toString());
log.info("articleCreateRequest 설명: {}", articleCreateRequest.getArticleType().getDescription());
ArticleFactory factory = factoryManager.getFactory(
articleCreateRequest.getArticleType().getDescription());

// 팩토리에서 article 생성
Article article = factory.createArticle(foundMember, articleCreateRequest);
Article article = factory.createArticle(foundMember, articleCreateRequest);
article.hideInMap(); // published 상태 아니면 map hidden

Article savedArticle = articleRepository.save(article);
Expand Down Expand Up @@ -147,6 +147,24 @@ public ArticleResponse getArticleById(Long articleId, String userRole, Long memb
throw new MallangsCustomException(ErrorCode.ARTICLE_NOT_FOUND);
}

// 실종 글타래 단건 조회 (수정본)
// 사용자는 map visiblie 인 경우
public ArticleResponse getLostArticleById(Long articleId) {
Article foundArticle = articleRepository.findById(articleId)
.orElseThrow(() -> new MallangsCustomException(ErrorCode.ARTICLE_NOT_FOUND));

try {
// ArticleResponse 로 반환 통일되게 팩토리메서드 작성 필요
ArticleFactory factory = factoryManager.getFactory(
foundArticle.getArticleType().getDescription());
log.info("factory. : {}", factory);

return factory.createResponse(foundArticle);
} catch (Exception e) {
throw new MallangsCustomException(ErrorCode.ARTICLE_NOT_FOUND);
}
}

// 목격제보 글타래 전체조회
public List<ArticleResponse> getSightArticleByLostId(Long LostArticleId) {
List<Article> articles = articleRepository.findSightingArticles(LostArticleId);
Expand Down
146 changes: 79 additions & 67 deletions src/main/java/com/mallangs/domain/article/service/LocationService.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@

import com.mallangs.domain.article.dto.response.MapBoundsResponse;
import com.mallangs.domain.article.repository.LocationRepository;

import java.util.List;
import java.util.Objects;

import com.mallangs.domain.member.repository.AddressRepository;
import com.mallangs.domain.member.repository.MemberRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
Expand All @@ -13,74 +17,82 @@
@RequiredArgsConstructor
public class LocationService {

private final LocationRepository locationRepository;

// 지도 조회 시 지도 표시, 글상태 체크
// 사용자 지도, 목록 조회 시 표시, 발생만 반환
// 관리자 목록 형태 조회 시 다 볼 수 있음

// 전체 조회
public List<MapBoundsResponse> findArticlesInBounds(double southWestLat, double southWestLon,
double northEastLat, double northEastLon) {
// 위도, 경도 순서로 전달해야 하므로, 순서를 바꿔서 호출
log.info("findArticlesInBounds");
log.info(String.valueOf(southWestLat));
log.info(String.valueOf(southWestLon));
log.info(String.valueOf(northEastLat));
log.info(String.valueOf(northEastLon));

return locationRepository.findArticlesInBounds(southWestLat, southWestLon, northEastLat,
northEastLon);
}

// 대분류 기준 조회
public List<MapBoundsResponse> findArticlesInBoundsByType(double southWestLat,
double southWestLon,
double northEastLat, double northEastLon, String type) {

log.info("findArticlesInBounds");
log.info(String.valueOf(southWestLat));
log.info(String.valueOf(southWestLon));
log.info(String.valueOf(northEastLat));
log.info(String.valueOf(northEastLon));

// 장소 public, user 구분
if (Objects.equals(type, "place") || Objects.equals(type, "user")) {
boolean isPublicData = Objects.equals(type, "place"); // place 면 true

return locationRepository.findPlaceArticlesInBoundsByType(southWestLat,
southWestLon, northEastLat, northEastLon, isPublicData);
private final LocationRepository locationRepository;

// 지도 조회 시 지도 표시, 글상태 체크
// 사용자 지도, 목록 조회 시 표시, 발생만 반환
// 관리자 목록 형태 조회 시 다 볼 수 있음
// 전체 조회
public List<MapBoundsResponse> findArticlesInBounds(double southWestLat, double southWestLon,
double northEastLat, double northEastLon) {
// 위도, 경도 순서로 전달해야 하므로, 순서를 바꿔서 호출
log.info("findArticlesInBounds");
log.info(String.valueOf(southWestLat));
log.info(String.valueOf(southWestLon));
log.info(String.valueOf(northEastLat));
log.info(String.valueOf(northEastLon));

return locationRepository.findArticlesInBounds(southWestLat, southWestLon, northEastLat,
northEastLon);
}

// 실종, 구조
return locationRepository.findArticlesInBoundsByType(
southWestLat, southWestLon,
northEastLat, northEastLon,
type);
}

// 장소 소분류 기준 조회
public List<MapBoundsResponse> findPlaceArticlesInBoundsByCategory(
double southWestLat, double southWestLon,
double northEastLat, double northEastLon,
String articleType, String placeCategory) {

log.info("findArticlesInBounds");
log.info(String.valueOf(southWestLat));
log.info(String.valueOf(southWestLon));
log.info(String.valueOf(northEastLat));
log.info(String.valueOf(northEastLon));

boolean isPublicData;

isPublicData = articleType.equalsIgnoreCase("place");
// true 면 공공 데이터 검색
// false 면 사용자 등록 정보 검색

return locationRepository.findPlaceArticlesInBoundsByCategory(
southWestLat, southWestLon,
northEastLat, northEastLon,
placeCategory, isPublicData);
}
// 대분류 기준 조회
public List<MapBoundsResponse> findArticlesInBoundsByType(double southWestLat,
double southWestLon,
double northEastLat, double northEastLon, String type) {

log.info("findArticlesInBounds");
log.info(String.valueOf(southWestLat));
log.info(String.valueOf(southWestLon));
log.info(String.valueOf(northEastLat));
log.info(String.valueOf(northEastLon));

try {
// 장소 public, user 구분
if (Objects.equals(type, "place")) {
boolean isPublicData = Objects.equals(type, "place"); // place 면 true

return locationRepository.findPlaceArticlesInBoundsByType(southWestLat,
southWestLon, northEastLat, northEastLon, isPublicData);
} else if (Objects.equals(type, "user")) {
return locationRepository.findUserInBoundsByCategory(southWestLat,
southWestLon, northEastLat, northEastLon);
}

// 실종, 구조
return locationRepository.findArticlesInBoundsByType(
southWestLat, southWestLon,
northEastLat, northEastLon,
type);

} catch (Exception e) {
log.error("대분류에서 실패하였습니다. {}", e.getMessage());
throw e;
}
}

// 장소 소분류 기준 조회
public List<MapBoundsResponse> findPlaceArticlesInBoundsByCategory(
double southWestLat, double southWestLon,
double northEastLat, double northEastLon,
String articleType, String placeCategory) {

log.info("findArticlesInBounds");
log.info(String.valueOf(southWestLat));
log.info(String.valueOf(southWestLon));
log.info(String.valueOf(northEastLat));
log.info(String.valueOf(northEastLon));

boolean isPublicData;

isPublicData = articleType.equalsIgnoreCase("place");
// true 면 공공 데이터 검색
// false 면 사용자 등록 정보 검색

return locationRepository.findPlaceArticlesInBoundsByCategory(
southWestLat, southWestLon,
northEastLat, northEastLon,
placeCategory, isPublicData);
}

}
22 changes: 22 additions & 0 deletions src/main/java/com/mallangs/domain/chat/redis/RedisPublisher.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.mallangs.domain.chat.redis;

import com.mallangs.domain.chat.dto.response.ChatMessageResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

@Log4j2
@Component
@RequiredArgsConstructor
public class RedisPublisher {

private final RedisTemplate<String, Object> redisTemplate;
//레디스함 채널명
private static final String CHAT_CHANNEL = "chat_channel";

//레디스함으로 메세지 송신
public void publish(ChatMessageResponse message) {
redisTemplate.convertAndSend(CHAT_CHANNEL, message);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,26 @@ public class RedisSubscriber implements MessageListener {
private final SimpMessageSendingOperations messagingTemplate;
private final RedisTemplate redisTemplate;

//Stomp로 송신
//stomp (레디스 거치지 않고) 바로 메세지 전송
public void sendMessage(ChatMessageResponse publishMessage) {
try {
log.info("레디스 펍섭의 publishMessage: {}", publishMessage);
messagingTemplate.convertAndSend("/sub/chat/room/" + publishMessage.getChatRoomId(), publishMessage);
} catch (Exception e) {
log.error("Exception {}", e.getMessage());
}
}
//redis로 송수신
//publish Redis 메세지 수신
@Override
public void onMessage(Message message, byte[] pattern) {
try {
//레디스 역직렬화
String publishMessage = (String) redisTemplate.getStringSerializer().deserialize(message.getBody());

ChatMessageResponse chatMessage = objectMapper.readValue(publishMessage, ChatMessageResponse.class);

//stomp 이용해서 구독자들에게 메세지 송신
messagingTemplate.convertAndSend("/sub/chat/room/" + chatMessage.getChatRoomId(), chatMessage);
} catch (Exception e) {
log.error(e.getMessage());
log.error("publish 레디스 메세지 -> stomp 메세지로 송신 실패 :{}", e.getMessage());
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.mallangs.domain.chat.entity.ChatMessage;
import com.mallangs.domain.chat.entity.ChatRoom;
import com.mallangs.domain.chat.entity.ParticipatedRoom;
import com.mallangs.domain.chat.redis.RedisPublisher;
import com.mallangs.domain.chat.redis.RedisSubscriber;
import com.mallangs.domain.chat.repository.ChatMessageRepository;
import com.mallangs.domain.chat.repository.ParticipatedRoomRepository;
Expand Down Expand Up @@ -41,6 +42,7 @@ public class ChatMessageService {

private final ChatMessageRepository chatMessageRepository;
private final ParticipatedRoomRepository participatedRoomRepository;
private final RedisPublisher redisPublisher;
private final RedisSubscriber redisSubscriber;
private final MemberRepository memberRepository;

Expand Down Expand Up @@ -79,7 +81,7 @@ public ChatMessageSuccessResponse sendMessage(ChatMessageRequest chatMessageRequ
log.info("마지막 메세지 보낼 채팅 정보: {}", chatMessageResponse.toString());

//redis로 채팅 보내기
redisSubscriber.sendMessage(chatMessageResponse);
redisPublisher.publish(chatMessageResponse);
return new ChatMessageSuccessResponse(savedChatMessage.getSender().getUserId().getValue());
} catch (Exception e) {
throw new MallangsCustomException(ErrorCode.FAILED_CREATE_CHAT_MESSAGE);
Expand Down
Loading

0 comments on commit 91622e3

Please sign in to comment.