From b49ca5f4ec756f98b225c7138ea07a612143f0fd Mon Sep 17 00:00:00 2001 From: Kim-Dong-Jun99 Date: Mon, 8 Jan 2024 18:22:01 +0900 Subject: [PATCH 1/5] =?UTF-8?q?Refactor=20:=20=EB=B3=80=EA=B2=BD=EB=90=9C?= =?UTF-8?q?=20API=20=EB=AA=85=EC=84=B8=20=EB=82=B4=EC=9A=A9=20=EB=B0=98?= =?UTF-8?q?=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../trip/controller/TripController.java | 10 ++++ .../dto/request/PathAndItemRequestMsg.java | 5 ++ .../trip/dto/response/TripBudgetMsg.java | 8 +++ .../tentenstomp/domain/trip/entity/Trip.java | 5 ++ .../domain/trip/service/TripItemService.java | 5 +- .../domain/trip/service/TripService.java | 52 +++++++++++++++++-- .../global/common/constant/TopicConstant.java | 1 + .../kafka/consumer/KafkaConsumer.java | 14 ++--- 8 files changed, 88 insertions(+), 12 deletions(-) create mode 100644 src/main/java/org/tenten/tentenstomp/domain/trip/dto/request/PathAndItemRequestMsg.java create mode 100644 src/main/java/org/tenten/tentenstomp/domain/trip/dto/response/TripBudgetMsg.java diff --git a/src/main/java/org/tenten/tentenstomp/domain/trip/controller/TripController.java b/src/main/java/org/tenten/tentenstomp/domain/trip/controller/TripController.java index 7fe2912..f42503e 100644 --- a/src/main/java/org/tenten/tentenstomp/domain/trip/controller/TripController.java +++ b/src/main/java/org/tenten/tentenstomp/domain/trip/controller/TripController.java @@ -45,4 +45,14 @@ public void connectMember(@DestinationVariable String tripId, @Payload MemberCon public void disconnectMember(@DestinationVariable String tripId, @Payload MemberDisconnectMsg memberDisconnectMsg) { tripService.disconnectMember(tripId, memberDisconnectMsg); } + + @MessageMapping("/trips/{tripId}/enterMember") + public void enterMember(@DestinationVariable String tripId, @Payload MemberConnectMsg memberConnectMsg) { + tripService.enterMember(tripId, memberConnectMsg); + } + + @MessageMapping("/trips/{tripId}/getPathAndItems") + public void getPathAndItems(@DestinationVariable String tripId, @Payload PathAndItemRequestMsg pathAndItemRequestMsg) { + tripService.getPathAndItems(tripId, pathAndItemRequestMsg); + } } diff --git a/src/main/java/org/tenten/tentenstomp/domain/trip/dto/request/PathAndItemRequestMsg.java b/src/main/java/org/tenten/tentenstomp/domain/trip/dto/request/PathAndItemRequestMsg.java new file mode 100644 index 0000000..31cac18 --- /dev/null +++ b/src/main/java/org/tenten/tentenstomp/domain/trip/dto/request/PathAndItemRequestMsg.java @@ -0,0 +1,5 @@ +package org.tenten.tentenstomp.domain.trip.dto.request; +public record PathAndItemRequestMsg( + String visitDate +) { +} diff --git a/src/main/java/org/tenten/tentenstomp/domain/trip/dto/response/TripBudgetMsg.java b/src/main/java/org/tenten/tentenstomp/domain/trip/dto/response/TripBudgetMsg.java new file mode 100644 index 0000000..dccbe35 --- /dev/null +++ b/src/main/java/org/tenten/tentenstomp/domain/trip/dto/response/TripBudgetMsg.java @@ -0,0 +1,8 @@ +package org.tenten.tentenstomp.domain.trip.dto.response; + +public record TripBudgetMsg( + Long tripId, + Long budget, + Long calculatedPrice +) { +} diff --git a/src/main/java/org/tenten/tentenstomp/domain/trip/entity/Trip.java b/src/main/java/org/tenten/tentenstomp/domain/trip/entity/Trip.java index 2475d81..942c343 100644 --- a/src/main/java/org/tenten/tentenstomp/domain/trip/entity/Trip.java +++ b/src/main/java/org/tenten/tentenstomp/domain/trip/entity/Trip.java @@ -64,4 +64,9 @@ public TripInfoMsg changeTripInfo(TripUpdateMsg request) { return new TripInfoMsg(this.getId(), request.startDate(), request.endDate(), this.getNumberOfPeople(), this.getTripName(), this.getTripStatus(), this.getArea(), this.getSubarea(), this.getBudget()); } + + public TripInfoMsg toTripInfo() { + return new TripInfoMsg(this.getId(), this.startDate.toString(), this.endDate.toString(), this.getNumberOfPeople(), this.getTripName(), this.getTripStatus(), + this.getArea(), this.getSubarea(), this.getBudget()); + } } \ No newline at end of file diff --git a/src/main/java/org/tenten/tentenstomp/domain/trip/service/TripItemService.java b/src/main/java/org/tenten/tentenstomp/domain/trip/service/TripItemService.java index ccbe97e..1905233 100644 --- a/src/main/java/org/tenten/tentenstomp/domain/trip/service/TripItemService.java +++ b/src/main/java/org/tenten/tentenstomp/domain/trip/service/TripItemService.java @@ -38,7 +38,7 @@ public void updateTripItemPrice(String tripItemId, TripItemPriceUpdateMsg priceU ); kafkaProducer.send(TRIP_ITEM, tripItemMsg); - + // TODO : budget } @Transactional public void updateTripItemVisitDate(String tripItemId, TripItemVisitDateUpdateMsg visitDateUpdateMsg) { @@ -67,6 +67,8 @@ public void updateTripItemVisitDate(String tripItemId, TripItemVisitDateUpdateMs kafkaProducer.send(TRIP_ITEM, tripItemMsgToNewDate); kafkaProducer.send(PATH, tripPathMsgToPastDate); kafkaProducer.send(PATH, tripPathMsgToNewDate); + // TODO : budget + } @Transactional public void deleteTripItem(String tripItemId) { @@ -84,6 +86,7 @@ public void deleteTripItem(String tripItemId) { kafkaProducer.send(TRIP_ITEM, tripItemMsg); kafkaProducer.send(PATH, tripPathMsg); + // TODO : budget } } diff --git a/src/main/java/org/tenten/tentenstomp/domain/trip/service/TripService.java b/src/main/java/org/tenten/tentenstomp/domain/trip/service/TripService.java index 1cfaf1c..72cd9b0 100644 --- a/src/main/java/org/tenten/tentenstomp/domain/trip/service/TripService.java +++ b/src/main/java/org/tenten/tentenstomp/domain/trip/service/TripService.java @@ -5,10 +5,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.tenten.tentenstomp.domain.trip.dto.request.*; -import org.tenten.tentenstomp.domain.trip.dto.response.TripInfoMsg; -import org.tenten.tentenstomp.domain.trip.dto.response.TripItemMsg; -import org.tenten.tentenstomp.domain.trip.dto.response.TripMemberMsg; -import org.tenten.tentenstomp.domain.trip.dto.response.TripPathMsg; +import org.tenten.tentenstomp.domain.trip.dto.response.*; import org.tenten.tentenstomp.domain.trip.entity.Trip; import org.tenten.tentenstomp.domain.trip.repository.TripItemRepository; import org.tenten.tentenstomp.global.messaging.kafka.producer.KafkaProducer; @@ -42,9 +39,13 @@ public void updateTrip(String tripId, TripUpdateMsg tripUpdateMsg) { Trip trip = tripRepository.getReferenceById(Long.parseLong(tripId)); TripInfoMsg tripResponseMsg = trip.changeTripInfo(tripUpdateMsg); + TripBudgetMsg tripBudgetMsg = new TripBudgetMsg( + trip.getId(), null, null + ); tripRepository.save(trip); kafkaProducer.send(TRIP_INFO, tripResponseMsg); + kafkaProducer.send(BUDGET, tripBudgetMsg); } @Transactional public void addTripItem(String tripId, TripItemAddMsg tripItemAddMsg) { @@ -59,9 +60,14 @@ public void addTripItem(String tripId, TripItemAddMsg tripItemAddMsg) { TripPathMsg tripPathMsg = new TripPathMsg( Long.parseLong(tripId), LocalDate.parse(tripItemAddMsg.visitDate()).toString(), null ); + TripBudgetMsg tripBudgetMsg = new TripBudgetMsg( + trip.getId(), null, null + ); kafkaProducer.send(TRIP_ITEM, tripItemMsg); kafkaProducer.send(PATH, tripPathMsg); + kafkaProducer.send(BUDGET, tripBudgetMsg); + } @Transactional public void updateTripItemOrder(String tripId, TripItemOrderUpdateMsg orderUpdateMsg) { @@ -75,9 +81,14 @@ public void updateTripItemOrder(String tripId, TripItemOrderUpdateMsg orderUpdat TripPathMsg tripPathMsg = new TripPathMsg( Long.parseLong(tripId), LocalDate.parse(orderUpdateMsg.visitDate()).toString(), null ); + TripBudgetMsg tripBudgetMsg = new TripBudgetMsg( + Long.parseLong(tripId), null, null + ); kafkaProducer.send(TRIP_ITEM, tripItemMsg); kafkaProducer.send(PATH, tripPathMsg); + kafkaProducer.send(BUDGET, tripBudgetMsg); + } @Transactional(readOnly = true) @@ -103,6 +114,39 @@ public void disconnectMember(String tripId, MemberDisconnectMsg memberDisconnect kafkaProducer.send(MEMBER, tripMemberMsg); } + @Transactional(readOnly = true) + public void enterMember(String tripId, MemberConnectMsg memberConnectMsg) { + Trip trip = tripRepository.getReferenceById(Long.parseLong(tripId)); + + TripInfoMsg tripResponseMsg = trip.toTripInfo(); + TripBudgetMsg tripBudgetMsg = new TripBudgetMsg( + trip.getId(), null, null + ); + TripItemMsg tripItemMsg = new TripItemMsg( + Long.parseLong(tripId), trip.getStartDate().toString(), null + ); + TripPathMsg tripPathMsg = new TripPathMsg( + Long.parseLong(tripId), trip.getStartDate().toString(), null + ); + + kafkaProducer.send(TRIP_INFO, tripResponseMsg); + kafkaProducer.send(TRIP_ITEM, tripItemMsg); + kafkaProducer.send(PATH, tripPathMsg); + kafkaProducer.send(BUDGET, tripBudgetMsg); + } + @Transactional(readOnly = true) + public void getPathAndItems(String tripId, PathAndItemRequestMsg pathAndItemRequestMsg) { + Trip trip = tripRepository.getReferenceById(Long.parseLong(tripId)); + + TripItemMsg tripItemMsg = new TripItemMsg( + Long.parseLong(tripId), pathAndItemRequestMsg.visitDate(), null + ); + TripPathMsg tripPathMsg = new TripPathMsg( + Long.parseLong(tripId), pathAndItemRequestMsg.visitDate(), null + ); + kafkaProducer.send(TRIP_ITEM, tripItemMsg); + kafkaProducer.send(PATH, tripPathMsg); + } } diff --git a/src/main/java/org/tenten/tentenstomp/global/common/constant/TopicConstant.java b/src/main/java/org/tenten/tentenstomp/global/common/constant/TopicConstant.java index 289df3c..6ec6bc3 100644 --- a/src/main/java/org/tenten/tentenstomp/global/common/constant/TopicConstant.java +++ b/src/main/java/org/tenten/tentenstomp/global/common/constant/TopicConstant.java @@ -5,4 +5,5 @@ public class TopicConstant { public static final String TRIP_ITEM = "tripItems"; public static final String PATH = "path"; public static final String MEMBER = "connectedMember"; + public static final String BUDGET = "budget"; } diff --git a/src/main/java/org/tenten/tentenstomp/global/messaging/kafka/consumer/KafkaConsumer.java b/src/main/java/org/tenten/tentenstomp/global/messaging/kafka/consumer/KafkaConsumer.java index 427965e..c6c1627 100644 --- a/src/main/java/org/tenten/tentenstomp/global/messaging/kafka/consumer/KafkaConsumer.java +++ b/src/main/java/org/tenten/tentenstomp/global/messaging/kafka/consumer/KafkaConsumer.java @@ -1,17 +1,11 @@ package org.tenten.tentenstomp.global.messaging.kafka.consumer; import lombok.RequiredArgsConstructor; -import org.apache.kafka.clients.consumer.ConsumerConfig; -import org.apache.kafka.common.internals.Topic; import org.springframework.kafka.annotation.KafkaListener; import org.springframework.messaging.simp.SimpMessageSendingOperations; import org.springframework.stereotype.Service; import org.tenten.tentenstomp.domain.trip.dto.request.TripUpdateMsg; -import org.tenten.tentenstomp.domain.trip.dto.response.TripInfoMsg; -import org.tenten.tentenstomp.domain.trip.dto.response.TripItemMsg; -import org.tenten.tentenstomp.domain.trip.dto.response.TripMemberMsg; -import org.tenten.tentenstomp.domain.trip.dto.response.TripPathMsg; -import org.tenten.tentenstomp.global.common.constant.TopicConstant; +import org.tenten.tentenstomp.domain.trip.dto.response.*; import org.tenten.tentenstomp.global.response.GlobalStompResponse; import org.tenten.tentenstomp.global.util.TopicUtil; @@ -51,4 +45,10 @@ public void updateTripPath(TripPathMsg tripPathMsg) { public void updateConnectedTripMember(TripMemberMsg tripMemberMsg) { messagingTemplate.convertAndSend(topicUtil.topicToReturnEndPoint(tripMemberMsg.tripId(), MEMBER), GlobalStompResponse.ok(tripMemberMsg)); } + + @KafkaListener(topics = BUDGET, groupId = GROUP_ID_CONFIG) + public void updateBudget(TripBudgetMsg tripBudgetMsg) { + messagingTemplate.convertAndSend(topicUtil.topicToReturnEndPoint(tripBudgetMsg.tripId(), BUDGET), GlobalStompResponse.ok(tripBudgetMsg)); + + } } From d9762a7d760fe7ed185973d99347a78b2092ec7f Mon Sep 17 00:00:00 2001 From: Kim-Dong-Jun99 Date: Tue, 9 Jan 2024 10:52:53 +0900 Subject: [PATCH 2/5] =?UTF-8?q?Feat=20:=20=EC=97=AC=ED=96=89=20=EC=95=84?= =?UTF-8?q?=EC=9D=B4=ED=85=9C=20=EB=B0=A9=EB=AC=B8=20=EA=B5=90=ED=86=B5=20?= =?UTF-8?q?=EC=88=98=EB=8B=A8=20=EB=B3=80=EA=B2=BD=20=EC=9D=B4=EB=B2=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=B2=98=EB=A6=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/trip/controller/TripItemController.java | 6 ++++++ .../tentenstomp/domain/trip/service/TripItemService.java | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/src/main/java/org/tenten/tentenstomp/domain/trip/controller/TripItemController.java b/src/main/java/org/tenten/tentenstomp/domain/trip/controller/TripItemController.java index ae4a0f5..ba4acd1 100644 --- a/src/main/java/org/tenten/tentenstomp/domain/trip/controller/TripItemController.java +++ b/src/main/java/org/tenten/tentenstomp/domain/trip/controller/TripItemController.java @@ -6,6 +6,7 @@ import org.springframework.messaging.handler.annotation.Payload; import org.springframework.web.bind.annotation.RestController; import org.tenten.tentenstomp.domain.trip.dto.request.TripItemPriceUpdateMsg; +import org.tenten.tentenstomp.domain.trip.dto.request.TripItemTransportationUpdateMsg; import org.tenten.tentenstomp.domain.trip.dto.request.TripItemVisitDateUpdateMsg; import org.tenten.tentenstomp.domain.trip.service.TripItemService; @@ -24,6 +25,11 @@ public void updateTripItemVisitDate(@DestinationVariable String tripItemId, @Pay tripItemService.updateTripItemVisitDate(tripItemId, visitDateUpdateMsg); } + @MessageMapping("/tripItems/{tripItemId}/updateTransportation") + public void updateTripItemTransportation(@DestinationVariable String tripItemId, @Payload TripItemTransportationUpdateMsg tripItemTransportationUpdateMsg) { + tripItemService.updateTripItemTransportation(tripItemId, tripItemTransportationUpdateMsg); + } + @MessageMapping("/tripItems/{tripItemId}/deleteItem") public void deleteTripItem(@DestinationVariable String tripItemId) { tripItemService.deleteTripItem(tripItemId); diff --git a/src/main/java/org/tenten/tentenstomp/domain/trip/service/TripItemService.java b/src/main/java/org/tenten/tentenstomp/domain/trip/service/TripItemService.java index 1905233..80ac81f 100644 --- a/src/main/java/org/tenten/tentenstomp/domain/trip/service/TripItemService.java +++ b/src/main/java/org/tenten/tentenstomp/domain/trip/service/TripItemService.java @@ -4,6 +4,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.tenten.tentenstomp.domain.trip.dto.request.TripItemPriceUpdateMsg; +import org.tenten.tentenstomp.domain.trip.dto.request.TripItemTransportationUpdateMsg; import org.tenten.tentenstomp.domain.trip.dto.request.TripItemVisitDateUpdateMsg; import org.tenten.tentenstomp.domain.trip.dto.response.TripItemMsg; import org.tenten.tentenstomp.domain.trip.dto.response.TripPathMsg; @@ -88,5 +89,9 @@ public void deleteTripItem(String tripItemId) { kafkaProducer.send(PATH, tripPathMsg); // TODO : budget + } + @Transactional + public void updateTripItemTransportation(String tripItemId, TripItemTransportationUpdateMsg tripItemTransportationUpdateMsg) { + } } From afd64eafba7a02f0bb963190fbea0f5e246c5289 Mon Sep 17 00:00:00 2001 From: Kim-Dong-Jun99 Date: Wed, 10 Jan 2024 00:07:19 +0900 Subject: [PATCH 3/5] =?UTF-8?q?Feat=20:=20=EC=86=8C=EC=BC=93=20=ED=86=B5?= =?UTF-8?q?=EC=8B=A0=20STOMP=20API=201=EC=B0=A8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/member/entity/Member.java | 2 - .../member/repository/MemberRepository.java | 11 + .../tour/repository/TourItemRepository.java | 7 + .../trip/controller/TripController.java | 30 +- .../trip/dto/request/TripItemAddMsg.java | 21 +- .../TripItemTransportationUpdateMsg.java | 8 + .../trip/dto/response/TripItemInfo.java | 19 ++ .../trip/dto/response/TripItemInfoMsg.java | 3 + .../domain/trip/dto/response/TripItemMsg.java | 21 ++ .../trip/dto/response/TripMemberMsg.java | 3 +- .../tentenstomp/domain/trip/entity/Trip.java | 20 ++ .../domain/trip/entity/TripItem.java | 25 +- .../trip/entity/TripLikedItemPreference.java | 4 +- .../trip/repository/TripItemRepository.java | 19 ++ .../domain/trip/service/TripItemService.java | 197 +++++++++---- .../domain/trip/service/TripService.java | 265 ++++++++++++------ .../tentenstomp/global/cache/RedisCache.java | 40 +++ .../global/common/constant/RedisConstant.java | 5 + .../global/component/PathComponent.java | 13 +- .../component/dto/request/TripPlace.java | 10 +- .../response/TripPathCalculationResult.java | 11 + .../global/converter/MapConverter.java | 42 +++ 22 files changed, 604 insertions(+), 172 deletions(-) create mode 100644 src/main/java/org/tenten/tentenstomp/domain/trip/dto/request/TripItemTransportationUpdateMsg.java create mode 100644 src/main/java/org/tenten/tentenstomp/domain/trip/dto/response/TripItemInfo.java create mode 100644 src/main/java/org/tenten/tentenstomp/global/cache/RedisCache.java create mode 100644 src/main/java/org/tenten/tentenstomp/global/common/constant/RedisConstant.java create mode 100644 src/main/java/org/tenten/tentenstomp/global/component/dto/response/TripPathCalculationResult.java create mode 100644 src/main/java/org/tenten/tentenstomp/global/converter/MapConverter.java diff --git a/src/main/java/org/tenten/tentenstomp/domain/member/entity/Member.java b/src/main/java/org/tenten/tentenstomp/domain/member/entity/Member.java index df942c0..8133199 100644 --- a/src/main/java/org/tenten/tentenstomp/domain/member/entity/Member.java +++ b/src/main/java/org/tenten/tentenstomp/domain/member/entity/Member.java @@ -65,6 +65,4 @@ public class Member extends BaseTimeEntity { @OneToMany(mappedBy = "member", fetch = LAZY, cascade = REMOVE) private final List likedItems = new ArrayList<>(); - @OneToMany(mappedBy = "creator", fetch = LAZY, cascade = REMOVE) - private final List tripItems = new ArrayList<>(); } \ No newline at end of file diff --git a/src/main/java/org/tenten/tentenstomp/domain/member/repository/MemberRepository.java b/src/main/java/org/tenten/tentenstomp/domain/member/repository/MemberRepository.java index 7a0b571..3d6e8bf 100644 --- a/src/main/java/org/tenten/tentenstomp/domain/member/repository/MemberRepository.java +++ b/src/main/java/org/tenten/tentenstomp/domain/member/repository/MemberRepository.java @@ -1,7 +1,18 @@ package org.tenten.tentenstomp.domain.member.repository; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.tenten.tentenstomp.domain.member.entity.Member; +import org.tenten.tentenstomp.domain.trip.dto.response.TripMemberInfoMsg; + +import java.util.List; +import java.util.Optional; public interface MemberRepository extends JpaRepository { + @Query("SELECT NEW org.tenten.tentenstomp.domain.trip.dto.response.TripMemberInfoMsg(m.id, m.nickname, m.profileImageUrl) " + + "FROM TripMember tm LEFT OUTER JOIN Member m ON tm.member.id = m.id WHERE tm.trip.id = :tripId") + List findTripMemberInfoByTripId(@Param("tripId") Long tripId); + @Query("SELECT NEW org.tenten.tentenstomp.domain.trip.dto.response.TripMemberInfoMsg(m.id, m.nickname, m.profileImageUrl) FROM Member m WHERE m.id = :memberId") + Optional findTripMemberInfoByMemberId(@Param("memberId") Long memberId); } diff --git a/src/main/java/org/tenten/tentenstomp/domain/tour/repository/TourItemRepository.java b/src/main/java/org/tenten/tentenstomp/domain/tour/repository/TourItemRepository.java index d26048f..1bdaa65 100644 --- a/src/main/java/org/tenten/tentenstomp/domain/tour/repository/TourItemRepository.java +++ b/src/main/java/org/tenten/tentenstomp/domain/tour/repository/TourItemRepository.java @@ -1,7 +1,14 @@ package org.tenten.tentenstomp.domain.tour.repository; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.tenten.tentenstomp.domain.tour.entity.TourItem; +import java.util.List; +import java.util.Map; + public interface TourItemRepository extends JpaRepository { + @Query("SELECT ti FROM TourItem ti WHERE ti.id in :tourItemIds ORDER BY ti.id ASC") + public List findTourItemByTourItemIds(@Param("tourItems") List tourItemIds); } diff --git a/src/main/java/org/tenten/tentenstomp/domain/trip/controller/TripController.java b/src/main/java/org/tenten/tentenstomp/domain/trip/controller/TripController.java index f42503e..c271e3f 100644 --- a/src/main/java/org/tenten/tentenstomp/domain/trip/controller/TripController.java +++ b/src/main/java/org/tenten/tentenstomp/domain/trip/controller/TripController.java @@ -21,21 +21,6 @@ public void testKafka(@Payload TripUpdateMsg tripUpdateMsg) { kafkaProducer.send("kafka", tripUpdateMsg); } - @MessageMapping("/trips/{tripId}/info") - public void editPlan(@DestinationVariable String tripId, @Payload TripUpdateMsg tripUpdateMsg) { - tripService.updateTrip(tripId, tripUpdateMsg); - } - - @MessageMapping("/trips/{tripId}/addTripItems") - public void addTripItem(@DestinationVariable String tripId, @Payload TripItemAddMsg tripItemAddMsg) { - tripService.addTripItem(tripId, tripItemAddMsg); - } - - @MessageMapping("/trips/{tripId}/updateTripItemOrder") - public void updateTripItemOrder(@DestinationVariable String tripId, @Payload TripItemOrderUpdateMsg orderUpdateMsg) { - tripService.updateTripItemOrder(tripId, orderUpdateMsg); - } - @MessageMapping("/trips/{tripId}/connectMember") public void connectMember(@DestinationVariable String tripId, @Payload MemberConnectMsg memberConnectMsg) { tripService.connectMember(tripId, memberConnectMsg); @@ -51,6 +36,21 @@ public void enterMember(@DestinationVariable String tripId, @Payload MemberConne tripService.enterMember(tripId, memberConnectMsg); } + @MessageMapping("/trips/{tripId}/info") + public void editPlan(@DestinationVariable String tripId, @Payload TripUpdateMsg tripUpdateMsg) { + tripService.updateTrip(tripId, tripUpdateMsg); + } + + @MessageMapping("/trips/{tripId}/addTripItems") + public void addTripItem(@DestinationVariable String tripId, @Payload TripItemAddMsg tripItemAddMsg) { + tripService.addTripItem(tripId, tripItemAddMsg); + } + + @MessageMapping("/trips/{tripId}/updateTripItemOrder") + public void updateTripItemOrder(@DestinationVariable String tripId, @Payload TripItemOrderUpdateMsg orderUpdateMsg) { + tripService.updateTripItemOrder(tripId, orderUpdateMsg); + } + @MessageMapping("/trips/{tripId}/getPathAndItems") public void getPathAndItems(@DestinationVariable String tripId, @Payload PathAndItemRequestMsg pathAndItemRequestMsg) { tripService.getPathAndItems(tripId, pathAndItemRequestMsg); diff --git a/src/main/java/org/tenten/tentenstomp/domain/trip/dto/request/TripItemAddMsg.java b/src/main/java/org/tenten/tentenstomp/domain/trip/dto/request/TripItemAddMsg.java index 05369ad..ade9262 100644 --- a/src/main/java/org/tenten/tentenstomp/domain/trip/dto/request/TripItemAddMsg.java +++ b/src/main/java/org/tenten/tentenstomp/domain/trip/dto/request/TripItemAddMsg.java @@ -1,19 +1,32 @@ package org.tenten.tentenstomp.domain.trip.dto.request; +import org.tenten.tentenstomp.domain.tour.entity.TourItem; +import org.tenten.tentenstomp.domain.trip.entity.Trip; +import org.tenten.tentenstomp.domain.trip.entity.TripItem; import org.tenten.tentenstomp.global.common.enums.Transportation; +import java.time.LocalDate; import java.util.List; +import static org.tenten.tentenstomp.global.common.enums.Transportation.PUBLIC_TRANSPORTATION; + public record TripItemAddMsg( String visitDate, List newTripItems ) { public record TripItemCreateRequest( - Long tourItemId, - Transportation transportation, - Long seqNum, - Long price + Long tourItemId ) { + public static TripItem toEntity(TourItem tourItem, Trip trip, Long seqNum, LocalDate visitDate) { + return TripItem.builder() + .transportation(PUBLIC_TRANSPORTATION) + .trip(trip) + .price(0L) + .seqNum(seqNum) + .tourItem(tourItem) + .visitDate(visitDate) + .build(); + } } } diff --git a/src/main/java/org/tenten/tentenstomp/domain/trip/dto/request/TripItemTransportationUpdateMsg.java b/src/main/java/org/tenten/tentenstomp/domain/trip/dto/request/TripItemTransportationUpdateMsg.java new file mode 100644 index 0000000..f63d4ce --- /dev/null +++ b/src/main/java/org/tenten/tentenstomp/domain/trip/dto/request/TripItemTransportationUpdateMsg.java @@ -0,0 +1,8 @@ +package org.tenten.tentenstomp.domain.trip.dto.request; + +import org.tenten.tentenstomp.global.common.enums.Transportation; + +public record TripItemTransportationUpdateMsg( + Transportation transportation +) { +} diff --git a/src/main/java/org/tenten/tentenstomp/domain/trip/dto/response/TripItemInfo.java b/src/main/java/org/tenten/tentenstomp/domain/trip/dto/response/TripItemInfo.java new file mode 100644 index 0000000..1ebb9a5 --- /dev/null +++ b/src/main/java/org/tenten/tentenstomp/domain/trip/dto/response/TripItemInfo.java @@ -0,0 +1,19 @@ +package org.tenten.tentenstomp.domain.trip.dto.response; + +import org.tenten.tentenstomp.global.common.enums.Transportation; + +import java.time.LocalDate; + +public record TripItemInfo( + Long tripItemId, + Long tourItemId, + String name, + String thumbnailUrl, + Long contentTypeId, + Transportation transportation, + Long seqNum, + LocalDate visitDate, + Long price +) { + +} \ No newline at end of file diff --git a/src/main/java/org/tenten/tentenstomp/domain/trip/dto/response/TripItemInfoMsg.java b/src/main/java/org/tenten/tentenstomp/domain/trip/dto/response/TripItemInfoMsg.java index aeca812..aa37fbb 100644 --- a/src/main/java/org/tenten/tentenstomp/domain/trip/dto/response/TripItemInfoMsg.java +++ b/src/main/java/org/tenten/tentenstomp/domain/trip/dto/response/TripItemInfoMsg.java @@ -2,6 +2,8 @@ import org.tenten.tentenstomp.global.common.enums.Transportation; +import java.time.LocalDate; + public record TripItemInfoMsg( Long tripItemId, Long tourItemId, @@ -13,4 +15,5 @@ public record TripItemInfoMsg( String visitDate, Long price ) { + } diff --git a/src/main/java/org/tenten/tentenstomp/domain/trip/dto/response/TripItemMsg.java b/src/main/java/org/tenten/tentenstomp/domain/trip/dto/response/TripItemMsg.java index e8e30ff..204b0ed 100644 --- a/src/main/java/org/tenten/tentenstomp/domain/trip/dto/response/TripItemMsg.java +++ b/src/main/java/org/tenten/tentenstomp/domain/trip/dto/response/TripItemMsg.java @@ -1,6 +1,12 @@ package org.tenten.tentenstomp.domain.trip.dto.response; +import org.tenten.tentenstomp.domain.trip.dto.request.TripItemPriceUpdateMsg; +import org.tenten.tentenstomp.domain.trip.entity.Trip; +import org.tenten.tentenstomp.domain.trip.entity.TripItem; +import org.tenten.tentenstomp.global.common.enums.Category; + import java.time.LocalDate; +import java.util.ArrayList; import java.util.List; public record TripItemMsg( @@ -8,4 +14,19 @@ public record TripItemMsg( String visitDate, List tripItems ) { + public static TripItemMsg fromTripItemList(Long tripId, String visitDate, List tripItems) { + return new TripItemMsg(tripId, visitDate, tripItems.stream().map(t-> new TripItemInfoMsg(t.getId(), t.getTourItem().getId(), t.getTourItem().getTitle(), t.getTourItem().getOriginalThumbnailUrl(), Category.fromCode(t.getTourItem().getContentTypeId()).toString(), t.getTransportation(), t.getSeqNum(), t.getVisitDate().toString(), t.getPrice())).toList()); + } + + public static TripItemMsg fromTripItemList(Long tripId, String visitDate, List tripItems, Long tripItemId, TripItemPriceUpdateMsg updateMsg) { + List tripItemInfoMsgs = new ArrayList<>(); + for (TripItem t : tripItems) { + if (t.getId().equals(tripItemId)) { + tripItemInfoMsgs.add(new TripItemInfoMsg(t.getId(), t.getTourItem().getId(), t.getTourItem().getTitle(), t.getTourItem().getOriginalThumbnailUrl(), Category.fromCode(t.getTourItem().getContentTypeId()).toString(), t.getTransportation(), t.getSeqNum(), t.getVisitDate().toString(), updateMsg.price())); + } else { + tripItemInfoMsgs.add(new TripItemInfoMsg(t.getId(), t.getTourItem().getId(), t.getTourItem().getTitle(), t.getTourItem().getOriginalThumbnailUrl(), Category.fromCode(t.getTourItem().getContentTypeId()).toString(), t.getTransportation(), t.getSeqNum(), t.getVisitDate().toString(), t.getPrice())); + } + } + return new TripItemMsg(tripId, visitDate, tripItemInfoMsgs); + } } diff --git a/src/main/java/org/tenten/tentenstomp/domain/trip/dto/response/TripMemberMsg.java b/src/main/java/org/tenten/tentenstomp/domain/trip/dto/response/TripMemberMsg.java index 352f539..a38205a 100644 --- a/src/main/java/org/tenten/tentenstomp/domain/trip/dto/response/TripMemberMsg.java +++ b/src/main/java/org/tenten/tentenstomp/domain/trip/dto/response/TripMemberMsg.java @@ -4,6 +4,7 @@ public record TripMemberMsg( Long tripId, - List connectedMembers + List connectedMembers, + List tripMembers ) { } diff --git a/src/main/java/org/tenten/tentenstomp/domain/trip/entity/Trip.java b/src/main/java/org/tenten/tentenstomp/domain/trip/entity/Trip.java index 942c343..182d058 100644 --- a/src/main/java/org/tenten/tentenstomp/domain/trip/entity/Trip.java +++ b/src/main/java/org/tenten/tentenstomp/domain/trip/entity/Trip.java @@ -5,14 +5,17 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import org.hibernate.annotations.ColumnDefault; import org.tenten.tentenstomp.domain.trip.dto.request.TripUpdateMsg; import org.tenten.tentenstomp.domain.trip.dto.response.TripInfoMsg; import org.tenten.tentenstomp.global.common.BaseTimeEntity; import org.tenten.tentenstomp.global.common.enums.TripStatus; +import org.tenten.tentenstomp.global.converter.MapConverter; import java.time.LocalDate; import java.util.ArrayList; import java.util.List; +import java.util.Map; import static jakarta.persistence.CascadeType.REMOVE; import static jakarta.persistence.EnumType.STRING; @@ -41,6 +44,13 @@ public class Trip extends BaseTimeEntity { private Boolean isDeleted; private String tripName; private Long budget; + @ColumnDefault("0") + private Long tripItemPriceSum; + @ColumnDefault("0") + private Long transportationPriceSum; + @Convert(converter = MapConverter.class) + @Column(columnDefinition = "JSON") + private Map tripPathPriceMap; @OneToMany(mappedBy = "trip", fetch = LAZY, cascade = REMOVE) private final List tripMembers = new ArrayList<>(); @@ -69,4 +79,14 @@ public TripInfoMsg toTripInfo() { return new TripInfoMsg(this.getId(), this.startDate.toString(), this.endDate.toString(), this.getNumberOfPeople(), this.getTripName(), this.getTripStatus(), this.getArea(), this.getSubarea(), this.getBudget()); } + + public void updateTransportationPriceSum(Long oldVisitDateTransportationPriceSum, Long newVisitDateTransportationPriceSum) { + this.transportationPriceSum -= oldVisitDateTransportationPriceSum; + this.transportationPriceSum += newVisitDateTransportationPriceSum; + } + + public void updateTripItemPriceSum(Long oldTripItemPrice, Long newTripItemPrice) { + this.tripItemPriceSum -= oldTripItemPrice; + this.tripItemPriceSum += newTripItemPrice; + } } \ No newline at end of file diff --git a/src/main/java/org/tenten/tentenstomp/domain/trip/entity/TripItem.java b/src/main/java/org/tenten/tentenstomp/domain/trip/entity/TripItem.java index 323ccff..e9d2f04 100644 --- a/src/main/java/org/tenten/tentenstomp/domain/trip/entity/TripItem.java +++ b/src/main/java/org/tenten/tentenstomp/domain/trip/entity/TripItem.java @@ -5,6 +5,7 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import org.hibernate.annotations.ColumnDefault; import org.tenten.tentenstomp.domain.member.entity.Member; import org.tenten.tentenstomp.domain.tour.entity.TourItem; import org.tenten.tentenstomp.global.common.BaseTimeEntity; @@ -27,21 +28,39 @@ public class TripItem extends BaseTimeEntity { @GeneratedValue(strategy = IDENTITY) @Column(name = "tripItemId") private Long id; + @Enumerated(STRING) private Transportation transportation; private Long seqNum; // 방문 순서 private LocalDate visitDate; + @ColumnDefault("0") private Long price; // 예상 비용 @ManyToOne @JoinColumn(name = "tripId") private Trip trip; - @ManyToOne - @JoinColumn(name = "memberId") - private Member creator; @ManyToOne @JoinColumn(name = "tourItemId") private TourItem tourItem; + + public void updateSeqNum(Long seqNum) { + this.seqNum = seqNum; + } + + public void updatePrice(Long price) { + this.price = price; + } + + public void updateVisitDate(LocalDate visitDate) { + this.visitDate = visitDate; + } + + public void updateTransportation(Transportation transportation) { + this.transportation = transportation; + } + public int compareWithSeqNum(TripItem compare) { + return Long.compare(this.seqNum, compare.seqNum); + } } \ No newline at end of file diff --git a/src/main/java/org/tenten/tentenstomp/domain/trip/entity/TripLikedItemPreference.java b/src/main/java/org/tenten/tentenstomp/domain/trip/entity/TripLikedItemPreference.java index 84f7410..3b534ec 100644 --- a/src/main/java/org/tenten/tentenstomp/domain/trip/entity/TripLikedItemPreference.java +++ b/src/main/java/org/tenten/tentenstomp/domain/trip/entity/TripLikedItemPreference.java @@ -19,8 +19,8 @@ public class TripLikedItemPreference { @Column(name = "tripLikedItemPreferenceId") private Long id; - private Boolean liked; - private Boolean disliked; + private Boolean prefer; + private Boolean notPrefer; @ManyToOne @JoinColumn(name = "tripMemberId") diff --git a/src/main/java/org/tenten/tentenstomp/domain/trip/repository/TripItemRepository.java b/src/main/java/org/tenten/tentenstomp/domain/trip/repository/TripItemRepository.java index 36a19e1..a330da2 100644 --- a/src/main/java/org/tenten/tentenstomp/domain/trip/repository/TripItemRepository.java +++ b/src/main/java/org/tenten/tentenstomp/domain/trip/repository/TripItemRepository.java @@ -1,7 +1,26 @@ package org.tenten.tentenstomp.domain.trip.repository; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.tenten.tentenstomp.domain.trip.dto.response.TripItemInfo; +import org.tenten.tentenstomp.domain.trip.entity.Trip; import org.tenten.tentenstomp.domain.trip.entity.TripItem; +import org.tenten.tentenstomp.global.component.dto.request.TripPlace; + +import java.time.LocalDate; +import java.util.List; public interface TripItemRepository extends JpaRepository { + @Query("SELECT NEW org.tenten.tentenstomp.domain.trip.dto.response.TripItemInfo(" + + "ti.id, t.id, t.title, t.originalThumbnailUrl, t.contentTypeId, ti.transportation, ti.seqNum, ti.visitDate, ti.price" + + ") FROM TripItem ti LEFT OUTER JOIN TourItem t ON ti.tourItem.id = t.id WHERE ti.trip.id = :tripId AND ti.visitDate = :visitDate ORDER BY ti.seqNum ASC") + List getTripItemInfoByTripIdAndVisitDate(@Param("tripId") Long tripId, @Param("visitDate") LocalDate visitDate); + + @Query("SELECT ti FROM TripItem ti JOIN FETCH ti.tourItem WHERE ti.trip.id = :tripId AND ti.visitDate = :visitDate ORDER BY ti.seqNum ASC") + List findTripItemByTripIdAndVisitDate(@Param("tripId") Long tripId, @Param("visitDate") LocalDate visitDate); + @Query("SELECT NEW org.tenten.tentenstomp.global.component.dto.request.TripPlace(" + + "ti.seqNum, ti.transportation, t.longitude, t.latitude, ti.price" + + ") FROM TripItem ti LEFT OUTER JOIN TourItem t ON ti.tourItem.id = t.id WHERE ti.trip.id = :tripId AND ti.visitDate = :visitDate ORDER BY ti.seqNum ASC") + List findTripPlaceByTripIdAndVisitDate(@Param("tripId") Long tripId, @Param("visitDate") LocalDate visitDate); } diff --git a/src/main/java/org/tenten/tentenstomp/domain/trip/service/TripItemService.java b/src/main/java/org/tenten/tentenstomp/domain/trip/service/TripItemService.java index 80ac81f..2bba0fa 100644 --- a/src/main/java/org/tenten/tentenstomp/domain/trip/service/TripItemService.java +++ b/src/main/java/org/tenten/tentenstomp/domain/trip/service/TripItemService.java @@ -6,92 +6,187 @@ import org.tenten.tentenstomp.domain.trip.dto.request.TripItemPriceUpdateMsg; import org.tenten.tentenstomp.domain.trip.dto.request.TripItemTransportationUpdateMsg; import org.tenten.tentenstomp.domain.trip.dto.request.TripItemVisitDateUpdateMsg; -import org.tenten.tentenstomp.domain.trip.dto.response.TripItemMsg; -import org.tenten.tentenstomp.domain.trip.dto.response.TripPathMsg; +import org.tenten.tentenstomp.domain.trip.dto.response.*; +import org.tenten.tentenstomp.domain.trip.entity.Trip; import org.tenten.tentenstomp.domain.trip.entity.TripItem; import org.tenten.tentenstomp.domain.trip.repository.TripItemRepository; +import org.tenten.tentenstomp.domain.trip.repository.TripRepository; +import org.tenten.tentenstomp.global.cache.RedisCache; +import org.tenten.tentenstomp.global.component.PathComponent; +import org.tenten.tentenstomp.global.component.dto.request.TripPlace; +import org.tenten.tentenstomp.global.component.dto.response.TripPathCalculationResult; import org.tenten.tentenstomp.global.exception.GlobalException; import org.tenten.tentenstomp.global.messaging.kafka.producer.KafkaProducer; import org.tenten.tentenstomp.global.messaging.redis.publisher.RedisPublisher; import org.tenten.tentenstomp.global.util.RedisChannelUtil; import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; import static org.springframework.http.HttpStatus.NOT_FOUND; -import static org.tenten.tentenstomp.global.common.constant.TopicConstant.PATH; -import static org.tenten.tentenstomp.global.common.constant.TopicConstant.TRIP_ITEM; +import static org.tenten.tentenstomp.global.common.constant.TopicConstant.*; +import static org.tenten.tentenstomp.global.common.constant.TopicConstant.BUDGET; @Service @RequiredArgsConstructor public class TripItemService { private final TripItemRepository tripItemRepository; - private final RedisChannelUtil redisChannelUtil; - private final RedisPublisher redisPublisher; + private final TripRepository tripRepository; + private final RedisCache redisCache; private final KafkaProducer kafkaProducer; + private final PathComponent pathComponent; @Transactional public void updateTripItemPrice(String tripItemId, TripItemPriceUpdateMsg priceUpdateMsg) { TripItem tripItem = tripItemRepository.findById(Long.parseLong(tripItemId)).orElseThrow(() -> new GlobalException("해당 아이디로 존재하는 tripItem이 없다 " + tripItemId, NOT_FOUND)); - /* - 비즈니스 로직 - */ - TripItemMsg tripItemMsg = new TripItemMsg( - tripItem.getTourItem().getId(), tripItem.getVisitDate().toString(), null - ); - - kafkaProducer.send(TRIP_ITEM, tripItemMsg); - // TODO : budget + Long oldPrice = tripItem.getPrice(); + Long newPrice = priceUpdateMsg.price(); + Trip trip = tripItem.getTrip(); + trip.updateTripItemPriceSum(oldPrice, newPrice); + tripItem.updatePrice(newPrice); + List tripItems = trip.getTripItems(); + TripBudgetMsg tripBudgetMsg = new TripBudgetMsg(trip.getId(), trip.getBudget(), trip.getTripItemPriceSum() + trip.getTransportationPriceSum()); + TripItemMsg tripItemMsg = TripItemMsg.fromTripItemList(trip.getId(), tripItem.getVisitDate().toString(), tripItems, tripItem.getId(), priceUpdateMsg); + sendToKafkaAndSave(tripBudgetMsg, tripItemMsg); } @Transactional public void updateTripItemVisitDate(String tripItemId, TripItemVisitDateUpdateMsg visitDateUpdateMsg) { TripItem tripItem = tripItemRepository.findById(Long.parseLong(tripItemId)).orElseThrow(() -> new GlobalException("해당 아이디로 존재하는 tripItem이 없다 " + tripItemId, NOT_FOUND)); + Trip trip = tripRepository.findById(tripItem.getTrip().getId()).orElseThrow(() -> new GlobalException("해당 아이디로 존재하는 trip이 없다 " + tripItem.getTrip().getId(), NOT_FOUND)); LocalDate pastDate = tripItem.getVisitDate(); LocalDate newDate = LocalDate.parse(visitDateUpdateMsg.visitDate()); - /* - 비즈니스 로직 - */ - - TripItemMsg tripItemMsgToPastDate = new TripItemMsg( - tripItem.getTourItem().getId(), pastDate.toString(), null - ); - TripItemMsg tripItemMsgToNewDate = new TripItemMsg( - tripItem.getTourItem().getId(), newDate.toString(), null - ); - - TripPathMsg tripPathMsgToPastDate = new TripPathMsg( - tripItem.getTourItem().getId(), pastDate.toString(), null - ); - TripPathMsg tripPathMsgToNewDate = new TripPathMsg( - tripItem.getTourItem().getId(), newDate.toString(), null - ); - - kafkaProducer.send(TRIP_ITEM, tripItemMsgToPastDate); - kafkaProducer.send(TRIP_ITEM, tripItemMsgToNewDate); - kafkaProducer.send(PATH, tripPathMsgToPastDate); - kafkaProducer.send(PATH, tripPathMsgToNewDate); - // TODO : budget + + List pastDateTripItems = tripItemRepository.findTripItemByTripIdAndVisitDate(tripItem.getTrip().getId(), pastDate); + List newDateTripItems = tripItemRepository.findTripItemByTripIdAndVisitDate(tripItem.getTrip().getId(), newDate); + + Long oldSeqNum = tripItem.getSeqNum(); + Long newSeqNum = (long) newDateTripItems.size(); + List newPastDateTripItems = new ArrayList<>(); + for (TripItem pastDateTripItem : pastDateTripItems) { + if (pastDateTripItem.getId().equals(tripItem.getId())) { + continue; + } + if (pastDateTripItem.getSeqNum() > oldSeqNum) { + pastDateTripItem.updateSeqNum(pastDateTripItem.getSeqNum() - 1); + } + newPastDateTripItems.add(pastDateTripItem); + } + + tripItem.updateSeqNum(newSeqNum); + tripItem.updateVisitDate(LocalDate.parse(visitDateUpdateMsg.visitDate())); + newDateTripItems.add(tripItem); + + TripPathCalculationResult pastDateTripPath = pathComponent.getTripPath(TripPlace.fromTripItems(newPastDateTripItems)); + TripPathCalculationResult newDateTripPath = pathComponent.getTripPath(TripPlace.fromTripItems(newDateTripItems)); + + Map tripPathPriceMap = trip.getTripPathPriceMap(); + trip.updateTransportationPriceSum(tripPathPriceMap.getOrDefault(pastDate.toString(), 0L), pastDateTripPath.pathPriceSum()); + trip.updateTransportationPriceSum(tripPathPriceMap.getOrDefault(newDate.toString(), 0L), newDateTripPath.pathPriceSum()); + tripPathPriceMap.put(pastDate.toString(), pastDateTripPath.pathPriceSum()); + tripPathPriceMap.put(newDate.toString(), newDateTripPath.pathPriceSum()); + tripRepository.save(trip); + + TripItemMsg pastDateTripItemMsg = TripItemMsg.fromTripItemList(trip.getId(), pastDate.toString(), newPastDateTripItems); + TripItemMsg newDateTripItemMsg = TripItemMsg.fromTripItemList(trip.getId(), newDate.toString(), newDateTripItems); + TripPathMsg pastDateTripPathMsg = new TripPathMsg(trip.getId(), pastDate.toString(), pastDateTripPath.tripPathInfoMsgs()); + TripPathMsg newDateTripPathMsg = new TripPathMsg(trip.getId(), newDate.toString(), newDateTripPath.tripPathInfoMsgs()); + TripBudgetMsg tripBudgetMsg = new TripBudgetMsg(trip.getId(), trip.getBudget(), trip.getTripItemPriceSum() + trip.getTransportationPriceSum()); + + sendToKafkaAndSave(pastDateTripItemMsg, newDateTripItemMsg, pastDateTripPathMsg, newDateTripPathMsg, tripBudgetMsg); } @Transactional public void deleteTripItem(String tripItemId) { TripItem tripItem = tripItemRepository.findById(Long.parseLong(tripItemId)).orElseThrow(() -> new GlobalException("해당 아이디로 존재하는 tripItem이 없다 " + tripItemId, NOT_FOUND)); + Trip trip = tripRepository.findById(tripItem.getTrip().getId()).orElseThrow(() -> new GlobalException("해당 아이디로 존재하는 trip이 없다 " + tripItem.getTrip().getId(), NOT_FOUND)); + LocalDate visitDate = tripItem.getVisitDate(); - /* - 비즈니스 로직 - */ - TripItemMsg tripItemMsg = new TripItemMsg( - Long.parseLong(tripItemId), visitDate.toString(), null - ); - TripPathMsg tripPathMsg = new TripPathMsg( - Long.parseLong(tripItemId), visitDate.toString(), null - ); - - kafkaProducer.send(TRIP_ITEM, tripItemMsg); - kafkaProducer.send(PATH, tripPathMsg); - // TODO : budget + + List tripItems = tripItemRepository.findTripItemByTripIdAndVisitDate(tripItem.getTrip().getId(), visitDate); + Long seqNum = tripItem.getSeqNum(); + List newTripItems = new ArrayList<>(); + for (TripItem newTripItem : tripItems) { + if (newTripItem.getId().equals(tripItem.getId())) { + continue; + } + if (newTripItem.getSeqNum() > seqNum) { + newTripItem.updateSeqNum(newTripItem.getSeqNum() - 1); + } + newTripItems.add(newTripItem); + } + + tripItemRepository.delete(tripItem); + TripPathCalculationResult tripPath = pathComponent.getTripPath(TripPlace.fromTripItems(newTripItems)); + Map tripPathPriceMap = trip.getTripPathPriceMap(); + trip.updateTransportationPriceSum(tripPathPriceMap.getOrDefault(visitDate.toString(), 0L), tripPath.pathPriceSum()); + tripPathPriceMap.put(visitDate.toString(), tripPath.pathPriceSum()); + tripRepository.save(trip); + + TripItemMsg tripItemMsg = TripItemMsg.fromTripItemList(trip.getId(), visitDate.toString(), newTripItems); + TripPathMsg tripPathMsg = new TripPathMsg(trip.getId(), visitDate.toString(), tripPath.tripPathInfoMsgs()); + TripBudgetMsg tripBudgetMsg = new TripBudgetMsg(trip.getId(), trip.getBudget(), trip.getTripItemPriceSum() + trip.getTransportationPriceSum()); + + sendToKafkaAndSave(tripItemMsg, tripPathMsg, tripBudgetMsg); } @Transactional public void updateTripItemTransportation(String tripItemId, TripItemTransportationUpdateMsg tripItemTransportationUpdateMsg) { + TripItem tripItem = tripItemRepository.findById(Long.parseLong(tripItemId)).orElseThrow(() -> new GlobalException("해당 아이디로 존재하는 tripItem이 없다 " + tripItemId, NOT_FOUND)); + Trip trip = tripRepository.findById(tripItem.getTrip().getId()).orElseThrow(() -> new GlobalException("해당 아이디로 존재하는 trip이 없다 " + tripItem.getTrip().getId(), NOT_FOUND)); + + LocalDate visitDate = tripItem.getVisitDate(); + List tripItems = tripItemRepository.findTripItemByTripIdAndVisitDate(tripItem.getTrip().getId(), visitDate); + for (TripItem newTripItem : tripItems) { + if (newTripItem.getId().equals(tripItem.getId())) { + newTripItem.updateTransportation(tripItemTransportationUpdateMsg.transportation()); + } + } + + tripItem.updateTransportation(tripItemTransportationUpdateMsg.transportation()); + tripItemRepository.save(tripItem); + TripPathCalculationResult tripPath = pathComponent.getTripPath(TripPlace.fromTripItems(tripItems)); + Map tripPathPriceMap = trip.getTripPathPriceMap(); + trip.updateTransportationPriceSum(tripPathPriceMap.getOrDefault(visitDate.toString(), 0L), tripPath.pathPriceSum()); + tripPathPriceMap.put(visitDate.toString(), tripPath.pathPriceSum()); + tripRepository.save(trip); + + TripItemMsg tripItemMsg = TripItemMsg.fromTripItemList(trip.getId(), visitDate.toString(), tripItems); + TripPathMsg tripPathMsg = new TripPathMsg(trip.getId(), visitDate.toString(), tripPath.tripPathInfoMsgs()); + TripBudgetMsg tripBudgetMsg = new TripBudgetMsg(trip.getId(), trip.getBudget(), trip.getTripItemPriceSum() + trip.getTransportationPriceSum()); + + sendToKafkaAndSave(tripItemMsg, tripPathMsg, tripBudgetMsg); } + + private void sendToKafkaAndSave(Object... dataArgs) { + for (Object data : dataArgs) { + if (data.getClass().equals(TripPathMsg.class)) { + kafkaProducer.send(PATH, data); + TripPathMsg tripPathMsg = (TripPathMsg) data; + redisCache.save(PATH, Long.toString(tripPathMsg.tripId()), tripPathMsg.visitDate(), tripPathMsg); + } + if (data.getClass().equals(TripItemMsg.class)) { + kafkaProducer.send(TRIP_ITEM, data); + TripItemMsg tripItemMsg = (TripItemMsg) data; + redisCache.save(TRIP_ITEM, Long.toString(tripItemMsg.tripId()), tripItemMsg.visitDate(), tripItemMsg); + } + if (data.getClass().equals(TripInfoMsg.class)) { + kafkaProducer.send(TRIP_INFO, data); + TripInfoMsg tripInfoMsg = (TripInfoMsg) data; + redisCache.save(TRIP_INFO, Long.toString(tripInfoMsg.tripId()), tripInfoMsg); + } + if (data.getClass().equals(TripMemberMsg.class)) { + kafkaProducer.send(MEMBER, data); + TripMemberMsg tripMemberMsg = (TripMemberMsg) data; + redisCache.save(MEMBER, Long.toString(tripMemberMsg.tripId()), tripMemberMsg); + } + if (data.getClass().equals(TripBudgetMsg.class)) { + kafkaProducer.send(BUDGET, data); + TripBudgetMsg tripBudgetMsg = (TripBudgetMsg) data; + redisCache.save(BUDGET, Long.toString(tripBudgetMsg.tripId()), tripBudgetMsg); + } + } + } + } diff --git a/src/main/java/org/tenten/tentenstomp/domain/trip/service/TripService.java b/src/main/java/org/tenten/tentenstomp/domain/trip/service/TripService.java index 72cd9b0..664807a 100644 --- a/src/main/java/org/tenten/tentenstomp/domain/trip/service/TripService.java +++ b/src/main/java/org/tenten/tentenstomp/domain/trip/service/TripService.java @@ -1,23 +1,28 @@ package org.tenten.tentenstomp.domain.trip.service; +import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; -import org.springframework.data.redis.listener.ChannelTopic; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.tenten.tentenstomp.domain.member.repository.MemberRepository; +import org.tenten.tentenstomp.domain.tour.repository.TourItemRepository; import org.tenten.tentenstomp.domain.trip.dto.request.*; +import org.tenten.tentenstomp.domain.trip.dto.request.TripItemAddMsg.TripItemCreateRequest; +import org.tenten.tentenstomp.domain.trip.dto.request.TripItemOrderUpdateMsg.OrderInfo; import org.tenten.tentenstomp.domain.trip.dto.response.*; import org.tenten.tentenstomp.domain.trip.entity.Trip; +import org.tenten.tentenstomp.domain.trip.entity.TripItem; import org.tenten.tentenstomp.domain.trip.repository.TripItemRepository; -import org.tenten.tentenstomp.global.messaging.kafka.producer.KafkaProducer; -import org.tenten.tentenstomp.global.messaging.redis.publisher.RedisPublisher; import org.tenten.tentenstomp.domain.trip.repository.TripRepository; -import org.tenten.tentenstomp.global.response.GlobalStompResponse; -import org.tenten.tentenstomp.global.util.RedisChannelUtil; +import org.tenten.tentenstomp.global.cache.RedisCache; +import org.tenten.tentenstomp.global.common.enums.Category; +import org.tenten.tentenstomp.global.component.PathComponent; +import org.tenten.tentenstomp.global.component.dto.request.TripPlace; +import org.tenten.tentenstomp.global.component.dto.response.TripPathCalculationResult; +import org.tenten.tentenstomp.global.messaging.kafka.producer.KafkaProducer; import java.time.LocalDate; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; +import java.util.*; import static org.tenten.tentenstomp.global.common.constant.TopicConstant.*; @@ -26,127 +31,205 @@ public class TripService { private final TripRepository tripRepository; - private final RedisChannelUtil redisChannelUtil; private final TripItemRepository tripItemRepository; - private final RedisPublisher redisPublisher; + private final MemberRepository memberRepository; + private final TourItemRepository tourItemRepository; private final KafkaProducer kafkaProducer; + private final RedisCache redisCache; + private final PathComponent pathComponent; + private final ObjectMapper objectMapper; + private final Map> tripConnectedMemberMap = new HashMap<>(); + + @Transactional + public void connectMember(String tripId, MemberConnectMsg memberConnectMsg) { + HashMap connectedMemberMap = tripConnectedMemberMap.getOrDefault(tripId, new HashMap<>()); + Optional tripMemberInfoByMemberId = memberRepository.findTripMemberInfoByMemberId(memberConnectMsg.memberId()); + tripMemberInfoByMemberId.ifPresent(tripMemberInfoMsg -> connectedMemberMap.put(memberConnectMsg.memberId(), tripMemberInfoMsg)); + + TripMemberMsg tripMemberMsg = new TripMemberMsg( + Long.parseLong(tripId), connectedMemberMap.values().stream().toList(), memberRepository.findTripMemberInfoByTripId(Long.parseLong(tripId)) + ); + tripConnectedMemberMap.put(tripId, connectedMemberMap); + sendToKafkaAndSave(tripMemberMsg); + + } + + @Transactional + public void disconnectMember(String tripId, MemberDisconnectMsg memberDisconnectMsg) { + HashMap connectedMemberMap = tripConnectedMemberMap.getOrDefault(tripId, new HashMap<>()); + connectedMemberMap.remove(memberDisconnectMsg.memberId()); + + TripMemberMsg tripMemberMsg = new TripMemberMsg( + Long.parseLong(tripId), connectedMemberMap.values().stream().toList(), memberRepository.findTripMemberInfoByTripId(Long.parseLong(tripId)) + ); + tripConnectedMemberMap.put(tripId, connectedMemberMap); + sendToKafkaAndSave(tripMemberMsg); + + } + + @Transactional + public void enterMember(String tripId, MemberConnectMsg memberConnectMsg) { + Trip trip = tripRepository.getReferenceById(Long.parseLong(tripId)); + + kafkaProducer.send(MEMBER, getTripMemberMsg(tripId)); + kafkaProducer.send(TRIP_INFO, trip.toTripInfo()); + kafkaProducer.send(TRIP_ITEM, getTripItemMsg(trip, trip.getStartDate().toString())); + kafkaProducer.send(PATH, getTripPathMsg(trip, trip.getStartDate().toString())); + kafkaProducer.send(BUDGET, getTripBudgetMsg(trip)); + } - private final Map> connectedMemberMap = new HashMap<>(); -// private final PathComponent pathComponent; @Transactional public void updateTrip(String tripId, TripUpdateMsg tripUpdateMsg) { Trip trip = tripRepository.getReferenceById(Long.parseLong(tripId)); - TripInfoMsg tripResponseMsg = trip.changeTripInfo(tripUpdateMsg); + TripInfoMsg tripInfoMsg = trip.changeTripInfo(tripUpdateMsg); TripBudgetMsg tripBudgetMsg = new TripBudgetMsg( - trip.getId(), null, null + trip.getId(), trip.getBudget(), trip.getTripItemPriceSum() + trip.getTransportationPriceSum() ); tripRepository.save(trip); - kafkaProducer.send(TRIP_INFO, tripResponseMsg); - kafkaProducer.send(BUDGET, tripBudgetMsg); + sendToKafkaAndSave(tripInfoMsg, tripBudgetMsg); + } + @Transactional public void addTripItem(String tripId, TripItemAddMsg tripItemAddMsg) { Trip trip = tripRepository.getReferenceById(Long.parseLong(tripId)); - /* - 비즈니스 로직 - */ + List tripItems = tripItemRepository.findTripItemByTripIdAndVisitDate(Long.parseLong(tripId), LocalDate.parse(tripItemAddMsg.visitDate())); + LocalDate visitDate = LocalDate.parse(tripItemAddMsg.visitDate()); + List newTripItems = new ArrayList<>(); + for (TripItemCreateRequest tripItemCreateRequest : tripItemAddMsg.newTripItems()) { + TripItem entity = TripItemCreateRequest.toEntity(tourItemRepository.getReferenceById(tripItemCreateRequest.tourItemId()), trip, (long) tripItems.size() + 1, visitDate); + newTripItems.add(entity); + tripItems.add(entity); + } + tripItemRepository.saveAll(newTripItems); + + updateBudgetAndItemsAndPath(trip, tripItems, tripItemAddMsg.visitDate()); - TripItemMsg tripItemMsg = new TripItemMsg( - Long.parseLong(tripId), LocalDate.parse(tripItemAddMsg.visitDate()).toString(), null - ); - TripPathMsg tripPathMsg = new TripPathMsg( - Long.parseLong(tripId), LocalDate.parse(tripItemAddMsg.visitDate()).toString(), null - ); - TripBudgetMsg tripBudgetMsg = new TripBudgetMsg( - trip.getId(), null, null - ); + } + + private void updateBudgetAndItemsAndPath(Trip trip, List tripItems, String visitDate) { + TripPathCalculationResult tripPath = pathComponent.getTripPath(TripPlace.fromTripItems(tripItems)); + Map tripPathPriceMap = trip.getTripPathPriceMap(); + trip.updateTransportationPriceSum(tripPathPriceMap.getOrDefault(visitDate, 0L), tripPath.pathPriceSum()); + tripPathPriceMap.put(visitDate, tripPath.pathPriceSum()); + tripRepository.save(trip); - kafkaProducer.send(TRIP_ITEM, tripItemMsg); - kafkaProducer.send(PATH, tripPathMsg); - kafkaProducer.send(BUDGET, tripBudgetMsg); + TripBudgetMsg tripBudgetMsg = new TripBudgetMsg(trip.getId(), trip.getBudget(), trip.getTripItemPriceSum() + trip.getTransportationPriceSum()); + TripItemMsg tripItemMsg = TripItemMsg.fromTripItemList(trip.getId(), visitDate, tripItems); + TripPathMsg tripPathMsg = new TripPathMsg(trip.getId(), visitDate, tripPath.tripPathInfoMsgs()); + sendToKafkaAndSave(tripBudgetMsg, tripItemMsg, tripPathMsg); } + @Transactional public void updateTripItemOrder(String tripId, TripItemOrderUpdateMsg orderUpdateMsg) { - /* - 비즈니스 로직 - */ - - TripItemMsg tripItemMsg = new TripItemMsg( - Long.parseLong(tripId), LocalDate.parse(orderUpdateMsg.visitDate()).toString(), null - ); - TripPathMsg tripPathMsg = new TripPathMsg( - Long.parseLong(tripId), LocalDate.parse(orderUpdateMsg.visitDate()).toString(), null - ); - TripBudgetMsg tripBudgetMsg = new TripBudgetMsg( - Long.parseLong(tripId), null, null - ); - - kafkaProducer.send(TRIP_ITEM, tripItemMsg); - kafkaProducer.send(PATH, tripPathMsg); - kafkaProducer.send(BUDGET, tripBudgetMsg); + Trip trip = tripRepository.getReferenceById(Long.parseLong(tripId)); + Map itemOrderMap = new HashMap<>(); + for (OrderInfo orderInfo : orderUpdateMsg.tripItemOrder()) { + itemOrderMap.put(orderInfo.tripItemId(), orderInfo.seqNum()); + } + List tripItems = trip.getTripItems(); + for (TripItem tripItem : tripItems) { + tripItem.updateSeqNum(itemOrderMap.get(tripItem.getId())); + } + updateBudgetAndItemsAndPath(trip, tripItems, orderUpdateMsg.visitDate()); } @Transactional(readOnly = true) - public void connectMember(String tripId, MemberConnectMsg memberConnectMsg) { - /* - 비즈니스 로직 - */ - TripMemberMsg tripMemberMsg = new TripMemberMsg( - Long.parseLong(tripId), null - ); + public void getPathAndItems(String tripId, PathAndItemRequestMsg pathAndItemRequestMsg) { + Trip trip = tripRepository.getReferenceById(Long.parseLong(tripId)); - kafkaProducer.send(MEMBER, tripMemberMsg); + kafkaProducer.send(TRIP_ITEM, getTripItemMsg(trip, pathAndItemRequestMsg.visitDate())); + kafkaProducer.send(PATH, getTripPathMsg(trip, pathAndItemRequestMsg.visitDate())); } - @Transactional(readOnly = true) - public void disconnectMember(String tripId, MemberDisconnectMsg memberDisconnectMsg) { - /* - 비즈니스 로직 - */ + + private void sendToKafkaAndSave(Object... dataArgs) { + for (Object data : dataArgs) { + if (data.getClass().equals(TripPathMsg.class)) { + kafkaProducer.send(PATH, data); + TripPathMsg tripPathMsg = (TripPathMsg) data; + redisCache.save(PATH, Long.toString(tripPathMsg.tripId()), tripPathMsg.visitDate(), tripPathMsg); + } + if (data.getClass().equals(TripItemMsg.class)) { + kafkaProducer.send(TRIP_ITEM, data); + TripItemMsg tripItemMsg = (TripItemMsg) data; + redisCache.save(TRIP_ITEM, Long.toString(tripItemMsg.tripId()), tripItemMsg.visitDate(), tripItemMsg); + } + if (data.getClass().equals(TripInfoMsg.class)) { + kafkaProducer.send(TRIP_INFO, data); + TripInfoMsg tripInfoMsg = (TripInfoMsg) data; + redisCache.save(TRIP_INFO, Long.toString(tripInfoMsg.tripId()), tripInfoMsg); + } + if (data.getClass().equals(TripMemberMsg.class)) { + kafkaProducer.send(MEMBER, data); + TripMemberMsg tripMemberMsg = (TripMemberMsg) data; + redisCache.save(MEMBER, Long.toString(tripMemberMsg.tripId()), tripMemberMsg); + } + if (data.getClass().equals(TripBudgetMsg.class)) { + kafkaProducer.send(BUDGET, data); + TripBudgetMsg tripBudgetMsg = (TripBudgetMsg) data; + redisCache.save(BUDGET, Long.toString(tripBudgetMsg.tripId()), tripBudgetMsg); + } + } + } + + private TripMemberMsg getTripMemberMsg(String tripId) { + Object cached = redisCache.get(MEMBER, tripId); + if (cached != null) { + return (TripMemberMsg) cached; + } + HashMap connectedMemberMap = tripConnectedMemberMap.getOrDefault(tripId, new HashMap<>()); TripMemberMsg tripMemberMsg = new TripMemberMsg( - Long.parseLong(tripId), null + Long.parseLong(tripId), connectedMemberMap.values().stream().toList(), memberRepository.findTripMemberInfoByTripId(Long.parseLong(tripId)) ); - - kafkaProducer.send(MEMBER, tripMemberMsg); + redisCache.save(MEMBER, tripId, tripMemberMsg); + return tripMemberMsg; } - @Transactional(readOnly = true) - public void enterMember(String tripId, MemberConnectMsg memberConnectMsg) { - Trip trip = tripRepository.getReferenceById(Long.parseLong(tripId)); + private TripBudgetMsg getTripBudgetMsg(Trip trip) { - TripInfoMsg tripResponseMsg = trip.toTripInfo(); + Object cached = redisCache.get(BUDGET, Long.toString(trip.getId())); + if (cached != null) { + return objectMapper.convertValue(cached, TripBudgetMsg.class); + } TripBudgetMsg tripBudgetMsg = new TripBudgetMsg( - trip.getId(), null, null - ); - TripItemMsg tripItemMsg = new TripItemMsg( - Long.parseLong(tripId), trip.getStartDate().toString(), null + trip.getId(), trip.getBudget(), trip.getTripItemPriceSum() + trip.getTransportationPriceSum() ); - TripPathMsg tripPathMsg = new TripPathMsg( - Long.parseLong(tripId), trip.getStartDate().toString(), null - ); - - kafkaProducer.send(TRIP_INFO, tripResponseMsg); - kafkaProducer.send(TRIP_ITEM, tripItemMsg); - kafkaProducer.send(PATH, tripPathMsg); - kafkaProducer.send(BUDGET, tripBudgetMsg); + redisCache.save(BUDGET, Long.toString(trip.getId()), tripBudgetMsg); + return tripBudgetMsg; } - @Transactional(readOnly = true) - public void getPathAndItems(String tripId, PathAndItemRequestMsg pathAndItemRequestMsg) { - Trip trip = tripRepository.getReferenceById(Long.parseLong(tripId)); + private TripItemMsg getTripItemMsg(Trip trip, String visitDate) { + Object cached = redisCache.get(TRIP_ITEM, Long.toString(trip.getId()), visitDate); + if (cached != null) { + return objectMapper.convertValue(cached, TripItemMsg.class); - TripItemMsg tripItemMsg = new TripItemMsg( - Long.parseLong(tripId), pathAndItemRequestMsg.visitDate(), null - ); - TripPathMsg tripPathMsg = new TripPathMsg( - Long.parseLong(tripId), pathAndItemRequestMsg.visitDate(), null - ); + } + List tripInfos = tripItemRepository.getTripItemInfoByTripIdAndVisitDate(trip.getId(), LocalDate.parse(visitDate)); + List tripItemInfoMsgs = tripInfos.stream().map(t -> new TripItemInfoMsg( + t.tripItemId(), t.tourItemId(), t.name(), t.thumbnailUrl(), Category.fromCode(t.contentTypeId()).getName(), t.transportation(), t.seqNum(), t.visitDate().toString(), t.price() + )).toList(); + TripItemMsg tripItemMsg = new TripItemMsg(trip.getId(), visitDate, tripItemInfoMsgs); + redisCache.save(TRIP_ITEM, Long.toString(trip.getId()), visitDate, tripItemMsg); + return tripItemMsg; + + } + + private TripPathMsg getTripPathMsg(Trip trip, String visitDate) { + Object cached = redisCache.get(PATH, Long.toString(trip.getId()), visitDate); + if (cached != null) { + return objectMapper.convertValue(cached, TripPathMsg.class); + } + TripPathCalculationResult tripPath = pathComponent.getTripPath(tripItemRepository.findTripPlaceByTripIdAndVisitDate(trip.getId(), LocalDate.parse(visitDate))); + TripPathMsg tripPathMsg = new TripPathMsg(trip.getId(), visitDate, tripPath.tripPathInfoMsgs()); + redisCache.save(PATH, Long.toString(trip.getId()), visitDate, tripPathMsg); + return tripPathMsg; - kafkaProducer.send(TRIP_ITEM, tripItemMsg); - kafkaProducer.send(PATH, tripPathMsg); } + + } diff --git a/src/main/java/org/tenten/tentenstomp/global/cache/RedisCache.java b/src/main/java/org/tenten/tentenstomp/global/cache/RedisCache.java new file mode 100644 index 0000000..922e655 --- /dev/null +++ b/src/main/java/org/tenten/tentenstomp/global/cache/RedisCache.java @@ -0,0 +1,40 @@ +package org.tenten.tentenstomp.global.cache; + +import lombok.RequiredArgsConstructor; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.tenten.tentenstomp.global.common.constant.RedisConstant; + +import java.util.concurrent.TimeUnit; + +import static org.tenten.tentenstomp.global.common.constant.RedisConstant.CACHE_EXPIRE_TIME_MS; + +@Component +@RequiredArgsConstructor +public class RedisCache { + private final RedisTemplate redisTemplate; + + public void save(String topic, String key, Object data) { + redisTemplate.opsForValue().set(topic+":"+key, data, CACHE_EXPIRE_TIME_MS, TimeUnit.MILLISECONDS); + } + + public void save(String topic, String key, String visitDate, Object data) { + redisTemplate.opsForValue().set(topic + ":" + key + ":" + visitDate, data, CACHE_EXPIRE_TIME_MS, TimeUnit.MILLISECONDS); + } + + public Object get(String topic, String key) { + return redisTemplate.opsForValue().get(topic+":"+key); + } + + public Object get(String topic, String key, String visitDate) { + return redisTemplate.opsForValue().get(topic+":"+key+":"+visitDate); + } + + public void delete(String topic, String key) { + redisTemplate.delete(topic +":"+key); + } + + public void delete(String topic, String key, String visitDate) { + redisTemplate.delete(topic + ":" + key + ":" + visitDate); + } +} diff --git a/src/main/java/org/tenten/tentenstomp/global/common/constant/RedisConstant.java b/src/main/java/org/tenten/tentenstomp/global/common/constant/RedisConstant.java new file mode 100644 index 0000000..6f859bc --- /dev/null +++ b/src/main/java/org/tenten/tentenstomp/global/common/constant/RedisConstant.java @@ -0,0 +1,5 @@ +package org.tenten.tentenstomp.global.common.constant; + +public class RedisConstant { + public static final Long CACHE_EXPIRE_TIME_MS = 1000 * 60 * 30L; +} diff --git a/src/main/java/org/tenten/tentenstomp/global/component/PathComponent.java b/src/main/java/org/tenten/tentenstomp/global/component/PathComponent.java index 48a6cea..ce375ca 100644 --- a/src/main/java/org/tenten/tentenstomp/global/component/PathComponent.java +++ b/src/main/java/org/tenten/tentenstomp/global/component/PathComponent.java @@ -9,6 +9,7 @@ import org.tenten.tentenstomp.global.common.annotation.GetExecutionTime; import org.tenten.tentenstomp.global.component.dto.request.TripPlace; import org.tenten.tentenstomp.global.component.dto.request.PathCalculateRequest; +import org.tenten.tentenstomp.global.component.dto.response.TripPathCalculationResult; import java.util.ArrayList; import java.util.List; @@ -35,9 +36,17 @@ public TripPathInfoMsg calculatePath(TripPlace fromPlace, TripPlace toPlace) { return new TripPathInfoMsg(fromPlace.seqNum(), toPlace.seqNum(), fromPlace.longitude(), fromPlace.latitude(), toPlace.longitude(), toPlace.latitude(), toPlace.transportation(), pathInfo); } @GetExecutionTime - public List getTripPath(List tripPlaceList) { + public TripPathCalculationResult getTripPath(List tripPlaceList) { List pathCalculateRequests = toPathCalculateRequest(tripPlaceList); - return pathCalculateRequests.stream().flatMap(pathCalculateRequest -> Stream.of(calculatePath(pathCalculateRequest.from(), pathCalculateRequest.to()))).toList(); + long priceSum = 0L; + List pathInfoMsgs = new ArrayList<>(); + for (PathCalculateRequest calculateRequest : pathCalculateRequests) { + TripPathInfoMsg tripPathInfoMsg = calculatePath(calculateRequest.from(), calculateRequest.to()); + pathInfoMsgs.add(tripPathInfoMsg); + priceSum += tripPathInfoMsg.pathInfo().price(); + } + return new TripPathCalculationResult(priceSum, pathInfoMsgs); + } diff --git a/src/main/java/org/tenten/tentenstomp/global/component/dto/request/TripPlace.java b/src/main/java/org/tenten/tentenstomp/global/component/dto/request/TripPlace.java index a22f361..239e3a3 100644 --- a/src/main/java/org/tenten/tentenstomp/global/component/dto/request/TripPlace.java +++ b/src/main/java/org/tenten/tentenstomp/global/component/dto/request/TripPlace.java @@ -1,11 +1,19 @@ package org.tenten.tentenstomp.global.component.dto.request; +import org.tenten.tentenstomp.domain.trip.entity.TripItem; import org.tenten.tentenstomp.global.common.enums.Transportation; +import java.util.ArrayList; +import java.util.List; + public record TripPlace( Long seqNum, Transportation transportation, String longitude, - String latitude + String latitude, + Long price ) { + public static List fromTripItems(List tripItems) { + return tripItems.stream().map(t -> new TripPlace(t.getSeqNum(), t.getTransportation(), t.getTourItem().getLongitude(), t.getTourItem().getLatitude(), t.getPrice())).toList(); + } } diff --git a/src/main/java/org/tenten/tentenstomp/global/component/dto/response/TripPathCalculationResult.java b/src/main/java/org/tenten/tentenstomp/global/component/dto/response/TripPathCalculationResult.java new file mode 100644 index 0000000..e4bf4d6 --- /dev/null +++ b/src/main/java/org/tenten/tentenstomp/global/component/dto/response/TripPathCalculationResult.java @@ -0,0 +1,11 @@ +package org.tenten.tentenstomp.global.component.dto.response; + +import org.tenten.tentenstomp.domain.trip.dto.response.TripPathInfoMsg; + +import java.util.List; + +public record TripPathCalculationResult( + Long pathPriceSum, + List tripPathInfoMsgs +) { +} diff --git a/src/main/java/org/tenten/tentenstomp/global/converter/MapConverter.java b/src/main/java/org/tenten/tentenstomp/global/converter/MapConverter.java new file mode 100644 index 0000000..0dbf2a1 --- /dev/null +++ b/src/main/java/org/tenten/tentenstomp/global/converter/MapConverter.java @@ -0,0 +1,42 @@ +package org.tenten.tentenstomp.global.converter; + +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.persistence.AttributeConverter; +import jakarta.persistence.Converter; +import org.springframework.util.ObjectUtils; +import org.springframework.util.StringUtils; + +import java.util.Map; + +@Converter +public class MapConverter implements AttributeConverter { + protected final ObjectMapper objectMapper; + + public MapConverter() { + this.objectMapper = new ObjectMapper(); + } + + @Override + public String convertToDatabaseColumn(Map map) { + if (ObjectUtils.isEmpty(map)) { + return null; + } + try { + return objectMapper.writeValueAsString(map); // 3 + } catch (Exception e) { + throw new RuntimeException(e); + } } + + @Override + public Map convertToEntityAttribute(String s) { + + if (StringUtils.hasText(s)) { + try { + return objectMapper.readValue(s, Map.class); // 5 + } catch (Exception e) { + throw new RuntimeException(e); + } + } + return null; + } +} From bd3026b8fa7dadec2e51d332982dc2e141ebeb51 Mon Sep 17 00:00:00 2001 From: Kim-Dong-Jun99 Date: Wed, 10 Jan 2024 00:29:47 +0900 Subject: [PATCH 4/5] =?UTF-8?q?Chore=20:=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EC=BD=94=EB=93=9C=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/tour/repository/TourItemRepository.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/main/java/org/tenten/tentenstomp/domain/tour/repository/TourItemRepository.java b/src/main/java/org/tenten/tentenstomp/domain/tour/repository/TourItemRepository.java index 1bdaa65..d26048f 100644 --- a/src/main/java/org/tenten/tentenstomp/domain/tour/repository/TourItemRepository.java +++ b/src/main/java/org/tenten/tentenstomp/domain/tour/repository/TourItemRepository.java @@ -1,14 +1,7 @@ package org.tenten.tentenstomp.domain.tour.repository; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; import org.tenten.tentenstomp.domain.tour.entity.TourItem; -import java.util.List; -import java.util.Map; - public interface TourItemRepository extends JpaRepository { - @Query("SELECT ti FROM TourItem ti WHERE ti.id in :tourItemIds ORDER BY ti.id ASC") - public List findTourItemByTourItemIds(@Param("tourItems") List tourItemIds); } From 08fb4378088b38c889254d33ff59426e53a31f6d Mon Sep 17 00:00:00 2001 From: Kim-Dong-Jun99 Date: Wed, 10 Jan 2024 15:40:30 +0900 Subject: [PATCH 5/5] =?UTF-8?q?Feat=20:=20STOMP=201=EC=B0=A8=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .http/NaverMap.http | 2 +- .http/Odsay.http | 7 +++++++ .json/AddTripItems.json | 8 +++++++ .json/GetPathAndItems.json | 3 +++ .json/TripItemPriceUpdateMsg.json | 3 +++ .json/TripItemTransportationUpdateMsg.json | 3 +++ .json/TripItemVistDateUpdateMsg.json | 3 +++ .json/UpdateTripItemOrder.json | 21 +++++++++++++++++++ .../trip/dto/response/TripPathInfoMsg.java | 2 +- .../tentenstomp/domain/trip/entity/Trip.java | 6 +++--- .../trip/repository/TripRepository.java | 6 ++++++ .../domain/trip/service/TripItemService.java | 19 +++++++---------- .../domain/trip/service/TripService.java | 10 +++++---- .../global/component/NaverMapComponent.java | 9 ++++---- .../global/component/OdsayComponent.java | 7 +++---- .../global/component/PathComponent.java | 12 +++++------ .../response/TripPathCalculationResult.java | 2 +- .../global/converter/MapConverter.java | 6 +++--- 18 files changed, 91 insertions(+), 38 deletions(-) create mode 100644 .json/AddTripItems.json create mode 100644 .json/GetPathAndItems.json create mode 100644 .json/TripItemPriceUpdateMsg.json create mode 100644 .json/TripItemTransportationUpdateMsg.json create mode 100644 .json/TripItemVistDateUpdateMsg.json create mode 100644 .json/UpdateTripItemOrder.json diff --git a/.http/NaverMap.http b/.http/NaverMap.http index 2f8a54f..187f53b 100644 --- a/.http/NaverMap.http +++ b/.http/NaverMap.http @@ -5,6 +5,6 @@ X-NCP-APIGW-API-KEY: {{naver-map-client-secret}} ### 자동차 경로 계산 api -GET https://naveropenapi.apigw.ntruss.com/map-direction-15/v1/driving?start=127.1058342,37.359708&goal=126.9284261,37.5258975 +GET https://naveropenapi.apigw.ntruss.com/map-direction-15/v1/driving?start=128.5175868107,36.5376537450&goal=128.5163479914,36.5390674494 X-NCP-APIGW-API-KEY-ID: {{naver-map-client-id}} X-NCP-APIGW-API-KEY: {{naver-map-client-secret}} \ No newline at end of file diff --git a/.http/Odsay.http b/.http/Odsay.http index dbc5446..4bcb3ad 100644 --- a/.http/Odsay.http +++ b/.http/Odsay.http @@ -11,3 +11,10 @@ Origin: https://weplanplans.site GET https://api.odsay.com/v1/api/searchPubTransPathT?apiKey={{odsay-key}}&SX=127.1051573&SY=37.3718141&EX=227.124206&EY=37.495701 Origin: https://weplanplans.site +### 대중교통 길 찾기 +GET https://api.odsay.com/v1/api/searchPubTransPathT?apiKey={{odsay-key}}&SX=128.5163479914&SY=36.5390674494&EX=128.5163479914&EY=36.5390674494 +Origin: https://weplanplans.site + +### 대중교통 길 찾기 +GET https://api.odsay.com/v1/api/searchPubTransPathT?apiKey={{odsay-key}}&SX=128.5163479914&SY=36.5390674494&EX=128.3383767680&EY=38.0731872541 +Origin: https://weplanplans.site \ No newline at end of file diff --git a/.json/AddTripItems.json b/.json/AddTripItems.json new file mode 100644 index 0000000..7adb6e7 --- /dev/null +++ b/.json/AddTripItems.json @@ -0,0 +1,8 @@ +{ + "visitDate": "2024-01-04", + "newTripItems": [ + { + "tourItemId": 72 + } + ] +} \ No newline at end of file diff --git a/.json/GetPathAndItems.json b/.json/GetPathAndItems.json new file mode 100644 index 0000000..874f2ef --- /dev/null +++ b/.json/GetPathAndItems.json @@ -0,0 +1,3 @@ +{ + "visitDate": "2024-01-03" +} \ No newline at end of file diff --git a/.json/TripItemPriceUpdateMsg.json b/.json/TripItemPriceUpdateMsg.json new file mode 100644 index 0000000..14d023f --- /dev/null +++ b/.json/TripItemPriceUpdateMsg.json @@ -0,0 +1,3 @@ +{ + "price": 50000 +} \ No newline at end of file diff --git a/.json/TripItemTransportationUpdateMsg.json b/.json/TripItemTransportationUpdateMsg.json new file mode 100644 index 0000000..8838697 --- /dev/null +++ b/.json/TripItemTransportationUpdateMsg.json @@ -0,0 +1,3 @@ +{ + "transportation": "CAR" +} \ No newline at end of file diff --git a/.json/TripItemVistDateUpdateMsg.json b/.json/TripItemVistDateUpdateMsg.json new file mode 100644 index 0000000..3cad74e --- /dev/null +++ b/.json/TripItemVistDateUpdateMsg.json @@ -0,0 +1,3 @@ +{ + "visitDate": "2024-01-04" +} \ No newline at end of file diff --git a/.json/UpdateTripItemOrder.json b/.json/UpdateTripItemOrder.json new file mode 100644 index 0000000..d33b99a --- /dev/null +++ b/.json/UpdateTripItemOrder.json @@ -0,0 +1,21 @@ +{ + "visitDate": "2024-01-03", + "tripItemOrder": [ + { + "tripItemId": 1, + "seqNum": 3 + }, + { + "tripItemId": 3, + "seqNum": 4 + }, + { + "tripItemId": 4, + "seqNum": 1 + }, + { + "tripItemId": 6, + "seqNum": 2 + } + ] +} \ No newline at end of file diff --git a/src/main/java/org/tenten/tentenstomp/domain/trip/dto/response/TripPathInfoMsg.java b/src/main/java/org/tenten/tentenstomp/domain/trip/dto/response/TripPathInfoMsg.java index daa826b..19489a4 100644 --- a/src/main/java/org/tenten/tentenstomp/domain/trip/dto/response/TripPathInfoMsg.java +++ b/src/main/java/org/tenten/tentenstomp/domain/trip/dto/response/TripPathInfoMsg.java @@ -14,7 +14,7 @@ public record TripPathInfoMsg( ) { public record PathInfo( - Long price, + Integer price, Double totalDistance, Long totalTime ){} diff --git a/src/main/java/org/tenten/tentenstomp/domain/trip/entity/Trip.java b/src/main/java/org/tenten/tentenstomp/domain/trip/entity/Trip.java index 182d058..53738fe 100644 --- a/src/main/java/org/tenten/tentenstomp/domain/trip/entity/Trip.java +++ b/src/main/java/org/tenten/tentenstomp/domain/trip/entity/Trip.java @@ -47,10 +47,10 @@ public class Trip extends BaseTimeEntity { @ColumnDefault("0") private Long tripItemPriceSum; @ColumnDefault("0") - private Long transportationPriceSum; + private Integer transportationPriceSum; @Convert(converter = MapConverter.class) @Column(columnDefinition = "JSON") - private Map tripPathPriceMap; + private Map tripPathPriceMap; @OneToMany(mappedBy = "trip", fetch = LAZY, cascade = REMOVE) private final List tripMembers = new ArrayList<>(); @@ -80,7 +80,7 @@ public TripInfoMsg toTripInfo() { this.getArea(), this.getSubarea(), this.getBudget()); } - public void updateTransportationPriceSum(Long oldVisitDateTransportationPriceSum, Long newVisitDateTransportationPriceSum) { + public void updateTransportationPriceSum(Integer oldVisitDateTransportationPriceSum, Integer newVisitDateTransportationPriceSum) { this.transportationPriceSum -= oldVisitDateTransportationPriceSum; this.transportationPriceSum += newVisitDateTransportationPriceSum; } diff --git a/src/main/java/org/tenten/tentenstomp/domain/trip/repository/TripRepository.java b/src/main/java/org/tenten/tentenstomp/domain/trip/repository/TripRepository.java index f008fbd..d0a85c2 100644 --- a/src/main/java/org/tenten/tentenstomp/domain/trip/repository/TripRepository.java +++ b/src/main/java/org/tenten/tentenstomp/domain/trip/repository/TripRepository.java @@ -1,7 +1,13 @@ package org.tenten.tentenstomp.domain.trip.repository; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.tenten.tentenstomp.domain.trip.entity.Trip; +import java.util.Optional; + public interface TripRepository extends JpaRepository { + @Query("SELECT t FROM Trip t JOIN FETCH t.tripItems WHERE t.id = :tripId") + Optional findTripByTripId(@Param("tripId") Long tripId); } diff --git a/src/main/java/org/tenten/tentenstomp/domain/trip/service/TripItemService.java b/src/main/java/org/tenten/tentenstomp/domain/trip/service/TripItemService.java index 2bba0fa..2b741b8 100644 --- a/src/main/java/org/tenten/tentenstomp/domain/trip/service/TripItemService.java +++ b/src/main/java/org/tenten/tentenstomp/domain/trip/service/TripItemService.java @@ -17,8 +17,6 @@ import org.tenten.tentenstomp.global.component.dto.response.TripPathCalculationResult; import org.tenten.tentenstomp.global.exception.GlobalException; import org.tenten.tentenstomp.global.messaging.kafka.producer.KafkaProducer; -import org.tenten.tentenstomp.global.messaging.redis.publisher.RedisPublisher; -import org.tenten.tentenstomp.global.util.RedisChannelUtil; import java.time.LocalDate; import java.util.ArrayList; @@ -27,7 +25,6 @@ import static org.springframework.http.HttpStatus.NOT_FOUND; import static org.tenten.tentenstomp.global.common.constant.TopicConstant.*; -import static org.tenten.tentenstomp.global.common.constant.TopicConstant.BUDGET; @Service @RequiredArgsConstructor @@ -61,7 +58,7 @@ public void updateTripItemVisitDate(String tripItemId, TripItemVisitDateUpdateMs List newDateTripItems = tripItemRepository.findTripItemByTripIdAndVisitDate(tripItem.getTrip().getId(), newDate); Long oldSeqNum = tripItem.getSeqNum(); - Long newSeqNum = (long) newDateTripItems.size(); + Long newSeqNum = (long) newDateTripItems.size()+1; List newPastDateTripItems = new ArrayList<>(); for (TripItem pastDateTripItem : pastDateTripItems) { if (pastDateTripItem.getId().equals(tripItem.getId())) { @@ -80,9 +77,9 @@ public void updateTripItemVisitDate(String tripItemId, TripItemVisitDateUpdateMs TripPathCalculationResult pastDateTripPath = pathComponent.getTripPath(TripPlace.fromTripItems(newPastDateTripItems)); TripPathCalculationResult newDateTripPath = pathComponent.getTripPath(TripPlace.fromTripItems(newDateTripItems)); - Map tripPathPriceMap = trip.getTripPathPriceMap(); - trip.updateTransportationPriceSum(tripPathPriceMap.getOrDefault(pastDate.toString(), 0L), pastDateTripPath.pathPriceSum()); - trip.updateTransportationPriceSum(tripPathPriceMap.getOrDefault(newDate.toString(), 0L), newDateTripPath.pathPriceSum()); + Map tripPathPriceMap = trip.getTripPathPriceMap(); + trip.updateTransportationPriceSum(tripPathPriceMap.getOrDefault(pastDate.toString(), 0), pastDateTripPath.pathPriceSum()); + trip.updateTransportationPriceSum(tripPathPriceMap.getOrDefault(newDate.toString(), 0), newDateTripPath.pathPriceSum()); tripPathPriceMap.put(pastDate.toString(), pastDateTripPath.pathPriceSum()); tripPathPriceMap.put(newDate.toString(), newDateTripPath.pathPriceSum()); tripRepository.save(trip); @@ -118,8 +115,8 @@ public void deleteTripItem(String tripItemId) { tripItemRepository.delete(tripItem); TripPathCalculationResult tripPath = pathComponent.getTripPath(TripPlace.fromTripItems(newTripItems)); - Map tripPathPriceMap = trip.getTripPathPriceMap(); - trip.updateTransportationPriceSum(tripPathPriceMap.getOrDefault(visitDate.toString(), 0L), tripPath.pathPriceSum()); + Map tripPathPriceMap = trip.getTripPathPriceMap(); + trip.updateTransportationPriceSum(tripPathPriceMap.getOrDefault(visitDate.toString(), 0), tripPath.pathPriceSum()); tripPathPriceMap.put(visitDate.toString(), tripPath.pathPriceSum()); tripRepository.save(trip); @@ -147,8 +144,8 @@ public void updateTripItemTransportation(String tripItemId, TripItemTransportati tripItemRepository.save(tripItem); TripPathCalculationResult tripPath = pathComponent.getTripPath(TripPlace.fromTripItems(tripItems)); - Map tripPathPriceMap = trip.getTripPathPriceMap(); - trip.updateTransportationPriceSum(tripPathPriceMap.getOrDefault(visitDate.toString(), 0L), tripPath.pathPriceSum()); + Map tripPathPriceMap = trip.getTripPathPriceMap(); + trip.updateTransportationPriceSum(tripPathPriceMap.getOrDefault(visitDate.toString(), 0), tripPath.pathPriceSum()); tripPathPriceMap.put(visitDate.toString(), tripPath.pathPriceSum()); tripRepository.save(trip); diff --git a/src/main/java/org/tenten/tentenstomp/domain/trip/service/TripService.java b/src/main/java/org/tenten/tentenstomp/domain/trip/service/TripService.java index 664807a..17487d4 100644 --- a/src/main/java/org/tenten/tentenstomp/domain/trip/service/TripService.java +++ b/src/main/java/org/tenten/tentenstomp/domain/trip/service/TripService.java @@ -19,11 +19,13 @@ import org.tenten.tentenstomp.global.component.PathComponent; import org.tenten.tentenstomp.global.component.dto.request.TripPlace; import org.tenten.tentenstomp.global.component.dto.response.TripPathCalculationResult; +import org.tenten.tentenstomp.global.exception.GlobalException; import org.tenten.tentenstomp.global.messaging.kafka.producer.KafkaProducer; import java.time.LocalDate; import java.util.*; +import static org.springframework.http.HttpStatus.NOT_FOUND; import static org.tenten.tentenstomp.global.common.constant.TopicConstant.*; @Service @@ -112,8 +114,8 @@ public void addTripItem(String tripId, TripItemAddMsg tripItemAddMsg) { private void updateBudgetAndItemsAndPath(Trip trip, List tripItems, String visitDate) { TripPathCalculationResult tripPath = pathComponent.getTripPath(TripPlace.fromTripItems(tripItems)); - Map tripPathPriceMap = trip.getTripPathPriceMap(); - trip.updateTransportationPriceSum(tripPathPriceMap.getOrDefault(visitDate, 0L), tripPath.pathPriceSum()); + Map tripPathPriceMap = trip.getTripPathPriceMap(); + trip.updateTransportationPriceSum(tripPathPriceMap.getOrDefault(visitDate, 0), tripPath.pathPriceSum()); tripPathPriceMap.put(visitDate, tripPath.pathPriceSum()); tripRepository.save(trip); @@ -126,7 +128,7 @@ private void updateBudgetAndItemsAndPath(Trip trip, List tripItems, St @Transactional public void updateTripItemOrder(String tripId, TripItemOrderUpdateMsg orderUpdateMsg) { - Trip trip = tripRepository.getReferenceById(Long.parseLong(tripId)); + Trip trip = tripRepository.findTripByTripId(Long.parseLong(tripId)).orElseThrow(() -> new GlobalException("해당 아이디로 존재하는 여정이 없습니다 " + tripId, NOT_FOUND)); Map itemOrderMap = new HashMap<>(); for (OrderInfo orderInfo : orderUpdateMsg.tripItemOrder()) { itemOrderMap.put(orderInfo.tripItemId(), orderInfo.seqNum()); @@ -180,7 +182,7 @@ private void sendToKafkaAndSave(Object... dataArgs) { private TripMemberMsg getTripMemberMsg(String tripId) { Object cached = redisCache.get(MEMBER, tripId); if (cached != null) { - return (TripMemberMsg) cached; + return objectMapper.convertValue(cached, TripMemberMsg.class); } HashMap connectedMemberMap = tripConnectedMemberMap.getOrDefault(tripId, new HashMap<>()); TripMemberMsg tripMemberMsg = new TripMemberMsg( diff --git a/src/main/java/org/tenten/tentenstomp/global/component/NaverMapComponent.java b/src/main/java/org/tenten/tentenstomp/global/component/NaverMapComponent.java index 354bc88..f699661 100644 --- a/src/main/java/org/tenten/tentenstomp/global/component/NaverMapComponent.java +++ b/src/main/java/org/tenten/tentenstomp/global/component/NaverMapComponent.java @@ -6,12 +6,13 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.*; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.UriComponents; import org.springframework.web.util.UriComponentsBuilder; -import org.tenten.tentenstomp.domain.trip.dto.response.TripPathInfoMsg; import org.tenten.tentenstomp.global.exception.GlobalException; import java.util.List; @@ -19,7 +20,7 @@ import static org.springframework.http.HttpMethod.GET; import static org.springframework.http.HttpStatus.CONFLICT; -import static org.tenten.tentenstomp.domain.trip.dto.response.TripPathInfoMsg.*; +import static org.tenten.tentenstomp.domain.trip.dto.response.TripPathInfoMsg.PathInfo; import static org.tenten.tentenstomp.global.common.constant.NaverMapConstant.NAVER_MAP_API_KEY_HEADER; import static org.tenten.tentenstomp.global.common.constant.NaverMapConstant.NAVER_MAP_CLIENT_ID_HEADER; @@ -69,7 +70,7 @@ public PathInfo calculatePathInfo(String fromLongitude, Integer fuelPrice = (Integer) summary.get("fuelPrice"); Integer distance = (Integer) summary.get("distance"); Integer duration = (Integer) summary.get("duration"); - return new PathInfo((long) duration / 60_000 , (double) distance, (long)tollFare + fuelPrice); + return new PathInfo(tollFare + fuelPrice , (double) distance, (long) duration / 60_000); } else { throw new GlobalException("자동차 경로를 조회할 수 없습니다.", CONFLICT); } diff --git a/src/main/java/org/tenten/tentenstomp/global/component/OdsayComponent.java b/src/main/java/org/tenten/tentenstomp/global/component/OdsayComponent.java index 4c232d1..a5befda 100644 --- a/src/main/java/org/tenten/tentenstomp/global/component/OdsayComponent.java +++ b/src/main/java/org/tenten/tentenstomp/global/component/OdsayComponent.java @@ -13,7 +13,6 @@ import org.springframework.web.client.RestTemplate; import org.springframework.web.util.UriComponents; import org.springframework.web.util.UriComponentsBuilder; -import org.tenten.tentenstomp.domain.trip.dto.response.TripPathInfoMsg; import org.tenten.tentenstomp.domain.trip.dto.response.TripPathInfoMsg.PathInfo; import org.tenten.tentenstomp.global.exception.GlobalException; @@ -56,10 +55,10 @@ public PathInfo calculatePathInfo(String fromLongitude, List> pathList = (List>) resultMap.get("path"); Map path = pathList.get(0); Map pathInfo = (Map) path.get("info"); - Integer payment = (Integer) pathInfo.get("payment"); - Double distance = (Double) pathInfo.get("totalDistance"); + Integer payment = (Integer) pathInfo.get("totalPayment"); + Double distance = Double.valueOf(Integer.toString((Integer) pathInfo.get("totalDistance"))); Integer totalTime = (Integer) pathInfo.get("totalTime"); - return new PathInfo((long) totalTime, distance, (long) payment); + return new PathInfo( payment, distance, (long) totalTime); } else { throw new GlobalException("대중교통 경로를 조회할 수 없습니다.", CONFLICT); } diff --git a/src/main/java/org/tenten/tentenstomp/global/component/PathComponent.java b/src/main/java/org/tenten/tentenstomp/global/component/PathComponent.java index ce375ca..89f0d67 100644 --- a/src/main/java/org/tenten/tentenstomp/global/component/PathComponent.java +++ b/src/main/java/org/tenten/tentenstomp/global/component/PathComponent.java @@ -2,18 +2,16 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; import org.tenten.tentenstomp.domain.trip.dto.response.TripPathInfoMsg; import org.tenten.tentenstomp.domain.trip.dto.response.TripPathInfoMsg.PathInfo; import org.tenten.tentenstomp.global.common.annotation.GetExecutionTime; -import org.tenten.tentenstomp.global.component.dto.request.TripPlace; import org.tenten.tentenstomp.global.component.dto.request.PathCalculateRequest; +import org.tenten.tentenstomp.global.component.dto.request.TripPlace; import org.tenten.tentenstomp.global.component.dto.response.TripPathCalculationResult; import java.util.ArrayList; import java.util.List; -import java.util.stream.Stream; import static org.tenten.tentenstomp.global.common.enums.Transportation.CAR; @@ -23,7 +21,7 @@ public class PathComponent { private final OdsayComponent odsayComponent; private final NaverMapComponent naverMapComponent; - @Async +// @Async public TripPathInfoMsg calculatePath(TripPlace fromPlace, TripPlace toPlace) { long startTime = System.currentTimeMillis(); PathInfo pathInfo; @@ -38,12 +36,14 @@ public TripPathInfoMsg calculatePath(TripPlace fromPlace, TripPlace toPlace) { @GetExecutionTime public TripPathCalculationResult getTripPath(List tripPlaceList) { List pathCalculateRequests = toPathCalculateRequest(tripPlaceList); - long priceSum = 0L; + int priceSum = 0; List pathInfoMsgs = new ArrayList<>(); for (PathCalculateRequest calculateRequest : pathCalculateRequests) { TripPathInfoMsg tripPathInfoMsg = calculatePath(calculateRequest.from(), calculateRequest.to()); pathInfoMsgs.add(tripPathInfoMsg); - priceSum += tripPathInfoMsg.pathInfo().price(); + if (tripPathInfoMsg.pathInfo() != null) { + priceSum += tripPathInfoMsg.pathInfo().price(); + } } return new TripPathCalculationResult(priceSum, pathInfoMsgs); diff --git a/src/main/java/org/tenten/tentenstomp/global/component/dto/response/TripPathCalculationResult.java b/src/main/java/org/tenten/tentenstomp/global/component/dto/response/TripPathCalculationResult.java index e4bf4d6..09059ee 100644 --- a/src/main/java/org/tenten/tentenstomp/global/component/dto/response/TripPathCalculationResult.java +++ b/src/main/java/org/tenten/tentenstomp/global/component/dto/response/TripPathCalculationResult.java @@ -5,7 +5,7 @@ import java.util.List; public record TripPathCalculationResult( - Long pathPriceSum, + Integer pathPriceSum, List tripPathInfoMsgs ) { } diff --git a/src/main/java/org/tenten/tentenstomp/global/converter/MapConverter.java b/src/main/java/org/tenten/tentenstomp/global/converter/MapConverter.java index 0dbf2a1..2294e41 100644 --- a/src/main/java/org/tenten/tentenstomp/global/converter/MapConverter.java +++ b/src/main/java/org/tenten/tentenstomp/global/converter/MapConverter.java @@ -9,7 +9,7 @@ import java.util.Map; @Converter -public class MapConverter implements AttributeConverter { +public class MapConverter implements AttributeConverter, String> { protected final ObjectMapper objectMapper; public MapConverter() { @@ -28,11 +28,11 @@ public String convertToDatabaseColumn(Map map) { } } @Override - public Map convertToEntityAttribute(String s) { + public Map convertToEntityAttribute(String s) { if (StringUtils.hasText(s)) { try { - return objectMapper.readValue(s, Map.class); // 5 + return (Map) objectMapper.readValue(s, Map.class); // 5 } catch (Exception e) { throw new RuntimeException(e); }