From dc5d9aa3804d1e8050dfea31b391e94f02bde68f Mon Sep 17 00:00:00 2001 From: JunsuPark Date: Tue, 12 Nov 2024 00:19:36 +0900 Subject: [PATCH] =?UTF-8?q?feat=20:=20=EC=95=8C=EB=A6=BC=20=EC=84=9C?= =?UTF-8?q?=EB=B2=84=20API=20=EC=97=B0=EB=8F=99=20(#188)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/showpot-dev-cd.yml | 1 + .../org/example/config/SecurityConfig.java | 2 +- ...wRelationArtistAndGenreServiceMessage.java | 8 +- .../show/service/ShowAdminService.java | 5 +- .../show/service/ShowAdminServiceTest.java | 20 ++-- .../org/example/config/UserApiConfig.java | 3 + .../controller/UserAlarmController.java | 66 ++++++------- .../dto/param/SimpleNotificationApiParam.java | 18 +++- .../HasUnreadNotificationApiResponse.java | 12 --- .../NotificationExistApiResponse.java | 16 ++++ .../response/NotificationsApiResponse.java | 12 --- .../example/property/AlarmServerProperty.java | 9 ++ .../org/example/service/UserAlarmService.java | 94 +++++++++++++++++++ .../NotificationExistServiceResponse.java | 10 ++ .../NotificationPaginationResponse.java | 25 +++++ .../response/NotificationServiceResponse.java | 64 +++++++++++++ .../src/main/resources/schema.sql | 1 + .../repository/show/ShowRepository.java | 2 +- .../org/example/usecase/ShowAdminUseCase.java | 4 +- .../java/org/example/usecase/ShowUseCase.java | 2 +- ...howRelationArtistAndGenreInfraMessage.java | 2 + .../publish/RedisMessagePublisher.java | 35 ++----- app/src/main/resources/application-dev.yml | 3 + app/src/main/resources/application-local.yml | 5 +- 24 files changed, 316 insertions(+), 103 deletions(-) delete mode 100644 app/api/user-api/src/main/java/org/example/controller/dto/response/HasUnreadNotificationApiResponse.java create mode 100644 app/api/user-api/src/main/java/org/example/controller/dto/response/NotificationExistApiResponse.java delete mode 100644 app/api/user-api/src/main/java/org/example/controller/dto/response/NotificationsApiResponse.java create mode 100644 app/api/user-api/src/main/java/org/example/property/AlarmServerProperty.java create mode 100644 app/api/user-api/src/main/java/org/example/service/UserAlarmService.java create mode 100644 app/api/user-api/src/main/java/org/example/service/dto/response/NotificationExistServiceResponse.java create mode 100644 app/api/user-api/src/main/java/org/example/service/dto/response/NotificationPaginationResponse.java create mode 100644 app/api/user-api/src/main/java/org/example/service/dto/response/NotificationServiceResponse.java diff --git a/.github/workflows/showpot-dev-cd.yml b/.github/workflows/showpot-dev-cd.yml index f30e01ef..b9fd85ad 100644 --- a/.github/workflows/showpot-dev-cd.yml +++ b/.github/workflows/showpot-dev-cd.yml @@ -43,6 +43,7 @@ jobs: spring.datasource.password: ${{ secrets.APPLICATION_DATASOURCE_PASSWORD }} spotify.client-id: ${{ secrets.SPOTIFY_CLIENT_ID }} spotify.client-secret: ${{ secrets.SPOTIFY_CLIENT_SECRET }} + alarm.api-url: ${{ secrets.ALARM_SERVER_API_URL }} - name: Build with Gradle Wrapper run: ./gradlew clean build -Dspring.profiles.active=dev diff --git a/app/api/common-api/src/main/java/org/example/config/SecurityConfig.java b/app/api/common-api/src/main/java/org/example/config/SecurityConfig.java index c4742906..9b14b112 100644 --- a/app/api/common-api/src/main/java/org/example/config/SecurityConfig.java +++ b/app/api/common-api/src/main/java/org/example/config/SecurityConfig.java @@ -109,7 +109,7 @@ private RequestMatcher getMatcherForUserAndAdmin() { antMatcher(HttpMethod.POST, "/api/v1/artists/unsubscribe"), antMatcher(HttpMethod.GET, "/api/v1/artists/subscriptions"), antMatcher(HttpMethod.GET, "/api/v1/users/notifications"), - antMatcher(HttpMethod.GET, "/api/v1/users/notifications/unread") + antMatcher(HttpMethod.GET, "/api/v1/users/notifications/exist") ); } } diff --git a/app/api/show-api/src/main/java/com/example/pub/message/ShowRelationArtistAndGenreServiceMessage.java b/app/api/show-api/src/main/java/com/example/pub/message/ShowRelationArtistAndGenreServiceMessage.java index 2e5b9dfe..c0ee7186 100644 --- a/app/api/show-api/src/main/java/com/example/pub/message/ShowRelationArtistAndGenreServiceMessage.java +++ b/app/api/show-api/src/main/java/com/example/pub/message/ShowRelationArtistAndGenreServiceMessage.java @@ -6,12 +6,18 @@ @Builder public record ShowRelationArtistAndGenreServiceMessage( + UUID showId, List artistIds, List genreIds ) { - public static ShowRelationArtistAndGenreServiceMessage of(List artistIds, List genreIds) { + public static ShowRelationArtistAndGenreServiceMessage of( + UUID showId, + List artistIds, + List genreIds + ) { return ShowRelationArtistAndGenreServiceMessage.builder() + .showId(showId) .artistIds(artistIds) .genreIds(genreIds) .build(); diff --git a/app/api/show-api/src/main/java/com/example/show/service/ShowAdminService.java b/app/api/show-api/src/main/java/com/example/show/service/ShowAdminService.java index 8aa473fe..0ad1298a 100644 --- a/app/api/show-api/src/main/java/com/example/show/service/ShowAdminService.java +++ b/app/api/show-api/src/main/java/com/example/show/service/ShowAdminService.java @@ -11,6 +11,7 @@ import java.util.UUID; import lombok.RequiredArgsConstructor; import org.example.dto.show.response.ShowInfoDomainResponse; +import org.example.entity.show.Show; import org.example.usecase.ArtistUseCase; import org.example.usecase.GenreUseCase; import org.example.usecase.ShowAdminUseCase; @@ -29,13 +30,14 @@ public class ShowAdminService { public void save(ShowCreateServiceRequest showCreateServiceRequest) { String imageURL = fileUploadComponent.uploadFile("show", showCreateServiceRequest.post()); - showAdminUseCase.save( + Show show = showAdminUseCase.save( showCreateServiceRequest.toDomainRequest(imageURL) ); messagePublisher.publishShow( "registerShow", ShowRelationArtistAndGenreServiceMessage.of( + show.getId(), showCreateServiceRequest.artistIds(), showCreateServiceRequest.genreIds() ) @@ -83,6 +85,7 @@ public void updateShow(UUID id, ShowUpdateServiceRequest showUpdateServiceReques messagePublisher.publishShow( "updateShow", ShowRelationArtistAndGenreServiceMessage.of( + id, artistIdsToPublish, genreIdsToPublish ) diff --git a/app/api/show-api/src/test/java/show/service/ShowAdminServiceTest.java b/app/api/show-api/src/test/java/show/service/ShowAdminServiceTest.java index ceca5106..797c8324 100644 --- a/app/api/show-api/src/test/java/show/service/ShowAdminServiceTest.java +++ b/app/api/show-api/src/test/java/show/service/ShowAdminServiceTest.java @@ -4,7 +4,6 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.willDoNothing; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -19,6 +18,7 @@ import java.util.UUID; import org.example.dto.show.request.ShowUpdateDomainRequest; import org.example.fixture.domain.ShowArtistFixture; +import org.example.fixture.domain.ShowFixture; import org.example.fixture.domain.ShowGenreFixture; import org.example.usecase.ArtistUseCase; import org.example.usecase.GenreUseCase; @@ -48,12 +48,16 @@ class ShowAdminServiceTest { void showCreateWithUploadedImageUrl() { //given ShowCreateServiceRequest showCreateServiceRequest = ShowRequestDtoFixture.showCreateServiceRequest(); + String url = "test_imageUrl"; given( fileUploadComponent.uploadFile( - "artist", + "show", showCreateServiceRequest.post() ) ).willReturn("test_imageUrl"); + given( + showAdminUseCase.save(any()) + ).willReturn(ShowFixture.deafultShow()); //when showAdminService.save(showCreateServiceRequest); @@ -67,10 +71,9 @@ void showCreateWithUploadedImageUrl() { void showCreateWithPublishRelationArtistIdsAndGenreIds() { //given var showCreateServiceRequest = ShowRequestDtoFixture.showCreateServiceRequest(); - var showCreationDomainRequest = showCreateServiceRequest.toDomainRequest( - "test_imageUrl" - ); - willDoNothing().given(showAdminUseCase).save(showCreationDomainRequest); + given( + showAdminUseCase.save(any()) + ).willReturn(ShowFixture.deafultShow()); //when showAdminService.save(showCreateServiceRequest); @@ -90,7 +93,7 @@ void showUpdateWithUploadedImageUrl() { UUID showId = UUID.randomUUID(); given( fileUploadComponent.uploadFile( - "artist", + "show", showUpdateServiceRequest.post() ) ).willReturn("test_imageUrl"); @@ -99,7 +102,8 @@ void showUpdateWithUploadedImageUrl() { showAdminService.updateShow(showId, showUpdateServiceRequest); //then - verify(showAdminUseCase, times(1)).updateShow(eq(showId), any(ShowUpdateDomainRequest.class)); + verify(showAdminUseCase, times(1)).updateShow(eq(showId), + any(ShowUpdateDomainRequest.class)); } @Test diff --git a/app/api/user-api/src/main/java/org/example/config/UserApiConfig.java b/app/api/user-api/src/main/java/org/example/config/UserApiConfig.java index 0d709c9d..244e3482 100644 --- a/app/api/user-api/src/main/java/org/example/config/UserApiConfig.java +++ b/app/api/user-api/src/main/java/org/example/config/UserApiConfig.java @@ -1,11 +1,14 @@ package org.example.config; +import org.example.property.AlarmServerProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @Configuration @Import(UserDomainConfig.class) +@EnableConfigurationProperties(AlarmServerProperty.class) @ComponentScan(basePackages = "org.example") public class UserApiConfig { diff --git a/app/api/user-api/src/main/java/org/example/controller/UserAlarmController.java b/app/api/user-api/src/main/java/org/example/controller/UserAlarmController.java index 97b4c131..6b7d7994 100644 --- a/app/api/user-api/src/main/java/org/example/controller/UserAlarmController.java +++ b/app/api/user-api/src/main/java/org/example/controller/UserAlarmController.java @@ -2,18 +2,19 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; -import java.time.LocalDateTime; -import java.util.List; +import jakarta.validation.constraints.Max; +import java.util.UUID; import lombok.RequiredArgsConstructor; import org.example.controller.dto.param.SimpleNotificationApiParam; -import org.example.controller.dto.response.HasUnreadNotificationApiResponse; -import org.example.controller.dto.response.NotificationsApiResponse; +import org.example.controller.dto.response.NotificationExistApiResponse; +import org.example.dto.response.PaginationApiResponse; import org.example.security.dto.AuthenticatedInfo; -import org.example.util.DateTimeUtil; +import org.example.service.UserAlarmService; import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @Tag(name = "유저 알림") @@ -22,50 +23,39 @@ @RequiredArgsConstructor public class UserAlarmController { - @GetMapping("/notifications/unread") - @Operation(summary = "안 읽은 알림 존재 여부") - public ResponseEntity hasUnreadNotifications( + private final UserAlarmService userAlarmService; + + @GetMapping("/notifications/exist") + @Operation(summary = "알림 미열람 존재 여부") + public ResponseEntity hasUnreadNotifications( @AuthenticationPrincipal AuthenticatedInfo info ) { + var response = userAlarmService.getNotificationExist(info.userId()); + return ResponseEntity.ok( - HasUnreadNotificationApiResponse.builder() - .hasUnreadNotification(true) - .build() + NotificationExistApiResponse.from(response) ); } @GetMapping("/notifications") @Operation(summary = "알림 목록") - public ResponseEntity getNotifications( + public ResponseEntity> getNotifications( + @RequestParam(value = "cursorId", required = false) UUID cursorId, + @RequestParam(value = "size") @Max(value = 30, message = "조회하는 데이터의 최대 개수는 30입니다.") + Integer size, @AuthenticationPrincipal AuthenticatedInfo info + ) { + var response = userAlarmService.findNotifications(info.userId(), cursorId, size); + var data = response.data().stream() + .map(SimpleNotificationApiParam::from) + .toList(); + return ResponseEntity.ok( - NotificationsApiResponse.builder() - .notifications( - List.of( - SimpleNotificationApiParam.builder() - .title("오하요 고자이마스") - .message("본문 데스") - .notifiedAt(DateTimeUtil.formatDateTime(LocalDateTime.of(2021, 9, 27, 0, 0, 0))) - .showId(java.util.UUID.randomUUID()) - .showImageURL("https://example.com/show.jpg") - .build(), - SimpleNotificationApiParam.builder() - .title("알림알림제목제목알림알림제목제목") - .message("알림본문본문알림본문본문알림본문본문") - .notifiedAt(DateTimeUtil.formatDateTime(LocalDateTime.of(2021, 9, 27, 12, 0, 0))) - .showId(java.util.UUID.randomUUID()) - .showImageURL("https://example.com/show.jpg") - .build(), - SimpleNotificationApiParam.builder() - .title("알림 제목") - .message("알림 본문") - .notifiedAt(DateTimeUtil.formatDateTime(LocalDateTime.of(2021, 9, 27, 23, 0, 0))) - .showId(java.util.UUID.randomUUID()) - .showImageURL("https://example.com/show.jpg") - .build() - ) - ) + PaginationApiResponse.builder() + .hasNext(response.hasNext()) + .data(data) + .cursor(response.cursor()) .build() ); } diff --git a/app/api/user-api/src/main/java/org/example/controller/dto/param/SimpleNotificationApiParam.java b/app/api/user-api/src/main/java/org/example/controller/dto/param/SimpleNotificationApiParam.java index 2b4370fd..129ca5e8 100644 --- a/app/api/user-api/src/main/java/org/example/controller/dto/param/SimpleNotificationApiParam.java +++ b/app/api/user-api/src/main/java/org/example/controller/dto/param/SimpleNotificationApiParam.java @@ -3,19 +3,35 @@ import io.swagger.v3.oas.annotations.media.Schema; import java.util.UUID; import lombok.Builder; +import org.example.service.dto.response.NotificationServiceResponse.NotificationInfoWithImageResponse; +import org.example.util.DateTimeUtil; @Builder public record SimpleNotificationApiParam( @Schema(description = "알림 제목") String title, + @Schema(description = "알림 본문") String message, - @Schema(description = "알림 시간") + + @Schema(description = "알림 생성 시간") String notifiedAt, + @Schema(description = "공연 ID") UUID showId, + @Schema(description = "공연 이미지 URL") String showImageURL ) { + public static SimpleNotificationApiParam from(NotificationInfoWithImageResponse response) { + return SimpleNotificationApiParam.builder() + .title(response.title()) + .message(response.content()) + .notifiedAt(DateTimeUtil.formatDateTime(response.createAt())) + .showId(response.showId()) + .showImageURL(response.imageURL()) + .build(); + } + } diff --git a/app/api/user-api/src/main/java/org/example/controller/dto/response/HasUnreadNotificationApiResponse.java b/app/api/user-api/src/main/java/org/example/controller/dto/response/HasUnreadNotificationApiResponse.java deleted file mode 100644 index e3fb562d..00000000 --- a/app/api/user-api/src/main/java/org/example/controller/dto/response/HasUnreadNotificationApiResponse.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.example.controller.dto.response; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Builder; - -@Builder -public record HasUnreadNotificationApiResponse( - @Schema(description = "안 읽은 알림 존재 여부") - boolean hasUnreadNotification -) { - -} diff --git a/app/api/user-api/src/main/java/org/example/controller/dto/response/NotificationExistApiResponse.java b/app/api/user-api/src/main/java/org/example/controller/dto/response/NotificationExistApiResponse.java new file mode 100644 index 00000000..71427277 --- /dev/null +++ b/app/api/user-api/src/main/java/org/example/controller/dto/response/NotificationExistApiResponse.java @@ -0,0 +1,16 @@ +package org.example.controller.dto.response; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import org.example.service.dto.response.NotificationExistServiceResponse; + +@Builder +public record NotificationExistApiResponse( + @Schema(description = "미열람 존재 여부") + boolean isExist +) { + + public static NotificationExistApiResponse from(NotificationExistServiceResponse response) { + return new NotificationExistApiResponse(response.isActivate()); + } +} diff --git a/app/api/user-api/src/main/java/org/example/controller/dto/response/NotificationsApiResponse.java b/app/api/user-api/src/main/java/org/example/controller/dto/response/NotificationsApiResponse.java deleted file mode 100644 index f49702e3..00000000 --- a/app/api/user-api/src/main/java/org/example/controller/dto/response/NotificationsApiResponse.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.example.controller.dto.response; - -import java.util.List; -import lombok.Builder; -import org.example.controller.dto.param.SimpleNotificationApiParam; - -@Builder -public record NotificationsApiResponse( - List notifications -) { - -} diff --git a/app/api/user-api/src/main/java/org/example/property/AlarmServerProperty.java b/app/api/user-api/src/main/java/org/example/property/AlarmServerProperty.java new file mode 100644 index 00000000..4cfbff29 --- /dev/null +++ b/app/api/user-api/src/main/java/org/example/property/AlarmServerProperty.java @@ -0,0 +1,9 @@ +package org.example.property; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties(prefix = "alarm") +public record AlarmServerProperty( + String apiURL +) { +} diff --git a/app/api/user-api/src/main/java/org/example/service/UserAlarmService.java b/app/api/user-api/src/main/java/org/example/service/UserAlarmService.java new file mode 100644 index 00000000..adc5c6ea --- /dev/null +++ b/app/api/user-api/src/main/java/org/example/service/UserAlarmService.java @@ -0,0 +1,94 @@ +package org.example.service; + +import java.util.List; +import java.util.NoSuchElementException; +import java.util.UUID; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.example.entity.show.Show; +import org.example.property.AlarmServerProperty; +import org.example.repository.show.ShowRepository; +import org.example.repository.user.UserRepository; +import org.example.service.dto.response.NotificationExistServiceResponse; +import org.example.service.dto.response.NotificationPaginationResponse; +import org.example.service.dto.response.NotificationPaginationResponse.NotificationInfoResponse; +import org.example.service.dto.response.NotificationServiceResponse; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestClient; + +@Slf4j +@Service +@RequiredArgsConstructor +public class UserAlarmService { + + private final UserRepository userRepository; + private final AlarmServerProperty alarmServerProperty; + private final ShowRepository showRepository; + + public NotificationExistServiceResponse getNotificationExist(UUID userId) { + String userFcmToken = findUserFcmTokenById(userId); + + ResponseEntity result = RestClient.builder() + .baseUrl(alarmServerProperty.apiURL() + "/show-alarm/checked?fcmToken=" + userFcmToken) + .build() + .get() + .retrieve() + .toEntity(NotificationExistServiceResponse.class); + + handleApiError(result, "getNotificationExist"); + return result.getBody(); + } + + public NotificationServiceResponse findNotifications(UUID userId, UUID cursorId, int size) { + String userFcmToken = findUserFcmTokenById(userId); + + ResponseEntity result = RestClient.builder() + .baseUrl(createNotificationsUrl(userFcmToken, cursorId, size)) + .build() + .post() + .retrieve() + .toEntity(NotificationPaginationResponse.class); + + handleApiError(result, "findNotifications"); + var response = result.getBody(); + + if (response != null) { + List showIds = response.data().stream() + .map(NotificationInfoResponse::showId) + .toList(); + List shows = showRepository.findShowsByIdInAndIsDeletedFalse(showIds); + + return NotificationServiceResponse.of(response, shows); + } + + return NotificationServiceResponse.noneData(); + } + + private String createNotificationsUrl(String userFcmToken, UUID cursorId, int size) { + StringBuilder urlBuilder = new StringBuilder(alarmServerProperty.apiURL()) + .append("/show-alarm?fcmToken=") + .append(userFcmToken) + .append("&size=") + .append(size); + + if (cursorId != null) { + urlBuilder.append("&cursorId=").append(cursorId); + } + + return urlBuilder.toString(); + } + + private String findUserFcmTokenById(UUID userId) { + return userRepository.findUserFcmTokensByUserId(userId) + .orElseThrow(NoSuchElementException::new); + } + + private void handleApiError(ResponseEntity response, String methodName) { + if (response.getStatusCode() == HttpStatus.INTERNAL_SERVER_ERROR) { + log.error("Alarm Server API failed in {}: {}", methodName, response); + throw new RuntimeException("Alarm Server API failed"); + } + } +} diff --git a/app/api/user-api/src/main/java/org/example/service/dto/response/NotificationExistServiceResponse.java b/app/api/user-api/src/main/java/org/example/service/dto/response/NotificationExistServiceResponse.java new file mode 100644 index 00000000..aa4d2ad8 --- /dev/null +++ b/app/api/user-api/src/main/java/org/example/service/dto/response/NotificationExistServiceResponse.java @@ -0,0 +1,10 @@ +package org.example.service.dto.response; + +import lombok.Builder; + +@Builder +public record NotificationExistServiceResponse( + boolean isActivate +) { + +} diff --git a/app/api/user-api/src/main/java/org/example/service/dto/response/NotificationPaginationResponse.java b/app/api/user-api/src/main/java/org/example/service/dto/response/NotificationPaginationResponse.java new file mode 100644 index 00000000..67d7f030 --- /dev/null +++ b/app/api/user-api/src/main/java/org/example/service/dto/response/NotificationPaginationResponse.java @@ -0,0 +1,25 @@ +package org.example.service.dto.response; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.UUID; +import org.example.dto.response.CursorApiResponse; + +public record NotificationPaginationResponse( + int size, + boolean hasNext, + List data, + CursorApiResponse cursor +) { + + public record NotificationInfoResponse( + UUID id, + UUID showId, + String title, + String content, + LocalDateTime createAt + ) { + + } + +} diff --git a/app/api/user-api/src/main/java/org/example/service/dto/response/NotificationServiceResponse.java b/app/api/user-api/src/main/java/org/example/service/dto/response/NotificationServiceResponse.java new file mode 100644 index 00000000..90eb72e2 --- /dev/null +++ b/app/api/user-api/src/main/java/org/example/service/dto/response/NotificationServiceResponse.java @@ -0,0 +1,64 @@ +package org.example.service.dto.response; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.stream.Collectors; +import lombok.Builder; +import org.example.dto.response.CursorApiResponse; +import org.example.entity.show.Show; + +public record NotificationServiceResponse( + int size, + boolean hasNext, + List data, + CursorApiResponse cursor +) { + + @Builder + public record NotificationInfoWithImageResponse( + UUID id, + UUID showId, + String title, + String content, + LocalDateTime createAt, + String imageURL + ) { + + + } + + public static NotificationServiceResponse of( + NotificationPaginationResponse response, + List shows + ) { + Map showIdToImageUrlMap = shows.stream() + .collect(Collectors.toMap(Show::getId, Show::getImage)); + + List updatedData = response.data().stream() + .map(info -> NotificationInfoWithImageResponse.builder() + .id(info.id()) + .showId(info.showId()) + .title(info.title()) + .content(info.content()) + .createAt(info.createAt()) + .imageURL(showIdToImageUrlMap.get(info.showId())) + .build() + ) + .toList(); + + return new NotificationServiceResponse( + response.size(), + response.hasNext(), + updatedData, + response.cursor() + ); + + } + + public static NotificationServiceResponse noneData() { + return new NotificationServiceResponse(0, false, List.of(), CursorApiResponse.noneCursor()); + } + +} diff --git a/app/domain/common-domain/src/main/resources/schema.sql b/app/domain/common-domain/src/main/resources/schema.sql index 345396dd..442ccf89 100644 --- a/app/domain/common-domain/src/main/resources/schema.sql +++ b/app/domain/common-domain/src/main/resources/schema.sql @@ -267,6 +267,7 @@ create table alarm.show_alarm created_at timestamp(3) not null, updated_at timestamp(3) not null, id uuid not null, + show_id uuid not null, user_fcm_token varchar(255) not null, title varchar(255) not null, content varchar(255) not null, diff --git a/app/domain/show-domain/src/main/java/org/example/repository/show/ShowRepository.java b/app/domain/show-domain/src/main/java/org/example/repository/show/ShowRepository.java index a0ac3dbf..f8048b4b 100644 --- a/app/domain/show-domain/src/main/java/org/example/repository/show/ShowRepository.java +++ b/app/domain/show-domain/src/main/java/org/example/repository/show/ShowRepository.java @@ -8,7 +8,7 @@ public interface ShowRepository extends JpaRepository, ShowQuerydslRepository { - List findShowsByIdIn(List showIds); + List findShowsByIdInAndIsDeletedFalse(List showIds); Optional findByIdAndIsDeletedFalse(UUID showId); } diff --git a/app/domain/show-domain/src/main/java/org/example/usecase/ShowAdminUseCase.java b/app/domain/show-domain/src/main/java/org/example/usecase/ShowAdminUseCase.java index 1cf97dba..ba2d3a25 100644 --- a/app/domain/show-domain/src/main/java/org/example/usecase/ShowAdminUseCase.java +++ b/app/domain/show-domain/src/main/java/org/example/usecase/ShowAdminUseCase.java @@ -33,7 +33,7 @@ public class ShowAdminUseCase { private final ShowTicketingTimeRepository showTicketingTimeRepository; @Transactional - public void save( + public Show save( ShowCreationDomainRequest request ) { Show show = request.toShow(); @@ -48,6 +48,8 @@ public void save( var showTicketingTimes = show.toShowTicketingTime(request.showTicketingTimes()); showTicketingTimeRepository.saveAll(showTicketingTimes); + + return show; } public List findShowDetailWithTicketingTimes() { diff --git a/app/domain/show-domain/src/main/java/org/example/usecase/ShowUseCase.java b/app/domain/show-domain/src/main/java/org/example/usecase/ShowUseCase.java index f7a68d74..7a0b2321 100644 --- a/app/domain/show-domain/src/main/java/org/example/usecase/ShowUseCase.java +++ b/app/domain/show-domain/src/main/java/org/example/usecase/ShowUseCase.java @@ -38,7 +38,7 @@ public ShowTicketingPaginationDomainResponse findShows(ShowPaginationDomainReque } public List findShowsInIds(List showIds) { - return showRepository.findShowsByIdIn(showIds); + return showRepository.findShowsByIdInAndIsDeletedFalse(showIds); } @Transactional diff --git a/app/infrastructure/message-queue/src/main/java/org/example/message/ShowRelationArtistAndGenreInfraMessage.java b/app/infrastructure/message-queue/src/main/java/org/example/message/ShowRelationArtistAndGenreInfraMessage.java index a516975e..12cc06e2 100644 --- a/app/infrastructure/message-queue/src/main/java/org/example/message/ShowRelationArtistAndGenreInfraMessage.java +++ b/app/infrastructure/message-queue/src/main/java/org/example/message/ShowRelationArtistAndGenreInfraMessage.java @@ -7,6 +7,7 @@ @Builder public record ShowRelationArtistAndGenreInfraMessage( + UUID showId, List artistIds, List genreIds ) { @@ -15,6 +16,7 @@ public static ShowRelationArtistAndGenreInfraMessage from( ShowRelationArtistAndGenreServiceMessage message ) { return ShowRelationArtistAndGenreInfraMessage.builder() + .showId(message.showId()) .artistIds(message.artistIds()) .genreIds(message.genreIds()) .build(); diff --git a/app/infrastructure/message-queue/src/main/java/org/example/publish/RedisMessagePublisher.java b/app/infrastructure/message-queue/src/main/java/org/example/publish/RedisMessagePublisher.java index 80a36398..750c8087 100644 --- a/app/infrastructure/message-queue/src/main/java/org/example/publish/RedisMessagePublisher.java +++ b/app/infrastructure/message-queue/src/main/java/org/example/publish/RedisMessagePublisher.java @@ -24,45 +24,30 @@ public class RedisMessagePublisher implements MessagePublisher { @Override public void publishShow(String topic, ShowRelationArtistAndGenreServiceMessage message) { var infraMessage = ShowRelationArtistAndGenreInfraMessage.from(message); - - template.convertAndSend(topic, infraMessage); - log.info("Message published successfully to topic: {}", topic); - log.info("Message Contents ( showRelationArtistAndGenreInfraMessage : {})", infraMessage); + publishMessage(topic, infraMessage); } @Override - public void publishArtistSubscription( - String topic, - ArtistSubscriptionServiceMessage message - ) { + public void publishArtistSubscription(String topic, ArtistSubscriptionServiceMessage message) { var infraMessage = ArtistSubscriptionInfraMessage.from(message); - - template.convertAndSend(topic, infraMessage); - log.info("Message published successfully to topic: {}", topic); - log.info("Message Contents ( artistSubscriptionMessage : {} )", infraMessage); + publishMessage(topic, infraMessage); } @Override - public void publishGenreSubscription( - String topic, - GenreSubscriptionServiceMessage message - ) { + public void publishGenreSubscription(String topic, GenreSubscriptionServiceMessage message) { var infraMessage = GenreSubscriptionInfraMessage.from(message); - - template.convertAndSend(topic, infraMessage); - log.info("Message published successfully to topic: {}", topic); - log.info("Message Contents ( genreSubscriptionMessage : {} )", infraMessage); + publishMessage(topic, infraMessage); } @Override - public void publishTicketingReservation( - String topic, - TicketingAlertsToReserveServiceMessage message - ) { + public void publishTicketingReservation(String topic, TicketingAlertsToReserveServiceMessage message) { var infraMessage = TicketingReservationInfraMessage.from(message); + publishMessage(topic, infraMessage); + } + private void publishMessage(String topic, Object infraMessage) { template.convertAndSend(topic, infraMessage); log.info("Message published successfully to topic: {}", topic); - log.info("Message Contents ( ticketingReservationMessage : {} )", infraMessage); + log.info("Message Contents ( {} : {} )", infraMessage.getClass().getName(), infraMessage); } } diff --git a/app/src/main/resources/application-dev.yml b/app/src/main/resources/application-dev.yml index f5e9592d..f0f802ef 100644 --- a/app/src/main/resources/application-dev.yml +++ b/app/src/main/resources/application-dev.yml @@ -26,3 +26,6 @@ token: secret-key: ${TOKEN_SECRET_KEY} access-token-expiration-seconds: 3600000 # 1hour = 1000(=1s) * 60 * 60 refresh-token-expiration-seconds: 1209600000 # 2weeks = 1000(=1s) * 60 * 60 * 24 * 14 + +alarm: + api-url: ${ALARM_SERVER_API_URL} \ No newline at end of file diff --git a/app/src/main/resources/application-local.yml b/app/src/main/resources/application-local.yml index 003236f6..0f8199c3 100644 --- a/app/src/main/resources/application-local.yml +++ b/app/src/main/resources/application-local.yml @@ -26,4 +26,7 @@ spring: token: secret-key: ahRhwlglftmrkwkfehlaussksmsdjraksrmadmfqjfrjtdlrhdkwnwlflsmswlqdptjgodqhrgkrptkftndlTDmfrjtdlek access-token-expiration-seconds: 3600000 # 1hour = 1000(=1s) * 60 * 60 - refresh-token-expiration-seconds: 1209600000 # 2weeks = 1000(=1s) * 60 * 60 * 24 * 14 \ No newline at end of file + refresh-token-expiration-seconds: 1209600000 # 2weeks = 1000(=1s) * 60 * 60 * 24 * 14 + +alarm: + api-url: http://localhost:8081/api/v1 \ No newline at end of file