From 9c842efa7d69296add57e6eaa7732d9696ee2b24 Mon Sep 17 00:00:00 2001 From: JunsuPark Date: Sun, 18 Aug 2024 15:21:11 +0900 Subject: [PATCH] =?UTF-8?q?feat=20:=20=ED=8B=B0=EC=BC=93=ED=8C=85=20?= =?UTF-8?q?=EC=95=8C=EB=A6=BC=20=EC=98=88=EC=95=BD=20=EA=B5=AC=EB=8F=85=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20(#8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/build.gradle | 2 + .../example/config/SubscriptionApiConfig.java | 48 +++++++------- ...java => SubscriptionMessageConverter.java} | 2 +- ....java => RegisterShowMessageListener.java} | 8 +-- ...=> SubscriptionArtistMessageListener.java} | 8 +-- ... => SubscriptionGenreMessageListener.java} | 8 +-- ... UnsubscriptionArtistMessageListener.java} | 8 +-- ...> UnsubscriptionGenreMessageListener.java} | 8 +-- ...er.java => UpdateShowMessageListener.java} | 8 +-- app/api/ticketing-api/build.gradle | 4 ++ .../example/config/TicketingApiConfig.java | 36 ++++++++++- .../converter/TicketingMessageConverter.java | 33 ++++++++++ .../TicketingAlertMessageListener.java | 23 +++++++ ...TicketingReservationMessageApiRequest.java | 26 ++++++++ .../service/TicketingAlertService.java | 20 ++++++ ...etingReservationMessageServiceRequest.java | 25 ++++++++ ...ketingReservationMessageDomainRequest.java | 16 +++++ .../org/example/entity/TicketingAlert.java | 13 +++- .../TicketingAlertRepository.java | 5 ++ .../usecase/TicketingAlertUseCase.java | 62 +++++++++++++++++++ 20 files changed, 311 insertions(+), 52 deletions(-) rename app/api/subscription-api/src/main/java/org/example/converter/{MessageConverter.java => SubscriptionMessageConverter.java} (98%) rename app/api/subscription-api/src/main/java/org/example/listener/{UpdateShowMessageLister.java => RegisterShowMessageListener.java} (70%) rename app/api/subscription-api/src/main/java/org/example/listener/{SubscriptionArtistMessageLister.java => SubscriptionArtistMessageListener.java} (69%) rename app/api/subscription-api/src/main/java/org/example/listener/{SubscriptionGenreMessageLister.java => SubscriptionGenreMessageListener.java} (69%) rename app/api/subscription-api/src/main/java/org/example/listener/{UnsubscriptionArtistMessageLister.java => UnsubscriptionArtistMessageListener.java} (69%) rename app/api/subscription-api/src/main/java/org/example/listener/{UnsubscriptionGenreMessageLister.java => UnsubscriptionGenreMessageListener.java} (69%) rename app/api/subscription-api/src/main/java/org/example/listener/{RegisterShowMessageLister.java => UpdateShowMessageListener.java} (70%) create mode 100644 app/api/ticketing-api/src/main/java/org/example/converter/TicketingMessageConverter.java create mode 100644 app/api/ticketing-api/src/main/java/org/example/listener/TicketingAlertMessageListener.java create mode 100644 app/api/ticketing-api/src/main/java/org/example/listener/dto/TicketingReservationMessageApiRequest.java create mode 100644 app/api/ticketing-api/src/main/java/org/example/service/TicketingAlertService.java create mode 100644 app/api/ticketing-api/src/main/java/org/example/service/dto/request/TicketingReservationMessageServiceRequest.java create mode 100644 app/domain/ticketing-domain/src/main/java/org/example/dto/request/TicketingReservationMessageDomainRequest.java create mode 100644 app/domain/ticketing-domain/src/main/java/org/example/usecase/TicketingAlertUseCase.java diff --git a/app/api/build.gradle b/app/api/build.gradle index ff1de09..8a531b0 100644 --- a/app/api/build.gradle +++ b/app/api/build.gradle @@ -3,6 +3,8 @@ allprojects { jar.enabled = true dependencies { + implementation project(":app:domain:common-domain") + implementation 'org.springframework.data:spring-data-commons:3.3.0' implementation "org.springframework.boot:spring-boot-starter-web" diff --git a/app/api/subscription-api/src/main/java/org/example/config/SubscriptionApiConfig.java b/app/api/subscription-api/src/main/java/org/example/config/SubscriptionApiConfig.java index 814d7d5..ee209b6 100644 --- a/app/api/subscription-api/src/main/java/org/example/config/SubscriptionApiConfig.java +++ b/app/api/subscription-api/src/main/java/org/example/config/SubscriptionApiConfig.java @@ -1,12 +1,12 @@ package org.example.config; import lombok.RequiredArgsConstructor; -import org.example.listener.RegisterShowMessageLister; -import org.example.listener.SubscriptionArtistMessageLister; -import org.example.listener.SubscriptionGenreMessageLister; -import org.example.listener.UnsubscriptionArtistMessageLister; -import org.example.listener.UnsubscriptionGenreMessageLister; -import org.example.listener.UpdateShowMessageLister; +import org.example.listener.RegisterShowMessageListener; +import org.example.listener.SubscriptionArtistMessageListener; +import org.example.listener.SubscriptionGenreMessageListener; +import org.example.listener.UnsubscriptionArtistMessageListener; +import org.example.listener.UnsubscriptionGenreMessageListener; +import org.example.listener.UpdateShowMessageListener; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @@ -21,52 +21,52 @@ @Import({ SubscriptionDomainConfig.class, PubSubConfig.class, - RegisterShowMessageLister.class, - UpdateShowMessageLister.class, - SubscriptionArtistMessageLister.class, - UnsubscriptionArtistMessageLister.class, - SubscriptionGenreMessageLister.class, - UnsubscriptionGenreMessageLister.class + RegisterShowMessageListener.class, + UpdateShowMessageListener.class, + SubscriptionArtistMessageListener.class, + UnsubscriptionArtistMessageListener.class, + SubscriptionGenreMessageListener.class, + UnsubscriptionGenreMessageListener.class }) @ComponentScan(basePackages = "org.example") @RequiredArgsConstructor public class SubscriptionApiConfig { - private final MessageListener registerShowMessageLister; - private final MessageListener updateShowMessageLister; - private final MessageListener subscriptionArtistMessageLister; - private final MessageListener unsubscriptionArtistMessageLister; - private final MessageListener subscriptionGenreMessageLister; - private final MessageListener unsubscriptionGenreMessageLister; + private final MessageListener registerShowMessageListener; + private final MessageListener updateShowMessageListener; + private final MessageListener subscriptionArtistMessageListener; + private final MessageListener unsubscriptionArtistMessageListener; + private final MessageListener subscriptionGenreMessageListener; + private final MessageListener unsubscriptionGenreMessageListener; @Bean MessageListenerAdapter registerShowMessageListenerAdapter() { - return new MessageListenerAdapter(registerShowMessageLister); + return new MessageListenerAdapter(registerShowMessageListener); } @Bean MessageListenerAdapter updateShowMessageListenerAdapter() { - return new MessageListenerAdapter(updateShowMessageLister); + return new MessageListenerAdapter(updateShowMessageListener); } @Bean MessageListenerAdapter subscriptionArtistMessageListerAdapter() { - return new MessageListenerAdapter(subscriptionArtistMessageLister); + return new MessageListenerAdapter(subscriptionArtistMessageListener); } @Bean MessageListenerAdapter unsubscriptionArtistMessageListerAdapter() { - return new MessageListenerAdapter(unsubscriptionArtistMessageLister); + return new MessageListenerAdapter(unsubscriptionArtistMessageListener); } @Bean MessageListenerAdapter subscriptionGenreMessageListerAdapter() { - return new MessageListenerAdapter(subscriptionGenreMessageLister); + return new MessageListenerAdapter(subscriptionGenreMessageListener); } @Bean MessageListenerAdapter unsubscriptionGenreMessageListerAdapter() { - return new MessageListenerAdapter(unsubscriptionGenreMessageLister); + return new MessageListenerAdapter(unsubscriptionGenreMessageListener); } @Bean diff --git a/app/api/subscription-api/src/main/java/org/example/converter/MessageConverter.java b/app/api/subscription-api/src/main/java/org/example/converter/SubscriptionMessageConverter.java similarity index 98% rename from app/api/subscription-api/src/main/java/org/example/converter/MessageConverter.java rename to app/api/subscription-api/src/main/java/org/example/converter/SubscriptionMessageConverter.java index dd1265e..1601fab 100644 --- a/app/api/subscription-api/src/main/java/org/example/converter/MessageConverter.java +++ b/app/api/subscription-api/src/main/java/org/example/converter/SubscriptionMessageConverter.java @@ -9,7 +9,7 @@ import org.springframework.data.redis.connection.Message; @Slf4j -public class MessageConverter { +public class SubscriptionMessageConverter { private static final ObjectMapper objectMapper = new ObjectMapper(); diff --git a/app/api/subscription-api/src/main/java/org/example/listener/UpdateShowMessageLister.java b/app/api/subscription-api/src/main/java/org/example/listener/RegisterShowMessageListener.java similarity index 70% rename from app/api/subscription-api/src/main/java/org/example/listener/UpdateShowMessageLister.java rename to app/api/subscription-api/src/main/java/org/example/listener/RegisterShowMessageListener.java index c6c7417..dee5921 100644 --- a/app/api/subscription-api/src/main/java/org/example/listener/UpdateShowMessageLister.java +++ b/app/api/subscription-api/src/main/java/org/example/listener/RegisterShowMessageListener.java @@ -1,7 +1,7 @@ package org.example.listener; import lombok.RequiredArgsConstructor; -import org.example.converter.MessageConverter; +import org.example.converter.SubscriptionMessageConverter; import org.example.service.SubscriptionAlarmService; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.data.redis.connection.Message; @@ -10,14 +10,14 @@ @Controller @RequiredArgsConstructor -@Qualifier(value = "updateShowMessageLister") -public class UpdateShowMessageLister implements MessageListener { +@Qualifier(value = "registerShowMessageListener") +public class RegisterShowMessageListener implements MessageListener { private final SubscriptionAlarmService subscriptionAlarmService; @Override public void onMessage(Message message, byte[] pattern) { - var request = MessageConverter.toShowRelationSubscriptionMessage(message); + var request = SubscriptionMessageConverter.toShowRelationSubscriptionMessage(message); subscriptionAlarmService.showRelationSubscription(request.toServiceRequest()); } diff --git a/app/api/subscription-api/src/main/java/org/example/listener/SubscriptionArtistMessageLister.java b/app/api/subscription-api/src/main/java/org/example/listener/SubscriptionArtistMessageListener.java similarity index 69% rename from app/api/subscription-api/src/main/java/org/example/listener/SubscriptionArtistMessageLister.java rename to app/api/subscription-api/src/main/java/org/example/listener/SubscriptionArtistMessageListener.java index 80506fa..b62b3f1 100644 --- a/app/api/subscription-api/src/main/java/org/example/listener/SubscriptionArtistMessageLister.java +++ b/app/api/subscription-api/src/main/java/org/example/listener/SubscriptionArtistMessageListener.java @@ -1,7 +1,7 @@ package org.example.listener; import lombok.RequiredArgsConstructor; -import org.example.converter.MessageConverter; +import org.example.converter.SubscriptionMessageConverter; import org.example.service.SubscriptionAlarmService; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.data.redis.connection.Message; @@ -10,14 +10,14 @@ @Controller @RequiredArgsConstructor -@Qualifier(value = "subscriptionArtistMessageLister") -public class SubscriptionArtistMessageLister implements MessageListener { +@Qualifier(value = "subscriptionArtistMessageListener") +public class SubscriptionArtistMessageListener implements MessageListener { private final SubscriptionAlarmService subscriptionAlarmService; @Override public void onMessage(Message message, byte[] pattern) { - var request = MessageConverter.toArtistSubscriptionMessage(message); + var request = SubscriptionMessageConverter.toArtistSubscriptionMessage(message); subscriptionAlarmService.artistSubscribe(request.toServiceRequest()); } diff --git a/app/api/subscription-api/src/main/java/org/example/listener/SubscriptionGenreMessageLister.java b/app/api/subscription-api/src/main/java/org/example/listener/SubscriptionGenreMessageListener.java similarity index 69% rename from app/api/subscription-api/src/main/java/org/example/listener/SubscriptionGenreMessageLister.java rename to app/api/subscription-api/src/main/java/org/example/listener/SubscriptionGenreMessageListener.java index 8723768..18eb1af 100644 --- a/app/api/subscription-api/src/main/java/org/example/listener/SubscriptionGenreMessageLister.java +++ b/app/api/subscription-api/src/main/java/org/example/listener/SubscriptionGenreMessageListener.java @@ -1,7 +1,7 @@ package org.example.listener; import lombok.RequiredArgsConstructor; -import org.example.converter.MessageConverter; +import org.example.converter.SubscriptionMessageConverter; import org.example.service.SubscriptionAlarmService; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.data.redis.connection.Message; @@ -10,14 +10,14 @@ @Controller @RequiredArgsConstructor -@Qualifier(value = "subscriptionGenreMessageLister") -public class SubscriptionGenreMessageLister implements MessageListener { +@Qualifier(value = "subscriptionGenreMessageListener") +public class SubscriptionGenreMessageListener implements MessageListener { private final SubscriptionAlarmService subscriptionAlarmService; @Override public void onMessage(Message message, byte[] pattern) { - var request = MessageConverter.toGenreSubscriptionMessage(message); + var request = SubscriptionMessageConverter.toGenreSubscriptionMessage(message); subscriptionAlarmService.genreSubscribe(request.toServiceRequest()); } diff --git a/app/api/subscription-api/src/main/java/org/example/listener/UnsubscriptionArtistMessageLister.java b/app/api/subscription-api/src/main/java/org/example/listener/UnsubscriptionArtistMessageListener.java similarity index 69% rename from app/api/subscription-api/src/main/java/org/example/listener/UnsubscriptionArtistMessageLister.java rename to app/api/subscription-api/src/main/java/org/example/listener/UnsubscriptionArtistMessageListener.java index d5a086d..af1fe06 100644 --- a/app/api/subscription-api/src/main/java/org/example/listener/UnsubscriptionArtistMessageLister.java +++ b/app/api/subscription-api/src/main/java/org/example/listener/UnsubscriptionArtistMessageListener.java @@ -1,7 +1,7 @@ package org.example.listener; import lombok.RequiredArgsConstructor; -import org.example.converter.MessageConverter; +import org.example.converter.SubscriptionMessageConverter; import org.example.service.SubscriptionAlarmService; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.data.redis.connection.Message; @@ -10,14 +10,14 @@ @Controller @RequiredArgsConstructor -@Qualifier(value = "unsubscriptionArtistMessageLister") -public class UnsubscriptionArtistMessageLister implements MessageListener { +@Qualifier(value = "unsubscriptionArtistMessageListener") +public class UnsubscriptionArtistMessageListener implements MessageListener { private final SubscriptionAlarmService subscriptionAlarmService; @Override public void onMessage(Message message, byte[] pattern) { - var request = MessageConverter.toArtistSubscriptionMessage(message); + var request = SubscriptionMessageConverter.toArtistSubscriptionMessage(message); subscriptionAlarmService.artistUnsubscribe(request.toServiceRequest()); } diff --git a/app/api/subscription-api/src/main/java/org/example/listener/UnsubscriptionGenreMessageLister.java b/app/api/subscription-api/src/main/java/org/example/listener/UnsubscriptionGenreMessageListener.java similarity index 69% rename from app/api/subscription-api/src/main/java/org/example/listener/UnsubscriptionGenreMessageLister.java rename to app/api/subscription-api/src/main/java/org/example/listener/UnsubscriptionGenreMessageListener.java index b894dca..557a7f8 100644 --- a/app/api/subscription-api/src/main/java/org/example/listener/UnsubscriptionGenreMessageLister.java +++ b/app/api/subscription-api/src/main/java/org/example/listener/UnsubscriptionGenreMessageListener.java @@ -1,7 +1,7 @@ package org.example.listener; import lombok.RequiredArgsConstructor; -import org.example.converter.MessageConverter; +import org.example.converter.SubscriptionMessageConverter; import org.example.service.SubscriptionAlarmService; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.data.redis.connection.Message; @@ -10,14 +10,14 @@ @Controller @RequiredArgsConstructor -@Qualifier(value = "unsubscriptionGenreMessageLister") -public class UnsubscriptionGenreMessageLister implements MessageListener { +@Qualifier(value = "unsubscriptionGenreMessageListener") +public class UnsubscriptionGenreMessageListener implements MessageListener { private final SubscriptionAlarmService subscriptionAlarmService; @Override public void onMessage(Message message, byte[] pattern) { - var request = MessageConverter.toGenreSubscriptionMessage(message); + var request = SubscriptionMessageConverter.toGenreSubscriptionMessage(message); subscriptionAlarmService.genreUnsubscribe(request.toServiceRequest()); } diff --git a/app/api/subscription-api/src/main/java/org/example/listener/RegisterShowMessageLister.java b/app/api/subscription-api/src/main/java/org/example/listener/UpdateShowMessageListener.java similarity index 70% rename from app/api/subscription-api/src/main/java/org/example/listener/RegisterShowMessageLister.java rename to app/api/subscription-api/src/main/java/org/example/listener/UpdateShowMessageListener.java index 1c68553..df64485 100644 --- a/app/api/subscription-api/src/main/java/org/example/listener/RegisterShowMessageLister.java +++ b/app/api/subscription-api/src/main/java/org/example/listener/UpdateShowMessageListener.java @@ -1,7 +1,7 @@ package org.example.listener; import lombok.RequiredArgsConstructor; -import org.example.converter.MessageConverter; +import org.example.converter.SubscriptionMessageConverter; import org.example.service.SubscriptionAlarmService; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.data.redis.connection.Message; @@ -10,14 +10,14 @@ @Controller @RequiredArgsConstructor -@Qualifier(value = "registerShowMessageLister") -public class RegisterShowMessageLister implements MessageListener { +@Qualifier(value = "updateShowMessageListener") +public class UpdateShowMessageListener implements MessageListener { private final SubscriptionAlarmService subscriptionAlarmService; @Override public void onMessage(Message message, byte[] pattern) { - var request = MessageConverter.toShowRelationSubscriptionMessage(message); + var request = SubscriptionMessageConverter.toShowRelationSubscriptionMessage(message); subscriptionAlarmService.showRelationSubscription(request.toServiceRequest()); } diff --git a/app/api/ticketing-api/build.gradle b/app/api/ticketing-api/build.gradle index a2b5dd2..83f8c8a 100644 --- a/app/api/ticketing-api/build.gradle +++ b/app/api/ticketing-api/build.gradle @@ -1,4 +1,8 @@ dependencies { implementation project(":app:domain:ticketing-domain") implementation project(":app:api:common-api") + + //redis sub + implementation 'org.springframework.data:spring-data-redis' + implementation 'io.lettuce:lettuce-core:6.3.0.RELEASE' } \ No newline at end of file diff --git a/app/api/ticketing-api/src/main/java/org/example/config/TicketingApiConfig.java b/app/api/ticketing-api/src/main/java/org/example/config/TicketingApiConfig.java index 881b035..ed978b3 100644 --- a/app/api/ticketing-api/src/main/java/org/example/config/TicketingApiConfig.java +++ b/app/api/ticketing-api/src/main/java/org/example/config/TicketingApiConfig.java @@ -1,12 +1,46 @@ package org.example.config; +import lombok.RequiredArgsConstructor; +import org.example.listener.TicketingAlertMessageListener; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import org.springframework.data.redis.connection.MessageListener; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.listener.ChannelTopic; +import org.springframework.data.redis.listener.RedisMessageListenerContainer; +import org.springframework.data.redis.listener.adapter.MessageListenerAdapter; @Configuration -@Import(TicketingDomainConfig.class) +@Import({ + PubSubConfig.class, + TicketingDomainConfig.class, + TicketingAlertMessageListener.class +}) @ComponentScan(basePackages = "org.example") +@RequiredArgsConstructor public class TicketingApiConfig { + private final MessageListener ticketingAlertMessageListener; + + @Bean + MessageListenerAdapter ticketingAlertMessageListenerAdapter() { + return new MessageListenerAdapter(ticketingAlertMessageListener); + } + + @Bean + RedisMessageListenerContainer ticketingAlertMessageListenerContainer( + RedisConnectionFactory connectionFactory, + MessageListenerAdapter ticketingAlertMessageListenerAdapter + ) { + + RedisMessageListenerContainer container = new RedisMessageListenerContainer(); + container.setConnectionFactory(connectionFactory); + container.addMessageListener( + ticketingAlertMessageListenerAdapter, + ChannelTopic.of("ticketingAlert") + ); + return container; + } } diff --git a/app/api/ticketing-api/src/main/java/org/example/converter/TicketingMessageConverter.java b/app/api/ticketing-api/src/main/java/org/example/converter/TicketingMessageConverter.java new file mode 100644 index 0000000..9dbc558 --- /dev/null +++ b/app/api/ticketing-api/src/main/java/org/example/converter/TicketingMessageConverter.java @@ -0,0 +1,33 @@ +package org.example.converter; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import lombok.extern.slf4j.Slf4j; +import org.example.listener.dto.TicketingReservationMessageApiRequest; +import org.springframework.data.redis.connection.Message; + +@Slf4j +public class TicketingMessageConverter { + + private static final ObjectMapper objectMapper = new ObjectMapper(); + + public static TicketingReservationMessageApiRequest toTicketingReservationMessage(Message message) { + try { + var convertedMessage = objectMapper.readValue( + message.getBody(), + TicketingReservationMessageApiRequest.class + ); + log.info("Message published successfully to topic: {}", + new String(message.getChannel())); + log.info( + "Subscribe Message Contents ( TicketingReservationMessageApiRequest : {} )", + message); + + return convertedMessage; + } catch (IOException e) { + log.error("Failed to convert message to TicketingReservationMessageApiRequest", e); + throw new IllegalArgumentException("메시지를 받지 못했습니다."); + } + } + +} diff --git a/app/api/ticketing-api/src/main/java/org/example/listener/TicketingAlertMessageListener.java b/app/api/ticketing-api/src/main/java/org/example/listener/TicketingAlertMessageListener.java new file mode 100644 index 0000000..8f5d2b2 --- /dev/null +++ b/app/api/ticketing-api/src/main/java/org/example/listener/TicketingAlertMessageListener.java @@ -0,0 +1,23 @@ +package org.example.listener; + +import lombok.RequiredArgsConstructor; +import org.example.converter.TicketingMessageConverter; +import org.example.service.TicketingAlertService; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.data.redis.connection.Message; +import org.springframework.data.redis.connection.MessageListener; +import org.springframework.stereotype.Controller; + +@Controller +@RequiredArgsConstructor +@Qualifier(value = "ticketingAlertMessageListener") +public class TicketingAlertMessageListener implements MessageListener { + + private final TicketingAlertService ticketingAlertService; + + @Override + public void onMessage(Message message, byte[] pattern) { + var request = TicketingMessageConverter.toTicketingReservationMessage(message); + ticketingAlertService.reserveTicketingAlert(request.toServiceRequest()); + } +} diff --git a/app/api/ticketing-api/src/main/java/org/example/listener/dto/TicketingReservationMessageApiRequest.java b/app/api/ticketing-api/src/main/java/org/example/listener/dto/TicketingReservationMessageApiRequest.java new file mode 100644 index 0000000..3f72eaf --- /dev/null +++ b/app/api/ticketing-api/src/main/java/org/example/listener/dto/TicketingReservationMessageApiRequest.java @@ -0,0 +1,26 @@ +package org.example.listener.dto; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.UUID; +import org.example.service.dto.request.TicketingReservationMessageServiceRequest; + +public record TicketingReservationMessageApiRequest( + String userFcmToken, + String name, + UUID showId, + List reserveAts +) { + + public TicketingReservationMessageServiceRequest toServiceRequest() { + return TicketingReservationMessageServiceRequest.builder() + .userFcmToken(userFcmToken) + .name(name) + .showId(showId) + .reserveAts(reserveAts.stream() + .map(LocalDateTime::parse) + .toList() + ) + .build(); + } +} diff --git a/app/api/ticketing-api/src/main/java/org/example/service/TicketingAlertService.java b/app/api/ticketing-api/src/main/java/org/example/service/TicketingAlertService.java new file mode 100644 index 0000000..79094de --- /dev/null +++ b/app/api/ticketing-api/src/main/java/org/example/service/TicketingAlertService.java @@ -0,0 +1,20 @@ +package org.example.service; + +import lombok.RequiredArgsConstructor; +import org.example.service.dto.request.TicketingReservationMessageServiceRequest; +import org.example.usecase.TicketingAlertUseCase; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class TicketingAlertService { + + private final TicketingAlertUseCase ticketingAlertUseCase; + + public void reserveTicketingAlert(TicketingReservationMessageServiceRequest request) { + ticketingAlertUseCase.reserveTicketingAlert(request.toDomainRequest()); + + //Todo Batch 작업 : 해당 공연에 대한 리스트를 뽑아서, 삭제 되어 있는것은 배치에서 삭제하고,추가된것은 배치에 넣음. + // -> 배치 이후 FCM + } +} diff --git a/app/api/ticketing-api/src/main/java/org/example/service/dto/request/TicketingReservationMessageServiceRequest.java b/app/api/ticketing-api/src/main/java/org/example/service/dto/request/TicketingReservationMessageServiceRequest.java new file mode 100644 index 0000000..5036887 --- /dev/null +++ b/app/api/ticketing-api/src/main/java/org/example/service/dto/request/TicketingReservationMessageServiceRequest.java @@ -0,0 +1,25 @@ +package org.example.service.dto.request; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.UUID; +import lombok.Builder; +import org.example.dto.request.TicketingReservationMessageDomainRequest; + +@Builder +public record TicketingReservationMessageServiceRequest( + String userFcmToken, + String name, + UUID showId, + List reserveAts +) { + + public TicketingReservationMessageDomainRequest toDomainRequest() { + return TicketingReservationMessageDomainRequest.builder() + .userFcmToken(userFcmToken) + .name(name) + .showId(showId) + .reserveAts(reserveAts) + .build(); + } +} diff --git a/app/domain/ticketing-domain/src/main/java/org/example/dto/request/TicketingReservationMessageDomainRequest.java b/app/domain/ticketing-domain/src/main/java/org/example/dto/request/TicketingReservationMessageDomainRequest.java new file mode 100644 index 0000000..0be6d8f --- /dev/null +++ b/app/domain/ticketing-domain/src/main/java/org/example/dto/request/TicketingReservationMessageDomainRequest.java @@ -0,0 +1,16 @@ +package org.example.dto.request; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.UUID; +import lombok.Builder; + +@Builder +public record TicketingReservationMessageDomainRequest( + String userFcmToken, + String name, + UUID showId, + List reserveAts +) { + +} diff --git a/app/domain/ticketing-domain/src/main/java/org/example/entity/TicketingAlert.java b/app/domain/ticketing-domain/src/main/java/org/example/entity/TicketingAlert.java index bb85e5c..e8264d2 100644 --- a/app/domain/ticketing-domain/src/main/java/org/example/entity/TicketingAlert.java +++ b/app/domain/ticketing-domain/src/main/java/org/example/entity/TicketingAlert.java @@ -6,6 +6,7 @@ import java.time.LocalDateTime; import java.util.UUID; import lombok.AccessLevel; +import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; @@ -21,9 +22,17 @@ public class TicketingAlert extends BaseEntity { @Column(name = "schedule_alert_time", nullable = false) private LocalDateTime alertTime; - @Column(name = "user_id", nullable = false) - private UUID userId; + @Column(name = "user_fcm_token", nullable = false) + private String userFcmToken; @Column(name = "show_id", nullable = false) private UUID showId; + + @Builder + private TicketingAlert(String name, LocalDateTime alertTime, String userFcmToken, UUID showId) { + this.name = name; + this.alertTime = alertTime; + this.userFcmToken = userFcmToken; + this.showId = showId; + } } diff --git a/app/domain/ticketing-domain/src/main/java/org/example/repository/ticketingalert/TicketingAlertRepository.java b/app/domain/ticketing-domain/src/main/java/org/example/repository/ticketingalert/TicketingAlertRepository.java index 3b17ac7..851c5bd 100644 --- a/app/domain/ticketing-domain/src/main/java/org/example/repository/ticketingalert/TicketingAlertRepository.java +++ b/app/domain/ticketing-domain/src/main/java/org/example/repository/ticketingalert/TicketingAlertRepository.java @@ -1,9 +1,14 @@ package org.example.repository.ticketingalert; +import java.util.List; import java.util.UUID; import org.example.entity.TicketingAlert; import org.springframework.data.jpa.repository.JpaRepository; public interface TicketingAlertRepository extends JpaRepository { + List findAllByUserFcmTokenAndShowIdAndIsDeletedFalse( + String userFcmToken, + UUID showId + ); } diff --git a/app/domain/ticketing-domain/src/main/java/org/example/usecase/TicketingAlertUseCase.java b/app/domain/ticketing-domain/src/main/java/org/example/usecase/TicketingAlertUseCase.java new file mode 100644 index 0000000..6d39454 --- /dev/null +++ b/app/domain/ticketing-domain/src/main/java/org/example/usecase/TicketingAlertUseCase.java @@ -0,0 +1,62 @@ +package org.example.usecase; + +import java.time.LocalDateTime; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.example.dto.request.TicketingReservationMessageDomainRequest; +import org.example.entity.BaseEntity; +import org.example.entity.TicketingAlert; +import org.example.repository.ticketingalert.TicketingAlertRepository; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +@Component +@RequiredArgsConstructor +public class TicketingAlertUseCase { + + private final TicketingAlertRepository ticketingAlertRepository; + + @Transactional + public void reserveTicketingAlert( + TicketingReservationMessageDomainRequest ticketingReservations + ) { + List existingAlerts = ticketingAlertRepository.findAllByUserFcmTokenAndShowIdAndIsDeletedFalse( + ticketingReservations.userFcmToken(), + ticketingReservations.showId() + ); + + List existingAlertTimes = existingAlerts.stream() + .map(TicketingAlert::getAlertTime) + .toList(); + + addAlerts(ticketingReservations, existingAlertTimes); + removeAlerts(ticketingReservations, existingAlerts); + } + + private void addAlerts( + TicketingReservationMessageDomainRequest ticketingReservation, + List existingAlertTimes + ) { + List alertsToAdd = ticketingReservation.reserveAts().stream() + .filter(reserveAt -> !existingAlertTimes.contains(reserveAt)) + .map(reserveAt -> TicketingAlert.builder() + .name(ticketingReservation.name()) + .alertTime(reserveAt) + .userFcmToken(ticketingReservation.userFcmToken()) + .showId(ticketingReservation.showId()) + .build() + ) + .toList(); + ticketingAlertRepository.saveAll(alertsToAdd); + } + + private void removeAlerts( + TicketingReservationMessageDomainRequest ticketingReservations, + List existingAlerts + ) { + List alertsToRemove = existingAlerts.stream() + .filter(alert -> !ticketingReservations.reserveAts().contains(alert.getAlertTime())) + .toList(); + alertsToRemove.forEach(BaseEntity::softDelete); + } +}