diff --git a/.gitignore b/.gitignore index c2065bc..ab8d764 100644 --- a/.gitignore +++ b/.gitignore @@ -25,7 +25,9 @@ bin/ out/ !**/src/main/**/out/ !**/src/test/**/out/ - +*.yml +/application.yml +SwaggerConfig.java ### NetBeans ### /nbproject/private/ /nbbuild/ diff --git a/README.md b/README.md index 7d07413..f50846f 100644 --- a/README.md +++ b/README.md @@ -1 +1,19 @@ # tf4-message + +# introduction + +- 외부 앱을 사용한 메세지 시스템 + + Slack +
+- Dependancies + + lombok
+ + web
+ + FeignClient
+ + RabbitMQ
+ + Mysql
+ + JPA
+
+- How to work + + +- diff --git a/build.gradle b/build.gradle index 6db0d76..5e99af1 100644 --- a/build.gradle +++ b/build.gradle @@ -39,6 +39,9 @@ dependencies { testImplementation 'org.springframework.amqp:spring-rabbit-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' implementation 'com.slack.api:slack-api-client:1.25.0' + implementation 'com.google.code.gson:gson:2.8.9' + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.5.0' + implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client' } dependencyManagement { @@ -47,6 +50,10 @@ dependencyManagement { } } +springBoot { + mainClass = 'com.tunaforce.message.MessageApplication' +} + tasks.named('test') { useJUnitPlatform() } diff --git a/src/main/java/com/tunaforce/message/MessageApplication.java b/src/main/java/com/tunaforce/message/MessageApplication.java index 3183e04..d23ec06 100644 --- a/src/main/java/com/tunaforce/message/MessageApplication.java +++ b/src/main/java/com/tunaforce/message/MessageApplication.java @@ -2,8 +2,16 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication +@EnableFeignClients +@EnableDiscoveryClient +@EnableJpaAuditing +@EnableScheduling public class MessageApplication { public static void main(String[] args) { diff --git a/src/main/java/com/tunaforce/message/api/ApiExceptionAdvice.java b/src/main/java/com/tunaforce/message/api/ApiExceptionAdvice.java index 8ad5f61..2d723f7 100644 --- a/src/main/java/com/tunaforce/message/api/ApiExceptionAdvice.java +++ b/src/main/java/com/tunaforce/message/api/ApiExceptionAdvice.java @@ -1,12 +1,15 @@ package com.tunaforce.message.api; +import com.slack.api.methods.SlackApiException; +import jakarta.servlet.http.HttpServletRequest; import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.servlet.resource.NoResourceFoundException; -import jakarta.servlet.http.HttpServletRequest; +import java.util.NoSuchElementException; @RestControllerAdvice public class ApiExceptionAdvice { @@ -45,6 +48,38 @@ public ResponseEntity> notFoundExceptionHandler(HttpServletR return ResponseEntity .ok(apiResponse); } + @ExceptionHandler(NoSuchElementException.class) + public ResponseEntity> noSuchElementExceptionHandler(HttpServletRequest request, final NoSuchElementException NoSuchElementException) { + ApiResponse apiResponse = ApiResponse.builder() + .status(ApiStatus.NOT_FOUND.getStatusCode()) + .message(ApiStatus.NOT_FOUND.getMessage()) + .errors(NoSuchElementException.getMessage()) + .build(); + + return ResponseEntity + .ok(apiResponse); + } + + @ExceptionHandler(SlackApiException.class) + public ResponseEntity> slackApiExceptionHandler(HttpServletRequest request, final SlackApiException slackApiException) { + ApiResponse apiResponse = ApiResponse.builder() + .status(ApiStatus.NOT_FOUND.getStatusCode()) + .message(ApiStatus.NOT_FOUND.getMessage()) + .errors(slackApiException.getMessage()) + .build(); + + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(apiResponse); + } + + @ExceptionHandler(SlackMessageSendException.class) + public ResponseEntity> handleSlackMessageSendException(SlackMessageSendException ex) { + ApiResponse apiResponse = ApiResponse.builder() + .status(HttpStatus.INTERNAL_SERVER_ERROR.value()) // 500 상태 코드 + .message("Slack 메시지 전송 실패") + .errors(ex.getMessage()) + .build(); + + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(apiResponse); + } - @ExceptionHandler() } \ No newline at end of file diff --git a/src/main/java/com/tunaforce/message/api/SlackMessageSendException.java b/src/main/java/com/tunaforce/message/api/SlackMessageSendException.java new file mode 100644 index 0000000..107f2d1 --- /dev/null +++ b/src/main/java/com/tunaforce/message/api/SlackMessageSendException.java @@ -0,0 +1,9 @@ +package com.tunaforce.message.api; + +import com.slack.api.methods.SlackApiException; + +public class SlackMessageSendException extends RuntimeException { + public SlackMessageSendException(String message) { + super(message); + } +} diff --git a/src/main/java/com/tunaforce/message/cmmn/ResultData.java b/src/main/java/com/tunaforce/message/cmmn/ResultData.java deleted file mode 100644 index 176af13..0000000 --- a/src/main/java/com/tunaforce/message/cmmn/ResultData.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.tunaforce.message.cmmn; - -public class ResultData { - private boolean success; - private T data; - private String error; - - public ResultData(boolean success, T data, String error) { - this.success = success; - this.data = data; - this.error = error; - } -} \ No newline at end of file diff --git a/src/main/java/com/tunaforce/message/cmmn/RouteData.java b/src/main/java/com/tunaforce/message/cmmn/RouteData.java new file mode 100644 index 0000000..5f7b550 --- /dev/null +++ b/src/main/java/com/tunaforce/message/cmmn/RouteData.java @@ -0,0 +1,52 @@ +package com.tunaforce.message.cmmn; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class RouteData { + //필수 필드만 추가 + // 출발지 + //출발지(경도,위도) + //<예시> start=127.12345,37.12345 + private String start; + // 도착지 + //목적지(경도,위도) + //':'로 구분하여 최대 10개의 목적지 입력 가능 + //입력한 목적지 중 가장 적은 비용으로 도달할 수 있는 목적지에 대한 경로 조회 <예시> goal=123.45678,34.56789:124.56789,35.67890 + private String goal; + //추후 리팩토링 시 추가 + //경유지 +// private String waypoints; + //경로 조회 옵션 + //trafast | tracomfort | traoptimal (기본값) | traavoidtoll | traavoidcaronly + //trafast : 실시간 빠른 길 + //tracomfort : 실시간 편한 길 + //traoptimal : 실시간 최적 + //traavoidtoll : 무료 우선 + //traavoidcaronly : 자동차 전용 도로 회피 우선 +// private String option; + //차량 타입 + //1 (기본값) | 2 | 3 | 4 | 5 | 6 + //1 : 1종 소형차 2축 차량(윤폭 279.4 mm 이하 승용차, 소형 승합차, 소형 화물차) + //2 : 2종 2축 차량(윤폭 279.4 mm 초과, 윤거 1,800 mm 이하 중형 승합차, 중형 화물차) 3 : 3종 대형차 2축 차량(윤폭 279.4 mm 초과, 윤거 1,800 mm 초과 대형 승합차, 2축 대형 + //화물차) + //4 : 4종 3축 대형 화물차 + //5 : 5종 4축 이상 특수 화물차 + //6 : 1종 경형 자동차(배기량 1000 cc 미만으로 길이 3.6 m, 너비 1.6 m, 높이 2.0 m 이하) +// private String cartype; + //연료 타입 + // asoline (기본값) | highgradegasoline | diesel | lpg + // gasoline : 휘발유 + // highgradegasoline : 고급 휘발유 + // diesel : 경유 + // lpg : LPG + // 유류비 계산에 활용 +// private String fueltype; + + public String returnQueryUri() { + return "?start=" + this.start + "&goal=" + this.goal; + } + +} diff --git a/src/main/java/com/tunaforce/message/cmmn/SlackMsg.java b/src/main/java/com/tunaforce/message/cmmn/SlackMsg.java index 48e6b25..8239a46 100644 --- a/src/main/java/com/tunaforce/message/cmmn/SlackMsg.java +++ b/src/main/java/com/tunaforce/message/cmmn/SlackMsg.java @@ -1,7 +1,5 @@ package com.tunaforce.message.cmmn; - -import com.msa.slacktest.SLACK.dto.request.RequestSlackSend; import com.slack.api.Slack; import com.slack.api.methods.SlackApiException; import com.slack.api.methods.request.chat.ChatPostMessageRequest; @@ -9,8 +7,11 @@ import com.slack.api.methods.request.conversations.ConversationsOpenRequest; import com.slack.api.methods.response.chat.ChatPostMessageResponse; import com.slack.api.methods.response.conversations.ConversationsOpenResponse; +import com.tunaforce.message.api.SlackMessageSendException; +import jakarta.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; +import okhttp3.Request; +import okhttp3.Response; import org.springframework.stereotype.Component; import java.io.IOException; @@ -20,19 +21,16 @@ @Component public class SlackMsg { - @Value("${slack.api.token}") - private String slackToken; - - @Value("${slack.channel.id}") - private String channelId; - - // @Value("${slack.user.id}") - // private String userId; + //토큰은 auth 모듈에서 api로 받아 redis에 저장 +// @Value("${slack.api.token}") +// private String slackToken; + //userid로 변경하여 auth 모듈에서 불러오기 +// @Value("${slack.channel.id}") +// private String channelId; - - public RequestSlackSend sendMessage(String message) { + public void sendMessageChannel(String slackToken, String channelId,String message) { Slack slack = Slack.getInstance(); try { @@ -51,19 +49,19 @@ public RequestSlackSend sendMessage(String message) { log.error("메시지 전송 실패: " + response.getError()); resultCheck = false; } - return new RequestSlackSend( - resultCheck, - message - ); +// return new RequestSlackSend( +// resultCheck, +// message +// ); } catch (SlackApiException | IOException e) { e.printStackTrace(); - return new RequestSlackSend( - false, - "Error : " + e.getMessage() + message - ); +// return new RequestSlackSend( +// false, +// "Error : " + e.getMessage() + message +// ); } } - public void sendDirectMessage(String userId, String message) throws IOException, SlackApiException { + public void sendDirectMessage(String slackToken,String userId, String message) throws IOException, SlackApiException { Slack slack = Slack.getInstance(); // 1. 사용자와의 DM 대화방 열기 @@ -73,8 +71,9 @@ public void sendDirectMessage(String userId, String message) throws IOException, .build() ); + if (!openResponse.isOk()) { - throw new RuntimeException("Error opening conversation: " + openResponse.getError()); + throw new SlackMessageSendException("Error opening conversation: " + openResponse.getError()); } else{ log.info("From. {} \n message has sent : {}",userId ,message); @@ -96,7 +95,7 @@ public void sendDirectMessage(String userId, String message) throws IOException, } - public void fetchHistory(Integer brCount) { + public void fetchHistory(String slackToken, String channelId, Integer brCount) { var client = Slack.getInstance().methods(); try { var response = client.conversationsHistory(ConversationsHistoryRequest.builder() diff --git a/src/main/java/com/tunaforce/message/config/AuditorAwareImpl.java b/src/main/java/com/tunaforce/message/config/AuditorAwareImpl.java index a7bcac2..a36620b 100644 --- a/src/main/java/com/tunaforce/message/config/AuditorAwareImpl.java +++ b/src/main/java/com/tunaforce/message/config/AuditorAwareImpl.java @@ -1,17 +1,45 @@ package com.tunaforce.message.config; +import jakarta.servlet.http.HttpServletRequest; +import org.jetbrains.annotations.NotNull; import org.springframework.data.domain.AuditorAware; -import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; import java.util.Optional; import java.util.UUID; -@Component -public class AuditorAwareImpl implements AuditorAware { +public class AuditorAwareImpl implements AuditorAware { + + @NotNull @Override - public Optional getCurrentAuditor(){ - //SecurityContext로 사용자 정보 반환 - return Optional.of(null); + public Optional getCurrentAuditor() { + try { + + + RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes(); + + ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + if (attr == null) { + return Optional.of(UUID.fromString("49195b81-db15-438c-8f1c-63b17739c027")); // 웹요청 없음 (예: 스케줄러 등) + } + + + // check type & casting + if (requestAttributes instanceof ServletRequestAttributes servletRequestAttributes) { + HttpServletRequest request = servletRequestAttributes.getRequest(); + String userId = request.getHeader("X-User-Id"); + + if (userId != null && !userId.isEmpty()) { + return Optional.of(UUID.fromString(userId)); + } + } + + return Optional.of(UUID.fromString("00000000-0000-0000-0000-000000000000")); + } catch (Exception ex) { + return Optional.of(UUID.fromString("49195b81-db15-438c-8f1c-63b17739c027")); // 웹요청 없음 (예: 스케줄러 등) + } } } diff --git a/src/main/java/com/tunaforce/message/config/JpaConfig.java b/src/main/java/com/tunaforce/message/config/JpaConfig.java index 1580838..9d30cb1 100644 --- a/src/main/java/com/tunaforce/message/config/JpaConfig.java +++ b/src/main/java/com/tunaforce/message/config/JpaConfig.java @@ -2,14 +2,16 @@ import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.data.domain.AuditorAware; -import org.springframework.stereotype.Component; -@Component +import java.util.UUID; + +@Configuration public class JpaConfig { @Bean - public AuditorAware auditorProvider() { - return new AuditAwareImpl(); + public AuditorAware auditorProvider() { + return new AuditorAwareImpl(); } } diff --git a/src/main/java/com/tunaforce/message/maps/controller/mapInfoController.java b/src/main/java/com/tunaforce/message/maps/controller/mapInfoController.java new file mode 100644 index 0000000..f43bd50 --- /dev/null +++ b/src/main/java/com/tunaforce/message/maps/controller/mapInfoController.java @@ -0,0 +1,45 @@ +package com.tunaforce.message.maps.controller; + + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.tunaforce.message.api.ApiResponse; +import com.tunaforce.message.maps.dto.naverMap.geocodeResponseDto; +import com.tunaforce.message.maps.dto.response.CoordinatesDataResponseDto; +import com.tunaforce.message.maps.service.mapInfoService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.UUID; + +@Slf4j +@RestController +@RequestMapping("/maps") +@RequiredArgsConstructor +public class mapInfoController { + + private final mapInfoService mapInfoService; + + //좌표 반환 API + @GetMapping("/Coordinates") + public ResponseEntity> getCoords( + @RequestParam String address, + @RequestHeader("X-User-Id") UUID userId + ) throws JsonProcessingException { + + log.info("{} -> \n Search address : {}",userId, address); + geocodeResponseDto resultDto = mapInfoService.getCoords(address); + CoordinatesDataResponseDto resultCoordinate = new CoordinatesDataResponseDto( + resultDto.getAddresses().get(0).getX(), + resultDto.getAddresses().get(0).getY() + ); + ApiResponse resultResponse = ApiResponse.success(resultCoordinate); + return ResponseEntity.ok(resultResponse); + + } + + + //경로 추적 - 예상 거리와 예상 시간 봔환 + +} diff --git a/src/main/java/com/tunaforce/message/maps/dto/naverMap/Address.java b/src/main/java/com/tunaforce/message/maps/dto/naverMap/Address.java new file mode 100644 index 0000000..e425f3d --- /dev/null +++ b/src/main/java/com/tunaforce/message/maps/dto/naverMap/Address.java @@ -0,0 +1,20 @@ +package com.tunaforce.message.maps.dto.naverMap; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class Address { + private String roadAddress; + private String jibunAddress; + private String englishAddress; + private List addressElements; + private String x; + private String y; + private double distance; +} diff --git a/src/main/java/com/tunaforce/message/maps/dto/naverMap/AddressElement.java b/src/main/java/com/tunaforce/message/maps/dto/naverMap/AddressElement.java new file mode 100644 index 0000000..6691e73 --- /dev/null +++ b/src/main/java/com/tunaforce/message/maps/dto/naverMap/AddressElement.java @@ -0,0 +1,18 @@ +package com.tunaforce.message.maps.dto.naverMap; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class AddressElement { + private List types; + private String longName; + private String shortName; + private String code; +} diff --git a/src/main/java/com/tunaforce/message/maps/dto/naverMap/Meta.java b/src/main/java/com/tunaforce/message/maps/dto/naverMap/Meta.java new file mode 100644 index 0000000..a0cb7e6 --- /dev/null +++ b/src/main/java/com/tunaforce/message/maps/dto/naverMap/Meta.java @@ -0,0 +1,14 @@ +package com.tunaforce.message.maps.dto.naverMap; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class Meta { + private int totalCount; + private int page; + private int count; +} diff --git a/src/main/java/com/tunaforce/message/maps/dto/naverMap/geocodeResponseDto.java b/src/main/java/com/tunaforce/message/maps/dto/naverMap/geocodeResponseDto.java new file mode 100644 index 0000000..38641d1 --- /dev/null +++ b/src/main/java/com/tunaforce/message/maps/dto/naverMap/geocodeResponseDto.java @@ -0,0 +1,31 @@ +package com.tunaforce.message.maps.dto.naverMap; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.*; + +import java.util.ArrayList; +import java.util.List; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Builder +@JsonInclude(JsonInclude.Include.NON_NULL) +public class geocodeResponseDto { + public String status; + public Meta meta; + public List
addresses; + public String errorMessage; + + public List getPoints() { + + List points = new ArrayList<>(); + + for (Address address : this.addresses) { + points.add(address.getX()+","+ address.getY()); + } + + return points; + }; +} diff --git a/src/main/java/com/tunaforce/message/maps/dto/naverRoute/Goal.java b/src/main/java/com/tunaforce/message/maps/dto/naverRoute/Goal.java new file mode 100644 index 0000000..ed32fb1 --- /dev/null +++ b/src/main/java/com/tunaforce/message/maps/dto/naverRoute/Goal.java @@ -0,0 +1,9 @@ +package com.tunaforce.message.maps.dto.naverRoute; + +import java.util.List; + +public record Goal( + int dir, + List location +) { +} diff --git a/src/main/java/com/tunaforce/message/maps/dto/naverRoute/Guide.java b/src/main/java/com/tunaforce/message/maps/dto/naverRoute/Guide.java new file mode 100644 index 0000000..70cd737 --- /dev/null +++ b/src/main/java/com/tunaforce/message/maps/dto/naverRoute/Guide.java @@ -0,0 +1,10 @@ +package com.tunaforce.message.maps.dto.naverRoute; + +public record Guide( + int distance, + int duration, + String instructions, + int pointIndex, + int type +) { +} diff --git a/src/main/java/com/tunaforce/message/maps/dto/naverRoute/Route.java b/src/main/java/com/tunaforce/message/maps/dto/naverRoute/Route.java new file mode 100644 index 0000000..4c0b37b --- /dev/null +++ b/src/main/java/com/tunaforce/message/maps/dto/naverRoute/Route.java @@ -0,0 +1,8 @@ +package com.tunaforce.message.maps.dto.naverRoute; + +import java.util.List; + +public record Route( + List traoptimal +) { +} diff --git a/src/main/java/com/tunaforce/message/maps/dto/naverRoute/Section.java b/src/main/java/com/tunaforce/message/maps/dto/naverRoute/Section.java new file mode 100644 index 0000000..f2cebcf --- /dev/null +++ b/src/main/java/com/tunaforce/message/maps/dto/naverRoute/Section.java @@ -0,0 +1,11 @@ +package com.tunaforce.message.maps.dto.naverRoute; + +public record Section( + int congestion, + int distance, + String name, + int pointCount, + int pointIndex, + int speed +) { +} diff --git a/src/main/java/com/tunaforce/message/maps/dto/naverRoute/Start.java b/src/main/java/com/tunaforce/message/maps/dto/naverRoute/Start.java new file mode 100644 index 0000000..689a45a --- /dev/null +++ b/src/main/java/com/tunaforce/message/maps/dto/naverRoute/Start.java @@ -0,0 +1,8 @@ +package com.tunaforce.message.maps.dto.naverRoute; + +import java.util.List; + +public record Start( + List location +) { +} diff --git a/src/main/java/com/tunaforce/message/maps/dto/naverRoute/Summary.java b/src/main/java/com/tunaforce/message/maps/dto/naverRoute/Summary.java new file mode 100644 index 0000000..9f9a63f --- /dev/null +++ b/src/main/java/com/tunaforce/message/maps/dto/naverRoute/Summary.java @@ -0,0 +1,16 @@ +package com.tunaforce.message.maps.dto.naverRoute; + +import java.util.List; + +public record Summary( + List> bbox, + String departureTime, + int distance, + int duration, + int fuelPrice, + Goal goal, + Start start, + int taxiFare, + int tollFare +) { +} diff --git a/src/main/java/com/tunaforce/message/maps/dto/naverRoute/Traoptimal.java b/src/main/java/com/tunaforce/message/maps/dto/naverRoute/Traoptimal.java new file mode 100644 index 0000000..f28b41d --- /dev/null +++ b/src/main/java/com/tunaforce/message/maps/dto/naverRoute/Traoptimal.java @@ -0,0 +1,11 @@ +package com.tunaforce.message.maps.dto.naverRoute; + +import java.util.List; + +public record Traoptimal( + List guide, + List> path, + List
section, + Summary summary +) { +} diff --git a/src/main/java/com/tunaforce/message/maps/dto/naverRoute/direction5ResponseDto.java b/src/main/java/com/tunaforce/message/maps/dto/naverRoute/direction5ResponseDto.java new file mode 100644 index 0000000..c2ec2d7 --- /dev/null +++ b/src/main/java/com/tunaforce/message/maps/dto/naverRoute/direction5ResponseDto.java @@ -0,0 +1,19 @@ +package com.tunaforce.message.maps.dto.naverRoute; + + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.*; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Builder +@JsonInclude(JsonInclude.Include.NON_NULL) +public class direction5ResponseDto { + private int code; + private String message; + private String currentDateTime; + private Route route; +} + diff --git a/src/main/java/com/tunaforce/message/maps/dto/response/CoordinatesDataResponseDto.java b/src/main/java/com/tunaforce/message/maps/dto/response/CoordinatesDataResponseDto.java new file mode 100644 index 0000000..fc72138 --- /dev/null +++ b/src/main/java/com/tunaforce/message/maps/dto/response/CoordinatesDataResponseDto.java @@ -0,0 +1,12 @@ +package com.tunaforce.message.maps.dto.response; + + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class CoordinatesDataResponseDto { + private String xLatitude; + private String yLongitude; +} diff --git a/src/main/java/com/tunaforce/message/maps/repository/mapInfoRepository.java b/src/main/java/com/tunaforce/message/maps/repository/mapInfoRepository.java new file mode 100644 index 0000000..72efbe3 --- /dev/null +++ b/src/main/java/com/tunaforce/message/maps/repository/mapInfoRepository.java @@ -0,0 +1,13 @@ +package com.tunaforce.message.maps.repository; + +import com.tunaforce.message.token.entity.MasterToken; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +import java.util.Optional; +import java.util.UUID; + +public interface mapInfoRepository extends JpaRepository { + @Query("select m from MasterToken m where m.deletedAt is null ") + Optional getMasterToken(); +} diff --git a/src/main/java/com/tunaforce/message/maps/service/ClientCoordinatesData.java b/src/main/java/com/tunaforce/message/maps/service/ClientCoordinatesData.java new file mode 100644 index 0000000..593e065 --- /dev/null +++ b/src/main/java/com/tunaforce/message/maps/service/ClientCoordinatesData.java @@ -0,0 +1,18 @@ +package com.tunaforce.message.maps.service; + + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestParam; + +//네이버 페인 클라이언트 인터페이스 +@FeignClient(name = "naverGeocode", url = "${Naver.API.Geocoding}") +public interface ClientCoordinatesData { + @GetMapping("/geocode") + String getGeocode( + @RequestHeader("X-NCP-APIGW-API-KEY-ID") String clientId, + @RequestHeader("X-NCP-APIGW-API-KEY") String clientSecret, + @RequestParam("query") String address + ); +} diff --git a/src/main/java/com/tunaforce/message/maps/service/ClientRoutesData.java b/src/main/java/com/tunaforce/message/maps/service/ClientRoutesData.java new file mode 100644 index 0000000..6a819c4 --- /dev/null +++ b/src/main/java/com/tunaforce/message/maps/service/ClientRoutesData.java @@ -0,0 +1,17 @@ +package com.tunaforce.message.maps.service; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestParam; + +@FeignClient(name = "naverRoute", url = "${Naver.API.Directions 5}") +public interface ClientRoutesData { + @GetMapping("/driving") + String getRoute( + @RequestHeader("X-NCP-APIGW-API-KEY-ID") String clientId, + @RequestHeader("X-NCP-APIGW-API-KEY") String clientSecret, + @RequestParam String start, + @RequestParam String goal + ); +} diff --git a/src/main/java/com/tunaforce/message/maps/service/mapInfoService.java b/src/main/java/com/tunaforce/message/maps/service/mapInfoService.java new file mode 100644 index 0000000..bbf6c0e --- /dev/null +++ b/src/main/java/com/tunaforce/message/maps/service/mapInfoService.java @@ -0,0 +1,81 @@ +package com.tunaforce.message.maps.service; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.tunaforce.message.cmmn.RouteData; +import com.tunaforce.message.maps.dto.naverMap.geocodeResponseDto; +import com.tunaforce.message.maps.dto.naverRoute.direction5ResponseDto; +import com.tunaforce.message.maps.dto.response.CoordinatesDataResponseDto; +import com.tunaforce.message.token.entity.MasterToken; +import com.tunaforce.message.maps.repository.mapInfoRepository; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.NoSuchElementException; + +@Slf4j +@Service +@RequiredArgsConstructor +public class mapInfoService { + + private final ClientCoordinatesData clientCoordinatesData; + private final ClientRoutesData clientRoutesData; + private final mapInfoRepository mapInfoRepository; + + // 경도 위도 값 반환 부 + public geocodeResponseDto getCoords(String address) throws JsonProcessingException { + MasterToken masterToken = mapInfoRepository.getMasterToken().orElseThrow( + () -> new NoSuchElementException("MasterTokens not found") + ); + //DB에서 가져와야함 + String Id = masterToken.getMapId(); + String Key = masterToken.getMapKey(); + log.info("Search Keys -> \n {} : {}",Id, Key); + String result = clientCoordinatesData.getGeocode( + Id, + Key, + address + ); + ObjectMapper dataParser = new ObjectMapper(); + + return dataParser.readValue(result, geocodeResponseDto.class); + + + } + + + //허브에서 경위도가 자체 + public direction5ResponseDto getRoute(RouteData routeData) throws JsonProcessingException { + log.info("get the long and lat data"); + //각 주소로 경위도를 반환한다. + geocodeResponseDto startCoordinate = getCoords(routeData.getStart()); + geocodeResponseDto endCoordinate = getCoords(routeData.getGoal()); + //네이버 API 필요 ID KEY + MasterToken masterToken = mapInfoRepository.getMasterToken().orElseThrow( + () -> new NoSuchElementException("MasterTokens not found") + ); + //DB에서 가져와야함 + String Id = masterToken.getMapId(); + String Key = masterToken.getMapKey(); + + String rowData = clientRoutesData.getRoute( + Id, + Key, + startCoordinate.getPoints().get(0), + endCoordinate.getPoints().get(0) + ); + + ObjectMapper dataParser = new ObjectMapper(); + return dataParser.readValue(rowData, direction5ResponseDto.class); + } + + // 시분초를 변환하는 함수 + public String convertMsToTimeString(long millis) { + long hours = millis / (1000 * 60 * 60); + long minutes = (millis / (1000 * 60)) % 60; + long seconds = (millis / 1000) % 60; + + return String.format("%02d:%02d:%02d", hours, minutes, seconds); + } +} diff --git a/src/main/java/com/tunaforce/message/message/DirectMessageScheduler.java b/src/main/java/com/tunaforce/message/message/DirectMessageScheduler.java new file mode 100644 index 0000000..ba256cb --- /dev/null +++ b/src/main/java/com/tunaforce/message/message/DirectMessageScheduler.java @@ -0,0 +1,154 @@ +package com.tunaforce.message.message; + + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.slack.api.methods.SlackApiException; +import com.tunaforce.message.cmmn.RouteData; +import com.tunaforce.message.cmmn.SlackMsg; +import com.tunaforce.message.maps.dto.naverRoute.Summary; +import com.tunaforce.message.maps.dto.naverRoute.direction5ResponseDto; +import com.tunaforce.message.maps.service.mapInfoService; +import com.tunaforce.message.message.dto.request.CreateMessageLogRequestDto; +import com.tunaforce.message.message.dto.response.MessageLogResponseDto; +import com.tunaforce.message.message.dto.response.delivery.DeliveryForm; +import com.tunaforce.message.message.dto.response.delivery.GetDeliveriesResponseDto; +import com.tunaforce.message.message.dto.response.delivery.GetDeliverymenResponseDto; +import com.tunaforce.message.message.dto.response.hub.HubResponseDto; +import com.tunaforce.message.message.dto.response.hub.HubsResponseDto; +import com.tunaforce.message.message.entity.DeliveryStatus; +import com.tunaforce.message.message.entity.MessageManagement; +import com.tunaforce.message.message.repository.MessageLogRepository; +import com.tunaforce.message.message.repository.StatusRepository; +import com.tunaforce.message.message.service.MessageService; +import com.tunaforce.message.message.service.feignClient.ClientDeliveryService; +import com.tunaforce.message.message.service.feignClient.ClientHubService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.UUID; +import java.util.stream.Collectors; + +@Component +@Slf4j +public class DirectMessageScheduler { + + @Autowired + private StatusRepository statusRepository; + @Autowired + private ClientHubService clientHubService; + @Autowired + private ClientDeliveryService clientDeliveryService; + @Autowired + private mapInfoService mIService; + @Autowired + private MessageService msgApp; + @Autowired + private MessageLogRepository messageLogRepository; + + //@Scheduled(fixedRate = 5000) + @Scheduled(cron = "${scheduler.second} ${scheduler.minute} ${scheduler.hour} * * *") // 매일 오전 6시 (초, 분, 시, 일, 월, 요일) + public void directMessageScheduler() throws NoSuchElementException, IOException, SlackApiException { + + LocalDateTime now = LocalDateTime.now(); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + DateTimeFormatter formattertime = DateTimeFormatter.ofPattern("HH:mm:ss"); + String today = now.format(formatter); + String nowTime = now.format(formattertime); + + //배송 리스트를 받아온다 + //배송 리스트에 대한 날짜로 받아옴 + DeliveryForm resultProduct = clientDeliveryService.getListDelivery(today); + if (resultProduct.getData().isEmpty()) { + return; + } + //허브 별 담당자 조회 + //role로 구분 + DeliveryForm resultAgents = clientDeliveryService.getListDeliverymen("Company"); +// + //허브 아이디로 각각 허브에 속한 담당자 끼리 묶는다 + Map> hubGrouped = + resultAgents.getData().stream().collect(Collectors.groupingBy(GetDeliverymenResponseDto::getHubId)); + // 배송 물품을 허브 별로 + Map> productsinHub = + resultProduct.getData().stream().collect(Collectors.groupingBy(GetDeliveriesResponseDto::getArrivalHubId)); + + //status db 검색 + //어제 마지막 값을 받아온다(배달원 순번 값) + List deliveryStatus = statusRepository.findAll(); + + + for (String hubId : hubGrouped.keySet()) { + List temphubList = productsinHub.get(hubId); + if (temphubList != null) { + List tempmenList = hubGrouped.get(hubId); + int idx =0; + //순번들을 별도로 받아 인덱스 값을 반환한다. + for (GetDeliveriesResponseDto productId : temphubList) { + + //차례로 경로 로그를 남긴다 + //productId 안에 있는 허브주소와 업체 주소를 함수에 넣는다. + + HubResponseDto temphubSingledto = clientHubService.getHub(productId.getArrivalHubId()); + + RouteData routePath = new RouteData( + temphubSingledto.getHubAddress(), + productId.getDeliveryAddress() + ); + + log.info("Search data : From. {}-> To. {}",routePath.getGoal(), routePath.getGoal()); + + direction5ResponseDto routeInfo = mIService.getRoute(routePath); + + Summary tempRoute = routeInfo.getRoute().traoptimal().get(0).summary(); + + + //전체 경로 거리 + int distance = tempRoute.distance(); + //전체 경로 소요시간 (ms) + int duration = tempRoute.duration(); + String routTime = mIService.convertMsToTimeString(duration); + //예상도착일시 (yyyy-MM-dd HH:mm:ss) + String departuretime = tempRoute.departureTime(); + log.info("Total route distance : {}", distance); + log.info("Total route time : {}", duration); + log.info("Total route prediction : {}", routTime); + + GetDeliverymenResponseDto manSingle = tempmenList.get(idx++); + + //위의 받은 값으로 각 담당자에서 메세지를 보낸다. + CreateMessageLogRequestDto msgInfo = new CreateMessageLogRequestDto( + "\n["+nowTime+"] -> \n"+"목적지 : " + routePath.getGoal(), + UUID.randomUUID(), + manSingle.getUserId() + ); + + + MessageLogResponseDto tempData = msgApp.sendMessage(UUID.fromString("49195b81-db15-438c-8f1c-63b17739c027"), msgInfo); + + //로그는 송신이 된 후에 쌓여야 함 + MessageManagement messageManagement = new MessageManagement(tempData); + messageLogRepository.save(messageManagement); + //앱을 통한 메세지 송신 로직 구성 + + + + } + } + + + } + } + +} + + + + diff --git a/src/main/java/com/tunaforce/message/message/controller/LogController.java b/src/main/java/com/tunaforce/message/message/controller/LogController.java new file mode 100644 index 0000000..46fe60e --- /dev/null +++ b/src/main/java/com/tunaforce/message/message/controller/LogController.java @@ -0,0 +1,82 @@ +package com.tunaforce.message.message.controller; + +import com.tunaforce.message.api.ApiResponse; +import com.tunaforce.message.message.dto.request.CreateRouteLogRequestDto; +import com.tunaforce.message.message.dto.response.SearchLogResponseDto; +import com.tunaforce.message.message.service.feignClient.ClientCoordinatesService; +import com.tunaforce.message.message.service.RoutLogService; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.UUID; + +@Slf4j +@Tag(name = "로그 CRUD") +@RestController +@RequestMapping("/log") +@RequiredArgsConstructor +public class LogController { + + private final RoutLogService routLogService; + private final ClientCoordinatesService ccs; + + + //경로 추적을 위한 + @GetMapping + public ResponseEntity>> getLogDatas( + @RequestHeader("X-User_Id") UUID user_Id, + @RequestHeader("X-Roles") String roles + ) throws Exception { + log.info("경로 기록 조회"); + log.info("{} has approached", user_Id); + log.info("{} role", roles); + + if (roles.equals("MASTER")) { + List tempList = routLogService.readAllLog(); + ApiResponse> resultDto = ApiResponse.success(tempList); + return ResponseEntity.ok(resultDto); + } + else{ + return ResponseEntity.status(HttpStatus.FORBIDDEN).build(); + } + + } + + + //deliveryID 값으로 검색하여 해당 값을 받아 수정 + //수정되는 값은 실제 데이터의 update : real_distance, real_time, curr_status + //실제 총 거리와 시간이 기입되면 배송 완료라고 가정한다. + @PutMapping + public ResponseEntity> updateLogRealData( + @RequestParam Long deliveryId, + @RequestHeader("X-User-Id") UUID user_Id, + @RequestHeader("X-Roles") String roles + + ) { + log.info("{} has approached", user_Id); + log.info("{} roles", roles); + + if (roles.equals("MASTER")) { + Boolean tempList = routLogService.updateStatus(deliveryId); + ApiResponse resultDto = ApiResponse.success(tempList); + return ResponseEntity.ok(resultDto); + } + else{ + return ResponseEntity.status(HttpStatus.FORBIDDEN).build(); + } + + } + + + //deliveryID 값으로 검색하여 해당 값을 받아 삭제 + @DeleteMapping + public ResponseEntity> deleteLogDatas(@RequestParam String deliveryId) { + return ResponseEntity.ok(null); + } + +} diff --git a/src/main/java/com/tunaforce/message/message/controller/MessageController.java b/src/main/java/com/tunaforce/message/message/controller/MessageController.java index a6b8043..65afe38 100644 --- a/src/main/java/com/tunaforce/message/message/controller/MessageController.java +++ b/src/main/java/com/tunaforce/message/message/controller/MessageController.java @@ -1,13 +1,63 @@ package com.tunaforce.message.message.controller; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import com.slack.api.methods.SlackApiException; +import com.tunaforce.message.api.ApiResponse; +import com.tunaforce.message.message.dto.request.CreateMessageLogRequestDto; +import com.tunaforce.message.message.dto.response.MessageLogResponseDto; +import com.tunaforce.message.message.service.MessageService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import java.io.IOException; +import java.util.List; +import java.util.Objects; +import java.util.UUID; + + +@Slf4j @RestController @RequestMapping("/messages") +@RequiredArgsConstructor public class MessageController { + private final MessageService msgService; + + //게이트 웨이에서 마스터 관리자를 제외한 모든 사용자에 대한 접근 제한(POST만 OPEN) + @GetMapping + public ResponseEntity>> getLogDatas( + @RequestHeader("X-User-Id") UUID userId, + @RequestHeader("X-Roles") String roles + ) { + log.info("{} has been approached",userId); + if (Objects.equals(roles, "Master")) + { + List tempSR = msgService.getAllLog(); + ApiResponse> reaultDto = ApiResponse.success(tempSR); + return ResponseEntity.ok(reaultDto); + } + else{ + return ResponseEntity.status(HttpStatus.FORBIDDEN).build(); + } + + } + + // + @PostMapping + public ResponseEntity> sendMessage( + @RequestBody CreateMessageLogRequestDto createMessageLogRequestDto, + @RequestHeader("X-User-Id") UUID userId + ) throws SlackApiException, IOException { + log.info("the Sender : " + userId); + //slackMsg 클래스 내부의 함수 호출 + MessageLogResponseDto mlr = msgService.sendMessage(userId ,createMessageLogRequestDto); + ApiResponse reaultDto = ApiResponse.success(mlr); + + return ResponseEntity.ok(reaultDto); + } diff --git a/src/main/java/com/tunaforce/message/message/dto/request/CreateLogRequestDto.java b/src/main/java/com/tunaforce/message/message/dto/request/CreateLogRequestDto.java deleted file mode 100644 index 6452ab0..0000000 --- a/src/main/java/com/tunaforce/message/message/dto/request/CreateLogRequestDto.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.tunaforce.message.message.dto.request; - -public record CreateLogRequestDto( - String content, - Long senderId, - Long receiverId -) { - -} diff --git a/src/main/java/com/tunaforce/message/message/dto/request/CreateMessageLogRequestDto.java b/src/main/java/com/tunaforce/message/message/dto/request/CreateMessageLogRequestDto.java new file mode 100644 index 0000000..e43b1bc --- /dev/null +++ b/src/main/java/com/tunaforce/message/message/dto/request/CreateMessageLogRequestDto.java @@ -0,0 +1,16 @@ +package com.tunaforce.message.message.dto.request; + +import jakarta.validation.constraints.NotNull; + +import java.util.UUID; + +public record CreateMessageLogRequestDto( + @NotNull + String content, + //Sender의 경우 헤더에 포함된 user_id로 구분 + UUID senderId, + @NotNull + UUID receiverId +) { + +} diff --git a/src/main/java/com/tunaforce/message/message/dto/request/CreateRouteLogRequestDto.java b/src/main/java/com/tunaforce/message/message/dto/request/CreateRouteLogRequestDto.java new file mode 100644 index 0000000..05d332e --- /dev/null +++ b/src/main/java/com/tunaforce/message/message/dto/request/CreateRouteLogRequestDto.java @@ -0,0 +1,18 @@ +package com.tunaforce.message.message.dto.request; + +import java.util.UUID; + +public class CreateRouteLogRequestDto { + private UUID deliveryIdx; + //배송 ID + private UUID deliveryId; + //허브 ID : 배송 테이블 내에 주소가 포함이 되어 있지만 허브ID로 배송 소속 기사 검색을 위함 + private UUID hubId; + //배송 목적지 ID + private UUID companyId; + //네이버API를 사용한 예상 거리 및 시간를 기록 + private String appxDistance; + private String appxTime; + //초기 테이블 생성 시 값은 배송 중으로 고정 + private String currstatus; +} diff --git a/src/main/java/com/tunaforce/message/message/dto/request/MapKeyRequestDto.java b/src/main/java/com/tunaforce/message/message/dto/request/MapKeyRequestDto.java new file mode 100644 index 0000000..761ed7a --- /dev/null +++ b/src/main/java/com/tunaforce/message/message/dto/request/MapKeyRequestDto.java @@ -0,0 +1,17 @@ +package com.tunaforce.message.message.dto.request; + +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.UUID; + +@Getter +@AllArgsConstructor +public class MapKeyRequestDto { + @NotNull(message = "userId가 누락 되었습니다.") + private UUID userId; + private String mapId; + private String mapkey; + private String messageToken; +} diff --git a/src/main/java/com/tunaforce/message/message/dto/response/MessageLogResponseDto.java b/src/main/java/com/tunaforce/message/message/dto/response/MessageLogResponseDto.java new file mode 100644 index 0000000..dc483ff --- /dev/null +++ b/src/main/java/com/tunaforce/message/message/dto/response/MessageLogResponseDto.java @@ -0,0 +1,28 @@ +package com.tunaforce.message.message.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.UUID; + +@Getter +@AllArgsConstructor +public class MessageLogResponseDto { + private String senderName; + private String content; + private String receiverName; + private UUID senderId; + private UUID receiverId; + + public MessageLogResponseDto(String name, String content, String name1) { + this.senderName = name; + this.content = content; + this.receiverName = name1; + } + + + public String getFormMessage(){ + return "From. " + senderName + + " -> " + content; + } +} diff --git a/src/main/java/com/tunaforce/message/message/dto/response/SearchLogResponseDto.java b/src/main/java/com/tunaforce/message/message/dto/response/SearchLogResponseDto.java new file mode 100644 index 0000000..e7cd9f0 --- /dev/null +++ b/src/main/java/com/tunaforce/message/message/dto/response/SearchLogResponseDto.java @@ -0,0 +1,19 @@ +package com.tunaforce.message.message.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +@AllArgsConstructor +public class SearchLogResponseDto { + private String hubId; + private String deliveryId; + private String CompanyId; + private String realDistance; + private String realTime; + private String currStatus; + + +} diff --git a/src/main/java/com/tunaforce/message/message/dto/response/auth/UserInformationResponseDto.java b/src/main/java/com/tunaforce/message/message/dto/response/auth/UserInformationResponseDto.java new file mode 100644 index 0000000..3605485 --- /dev/null +++ b/src/main/java/com/tunaforce/message/message/dto/response/auth/UserInformationResponseDto.java @@ -0,0 +1,18 @@ +package com.tunaforce.message.message.dto.response.auth; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.UUID; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class UserInformationResponseDto { + private UUID userId; + private String username; + private String slackId; + private String role; + private String deptId; +} diff --git a/src/main/java/com/tunaforce/message/message/dto/response/delivery/DeliveryForm.java b/src/main/java/com/tunaforce/message/message/dto/response/delivery/DeliveryForm.java new file mode 100644 index 0000000..625c2ab --- /dev/null +++ b/src/main/java/com/tunaforce/message/message/dto/response/delivery/DeliveryForm.java @@ -0,0 +1,22 @@ +package com.tunaforce.message.message.dto.response.delivery; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.*; + +import java.util.List; + + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Builder +@JsonInclude(JsonInclude.Include.NON_NULL) +public class DeliveryForm { + private List data; + private int page; + private int size; + private int totalElements; + private int totalPages; + private String sort; +} diff --git a/src/main/java/com/tunaforce/message/message/dto/response/delivery/GetDeliveriesResponseDto.java b/src/main/java/com/tunaforce/message/message/dto/response/delivery/GetDeliveriesResponseDto.java new file mode 100644 index 0000000..44df5eb --- /dev/null +++ b/src/main/java/com/tunaforce/message/message/dto/response/delivery/GetDeliveriesResponseDto.java @@ -0,0 +1,24 @@ +package com.tunaforce.message.message.dto.response.delivery; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.*; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Builder +@JsonInclude(JsonInclude.Include.NON_NULL) +public class GetDeliveriesResponseDto { + private String deliveryId; + private String orderId; + private String status; + private String departureHubId; + private String arrivalHubId; + private String deliveryAddress; + private String receivedUserId; + private String receivedSlackId; + private String companyDeliveryAgentId; + private String createdAt; + private String updatedAt; +} \ No newline at end of file diff --git a/src/main/java/com/tunaforce/message/message/dto/response/delivery/GetDeliverymenResponseDto.java b/src/main/java/com/tunaforce/message/message/dto/response/delivery/GetDeliverymenResponseDto.java new file mode 100644 index 0000000..47d20fd --- /dev/null +++ b/src/main/java/com/tunaforce/message/message/dto/response/delivery/GetDeliverymenResponseDto.java @@ -0,0 +1,22 @@ +package com.tunaforce.message.message.dto.response.delivery; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.tunaforce.message.message.entity.Timestamped; +import lombok.*; + +import java.util.UUID; + + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Builder +@JsonInclude(JsonInclude.Include.NON_NULL) +public class GetDeliverymenResponseDto extends Timestamped { + private UUID userId; + private String deliveryType; + private Long deliverySeq; + private String hubId; + private String slackId; +} diff --git a/src/main/java/com/tunaforce/message/message/dto/response/hub/HubResponseDto.java b/src/main/java/com/tunaforce/message/message/dto/response/hub/HubResponseDto.java new file mode 100644 index 0000000..d1d6aac --- /dev/null +++ b/src/main/java/com/tunaforce/message/message/dto/response/hub/HubResponseDto.java @@ -0,0 +1,20 @@ +package com.tunaforce.message.message.dto.response.hub; + + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.*; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Builder +@JsonInclude(JsonInclude.Include.NON_NULL) +public class HubResponseDto{ + private Long Id; + private String hubName; + private String hubAddress; + private String latitude; + private String longitude; + +} diff --git a/src/main/java/com/tunaforce/message/message/dto/response/hub/HubsResponseDto.java b/src/main/java/com/tunaforce/message/message/dto/response/hub/HubsResponseDto.java new file mode 100644 index 0000000..3bf58d4 --- /dev/null +++ b/src/main/java/com/tunaforce/message/message/dto/response/hub/HubsResponseDto.java @@ -0,0 +1,16 @@ +package com.tunaforce.message.message.dto.response.hub; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.*; + +import java.util.List; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Builder +@JsonInclude(JsonInclude.Include.NON_NULL) +public class HubsResponseDto { + List content; +} diff --git a/src/main/java/com/tunaforce/message/message/dto/response/map/MapKeyReesponseDto.java b/src/main/java/com/tunaforce/message/message/dto/response/map/MapKeyReesponseDto.java new file mode 100644 index 0000000..47a792d --- /dev/null +++ b/src/main/java/com/tunaforce/message/message/dto/response/map/MapKeyReesponseDto.java @@ -0,0 +1,25 @@ +package com.tunaforce.message.message.dto.response.map; + +import com.tunaforce.message.token.entity.MasterToken; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +import java.util.UUID; + +@Getter +@AllArgsConstructor +@Builder +public class MapKeyReesponseDto { + private UUID userId; + private String mapId; + private String mapKey; + private String messageAppToken; + + public MapKeyReesponseDto(MasterToken token) { + this.userId = token.getUserId(); + this.mapId = token.getMapId(); + this.mapKey = token.getMapKey(); + this.messageAppToken = token.getMessageAppToken(); + } +} diff --git a/src/main/java/com/tunaforce/message/message/dto/response/map/MapRouteResponseDto.java b/src/main/java/com/tunaforce/message/message/dto/response/map/MapRouteResponseDto.java new file mode 100644 index 0000000..6a2f0d1 --- /dev/null +++ b/src/main/java/com/tunaforce/message/message/dto/response/map/MapRouteResponseDto.java @@ -0,0 +1,5 @@ +package com.tunaforce.message.message.dto.response.map; + + +public class MapRouteResponseDto { +} diff --git a/src/main/java/com/tunaforce/message/message/entity/DeliveryRouteLog.java b/src/main/java/com/tunaforce/message/message/entity/DeliveryRouteLog.java index 2403a06..e6be879 100644 --- a/src/main/java/com/tunaforce/message/message/entity/DeliveryRouteLog.java +++ b/src/main/java/com/tunaforce/message/message/entity/DeliveryRouteLog.java @@ -3,17 +3,21 @@ import jakarta.persistence.*; import lombok.AllArgsConstructor; +import lombok.Getter; import lombok.NoArgsConstructor; +import java.util.UUID; + +@Getter @NoArgsConstructor @AllArgsConstructor @Entity @Table(name = "p_routeLog") -public class DeliveryRouteLog { +public class DeliveryRouteLog extends Timestamped { @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long deliveryIdx; + //@GeneratedValue(strategy = GenerationType.IDENTITY) + private UUID deliveryIdx; @Column(name = "delivery_Id", nullable = false) private String deliveryId; @Column(name = "hub_Id", nullable = false) @@ -40,4 +44,8 @@ public void updateRealInfo(){ } + public void deleteLog(UUID deliveryId){ + delete(deliveryId); + } + } diff --git a/src/main/java/com/tunaforce/message/message/entity/DeliveryStatus.java b/src/main/java/com/tunaforce/message/message/entity/DeliveryStatus.java new file mode 100644 index 0000000..63abb13 --- /dev/null +++ b/src/main/java/com/tunaforce/message/message/entity/DeliveryStatus.java @@ -0,0 +1,25 @@ +package com.tunaforce.message.message.entity; + + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.UUID; + +@Getter +@Entity +@Table(name = "p_delivery_status") +@AllArgsConstructor +@NoArgsConstructor +public class DeliveryStatus extends Timestamped { + @Id + private UUID userId; + @Column(length = 100) + private String hubId; + private Long deliverySeq; +} diff --git a/src/main/java/com/tunaforce/message/message/entity/MessageManagement.java b/src/main/java/com/tunaforce/message/message/entity/MessageManagement.java index 57e36b7..8786afc 100644 --- a/src/main/java/com/tunaforce/message/message/entity/MessageManagement.java +++ b/src/main/java/com/tunaforce/message/message/entity/MessageManagement.java @@ -1,13 +1,18 @@ package com.tunaforce.message.message.entity; +import com.slack.api.methods.SlackApiException; +import com.tunaforce.message.message.dto.request.CreateMessageLogRequestDto; +import com.tunaforce.message.message.dto.response.MessageLogResponseDto; import jakarta.persistence.*; import lombok.AllArgsConstructor; +import lombok.Getter; import lombok.NoArgsConstructor; -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; +import java.io.IOException; +import java.util.UUID; +@Getter @Entity @Table(name = "p_messageLog") @NoArgsConstructor @@ -19,17 +24,33 @@ public class MessageManagement extends Timestamped { private Long messageIdx; @Column(nullable = false) private String content; - @Column( name = "sender_Id",updatable = false,nullable = false) - private Long senderId; - @Column(name = "receiver_Id", updatable = false,nullable = false) - private Long receiverId; + @Column(name = "sender_Id", updatable = false, nullable = false) + private UUID senderId; + @Column(name = "receiver_Id", updatable = false, nullable = false) + private UUID receiverId; - public void MessageManagement (String content, Long senderId, Long receiverId) { + public MessageManagement(String content, UUID senderId, UUID receiverId) { this.content = content; this.senderId = senderId; this.receiverId = receiverId; } + + public MessageManagement(MessageLogResponseDto messageLogResponseDto){ + this.content = messageLogResponseDto.getContent(); + this.senderId = messageLogResponseDto.getSenderId(); + this.receiverId = messageLogResponseDto.getReceiverId(); + } + + public MessageManagement(CreateMessageLogRequestDto createMessageLogRequestDto) { + this.content = createMessageLogRequestDto.content(); + this.senderId = createMessageLogRequestDto.senderId(); + this.receiverId = createMessageLogRequestDto.receiverId(); + } + + public void deleteMessageLog(UUID messageId) { + delete(messageId); + } } diff --git a/src/main/java/com/tunaforce/message/message/repository/MessageCreateJPaRepository.java b/src/main/java/com/tunaforce/message/message/repository/MessageLogRepository.java similarity index 54% rename from src/main/java/com/tunaforce/message/message/repository/MessageCreateJPaRepository.java rename to src/main/java/com/tunaforce/message/message/repository/MessageLogRepository.java index dc16e72..f3a8d42 100644 --- a/src/main/java/com/tunaforce/message/message/repository/MessageCreateJPaRepository.java +++ b/src/main/java/com/tunaforce/message/message/repository/MessageLogRepository.java @@ -2,6 +2,8 @@ import com.tunaforce.message.message.entity.MessageManagement; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; -public interface MessageCreateJPaRepository extends JpaRepository { +@Repository +public interface MessageLogRepository extends JpaRepository { } diff --git a/src/main/java/com/tunaforce/message/message/repository/RoutLogJPaRepository.java b/src/main/java/com/tunaforce/message/message/repository/RoutLogJPaRepository.java new file mode 100644 index 0000000..40f2417 --- /dev/null +++ b/src/main/java/com/tunaforce/message/message/repository/RoutLogJPaRepository.java @@ -0,0 +1,17 @@ +package com.tunaforce.message.message.repository; + +import com.tunaforce.message.message.entity.DeliveryRouteLog; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +@Repository +public interface RoutLogJPaRepository extends JpaRepository { + + @Query("SELECT D FROM DeliveryRouteLog D WHERE D.deliveryId = :deliveryId") + Optional> findDeliveryRouteLogByDeliveryId(UUID deliveryId); +} diff --git a/src/main/java/com/tunaforce/message/message/repository/StatusRepository.java b/src/main/java/com/tunaforce/message/message/repository/StatusRepository.java new file mode 100644 index 0000000..1a6f3e8 --- /dev/null +++ b/src/main/java/com/tunaforce/message/message/repository/StatusRepository.java @@ -0,0 +1,10 @@ +package com.tunaforce.message.message.repository; + +import com.tunaforce.message.message.entity.DeliveryStatus; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface StatusRepository extends JpaRepository { + +} diff --git a/src/main/java/com/tunaforce/message/message/service/MessageService.java b/src/main/java/com/tunaforce/message/message/service/MessageService.java index 1e10923..441afba 100644 --- a/src/main/java/com/tunaforce/message/message/service/MessageService.java +++ b/src/main/java/com/tunaforce/message/message/service/MessageService.java @@ -1,21 +1,79 @@ package com.tunaforce.message.message.service; - -import com.tunaforce.message.message.dto.request.CreateLogRequestDto; -import com.tunaforce.message.message.dto.response.CreateLogResponseDto; +import com.slack.api.methods.SlackApiException; +import com.tunaforce.message.cmmn.SlackMsg; +import com.tunaforce.message.message.dto.request.CreateMessageLogRequestDto; +import com.tunaforce.message.message.dto.response.MessageLogResponseDto; +import com.tunaforce.message.message.dto.response.auth.UserInformationResponseDto; +import com.tunaforce.message.token.entity.MasterToken; import com.tunaforce.message.message.entity.MessageManagement; -import com.tunaforce.message.message.repository.MessageCreateJPaRepository; +import com.tunaforce.message.message.repository.MessageLogRepository; +import com.tunaforce.message.token.repository.TokenKeyJpaRepository; +import com.tunaforce.message.message.service.feignClient.ClientAuthService; +import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import java.io.IOException; +import java.util.List; +import java.util.UUID; + @Service @RequiredArgsConstructor public class MessageService { - private final MessageCreateJPaRepository messageCreateJPaRepository; + private final TokenKeyJpaRepository tokenKeyJpaRepository; + private final MessageLogRepository messageLogRepository; + private final ClientAuthService clientAuthService; + //슬랙 앱으로 보내는 함수 사용 + private final SlackMsg slackMsg; + + @Transactional + public MessageLogResponseDto sendMessage(UUID senderId, CreateMessageLogRequestDto createMessageLogRequestDto) throws SlackApiException, IOException { + //원래는 senderId와 receiverId를 Auth에서 name을 받아서 입력하도록 함 + //테스트로 주석 처리 + //senderID는 나중에 messageManagement에서 값을 반환 받을 때 필요 + //여기서 senderId는 유저아이디임 slackID가 아님 + UserInformationResponseDto senderAppId = clientAuthService.getUserInfo(senderId); + UserInformationResponseDto receiverAppId = clientAuthService.getUserInfo(createMessageLogRequestDto.receiverId()); + + //redis에 저장로직 추후 추가 + + //받은 값과 조회한 값을 기준으로 응답 데이터 만듬 + MessageLogResponseDto resultData = new MessageLogResponseDto( + senderAppId.getUsername(), + createMessageLogRequestDto.content(), + receiverAppId.getUsername(), + senderId, + createMessageLogRequestDto.receiverId() + ); + + //토큰 받아오는 로직 + //이 테이블은 논리적으로 제거가 안된 값이 여러개의 값이 존재할 수 없음 + //deletedAt 부분인 null이 아닌 값 즉 논리적 제거가 되지 않은 값 + MasterToken tempKeys = tokenKeyJpaRepository.findByDeletedAt().get(0); + + slackMsg.sendDirectMessage( + tempKeys.getMessageAppToken(), + receiverAppId.getSlackId(), + resultData.getFormMessage() + ); + + + + + return resultData; + + } + + public List getAllLog(){ + List msgManagement = messageLogRepository.findAll(); - public CreateLogResponseDto create(CreateLogRequestDto createLogRequestDto) { - MessageManagement messageManagement = ; - messageCreateJPaRepository.save(); - return + return msgManagement.stream() + .map(entity -> new CreateMessageLogRequestDto( + entity.getContent(), + entity.getSenderId(), + entity.getReceiverId() + )) + .toList(); } } diff --git a/src/main/java/com/tunaforce/message/message/service/RoutLogService.java b/src/main/java/com/tunaforce/message/message/service/RoutLogService.java new file mode 100644 index 0000000..bc8e1a3 --- /dev/null +++ b/src/main/java/com/tunaforce/message/message/service/RoutLogService.java @@ -0,0 +1,53 @@ +package com.tunaforce.message.message.service; + + +import com.tunaforce.message.maps.service.ClientRoutesData; +import com.tunaforce.message.cmmn.RouteData; +import com.tunaforce.message.message.dto.response.SearchLogResponseDto; +import com.tunaforce.message.message.entity.DeliveryRouteLog; +import com.tunaforce.message.message.repository.RoutLogJPaRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.NoSuchElementException; +import java.util.UUID; +import java.util.stream.Collectors; + +@Service +@RequiredArgsConstructor +public class RoutLogService { + private final RoutLogJPaRepository routLogJPaRepository; + private final ClientRoutesData clientRoutesData; + + public List readAllLog() { + List results = routLogJPaRepository.findAll(); + return results.stream() + .map(entity -> SearchLogResponseDto.builder() + .hubId(String.valueOf(entity.getHubId())) + .deliveryId(String.valueOf(entity.getDeliveryId())) + .CompanyId(String.valueOf(entity.getCompanyId())) + .realDistance(String.valueOf(entity.getRealDistance())) + .realTime(String.valueOf(entity.getRealTime())) + .currStatus(String.valueOf(entity.getCurrstatus())) + .build() + ).collect(Collectors.toList()); + } + + public boolean updateStatus(Long deliveryId){ + return true; + } + + public boolean deleteLog(UUID deliveryId){ + DeliveryRouteLog deliveryRouteLog = routLogJPaRepository.findById(deliveryId).orElseThrow(() -> + new NoSuchElementException("데이터가 존재하지 않습니다.")); + + deliveryRouteLog.deleteLog(deliveryRouteLog.getDeliveryIdx()); + return true; + } + + public void getRoute(RouteData routeData){ + + + } +} diff --git a/src/main/java/com/tunaforce/message/message/service/feignClient/ClientAuthService.java b/src/main/java/com/tunaforce/message/message/service/feignClient/ClientAuthService.java new file mode 100644 index 0000000..c689a18 --- /dev/null +++ b/src/main/java/com/tunaforce/message/message/service/feignClient/ClientAuthService.java @@ -0,0 +1,17 @@ +package com.tunaforce.message.message.service.feignClient; + + +import com.tunaforce.message.message.dto.response.auth.UserInformationResponseDto; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; + +import java.util.UUID; + +@FeignClient(name = "auth-Service", url = "${Clients.Auth}") +public interface ClientAuthService { + //시용자 정보의 앱 ID가 필요 + @GetMapping("/users/{user_id}") + UserInformationResponseDto getUserInfo(@PathVariable("user_id") UUID userId); + +} diff --git a/src/main/java/com/tunaforce/message/message/service/feignClient/ClientCoordinatesService.java b/src/main/java/com/tunaforce/message/message/service/feignClient/ClientCoordinatesService.java new file mode 100644 index 0000000..b8502d6 --- /dev/null +++ b/src/main/java/com/tunaforce/message/message/service/feignClient/ClientCoordinatesService.java @@ -0,0 +1,33 @@ +package com.tunaforce.message.message.service.feignClient; + +import com.tunaforce.message.maps.service.ClientCoordinatesData; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +@RequiredArgsConstructor +public class ClientCoordinatesService { + private final ClientCoordinatesData clientCoordinatesData; + + public String getCoordinates(String clientId, String clientSecret, String address) { + String result = clientCoordinatesData.getGeocode( + clientId, + clientSecret, + address + ); + log.info("the Data from Naver : " + result); + // JSON 파싱 (Jackson 등 사용) +// com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper(); +// com.fasterxml.jackson.databind.JsonNode root = mapper.readTree(result); +// if (root.path("addresses").isArray() && root.path("addresses").size() > 0) { +// com.fasterxml.jackson.databind.JsonNode addr = root.path("addresses").get(0); +// String x = addr.get("x").asText(); // 경도 +// String y = addr.get("y").asText(); // 위도 +// return new String[]{x, y}; +// } +// return null; + return result; + } +} diff --git a/src/main/java/com/tunaforce/message/message/service/feignClient/ClientDeliveryService.java b/src/main/java/com/tunaforce/message/message/service/feignClient/ClientDeliveryService.java new file mode 100644 index 0000000..7bb4ee5 --- /dev/null +++ b/src/main/java/com/tunaforce/message/message/service/feignClient/ClientDeliveryService.java @@ -0,0 +1,29 @@ +package com.tunaforce.message.message.service.feignClient; + + +import com.tunaforce.message.message.dto.response.delivery.DeliveryForm; +import com.tunaforce.message.message.dto.response.delivery.GetDeliveriesResponseDto; +import com.tunaforce.message.message.dto.response.delivery.GetDeliverymenResponseDto; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.stereotype.Service; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import java.util.List; + +@Service +@FeignClient(name="delivery-service", url="${Clients.Delivery}") +public interface ClientDeliveryService { + //물품 배송에 대한 리스트 - 금일자로 된 리스트 할당을 받아야함 + @GetMapping("/deliveries") + DeliveryForm getListDelivery(@RequestParam("q") String p); + + //업체 배송 담당자 조건으로 쿼리 + @GetMapping("/delivery-agents") + DeliveryForm getListDeliverymen(@RequestParam("q") String role); +//http://localhost:3370/delivery-agents?q=hub + + //업체 배송 담당자 배정 후 배송 테이블에 업체 배송 담당자 ID 업데이트 +// @PostMapping("/deliveries") + +} diff --git a/src/main/java/com/tunaforce/message/message/service/feignClient/ClientHubService.java b/src/main/java/com/tunaforce/message/message/service/feignClient/ClientHubService.java new file mode 100644 index 0000000..6c726f9 --- /dev/null +++ b/src/main/java/com/tunaforce/message/message/service/feignClient/ClientHubService.java @@ -0,0 +1,21 @@ +package com.tunaforce.message.message.service.feignClient; + +import com.tunaforce.message.message.dto.response.hub.HubResponseDto; +import com.tunaforce.message.message.dto.response.hub.HubsResponseDto; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestParam; + +@FeignClient(name = "hub-Service", url = "${Clients.Hub}") +public interface ClientHubService { + @GetMapping("/hubs/{hub_id}") + HubResponseDto getHub(@PathVariable("hub_id") String hub_id); + + @GetMapping("/hubs") + HubsResponseDto getHubs( + @RequestParam Integer page, + @RequestParam Integer size + ); + +} diff --git a/src/main/java/com/tunaforce/message/token/controller/RegistrationController.java b/src/main/java/com/tunaforce/message/token/controller/RegistrationController.java new file mode 100644 index 0000000..d9d19c3 --- /dev/null +++ b/src/main/java/com/tunaforce/message/token/controller/RegistrationController.java @@ -0,0 +1,78 @@ +package com.tunaforce.message.token.controller; + +import com.tunaforce.message.api.ApiResponse; +import com.tunaforce.message.message.dto.request.MapKeyRequestDto; +import com.tunaforce.message.message.dto.response.map.MapKeyReesponseDto; +import com.tunaforce.message.token.service.RegistrationService; +import jakarta.transaction.Transactional; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.cloud.logging.LoggingRebinder; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.resource.NoResourceFoundException; + +import java.util.List; +import java.util.UUID; + +@Slf4j +@RestController +@RequestMapping("/token") +@RequiredArgsConstructor +public class RegistrationController { + + private final RegistrationService registrationService; + private final LoggingRebinder loggingRebinder; + + @GetMapping + public ResponseEntity>> getAllTokens() { + return ResponseEntity.ok(ApiResponse.success(registrationService.getAllTokens())); + } + + @GetMapping("/{userId}") + public ResponseEntity> getTokens(@PathVariable UUID userId) + throws NoResourceFoundException { + MapKeyReesponseDto token = registrationService.getTokens(userId); + return ResponseEntity.ok(ApiResponse.success(token)); + } + + + + //map관련 키 value 등록 + //userId 는 필수 값 + + @PostMapping + @Transactional + public ResponseEntity> mapRegisterToken( + @RequestBody @Valid MapKeyRequestDto mapKeyRequestDto, + @RequestParam("X-User-Id") UUID userId, + @RequestHeader("X-Roles") String roles + ) { + log.info("{} has approached",userId); + log.info("{} Roles",roles); + + if (roles.contains("MASTER")) { + registrationService.createTokens(mapKeyRequestDto); + ApiResponse resultDto = ApiResponse.success("null"); + return ResponseEntity.ok(resultDto); + } + else{ + return ResponseEntity.status(HttpStatus.FORBIDDEN).build(); + } + + } + + + @DeleteMapping + public ResponseEntity> deleteToken( + @RequestParam UUID userId + ) throws NoResourceFoundException { + registrationService.deleteTokens(userId); + ApiResponse resultDto = ApiResponse.success("null"); + return ResponseEntity.ok(resultDto); + } + + +} diff --git a/src/main/java/com/tunaforce/message/token/entity/MasterToken.java b/src/main/java/com/tunaforce/message/token/entity/MasterToken.java new file mode 100644 index 0000000..8a8ace3 --- /dev/null +++ b/src/main/java/com/tunaforce/message/token/entity/MasterToken.java @@ -0,0 +1,44 @@ +package com.tunaforce.message.token.entity; + +import com.tunaforce.message.message.dto.request.MapKeyRequestDto; +import com.tunaforce.message.message.entity.Timestamped; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.util.UUID; + +@Getter +@Setter +@Entity +@Table(name = "p_master_tokens") +@NoArgsConstructor +@AllArgsConstructor +public class MasterToken extends Timestamped { + //추후 리팩토링 + // 구조 변경 필요 + // 사용 앱 이름 + // 사용 헤더명 이름 + // 사용 키 + @Id + private UUID userId; + @Column(length = 150, name = "map_id") + private String mapId; + @Column(length = 150, name = "map_key") + private String mapKey; + @Column(length = 150, name = "message_token") + private String messageAppToken; + + public MasterToken(MapKeyRequestDto mapKeyRequestDto) { + this.userId = mapKeyRequestDto.getUserId(); + this.mapId = mapKeyRequestDto.getMapId(); + this.mapKey = mapKeyRequestDto.getMapkey(); + this.messageAppToken = mapKeyRequestDto.getMessageToken(); + } + + public void deleteTokens(UUID userId) { + delete(userId); + } +} diff --git a/src/main/java/com/tunaforce/message/token/repository/TokenKeyJpaRepository.java b/src/main/java/com/tunaforce/message/token/repository/TokenKeyJpaRepository.java new file mode 100644 index 0000000..2ca10b6 --- /dev/null +++ b/src/main/java/com/tunaforce/message/token/repository/TokenKeyJpaRepository.java @@ -0,0 +1,17 @@ +package com.tunaforce.message.token.repository; + +import com.tunaforce.message.token.entity.MasterToken; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.UUID; + +@Repository +public interface TokenKeyJpaRepository extends JpaRepository { + + @Query("SELECT M FROM MasterToken M WHERE M.deletedAt is null") + List findByDeletedAt(); + +} diff --git a/src/main/java/com/tunaforce/message/token/service/RegistrationService.java b/src/main/java/com/tunaforce/message/token/service/RegistrationService.java new file mode 100644 index 0000000..22c7bf9 --- /dev/null +++ b/src/main/java/com/tunaforce/message/token/service/RegistrationService.java @@ -0,0 +1,88 @@ +package com.tunaforce.message.token.service; + + +import com.tunaforce.message.message.dto.request.MapKeyRequestDto; +import com.tunaforce.message.message.dto.response.map.MapKeyReesponseDto; +import com.tunaforce.message.token.entity.MasterToken; +import com.tunaforce.message.token.repository.TokenKeyJpaRepository; +import jakarta.transaction.Transactional; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpMethod; +import org.springframework.stereotype.Service; +import org.springframework.web.servlet.resource.NoResourceFoundException; + +import java.util.*; + +@Service +@RequiredArgsConstructor +public class RegistrationService { + + private final TokenKeyJpaRepository tokenKeyJpaRepository; + + //앱 토큰 추가 + @Transactional + public MapKeyReesponseDto updateTokens(MapKeyRequestDto mapKeyRequestDto) + throws NoResourceFoundException { + UUID userId = mapKeyRequestDto.getUserId(); + + // 1. userId로 기존 엔티티 조회 + MasterToken token = tokenKeyJpaRepository.findById(userId).orElseThrow( + ()-> new NoResourceFoundException(HttpMethod.GET,"해당 userId가 존재하지 않습니다.") + ); + + // 2. null이 아닌 필드만 업데이트 + if (mapKeyRequestDto.getMapId() != null) { + token.setMapId(mapKeyRequestDto.getMapId()); + } + if (mapKeyRequestDto.getMapkey() != null) { + token.setMapKey(mapKeyRequestDto.getMapkey()); + } + if (mapKeyRequestDto.getMessageToken() != null) { + token.setMessageAppToken(mapKeyRequestDto.getMessageToken()); + } + MapKeyReesponseDto resultDto = new MapKeyReesponseDto(token); + // 3. 트랜잭션 커밋 시점에 자동 업데이트 됨 + return resultDto; + } + + //@Transactional + public void createTokens(MapKeyRequestDto mapKeyRequestDto){ + MasterToken masterToken = new MasterToken( + mapKeyRequestDto.getUserId(), + mapKeyRequestDto.getMapId(), + mapKeyRequestDto.getMapkey(), + mapKeyRequestDto.getMessageToken() + ); + MasterToken temp = tokenKeyJpaRepository.save(masterToken); + } + + + //앱 변경시에 논리적 DB 제거 + public void deleteTokens(UUID userId) throws NoResourceFoundException { + MasterToken mT = tokenKeyJpaRepository.findById(userId).orElseThrow( + ()-> new NoResourceFoundException(HttpMethod.GET,"해당 userId가 존재하지 않습니다.") + ); + + mT.delete(userId); + } + + public MapKeyReesponseDto getTokens(UUID userId) throws NoResourceFoundException { + MasterToken mT = tokenKeyJpaRepository.findById(userId).orElseThrow( + ()-> new NoResourceFoundException(HttpMethod.GET,"Token not found")); + + return MapKeyReesponseDto.builder() + .userId(mT.getUserId()) + .mapId(mT.getMapId()) + .mapKey(mT.getMapKey()) + .messageAppToken(mT.getMessageAppToken()) + .build(); + + } + + public List getAllTokens(){ + List mT = tokenKeyJpaRepository.findAll(); + return mT.stream() + .map(MapKeyReesponseDto::new) + .toList(); + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties deleted file mode 100644 index 00cb0fb..0000000 --- a/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -spring.application.name=message diff --git a/src/test/java/com/tunaforce/message/GetCoordinatesTest.java b/src/test/java/com/tunaforce/message/GetCoordinatesTest.java new file mode 100644 index 0000000..856aafe --- /dev/null +++ b/src/test/java/com/tunaforce/message/GetCoordinatesTest.java @@ -0,0 +1,183 @@ +package com.tunaforce.message; + + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.tunaforce.message.cmmn.RouteData; +import com.tunaforce.message.maps.dto.naverRoute.Route; +import com.tunaforce.message.maps.dto.naverRoute.Summary; +import com.tunaforce.message.maps.dto.naverRoute.direction5ResponseDto; +import com.tunaforce.message.maps.service.ClientCoordinatesData; +import com.tunaforce.message.maps.service.ClientRoutesData; +import com.tunaforce.message.maps.dto.naverMap.geocodeResponseDto; +import com.tunaforce.message.maps.service.mapInfoService; +import com.tunaforce.message.message.DirectMessageScheduler; +import com.tunaforce.message.message.dto.response.delivery.DeliveryForm; +import com.tunaforce.message.message.dto.response.delivery.GetDeliveriesResponseDto; +import com.tunaforce.message.message.dto.response.delivery.GetDeliverymenResponseDto; +import com.tunaforce.message.message.service.feignClient.ClientDeliveryService; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Configuration; + +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.stream.Collectors; + +@Configuration +@SpringBootTest +public class GetCoordinatesTest { + + @Autowired + private ClientCoordinatesData clientCoordinatesData; + @Autowired + private ClientRoutesData clientRoutesData; + @Autowired + private mapInfoService mapInfoService; + + + @Test + @DisplayName("경도 위도 데이터 수신 테스트") + void getCoordinatesTest() throws Exception { + + String Id = "osh066qnrv"; + String Key = "uvvXHOeBUf3sEaIBaCX5jqBbJHBZqYNrem0s07lj"; + + String result = clientCoordinatesData.getGeocode( + Id, + Key, + "거창군 마리면 풍계1길 27-103" + ); + ObjectMapper test = new ObjectMapper(); + geocodeResponseDto tester = test.readValue(result, geocodeResponseDto.class); + + String ss = tester.addresses.get(0).getX(); + //String resultsData = ccs.getCoordinates( Id, Key,"대구 비산동 320-9"); + System.out.println("ss = " + ss); + System.out.println("resultsData = " + result); + } + + @Test + @DisplayName("루트 데이터 수신 테스트") + void getRoute() throws JsonProcessingException { + String Id = "osh066qnrv"; + String Key = "uvvXHOeBUf3sEaIBaCX5jqBbJHBZqYNrem0s07lj"; + + String geochang = clientCoordinatesData.getGeocode( + Id, + Key, + "거창군 마리면 풍계1길 27-103" + ); + + String daegu = clientCoordinatesData.getGeocode( + Id, + Key, + "대구광역시 서구 비산동 320-9" + ); + + + ObjectMapper test = new ObjectMapper(); + geocodeResponseDto geochangdto = test.readValue(geochang, geocodeResponseDto.class); + geocodeResponseDto daegudto = test.readValue(daegu, geocodeResponseDto.class); + + String resultData = clientRoutesData.getRoute( + Id, + Key, + daegudto.getAddresses().get(0).getX() + "," + daegudto.getAddresses().get(0).getY(), + geochangdto.getAddresses().get(0).getX() + "," + geochangdto.getAddresses().get(0).getY() + + ); + + + System.out.println("resultData = " + resultData); + } + + + @Autowired + mapInfoService mIService; + + @Test + @DisplayName("루트 데이터2 테스트") + void getRoute2() throws JsonProcessingException { + RouteData routeData = new RouteData( + "거창군 마리면 풍계1길 27-103", + "대구광역시 서구 비산동 320-9" + ); + + + String startStr = routeData.getStart(); + String endStr = routeData.getGoal(); + + //DB에서 가져와야함 + String Id = "osh066qnrv"; + String Key = "uvvXHOeBUf3sEaIBaCX5jqBbJHBZqYNrem0s07lj"; + ; + + String result = clientCoordinatesData.getGeocode( + Id, + Key, + routeData.getStart() + ); + ObjectMapper dataParser = new ObjectMapper(); + + geocodeResponseDto startCoordinate = dataParser.readValue(result, geocodeResponseDto.class); + + result = clientCoordinatesData.getGeocode( + Id, + Key, + routeData.getGoal() + ); + + geocodeResponseDto endCoordinate = dataParser.readValue(result, geocodeResponseDto.class); + + + String rowData = clientRoutesData.getRoute( + Id, + Key, + startCoordinate.getPoints().get(0), + endCoordinate.getPoints().get(0) + ); + + direction5ResponseDto direction5Response = dataParser.readValue(rowData, direction5ResponseDto.class); + + Summary tempRoute = direction5Response.getRoute().traoptimal().get(0).summary(); + + //전체 경로 거리 + int distance = tempRoute.distance(); + //전체 경로 소요시간 (ms) + int duration = tempRoute.duration(); + String routTime = mIService.convertMsToTimeString(duration); + //예상도착일시 (yyyy-MM-dd HH:mm:ss) + String departuretime = tempRoute.departureTime(); + + + System.out.println("resultData = " + rowData); + Assertions.assertThat(rowData).isNotNull(); + } + + @Autowired + ClientDeliveryService clientDeliveryService; + + @Test + @DisplayName("허브 좌표 테스트") + void getHubs() throws JsonProcessingException { + + + DeliveryForm tempData = clientDeliveryService.getListDelivery("2025-08-22"); +//허브 별 담당자 조회 + //role로 구분 + DeliveryForm resultAgents = clientDeliveryService.getListDeliverymen("Company"); + + + + + + + } + +}