Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 스터디 알림 기능을 구현한다. #593

Draft
wants to merge 8 commits into
base: BE/develop
Choose a base branch
from
3 changes: 3 additions & 0 deletions backend/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ dependencies {
annotationProcessor "javax.persistence:javax.persistence-api"
annotationProcessor "javax.annotation:javax.annotation-api"
annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jpa"

// fcm
implementation 'com.google.firebase:firebase-admin:9.1.1'
}

tasks.named('test') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import com.yigongil.backend.config.oauth.GithubProfileResponse;
import com.yigongil.backend.domain.member.Member;
import com.yigongil.backend.domain.member.MemberRepository;
import com.yigongil.backend.request.TokenRequest;
import com.yigongil.backend.request.RefreshTokenRequest;
import com.yigongil.backend.response.TokenResponse;
import java.util.Optional;
import org.springframework.stereotype.Service;
Expand Down Expand Up @@ -40,7 +40,7 @@ public TokenResponse login(String code) {
return createTokens(id);
}

public TokenResponse refresh(TokenRequest request) {
public TokenResponse refresh(RefreshTokenRequest request) {
String refreshToken = request.refreshToken();

jwtTokenProvider.detectTokenTheft(refreshToken);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.yigongil.backend.application;

import com.yigongil.backend.domain.event.MemberDeleteEvent;
import com.yigongil.backend.domain.event.MemberDeletedEvent;
import org.springframework.stereotype.Component;
import org.springframework.transaction.event.TransactionPhase;
import org.springframework.transaction.event.TransactionalEventListener;
Expand All @@ -15,7 +15,7 @@ public StudyEventListener(StudyService studyService) {
}

@TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT)
public void listenMemberDeleteEvent(MemberDeleteEvent event) {
public void listenMemberDeleteEvent(MemberDeletedEvent event) {
studyService.deleteByMasterId(event.memberId());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.stereotype.Service;
Expand All @@ -47,6 +49,9 @@ public class StudyService {
private final FeedService feedService;
private final RoundRepository roundRepository;

@Autowired
EntityManager em;

public StudyService(
StudyRepository studyRepository,
StudyMemberRepository studyMemberRepository,
Expand Down Expand Up @@ -128,6 +133,7 @@ public List<MyStudyResponse> findMyStudies(Member member) {
public void apply(Member member, Long studyId) {
Study study = findStudyById(studyId);
study.apply(member);
// studyRepository.save(study);
}

@Transactional
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,17 @@
package com.yigongil.backend.domain;

import com.yigongil.backend.domain.event.DomainEvent;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import javax.persistence.Column;
import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
import javax.persistence.Transient;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.domain.AfterDomainEventPublication;
import org.springframework.data.domain.DomainEvents;
import org.springframework.data.domain.AbstractAggregateRoot;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
public abstract class BaseEntity {
public abstract class BaseEntity extends AbstractAggregateRoot<BaseEntity> {

@CreatedDate
@Column(nullable = false)
Expand All @@ -25,23 +20,6 @@ public abstract class BaseEntity {
@LastModifiedDate
protected LocalDateTime updatedAt;

@Transient
private Collection<DomainEvent> domainEvents = new ArrayList<>();

@DomainEvents
public Collection<DomainEvent> events() {
return domainEvents;
}

@AfterDomainEventPublication
public void clear() {
domainEvents.clear();
}

protected void register(DomainEvent event) {
domainEvents.add(event);
}

public LocalDateTime getCreatedAt() {
return createdAt;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.yigongil.backend.domain.certification;

import com.yigongil.backend.domain.BaseEntity;
import com.yigongil.backend.domain.event.CertificationCreatedEvent;
import com.yigongil.backend.domain.member.Member;
import com.yigongil.backend.domain.round.Round;
import com.yigongil.backend.domain.study.Study;
Expand All @@ -11,6 +12,7 @@
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.PostPersist;
import lombok.Builder;
import lombok.Getter;

Expand Down Expand Up @@ -59,4 +61,9 @@ public Certification(
this.createdAt = createdAt;
this.round = round;
}

@PostPersist
public void registerCreatedEvent() {
registerEvent(new CertificationCreatedEvent(study.getId(), study.getName(), author.getGithubId()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.yigongil.backend.domain.event;

public record CertificationCreatedEvent(
Long studyId,
String studyName,
String authorGithubId
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.yigongil.backend.domain.event;

import java.time.LocalDateTime;

public record FeedPostCreatedEvent
(
Long studyId,
String studyName,
String authorGithubId,
String content,
String imageUrl,
LocalDateTime createdAt
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이벤트 중에서 이 녀석만 createdAt을 가지고 있는 이유가 무엇인가요??

) implements DomainEvent {

}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.yigongil.backend.domain.event;

public record MemberDeletedEvent(Long memberId) implements DomainEvent {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.yigongil.backend.domain.event;

public record MustDoUpdatedEvent(
Long studyId,
String studyName,
String mustDo
) implements DomainEvent{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.yigongil.backend.domain.event;

public record StudyAppliedEvent(Long studyMasterId, String studyName, String appliedMemberGithubId) implements DomainEvent {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.yigongil.backend.domain.event;

public record StudyCreatedEvent(Long studyId, Long masterId) implements DomainEvent {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.yigongil.backend.domain.event;

public record StudyPermittedEvent(Long permittedMemberId, Long studyId, String studyName) implements DomainEvent {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.yigongil.backend.domain.event;

public record StudyStartedEvent(Long studyId, String studyName) implements DomainEvent {

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.yigongil.backend.domain.feedpost;

import com.yigongil.backend.domain.BaseEntity;
import com.yigongil.backend.domain.event.FeedPostCreatedEvent;
import com.yigongil.backend.domain.member.Member;
import com.yigongil.backend.domain.study.Study;
import java.time.LocalDateTime;
Expand All @@ -11,6 +12,7 @@
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.PostPersist;
import lombok.Builder;
import lombok.Getter;

Expand Down Expand Up @@ -54,6 +56,18 @@ public FeedPost(
this.createdAt = createdAt;
}

@PostPersist
public void registerCreatedEvent() {
registerEvent(new FeedPostCreatedEvent(
study.getId(),
study.getName(),
author.getGithubId(),
content,
imageUrl,
createdAt
));
}

@Override
public boolean equals(Object o) {
if (this == o) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.yigongil.backend.domain.member;

import com.yigongil.backend.domain.BaseEntity;
import com.yigongil.backend.domain.event.MemberDeleteEvent;
import com.yigongil.backend.domain.event.MemberDeletedEvent;
import java.util.Objects;
import javax.persistence.Column;
import javax.persistence.Embedded;
Expand Down Expand Up @@ -103,7 +103,7 @@ public String getIntroduction() {

@PreRemove
public void registerDeleteEvent() {
register(new MemberDeleteEvent(id));
registerEvent(new MemberDeletedEvent(id));
}

public void addExperience(int exp) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.yigongil.backend.domain.round;

import com.yigongil.backend.domain.BaseEntity;
import com.yigongil.backend.domain.event.MustDoUpdatedEvent;
import com.yigongil.backend.domain.meetingdayoftheweek.MeetingDayOfTheWeek;
import com.yigongil.backend.domain.member.Member;
import com.yigongil.backend.domain.roundofmember.RoundOfMember;
Expand Down Expand Up @@ -106,6 +107,7 @@ public void updateMustDo(Member author, String content) {
validateTodoLength(content);
validateMaster(author);
mustDo = content;
registerEvent(new MustDoUpdatedEvent(study.getId(), study.getName(), content));
}

public void validateMaster(Member member) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package com.yigongil.backend.domain.study;

import com.yigongil.backend.domain.BaseEntity;
import com.yigongil.backend.domain.event.StudyAppliedEvent;
import com.yigongil.backend.domain.event.StudyCreatedEvent;
import com.yigongil.backend.domain.event.StudyPermittedEvent;
import com.yigongil.backend.domain.event.StudyStartedEvent;
import com.yigongil.backend.domain.meetingdayoftheweek.MeetingDayOfTheWeek;
import com.yigongil.backend.domain.member.Member;
import com.yigongil.backend.domain.round.Round;
Expand Down Expand Up @@ -33,6 +37,7 @@
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.PostPersist;
import lombok.Builder;
import lombok.Getter;
import org.hibernate.annotations.Cascade;
Expand Down Expand Up @@ -151,6 +156,11 @@ public static Study initializeStudyOf(
.build();
}

@PostPersist
public void registerCreatedEvent() {
registerEvent(new StudyCreatedEvent(id, getMaster().getId()));
}

private void validateNumberOfMaximumMembers(Integer numberOfMaximumMembers) {
if (numberOfMaximumMembers < MIN_MEMBER_SIZE || numberOfMaximumMembers > MAX_MEMBER_SIZE) {
throw new InvalidNumberOfMaximumStudyMember(
Expand Down Expand Up @@ -193,6 +203,8 @@ public void permit(Member applicant, Member master) {
.filter(studyMember -> studyMember.getMember().equals(applicant))
.findAny()
.ifPresent(StudyMember::participate);

registerEvent(new StudyPermittedEvent(applicant.getId(), id, name));
}

public void validateMemberSize() {
Expand Down Expand Up @@ -224,6 +236,7 @@ public void start(Member member, List<DayOfWeek> daysOfTheWeek, LocalDateTime st
this.processingStatus = ProcessingStatus.PROCESSING;
initializeMeetingDaysOfTheWeek(daysOfTheWeek);
initializeRounds(startAt.toLocalDate());
registerEvent(new StudyStartedEvent(id, name));
}

private void deleteLeftApplicant() {
Expand Down Expand Up @@ -398,6 +411,8 @@ public void apply(Member member) {
.member(member)
.studyResult(StudyResult.NONE)
.build());

registerEvent(new StudyAppliedEvent(getMaster().getId(), name, member.getGithubId()));
}

private void validateApplicant(Member member) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.yigongil.backend.exception;

import org.springframework.http.HttpStatus;

public class MemberNotRegisteredException extends HttpException {

public MemberNotRegisteredException(final String message, final String input) {
super(HttpStatus.BAD_REQUEST, message, input);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.yigongil.backend.infra;

import com.google.firebase.messaging.FirebaseMessaging;
import com.google.firebase.messaging.Message;
import java.util.List;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;

@Profile(value = {"prod", "dev"})
@Component
public class FirebaseCloudMessageSender implements MessageSender {

private final FirebaseMessaging firebaseMessaging;

public FirebaseCloudMessageSender(FirebaseMessaging firebaseMessaging) {
this.firebaseMessaging = firebaseMessaging;
}

@Override
public void subscribeToTopicAsync(List<String> tokens, String topic) {
firebaseMessaging.subscribeToTopicAsync(tokens, topic);
}

@Override
public void send(String message, String topic) {
Message topicMessage = Message.builder()
.setTopic(topic)
.putData("message", message)
.build();
firebaseMessaging.sendAsync(topicMessage);
}
}
Loading