From a5dd7420e1a4f53807e67947bac4988ef3585076 Mon Sep 17 00:00:00 2001 From: Kijun Kwon <39583312+kkjsw17@users.noreply.github.com> Date: Mon, 26 Aug 2024 22:04:26 +0900 Subject: [PATCH] =?UTF-8?q?[SAMBAD-301]=20=EC=86=90=20=ED=9D=94=EB=93=A4?= =?UTF-8?q?=EA=B8=B0=20=EC=95=8C=EB=A6=BC=20=EC=B6=94=EA=B0=80=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20=EC=A0=9C=EA=B3=B5=20=EB=B0=A9=EC=8B=9D=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20(#140)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../event/application/EventService.java | 22 ++++---- .../sambad/moring/event/domain/Event.java | 21 +++----- .../event/domain/EventMessageTemplate.java | 4 ++ .../event/domain/MapToJsonConverter.java | 41 --------------- .../event/presentation/EventController.java | 19 +++---- .../event/presentation/EventFacade.java | 50 +++++++++++++++++++ .../response/EventListResponse.java | 10 +--- .../presentation/response/EventResponse.java | 7 ++- .../application/HandWavingRepository.java | 2 + .../application/HandWavingService.java | 21 +++++--- .../meeting/handwaving/domain/HandWaving.java | 12 ++++- .../handwaving/domain/HandWavingSummary.java | 30 +++++++++++ .../HandWavingJpaRepository.java | 4 ++ .../HandWavingRepositoryImpl.java | 5 ++ 14 files changed, 157 insertions(+), 91 deletions(-) delete mode 100644 src/main/java/org/depromeet/sambad/moring/event/domain/MapToJsonConverter.java create mode 100644 src/main/java/org/depromeet/sambad/moring/event/presentation/EventFacade.java create mode 100644 src/main/java/org/depromeet/sambad/moring/meeting/handwaving/domain/HandWavingSummary.java diff --git a/src/main/java/org/depromeet/sambad/moring/event/application/EventService.java b/src/main/java/org/depromeet/sambad/moring/event/application/EventService.java index c439a685..02bba12a 100644 --- a/src/main/java/org/depromeet/sambad/moring/event/application/EventService.java +++ b/src/main/java/org/depromeet/sambad/moring/event/application/EventService.java @@ -11,6 +11,7 @@ import org.depromeet.sambad.moring.event.infrastructure.EventProperties; import org.depromeet.sambad.moring.event.presentation.excepiton.NotFoundEventException; import org.depromeet.sambad.moring.event.presentation.response.PollingEventListResponse; +import org.depromeet.sambad.moring.meeting.handwaving.domain.HandWaving; import org.depromeet.sambad.moring.meeting.member.domain.MeetingMemberValidator; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -31,21 +32,28 @@ public class EventService { private final EventProperties eventProperties; public void publish(Long userId, Long meetingId, EventType type) { - this.publish(userId, meetingId, type, Map.of(), Map.of()); + this.publish(userId, meetingId, type, Map.of()); } - public void publish( - Long userId, Long meetingId, EventType type, Map contentsMap, Map additionalData + public void publishHandWavingEvent( + Long userId, Long meetingId, EventType type, Map contentsMap, HandWaving handWaving ) { + Event event = this.publish(userId, meetingId, type, contentsMap); + handWaving.mapEvent(event); + } + + private Event publish(Long userId, Long meetingId, EventType type, Map contentsMap) { if (meetingMemberValidator.isNotUserOfMeeting(userId, meetingId)) { log.warn("User is not member of meeting. userId: {}, meetingId: {}", userId, meetingId); - return; + return null; } String message = constructEventMessage(type, contentsMap); - Event event = Event.publish(userId, meetingId, type, message, additionalData); + Event event = Event.publish(userId, meetingId, type, message); eventRepository.save(event); + + return event; } public void inactivate(Long eventId) { @@ -86,10 +94,6 @@ public void inactivateLastEventsOfAllMemberByType(Long meetingId, EventType even } private String constructEventMessage(EventType type, Map contentsMap) { - if (contentsMap.isEmpty()) { - return null; - } - return eventMessageTemplateRepository.findByType(type) .map(template -> template.replaceTemplateVariables(contentsMap)) .orElse(null); diff --git a/src/main/java/org/depromeet/sambad/moring/event/domain/Event.java b/src/main/java/org/depromeet/sambad/moring/event/domain/Event.java index ea6ae1f7..a9a145ee 100644 --- a/src/main/java/org/depromeet/sambad/moring/event/domain/Event.java +++ b/src/main/java/org/depromeet/sambad/moring/event/domain/Event.java @@ -4,15 +4,14 @@ import static jakarta.persistence.GenerationType.*; import static lombok.AccessLevel.*; import static org.depromeet.sambad.moring.event.domain.EventStatus.*; +import static org.depromeet.sambad.moring.event.domain.EventType.*; import static org.depromeet.sambad.moring.meeting.question.domain.MeetingQuestion.*; import java.time.LocalDateTime; -import java.util.Map; import org.depromeet.sambad.moring.common.domain.BaseTimeEntity; import jakarta.persistence.Column; -import jakarta.persistence.Convert; import jakarta.persistence.Entity; import jakarta.persistence.Enumerated; import jakarta.persistence.GeneratedValue; @@ -44,13 +43,8 @@ public class Event extends BaseTimeEntity { private LocalDateTime expiredAt; - @Column(columnDefinition = "text") - @Convert(converter = MapToJsonConverter.class) - private Map additionalData = Map.of(); - private Event( - Long userId, Long meetingId, EventType type, EventStatus status, String message, LocalDateTime expiredAt, - Map additionalData + Long userId, Long meetingId, EventType type, EventStatus status, String message, LocalDateTime expiredAt ) { this.userId = userId; this.meetingId = meetingId; @@ -58,14 +52,11 @@ private Event( this.status = status; this.message = message; this.expiredAt = expiredAt; - this.additionalData = additionalData; } - public static Event publish( - Long userId, Long meetingId, EventType type, String message, Map additionalData - ) { + public static Event publish(Long userId, Long meetingId, EventType type, String message) { LocalDateTime expiredAt = LocalDateTime.now().plusSeconds(RESPONSE_TIME_LIMIT_SECONDS); - return new Event(userId, meetingId, type, ACTIVE, message, expiredAt, additionalData); + return new Event(userId, meetingId, type, ACTIVE, message, expiredAt); } public void inactivate() { @@ -85,4 +76,8 @@ private boolean isExpired() { public boolean isActive() { return status == ACTIVE; } + + public boolean isHandWavingEvent() { + return type == HAND_WAVING_REQUESTED; + } } diff --git a/src/main/java/org/depromeet/sambad/moring/event/domain/EventMessageTemplate.java b/src/main/java/org/depromeet/sambad/moring/event/domain/EventMessageTemplate.java index 912701f8..ac838fdb 100644 --- a/src/main/java/org/depromeet/sambad/moring/event/domain/EventMessageTemplate.java +++ b/src/main/java/org/depromeet/sambad/moring/event/domain/EventMessageTemplate.java @@ -33,6 +33,10 @@ public class EventMessageTemplate { private String template; public String replaceTemplateVariables(Map contentsMap) { + if (contentsMap == null) { + return template; + } + String message = template; for (String key : contentsMap.keySet()) { String regex = Pattern.quote("#{" + key + "}"); diff --git a/src/main/java/org/depromeet/sambad/moring/event/domain/MapToJsonConverter.java b/src/main/java/org/depromeet/sambad/moring/event/domain/MapToJsonConverter.java deleted file mode 100644 index 4960587b..00000000 --- a/src/main/java/org/depromeet/sambad/moring/event/domain/MapToJsonConverter.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.depromeet.sambad.moring.event.domain; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; - -import jakarta.persistence.AttributeConverter; -import jakarta.persistence.Converter; - -@Converter -public class MapToJsonConverter implements AttributeConverter, String> { - - private final ObjectMapper objectMapper = new ObjectMapper(); - - @Override - public String convertToDatabaseColumn(Map attribute) { - if (attribute == null) { - return null; - } - try { - return objectMapper.writeValueAsString(attribute); - } catch (JsonProcessingException e) { - throw new IllegalArgumentException("Could not convert map to JSON", e); - } - } - - @Override - public Map convertToEntityAttribute(String dbData) { - if (dbData == null) { - return null; - } - try { - return objectMapper.readValue(dbData, HashMap.class); - } catch (IOException e) { - throw new IllegalArgumentException("Could not convert JSON to map", e); - } - } -} diff --git a/src/main/java/org/depromeet/sambad/moring/event/presentation/EventController.java b/src/main/java/org/depromeet/sambad/moring/event/presentation/EventController.java index 65c8be53..4bbf73a5 100644 --- a/src/main/java/org/depromeet/sambad/moring/event/presentation/EventController.java +++ b/src/main/java/org/depromeet/sambad/moring/event/presentation/EventController.java @@ -1,9 +1,6 @@ package org.depromeet.sambad.moring.event.presentation; -import java.util.List; - import org.depromeet.sambad.moring.event.application.EventService; -import org.depromeet.sambad.moring.event.domain.Event; import org.depromeet.sambad.moring.event.presentation.response.EventListResponse; import org.depromeet.sambad.moring.event.presentation.response.PollingEventListResponse; import org.depromeet.sambad.moring.user.presentation.resolver.UserId; @@ -27,20 +24,24 @@ @RequiredArgsConstructor @RequestMapping("/v1/events") public class EventController { + private final EventService eventService; + private final EventFacade eventFacade; @Operation(summary = "알림 목록 조회", description = """

Description

모임원이 수령해야 하는 알림 목록을 조회합니다. - +

Event Type List

* QUESTION_REGISTERED: 릴레이 질문이 등록되어 답변 가능한 경우 * TARGET_MEMBER: 릴레이 질문 등록 대상자로 선정된 경우 * HAND_WAVING_REQUESTED: 손 흔들기 요청이 들어온 경우 - +

Additional Data

Event Type에 따라 addionalData가 다르게 반환됩니다. - * HAND_WAVING_REQUESTED: {"handWavingId": 1}""") + * HAND_WAVING_REQUESTED: {"handWavingId": 1, "status": "ACCEPTED"} + * status == REQUESTED 일 떄에만 수락 / 거절 버튼 표시되면 될 것 같습니다.""" + ) @ApiResponses({ @ApiResponse(responseCode = "200", description = "알림 목록 조회 성공"), @ApiResponse(responseCode = "403", description = "USER_NOT_MEMBER_OF_MEETING") @@ -51,13 +52,13 @@ public ResponseEntity getEvents( @Parameter(description = "모임 ID", example = "1", required = true) @PathVariable("meetingId") @Positive Long meetingId ) { - List events = eventService.getEvents(userId, meetingId); - return ResponseEntity.ok(EventListResponse.from(events)); + EventListResponse response = eventFacade.getEventsResponse(userId, meetingId); + return ResponseEntity.ok(response); } @Operation(summary = "사용자가 받아야 하는 이벤트 목록 조회", description = """ 사용자가 받아야 하는 이벤트의 목록을 조회합니다. - + Event List * QUESTION_REGISTERED: 릴레이 질문이 등록되어 답변 가능한 경우 * TARGET_MEMBER: 릴레이 질문 등록 대상자로 선정된 경우 diff --git a/src/main/java/org/depromeet/sambad/moring/event/presentation/EventFacade.java b/src/main/java/org/depromeet/sambad/moring/event/presentation/EventFacade.java new file mode 100644 index 00000000..ed4b738f --- /dev/null +++ b/src/main/java/org/depromeet/sambad/moring/event/presentation/EventFacade.java @@ -0,0 +1,50 @@ +package org.depromeet.sambad.moring.event.presentation; + +import java.util.List; + +import org.depromeet.sambad.moring.event.application.EventService; +import org.depromeet.sambad.moring.event.domain.Event; +import org.depromeet.sambad.moring.event.presentation.response.EventListResponse; +import org.depromeet.sambad.moring.event.presentation.response.EventResponse; +import org.depromeet.sambad.moring.meeting.handwaving.application.HandWavingService; +import org.depromeet.sambad.moring.meeting.handwaving.domain.HandWavingSummary; +import org.springframework.stereotype.Service; + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Service +public class EventFacade { + + private final EventService eventService; + private final HandWavingService handWavingService; + + public EventListResponse getEventsResponse(Long userId, Long meetingId) { + List events = eventService.getEvents(userId, meetingId); + List handWavingSummaries = fetchHandWavingEventSummaries(events); + + return mapToEventListResponse(events, handWavingSummaries); + } + + private List fetchHandWavingEventSummaries(List events) { + List handWavingEvents = events.stream() + .filter(Event::isHandWavingEvent) + .toList(); + + return handWavingService.getHandWavingSummariesBy(handWavingEvents); + } + + private EventListResponse mapToEventListResponse(List events, List handWavingSummaries) { + List responses = events.stream() + .map(event -> mapToResponseConsiderEventType(event, handWavingSummaries)) + .toList(); + + return EventListResponse.from(responses); + } + + private EventResponse mapToResponseConsiderEventType(Event event, List handWavingSummaries) { + HandWavingSummary additionalData = HandWavingSummary.findSummaryByEvent(handWavingSummaries, event); + + return EventResponse.from(event, additionalData); + } +} diff --git a/src/main/java/org/depromeet/sambad/moring/event/presentation/response/EventListResponse.java b/src/main/java/org/depromeet/sambad/moring/event/presentation/response/EventListResponse.java index 7f966b5a..7415f514 100644 --- a/src/main/java/org/depromeet/sambad/moring/event/presentation/response/EventListResponse.java +++ b/src/main/java/org/depromeet/sambad/moring/event/presentation/response/EventListResponse.java @@ -4,8 +4,6 @@ import java.util.List; -import org.depromeet.sambad.moring.event.domain.Event; - import io.swagger.v3.oas.annotations.media.Schema; public record EventListResponse( @@ -13,11 +11,7 @@ public record EventListResponse( List contents ) { - public static EventListResponse from(List events) { - List contents = events.stream() - .map(EventResponse::from) - .toList(); - - return new EventListResponse(contents); + public static EventListResponse from(List events) { + return new EventListResponse(events); } } diff --git a/src/main/java/org/depromeet/sambad/moring/event/presentation/response/EventResponse.java b/src/main/java/org/depromeet/sambad/moring/event/presentation/response/EventResponse.java index 03910ce4..1449a1f0 100644 --- a/src/main/java/org/depromeet/sambad/moring/event/presentation/response/EventResponse.java +++ b/src/main/java/org/depromeet/sambad/moring/event/presentation/response/EventResponse.java @@ -4,7 +4,6 @@ import java.util.Arrays; import java.util.List; -import java.util.Map; import java.util.Optional; import org.depromeet.sambad.moring.event.domain.Event; @@ -27,12 +26,12 @@ public record EventResponse( EventStatus status, @Schema(description = "이벤트 타입 별로 필요한 추가 데이터", example = "{\"handWavingId\": 9}", requiredMode = NOT_REQUIRED) - Map additionalData, + Object additionalData, @Schema(description = "이벤트 생성 시간 타임 스탬프", example = "1724252079282", requiredMode = REQUIRED) Long createdAt ) { - public static EventResponse from(Event event) { + public static EventResponse from(Event event, Object additionalData) { List messages = Optional.ofNullable(event.getMessage()) .map(message -> Arrays.asList(message.split("\n"))) .orElse(List.of()); @@ -42,7 +41,7 @@ public static EventResponse from(Event event) { event.getType(), messages, event.getStatus(), - event.getAdditionalData(), + additionalData, event.getCreatedAtWithEpochMilli() ); } diff --git a/src/main/java/org/depromeet/sambad/moring/meeting/handwaving/application/HandWavingRepository.java b/src/main/java/org/depromeet/sambad/moring/meeting/handwaving/application/HandWavingRepository.java index 65ca47bf..c680b579 100644 --- a/src/main/java/org/depromeet/sambad/moring/meeting/handwaving/application/HandWavingRepository.java +++ b/src/main/java/org/depromeet/sambad/moring/meeting/handwaving/application/HandWavingRepository.java @@ -15,4 +15,6 @@ public interface HandWavingRepository { Optional findFirstBySenderIdAndReceiverIdOrderByIdDesc(Long senderMemberId, Long receiverMemberId); List findHandWavedMembersByMeetingMemberId(Long meetingMemberId); + + List findAllByEventIdIn(List eventIds); } diff --git a/src/main/java/org/depromeet/sambad/moring/meeting/handwaving/application/HandWavingService.java b/src/main/java/org/depromeet/sambad/moring/meeting/handwaving/application/HandWavingService.java index e02b4965..045c0b22 100644 --- a/src/main/java/org/depromeet/sambad/moring/meeting/handwaving/application/HandWavingService.java +++ b/src/main/java/org/depromeet/sambad/moring/meeting/handwaving/application/HandWavingService.java @@ -3,12 +3,14 @@ import static org.depromeet.sambad.moring.event.domain.EventType.*; import static org.depromeet.sambad.moring.meeting.handwaving.domain.HandWavingStatus.NOT_REQUESTED; +import java.util.List; import java.util.Map; import java.util.Optional; import org.depromeet.sambad.moring.event.application.EventService; +import org.depromeet.sambad.moring.event.domain.Event; import org.depromeet.sambad.moring.meeting.handwaving.domain.HandWaving; -import org.depromeet.sambad.moring.meeting.handwaving.domain.HandWavingStatus; +import org.depromeet.sambad.moring.meeting.handwaving.domain.HandWavingSummary; import org.depromeet.sambad.moring.meeting.handwaving.presentation.exception.NotFoundHandWavingException; import org.depromeet.sambad.moring.meeting.handwaving.presentation.request.HandWavingRequest; import org.depromeet.sambad.moring.meeting.handwaving.presentation.response.HandWavingStatusResponse; @@ -64,6 +66,17 @@ public void ignoreHandWaving(Long userId, Long meetingId, Long handWavingId) { handWaving.reject(); } + public List getHandWavingSummariesBy(List events) { + List eventIds = events.stream() + .map(Event::getId) + .toList(); + + return handWavingRepository.findAllByEventIdIn(eventIds) + .stream() + .map(HandWavingSummary::from) + .toList(); + } + private Optional getHandWavingBySenderIdAndReceiverId(Long senderMemberId, Long receiverMemberId) { return handWavingRepository.findFirstBySenderIdAndReceiverIdOrderByIdDesc(senderMemberId, receiverMemberId); } @@ -82,13 +95,9 @@ private void publishRequestedEvent(HandWaving handWaving) { "receiver", receiver.getName() ); - Map additionalData = Map.of( - "handWavingId", handWaving.getId() - ); - Long userId = receiver.getUser().getId(); Long meetingId = receiver.getMeeting().getId(); - eventService.publish(userId, meetingId, HAND_WAVING_REQUESTED, contentsMap, additionalData); + eventService.publishHandWavingEvent(userId, meetingId, HAND_WAVING_REQUESTED, contentsMap, handWaving); } } diff --git a/src/main/java/org/depromeet/sambad/moring/meeting/handwaving/domain/HandWaving.java b/src/main/java/org/depromeet/sambad/moring/meeting/handwaving/domain/HandWaving.java index 6c5c35e5..1231e899 100644 --- a/src/main/java/org/depromeet/sambad/moring/meeting/handwaving/domain/HandWaving.java +++ b/src/main/java/org/depromeet/sambad/moring/meeting/handwaving/domain/HandWaving.java @@ -4,6 +4,7 @@ import static org.depromeet.sambad.moring.meeting.handwaving.domain.HandWavingStatus.REQUESTED; import org.depromeet.sambad.moring.common.domain.BaseTimeEntity; +import org.depromeet.sambad.moring.event.domain.Event; import org.depromeet.sambad.moring.meeting.handwaving.presentation.exception.InvalidHandWavingReceiverException; import org.depromeet.sambad.moring.meeting.handwaving.presentation.exception.InvalidHandWavingStatusChangeException; import org.depromeet.sambad.moring.meeting.member.domain.MeetingMember; @@ -39,10 +40,12 @@ public class HandWaving extends BaseTimeEntity { @JoinColumn(name = "receiver_id") private MeetingMember receiver; + private Long eventId; + @Enumerated(STRING) private HandWavingStatus status; - public HandWaving(MeetingMember sender, MeetingMember receiver) { + private HandWaving(MeetingMember sender, MeetingMember receiver) { this.sender = sender; this.receiver = receiver; this.status = REQUESTED; @@ -68,6 +71,13 @@ public void validateIsReceiver(Long receiverUserId) { } } + public void mapEvent(Event event) { + if (this.eventId == null) { + return; + } + this.eventId = event.getId(); + } + private void validateStatusIsRequested() { if (this.status != REQUESTED) { throw new InvalidHandWavingStatusChangeException(); diff --git a/src/main/java/org/depromeet/sambad/moring/meeting/handwaving/domain/HandWavingSummary.java b/src/main/java/org/depromeet/sambad/moring/meeting/handwaving/domain/HandWavingSummary.java new file mode 100644 index 00000000..8a244948 --- /dev/null +++ b/src/main/java/org/depromeet/sambad/moring/meeting/handwaving/domain/HandWavingSummary.java @@ -0,0 +1,30 @@ +package org.depromeet.sambad.moring.meeting.handwaving.domain; + +import java.util.List; +import java.util.Objects; + +import org.depromeet.sambad.moring.event.domain.Event; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +public record HandWavingSummary( + Long handWavingId, + HandWavingStatus status, + @JsonIgnore + Long eventId +) { + public static HandWavingSummary from(HandWaving handWaving) { + return new HandWavingSummary(handWaving.getId(), handWaving.getStatus(), handWaving.getEventId()); + } + + public static HandWavingSummary findSummaryByEvent(List handWavingSummaries, Event event) { + return handWavingSummaries.stream() + .filter(summary -> summary.shouldBelongTo(event)) + .findFirst() + .orElse(null); + } + + public boolean shouldBelongTo(Event event) { + return Objects.equals(eventId, event.getId()); + } +} diff --git a/src/main/java/org/depromeet/sambad/moring/meeting/handwaving/infrastructure/HandWavingJpaRepository.java b/src/main/java/org/depromeet/sambad/moring/meeting/handwaving/infrastructure/HandWavingJpaRepository.java index a2d495c8..0beedb45 100644 --- a/src/main/java/org/depromeet/sambad/moring/meeting/handwaving/infrastructure/HandWavingJpaRepository.java +++ b/src/main/java/org/depromeet/sambad/moring/meeting/handwaving/infrastructure/HandWavingJpaRepository.java @@ -1,5 +1,6 @@ package org.depromeet.sambad.moring.meeting.handwaving.infrastructure; +import java.util.List; import java.util.Optional; import org.depromeet.sambad.moring.meeting.handwaving.domain.HandWaving; @@ -8,4 +9,7 @@ public interface HandWavingJpaRepository extends JpaRepository { Optional findFirstBySenderIdAndReceiverIdOrderByIdDesc(Long senderMemberId, Long receiverMemberId); + + List findAllByEventIdIn(List eventIds); + } diff --git a/src/main/java/org/depromeet/sambad/moring/meeting/handwaving/infrastructure/HandWavingRepositoryImpl.java b/src/main/java/org/depromeet/sambad/moring/meeting/handwaving/infrastructure/HandWavingRepositoryImpl.java index 91e9f69b..78716f67 100644 --- a/src/main/java/org/depromeet/sambad/moring/meeting/handwaving/infrastructure/HandWavingRepositoryImpl.java +++ b/src/main/java/org/depromeet/sambad/moring/meeting/handwaving/infrastructure/HandWavingRepositoryImpl.java @@ -54,4 +54,9 @@ public List findHandWavedMembersByMeetingMemberId(Long meetingMem ) .fetch(); } + + @Override + public List findAllByEventIdIn(List eventIds) { + return handWavingJpaRepository.findAllByEventIdIn(eventIds); + } }